Example #1
0
/**
 * Module entry point
 *
 * Initialize moduel-wide resources and register driver
 */
int
init_module(void)
{
   VMK_ReturnStatus vmkStatus;

   Nvme_LogNoHandle("Loading driver %s.", NVME_DRIVER_IDENT);

   Nvme_ValidateModuleParams();

#if VMKAPIDDK_VERSION >= 650
   VMK_ASSERT(sizeof(NvmeIoRequest) <= vmk_ScsiCmdGetDriverFrameSize());
#endif

   /* Always initialize heap in the first place. */
   vmkStatus = HeapCreate();
   if (vmkStatus != VMK_OK) {
      Nvme_LogNoHandle("failed to create driver heap, 0x%x.", vmkStatus);
      return vmkStatus;
   }

   /* Initialize log components, and set default log level based on
    * module parameter.
    */
   vmkStatus = LogHandleCreate(nvme_log_level);
   if (vmkStatus != VMK_OK) {
      Nvme_LogNoHandle("failed to create log handle, 0x%x.", vmkStatus);
      goto destroy_heap;
   }

   /* Initialize mem pool. mem pool is used for allocating large
    * physically contiguous memory.
    */
   vmkStatus = MemPoolCreate();
   if (vmkStatus != VMK_OK) {
      EPRINT("failed to create mem pool, 0x%x.", vmkStatus);
      goto destroy_log;
   }

   /** Initialize global management handle */
   vmkStatus = NvmeMgmt_GlobalInitialize();
   if (vmkStatus != VMK_OK) {
      EPRINT("failed to initialize global management interface, 0x%x.", vmkStatus);
      goto destroy_mpool;
   }

   /** Initialize global lock */
   vmkStatus = OsLib_LockCreateNoRank(NVME_GLOBAL_LOCK_NAME,
      &NVME_DRIVER_RES_LOCK);
   if (vmkStatus != VMK_OK) {
      EPRINT("failed to initialize global lock, 0x%x.", vmkStatus);
      goto destroy_mgmt;
   }

   /** Initialize adapter list */
   vmk_ListInit(&NVME_DRIVER_RES_ADAPTERLIST);

   /* TODO: Do we have other global resources to initialize here? */

   /* Finally, register driver */
   vmkStatus = NvmeDriver_Register();
   if (vmkStatus != VMK_OK) {
      EPRINT("failed to register driver, 0x%x.", vmkStatus);
      goto destroy_lock;
   }

   IPRINT("module initialized successfully.");

   return 0;

destroy_lock:
   OsLib_LockDestroy(&NVME_DRIVER_RES_LOCK);

destroy_mgmt:
   NvmeMgmt_GlobalDestroy();

destroy_mpool:
   MemPoolDestroy();

destroy_log:
   LogHandleDestroy();

destroy_heap:
   HeapDestroy();

   return vmkStatus;
}
Example #2
0
/**
 * Attach and bring up controller
 *
 * Allocate controller related resources
 *
 * @param [in] ctrlr controller instance
 */
VMK_ReturnStatus
NvmeCtrlr_Attach(struct NvmeCtrlr *ctrlr)
{
   VMK_ReturnStatus vmkStatus;
   char lockName[VMK_MISC_NAME_MAX];

   /**
    * Set initial state.
    *
    * Note: lock is not initialized by here, so do not use locking.
    */
   NvmeState_SetCtrlrState(ctrlr, NVME_CTRLR_STATE_INIT, VMK_FALSE);

   /**
    * Initialize PCI resources first to access controller bars.
    *
    * Note: has to initialize PCI resource first, all the following operations
    *       require BARs to be mapped already.
    */
   vmkStatus = PciInit(ctrlr);
   if (vmkStatus != VMK_OK) {
      return vmkStatus;
   }

   vmkStatus = NvmeCtrlr_ValidateParams(ctrlr);
   if (vmkStatus != VMK_OK) {
      goto cleanup_pci;
   }

   /* Initialize DMA facilities (dma engine, sg handle, etc.) */
   vmkStatus = OsLib_DmaInit(&ctrlr->ctrlOsResources);
   if (vmkStatus != VMK_OK) {
      goto cleanup_pci;
   }

   /* Initialize interrupt */
   vmkStatus = IntrInit(ctrlr);
   if (vmkStatus != VMK_OK) {
      goto cleanup_dma;
   }

   /* Initialize lock domain for locks within this controller */
   vmkStatus = OsLib_LockDomainCreate(&ctrlr->ctrlOsResources,
			Nvme_GetCtrlrName(ctrlr));
   if (vmkStatus != VMK_OK) {
      goto cleanup_intr;
   }

   /* Initialize lock */
   vmk_StringFormat(lockName, sizeof(lockName), NULL, "%s-lock",
                    Nvme_GetCtrlrName(ctrlr));
   vmkStatus = OsLib_LockCreate(&ctrlr->ctrlOsResources, NVME_LOCK_RANK_LOW,
      lockName, &ctrlr->lock);
   if (vmkStatus != VMK_OK) {
      goto cleanup_lockdomain;
   }

   /* Initialize task management mutex */
   vmk_StringFormat(lockName, sizeof(lockName), NULL, "%s-mutex",
                    Nvme_GetCtrlrName(ctrlr));
   vmkStatus = OsLib_SemaphoreCreate(lockName, 1, &ctrlr->taskMgmtMutex);
   if (vmkStatus != VMK_OK) {
      goto cleanup_lock;
   }
   vmkStatus = OsLib_TimerQueueCreate(ctrlr);
   if (vmkStatus != VMK_OK) {
      goto cleanup_sema;
   }


#if EXC_HANDLER
  vmkStatus = OsLib_SetupExceptionHandler(ctrlr);
   if (vmkStatus != VMK_OK) {
      EPRINT("The device can not handle exceptions.");
      goto cleanup_timer_queue;
   }
#endif

   /*
    * TODO: Initialize and kick off timers and kernel thread
    */
#if 0
   vmkStatus = NvmeCtrlr_CreateLogWorld(ctrlr);
   if (vmkStatus != VMK_OK) {
      goto cleanup_intr;
   }
#endif

   vmkStatus = CreateScsiUnmapSlab(ctrlr);
   if (vmkStatus != VMK_OK) {
      #if EXC_HANDLER
         goto cleanup_exc_handler;
      #else
         goto cleanup_timer_queue;
      #endif
   }

#if NVME_MUL_COMPL_WORLD
   vmkStatus = OsLib_StartCompletionWorlds(ctrlr);
   if (vmkStatus != VMK_OK) {
      EPRINT("Failed to create completion worlds. vmkStatus: 0x%x.",  \
            vmkStatus);
      goto cleanup_unmap_slab;

   }
#endif

   vmkStatus = NvmeCtrlr_AdminQueueSetup(ctrlr);
   if (vmkStatus != VMK_OK) {
#if NVME_MUL_COMPL_WORLD
      goto cleanup_compl_worlds;
#else
      goto cleanup_unmap_slab;
#endif
   }

   #if NVME_DEBUG_INJECT_ERRORS
      NvmeDebug_ErrorInjectInit(ctrlr->errCounters);
   #endif

   /**
    * Initialize all other essential members
    */
   vmk_ListInit(&ctrlr->nsList);

   return VMK_OK;

#if NVME_MUL_COMPL_WORLD
cleanup_compl_worlds:
   OsLib_EndCompletionWorlds(ctrlr);
#endif

cleanup_unmap_slab:
   vmk_SlabDestroy(ctrlr->scsiUnmapSlabId);


#if EXC_HANDLER
cleanup_exc_handler:
   OsLib_ShutdownExceptionHandler(ctrlr);
#endif

cleanup_timer_queue:
   OsLib_TimerQueueDestroy(ctrlr);


cleanup_sema:
   OsLib_SemaphoreDestroy(&ctrlr->taskMgmtMutex);

cleanup_lock:
   OsLib_LockDestroy(&ctrlr->lock);

cleanup_lockdomain:
   OsLib_LockDomainDestroy(&ctrlr->ctrlOsResources);

cleanup_intr:
   IntrCleanup(ctrlr);

cleanup_dma:
   OsLib_DmaCleanup(&ctrlr->ctrlOsResources);

cleanup_pci:
   PciCleanup(ctrlr);

   NvmeState_SetCtrlrState(ctrlr, NVME_CTRLR_STATE_FAILED, VMK_FALSE);

   DPRINT_CTRLR("failed to attach controller, 0x%x.", vmkStatus);

   return vmkStatus;
}