Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 // Copyright 2014 Cisco Systems, Inc.  All rights reserved.
0003 
0004 #include <linux/module.h>
0005 #include <linux/mempool.h>
0006 #include <linux/string.h>
0007 #include <linux/slab.h>
0008 #include <linux/errno.h>
0009 #include <linux/init.h>
0010 #include <linux/pci.h>
0011 #include <linux/skbuff.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/spinlock.h>
0014 #include <linux/workqueue.h>
0015 #include <scsi/scsi_host.h>
0016 #include <scsi/scsi_tcq.h>
0017 
0018 #include "snic.h"
0019 #include "snic_fwint.h"
0020 
0021 #define PCI_DEVICE_ID_CISCO_SNIC    0x0046
0022 
0023 /* Supported devices by snic module */
0024 static struct pci_device_id snic_id_table[] = {
0025     {PCI_DEVICE(0x1137, PCI_DEVICE_ID_CISCO_SNIC) },
0026     { 0, }  /* end of table */
0027 };
0028 
0029 unsigned int snic_log_level = 0x0;
0030 module_param(snic_log_level, int, S_IRUGO|S_IWUSR);
0031 MODULE_PARM_DESC(snic_log_level, "bitmask for snic logging levels");
0032 
0033 #ifdef CONFIG_SCSI_SNIC_DEBUG_FS
0034 unsigned int snic_trace_max_pages = 16;
0035 module_param(snic_trace_max_pages, uint, S_IRUGO|S_IWUSR);
0036 MODULE_PARM_DESC(snic_trace_max_pages,
0037         "Total allocated memory pages for snic trace buffer");
0038 
0039 #endif
0040 unsigned int snic_max_qdepth = SNIC_DFLT_QUEUE_DEPTH;
0041 module_param(snic_max_qdepth, uint, S_IRUGO | S_IWUSR);
0042 MODULE_PARM_DESC(snic_max_qdepth, "Queue depth to report for each LUN");
0043 
0044 /*
0045  * snic_slave_alloc : callback function to SCSI Mid Layer, called on
0046  * scsi device initialization.
0047  */
0048 static int
0049 snic_slave_alloc(struct scsi_device *sdev)
0050 {
0051     struct snic_tgt *tgt = starget_to_tgt(scsi_target(sdev));
0052 
0053     if (!tgt || snic_tgt_chkready(tgt))
0054         return -ENXIO;
0055 
0056     return 0;
0057 }
0058 
0059 /*
0060  * snic_slave_configure : callback function to SCSI Mid Layer, called on
0061  * scsi device initialization.
0062  */
0063 static int
0064 snic_slave_configure(struct scsi_device *sdev)
0065 {
0066     struct snic *snic = shost_priv(sdev->host);
0067     u32 qdepth = 0, max_ios = 0;
0068     int tmo = SNIC_DFLT_CMD_TIMEOUT * HZ;
0069 
0070     /* Set Queue Depth */
0071     max_ios = snic_max_qdepth;
0072     qdepth = min_t(u32, max_ios, SNIC_MAX_QUEUE_DEPTH);
0073     scsi_change_queue_depth(sdev, qdepth);
0074 
0075     if (snic->fwinfo.io_tmo > 1)
0076         tmo = snic->fwinfo.io_tmo * HZ;
0077 
0078     /* FW requires extended timeouts */
0079     blk_queue_rq_timeout(sdev->request_queue, tmo);
0080 
0081     return 0;
0082 }
0083 
0084 static int
0085 snic_change_queue_depth(struct scsi_device *sdev, int qdepth)
0086 {
0087     struct snic *snic = shost_priv(sdev->host);
0088     int qsz = 0;
0089 
0090     qsz = min_t(u32, qdepth, SNIC_MAX_QUEUE_DEPTH);
0091     if (qsz < sdev->queue_depth)
0092         atomic64_inc(&snic->s_stats.misc.qsz_rampdown);
0093     else if (qsz > sdev->queue_depth)
0094         atomic64_inc(&snic->s_stats.misc.qsz_rampup);
0095 
0096     atomic64_set(&snic->s_stats.misc.last_qsz, sdev->queue_depth);
0097 
0098     scsi_change_queue_depth(sdev, qsz);
0099 
0100     return sdev->queue_depth;
0101 }
0102 
0103 static struct scsi_host_template snic_host_template = {
0104     .module = THIS_MODULE,
0105     .name = SNIC_DRV_NAME,
0106     .queuecommand = snic_queuecommand,
0107     .eh_abort_handler = snic_abort_cmd,
0108     .eh_device_reset_handler = snic_device_reset,
0109     .eh_host_reset_handler = snic_host_reset,
0110     .slave_alloc = snic_slave_alloc,
0111     .slave_configure = snic_slave_configure,
0112     .change_queue_depth = snic_change_queue_depth,
0113     .this_id = -1,
0114     .cmd_per_lun = SNIC_DFLT_QUEUE_DEPTH,
0115     .can_queue = SNIC_MAX_IO_REQ,
0116     .sg_tablesize = SNIC_MAX_SG_DESC_CNT,
0117     .max_sectors = 0x800,
0118     .shost_groups = snic_host_groups,
0119     .track_queue_depth = 1,
0120     .cmd_size = sizeof(struct snic_internal_io_state),
0121     .proc_name = "snic_scsi",
0122 };
0123 
0124 /*
0125  * snic_handle_link_event : Handles link events such as link up/down/error
0126  */
0127 void
0128 snic_handle_link_event(struct snic *snic)
0129 {
0130     unsigned long flags;
0131 
0132     spin_lock_irqsave(&snic->snic_lock, flags);
0133     if (snic->stop_link_events) {
0134         spin_unlock_irqrestore(&snic->snic_lock, flags);
0135 
0136         return;
0137     }
0138     spin_unlock_irqrestore(&snic->snic_lock, flags);
0139 
0140     queue_work(snic_glob->event_q, &snic->link_work);
0141 } /* end of snic_handle_link_event */
0142 
0143 /*
0144  * snic_notify_set : sets notification area
0145  * This notification area is to receive events from fw
0146  * Note: snic supports only MSIX interrupts, in which we can just call
0147  *  svnic_dev_notify_set directly
0148  */
0149 static int
0150 snic_notify_set(struct snic *snic)
0151 {
0152     int ret = 0;
0153     enum vnic_dev_intr_mode intr_mode;
0154 
0155     intr_mode = svnic_dev_get_intr_mode(snic->vdev);
0156 
0157     if (intr_mode == VNIC_DEV_INTR_MODE_MSIX) {
0158         ret = svnic_dev_notify_set(snic->vdev, SNIC_MSIX_ERR_NOTIFY);
0159     } else {
0160         SNIC_HOST_ERR(snic->shost,
0161                   "Interrupt mode should be setup before devcmd notify set %d\n",
0162                   intr_mode);
0163         ret = -1;
0164     }
0165 
0166     return ret;
0167 } /* end of snic_notify_set */
0168 
0169 /*
0170  * snic_dev_wait : polls vnic open status.
0171  */
0172 static int
0173 snic_dev_wait(struct vnic_dev *vdev,
0174         int (*start)(struct vnic_dev *, int),
0175         int (*finished)(struct vnic_dev *, int *),
0176         int arg)
0177 {
0178     unsigned long time;
0179     int ret, done;
0180     int retry_cnt = 0;
0181 
0182     ret = start(vdev, arg);
0183     if (ret)
0184         return ret;
0185 
0186     /*
0187      * Wait for func to complete...2 seconds max.
0188      *
0189      * Sometimes schedule_timeout_uninterruptible take long time
0190      * to wakeup, which results skipping retry. The retry counter
0191      * ensures to retry at least two times.
0192      */
0193     time = jiffies + (HZ * 2);
0194     do {
0195         ret = finished(vdev, &done);
0196         if (ret)
0197             return ret;
0198 
0199         if (done)
0200             return 0;
0201         schedule_timeout_uninterruptible(HZ/10);
0202         ++retry_cnt;
0203     } while (time_after(time, jiffies) || (retry_cnt < 3));
0204 
0205     return -ETIMEDOUT;
0206 } /* end of snic_dev_wait */
0207 
0208 /*
0209  * snic_cleanup: called by snic_remove
0210  * Stops the snic device, masks all interrupts, Completed CQ entries are
0211  * drained. Posted WQ/RQ/Copy-WQ entries are cleanup
0212  */
0213 static int
0214 snic_cleanup(struct snic *snic)
0215 {
0216     unsigned int i;
0217     int ret;
0218 
0219     svnic_dev_disable(snic->vdev);
0220     for (i = 0; i < snic->intr_count; i++)
0221         svnic_intr_mask(&snic->intr[i]);
0222 
0223     for (i = 0; i < snic->wq_count; i++) {
0224         ret = svnic_wq_disable(&snic->wq[i]);
0225         if (ret)
0226             return ret;
0227     }
0228 
0229     /* Clean up completed IOs */
0230     snic_fwcq_cmpl_handler(snic, -1);
0231 
0232     snic_wq_cmpl_handler(snic, -1);
0233 
0234     /* Clean up the IOs that have not completed */
0235     for (i = 0; i < snic->wq_count; i++)
0236         svnic_wq_clean(&snic->wq[i], snic_free_wq_buf);
0237 
0238     for (i = 0; i < snic->cq_count; i++)
0239         svnic_cq_clean(&snic->cq[i]);
0240 
0241     for (i = 0; i < snic->intr_count; i++)
0242         svnic_intr_clean(&snic->intr[i]);
0243 
0244     /* Cleanup snic specific requests */
0245     snic_free_all_untagged_reqs(snic);
0246 
0247     /* Cleanup Pending SCSI commands */
0248     snic_shutdown_scsi_cleanup(snic);
0249 
0250     for (i = 0; i < SNIC_REQ_MAX_CACHES; i++)
0251         mempool_destroy(snic->req_pool[i]);
0252 
0253     return 0;
0254 } /* end of snic_cleanup */
0255 
0256 
0257 static void
0258 snic_iounmap(struct snic *snic)
0259 {
0260     if (snic->bar0.vaddr)
0261         iounmap(snic->bar0.vaddr);
0262 }
0263 
0264 /*
0265  * snic_vdev_open_done : polls for svnic_dev_open cmd completion.
0266  */
0267 static int
0268 snic_vdev_open_done(struct vnic_dev *vdev, int *done)
0269 {
0270     struct snic *snic = svnic_dev_priv(vdev);
0271     int ret;
0272     int nretries = 5;
0273 
0274     do {
0275         ret = svnic_dev_open_done(vdev, done);
0276         if (ret == 0)
0277             break;
0278 
0279         SNIC_HOST_INFO(snic->shost, "VNIC_DEV_OPEN Timedout.\n");
0280     } while (nretries--);
0281 
0282     return ret;
0283 } /* end of snic_vdev_open_done */
0284 
0285 /*
0286  * snic_add_host : registers scsi host with ML
0287  */
0288 static int
0289 snic_add_host(struct Scsi_Host *shost, struct pci_dev *pdev)
0290 {
0291     int ret = 0;
0292 
0293     ret = scsi_add_host(shost, &pdev->dev);
0294     if (ret) {
0295         SNIC_HOST_ERR(shost,
0296                   "snic: scsi_add_host failed. %d\n",
0297                   ret);
0298 
0299         return ret;
0300     }
0301 
0302     SNIC_BUG_ON(shost->work_q != NULL);
0303     snprintf(shost->work_q_name, sizeof(shost->work_q_name), "scsi_wq_%d",
0304          shost->host_no);
0305     shost->work_q = create_singlethread_workqueue(shost->work_q_name);
0306     if (!shost->work_q) {
0307         SNIC_HOST_ERR(shost, "Failed to Create ScsiHost wq.\n");
0308 
0309         ret = -ENOMEM;
0310     }
0311 
0312     return ret;
0313 } /* end of snic_add_host */
0314 
0315 static void
0316 snic_del_host(struct Scsi_Host *shost)
0317 {
0318     if (!shost->work_q)
0319         return;
0320 
0321     destroy_workqueue(shost->work_q);
0322     shost->work_q = NULL;
0323     scsi_remove_host(shost);
0324 }
0325 
0326 int
0327 snic_get_state(struct snic *snic)
0328 {
0329     return atomic_read(&snic->state);
0330 }
0331 
0332 void
0333 snic_set_state(struct snic *snic, enum snic_state state)
0334 {
0335     SNIC_HOST_INFO(snic->shost, "snic state change from %s to %s\n",
0336                snic_state_to_str(snic_get_state(snic)),
0337                snic_state_to_str(state));
0338 
0339     atomic_set(&snic->state, state);
0340 }
0341 
0342 /*
0343  * snic_probe : Initialize the snic interface.
0344  */
0345 static int
0346 snic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
0347 {
0348     struct Scsi_Host *shost;
0349     struct snic *snic;
0350     mempool_t *pool;
0351     unsigned long flags;
0352     u32 max_ios = 0;
0353     int ret, i;
0354 
0355     /* Device Information */
0356     SNIC_INFO("snic device %4x:%4x:%4x:%4x: ",
0357           pdev->vendor, pdev->device, pdev->subsystem_vendor,
0358           pdev->subsystem_device);
0359 
0360     SNIC_INFO("snic device bus %x: slot %x: fn %x\n",
0361           pdev->bus->number, PCI_SLOT(pdev->devfn),
0362           PCI_FUNC(pdev->devfn));
0363 
0364     /*
0365      * Allocate SCSI Host and setup association between host, and snic
0366      */
0367     shost = scsi_host_alloc(&snic_host_template, sizeof(struct snic));
0368     if (!shost) {
0369         SNIC_ERR("Unable to alloc scsi_host\n");
0370         ret = -ENOMEM;
0371 
0372         goto prob_end;
0373     }
0374     snic = shost_priv(shost);
0375     snic->shost = shost;
0376 
0377     snprintf(snic->name, sizeof(snic->name) - 1, "%s%d", SNIC_DRV_NAME,
0378          shost->host_no);
0379 
0380     SNIC_HOST_INFO(shost,
0381                "snic%d = %p shost = %p device bus %x: slot %x: fn %x\n",
0382                shost->host_no, snic, shost, pdev->bus->number,
0383                PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
0384 #ifdef CONFIG_SCSI_SNIC_DEBUG_FS
0385     /* Per snic debugfs init */
0386     snic_stats_debugfs_init(snic);
0387 #endif
0388 
0389     /* Setup PCI Resources */
0390     pci_set_drvdata(pdev, snic);
0391     snic->pdev = pdev;
0392 
0393     ret = pci_enable_device(pdev);
0394     if (ret) {
0395         SNIC_HOST_ERR(shost,
0396                   "Cannot enable PCI Resources, aborting : %d\n",
0397                   ret);
0398 
0399         goto err_free_snic;
0400     }
0401 
0402     ret = pci_request_regions(pdev, SNIC_DRV_NAME);
0403     if (ret) {
0404         SNIC_HOST_ERR(shost,
0405                   "Cannot obtain PCI Resources, aborting : %d\n",
0406                   ret);
0407 
0408         goto err_pci_disable;
0409     }
0410 
0411     pci_set_master(pdev);
0412 
0413     /*
0414      * Query PCI Controller on system for DMA addressing
0415      * limitation for the device. Try 43-bit first, and
0416      * fail to 32-bit.
0417      */
0418     ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(43));
0419     if (ret) {
0420         ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
0421         if (ret) {
0422             SNIC_HOST_ERR(shost,
0423                       "No Usable DMA Configuration, aborting %d\n",
0424                       ret);
0425             goto err_rel_regions;
0426         }
0427     }
0428 
0429     /* Map vNIC resources from BAR0 */
0430     if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
0431         SNIC_HOST_ERR(shost, "BAR0 not memory mappable aborting.\n");
0432 
0433         ret = -ENODEV;
0434         goto err_rel_regions;
0435     }
0436 
0437     snic->bar0.vaddr = pci_iomap(pdev, 0, 0);
0438     if (!snic->bar0.vaddr) {
0439         SNIC_HOST_ERR(shost,
0440                   "Cannot memory map BAR0 res hdr aborting.\n");
0441 
0442         ret = -ENODEV;
0443         goto err_rel_regions;
0444     }
0445 
0446     snic->bar0.bus_addr = pci_resource_start(pdev, 0);
0447     snic->bar0.len = pci_resource_len(pdev, 0);
0448     SNIC_BUG_ON(snic->bar0.bus_addr == 0);
0449 
0450     /* Devcmd2 Resource Allocation and Initialization */
0451     snic->vdev = svnic_dev_alloc_discover(NULL, snic, pdev, &snic->bar0, 1);
0452     if (!snic->vdev) {
0453         SNIC_HOST_ERR(shost, "vNIC Resource Discovery Failed.\n");
0454 
0455         ret = -ENODEV;
0456         goto err_iounmap;
0457     }
0458 
0459     ret = svnic_dev_cmd_init(snic->vdev, 0);
0460     if (ret) {
0461         SNIC_HOST_INFO(shost, "Devcmd2 Init Failed. err = %d\n", ret);
0462 
0463         goto err_vnic_unreg;
0464     }
0465 
0466     ret = snic_dev_wait(snic->vdev, svnic_dev_open, snic_vdev_open_done, 0);
0467     if (ret) {
0468         SNIC_HOST_ERR(shost,
0469                   "vNIC dev open failed, aborting. %d\n",
0470                   ret);
0471 
0472         goto err_vnic_unreg;
0473     }
0474 
0475     ret = svnic_dev_init(snic->vdev, 0);
0476     if (ret) {
0477         SNIC_HOST_ERR(shost,
0478                   "vNIC dev init failed. aborting. %d\n",
0479                   ret);
0480 
0481         goto err_dev_close;
0482     }
0483 
0484     /* Get vNIC information */
0485     ret = snic_get_vnic_config(snic);
0486     if (ret) {
0487         SNIC_HOST_ERR(shost,
0488                   "Get vNIC configuration failed, aborting. %d\n",
0489                   ret);
0490 
0491         goto err_dev_close;
0492     }
0493 
0494     /* Configure Maximum Outstanding IO reqs */
0495     max_ios = snic->config.io_throttle_count;
0496     if (max_ios != SNIC_UCSM_DFLT_THROTTLE_CNT_BLD)
0497         shost->can_queue = min_t(u32, SNIC_MAX_IO_REQ,
0498                      max_t(u32, SNIC_MIN_IO_REQ, max_ios));
0499 
0500     snic->max_tag_id = shost->can_queue;
0501 
0502     shost->max_lun = snic->config.luns_per_tgt;
0503     shost->max_id = SNIC_MAX_TARGET;
0504 
0505     shost->max_cmd_len = MAX_COMMAND_SIZE; /*defined in scsi_cmnd.h*/
0506 
0507     snic_get_res_counts(snic);
0508 
0509     /*
0510      * Assumption: Only MSIx is supported
0511      */
0512     ret = snic_set_intr_mode(snic);
0513     if (ret) {
0514         SNIC_HOST_ERR(shost,
0515                   "Failed to set intr mode aborting. %d\n",
0516                   ret);
0517 
0518         goto err_dev_close;
0519     }
0520 
0521     ret = snic_alloc_vnic_res(snic);
0522     if (ret) {
0523         SNIC_HOST_ERR(shost,
0524                   "Failed to alloc vNIC resources aborting. %d\n",
0525                   ret);
0526 
0527         goto err_clear_intr;
0528     }
0529 
0530     /* Initialize specific lists */
0531     INIT_LIST_HEAD(&snic->list);
0532 
0533     /*
0534      * spl_cmd_list for maintaining snic specific cmds
0535      * such as EXCH_VER_REQ, REPORT_TARGETS etc
0536      */
0537     INIT_LIST_HEAD(&snic->spl_cmd_list);
0538     spin_lock_init(&snic->spl_cmd_lock);
0539 
0540     /* initialize all snic locks */
0541     spin_lock_init(&snic->snic_lock);
0542 
0543     for (i = 0; i < SNIC_WQ_MAX; i++)
0544         spin_lock_init(&snic->wq_lock[i]);
0545 
0546     for (i = 0; i < SNIC_IO_LOCKS; i++)
0547         spin_lock_init(&snic->io_req_lock[i]);
0548 
0549     pool = mempool_create_slab_pool(2,
0550                 snic_glob->req_cache[SNIC_REQ_CACHE_DFLT_SGL]);
0551     if (!pool) {
0552         SNIC_HOST_ERR(shost, "dflt sgl pool creation failed\n");
0553 
0554         ret = -ENOMEM;
0555         goto err_free_res;
0556     }
0557 
0558     snic->req_pool[SNIC_REQ_CACHE_DFLT_SGL] = pool;
0559 
0560     pool = mempool_create_slab_pool(2,
0561                 snic_glob->req_cache[SNIC_REQ_CACHE_MAX_SGL]);
0562     if (!pool) {
0563         SNIC_HOST_ERR(shost, "max sgl pool creation failed\n");
0564 
0565         ret = -ENOMEM;
0566         goto err_free_dflt_sgl_pool;
0567     }
0568 
0569     snic->req_pool[SNIC_REQ_CACHE_MAX_SGL] = pool;
0570 
0571     pool = mempool_create_slab_pool(2,
0572                 snic_glob->req_cache[SNIC_REQ_TM_CACHE]);
0573     if (!pool) {
0574         SNIC_HOST_ERR(shost, "snic tmreq info pool creation failed.\n");
0575 
0576         ret = -ENOMEM;
0577         goto err_free_max_sgl_pool;
0578     }
0579 
0580     snic->req_pool[SNIC_REQ_TM_CACHE] = pool;
0581 
0582     /* Initialize snic state */
0583     atomic_set(&snic->state, SNIC_INIT);
0584 
0585     atomic_set(&snic->ios_inflight, 0);
0586 
0587     /* Setup notification buffer area */
0588     ret = snic_notify_set(snic);
0589     if (ret) {
0590         SNIC_HOST_ERR(shost,
0591                   "Failed to alloc notify buffer aborting. %d\n",
0592                   ret);
0593 
0594         goto err_free_tmreq_pool;
0595     }
0596 
0597     spin_lock_irqsave(&snic_glob->snic_list_lock, flags);
0598     list_add_tail(&snic->list, &snic_glob->snic_list);
0599     spin_unlock_irqrestore(&snic_glob->snic_list_lock, flags);
0600 
0601     snic_disc_init(&snic->disc);
0602     INIT_WORK(&snic->tgt_work, snic_handle_tgt_disc);
0603     INIT_WORK(&snic->disc_work, snic_handle_disc);
0604     INIT_WORK(&snic->link_work, snic_handle_link);
0605 
0606     /* Enable all queues */
0607     for (i = 0; i < snic->wq_count; i++)
0608         svnic_wq_enable(&snic->wq[i]);
0609 
0610     ret = svnic_dev_enable_wait(snic->vdev);
0611     if (ret) {
0612         SNIC_HOST_ERR(shost,
0613                   "vNIC dev enable failed w/ error %d\n",
0614                   ret);
0615 
0616         goto err_vdev_enable;
0617     }
0618 
0619     ret = snic_request_intr(snic);
0620     if (ret) {
0621         SNIC_HOST_ERR(shost, "Unable to request irq. %d\n", ret);
0622 
0623         goto err_req_intr;
0624     }
0625 
0626     for (i = 0; i < snic->intr_count; i++)
0627         svnic_intr_unmask(&snic->intr[i]);
0628 
0629     /* Get snic params */
0630     ret = snic_get_conf(snic);
0631     if (ret) {
0632         SNIC_HOST_ERR(shost,
0633                   "Failed to get snic io config from FW w err %d\n",
0634                   ret);
0635 
0636         goto err_get_conf;
0637     }
0638 
0639     /*
0640      * Initialization done with PCI system, hardware, firmware.
0641      * Add shost to SCSI
0642      */
0643     ret = snic_add_host(shost, pdev);
0644     if (ret) {
0645         SNIC_HOST_ERR(shost,
0646                   "Adding scsi host Failed ... exiting. %d\n",
0647                   ret);
0648 
0649         goto err_get_conf;
0650     }
0651 
0652     snic_set_state(snic, SNIC_ONLINE);
0653 
0654     ret = snic_disc_start(snic);
0655     if (ret) {
0656         SNIC_HOST_ERR(shost, "snic_probe:Discovery Failed w err = %d\n",
0657                   ret);
0658 
0659         goto err_get_conf;
0660     }
0661 
0662     SNIC_HOST_INFO(shost, "SNIC Device Probe Successful.\n");
0663 
0664     return 0;
0665 
0666 err_get_conf:
0667     snic_free_all_untagged_reqs(snic);
0668 
0669     for (i = 0; i < snic->intr_count; i++)
0670         svnic_intr_mask(&snic->intr[i]);
0671 
0672     snic_free_intr(snic);
0673 
0674 err_req_intr:
0675     svnic_dev_disable(snic->vdev);
0676 
0677 err_vdev_enable:
0678     svnic_dev_notify_unset(snic->vdev);
0679 
0680     for (i = 0; i < snic->wq_count; i++) {
0681         int rc = 0;
0682 
0683         rc = svnic_wq_disable(&snic->wq[i]);
0684         if (rc) {
0685             SNIC_HOST_ERR(shost,
0686                       "WQ Disable Failed w/ err = %d\n", rc);
0687 
0688              break;
0689         }
0690     }
0691     snic_del_host(snic->shost);
0692 
0693 err_free_tmreq_pool:
0694     mempool_destroy(snic->req_pool[SNIC_REQ_TM_CACHE]);
0695 
0696 err_free_max_sgl_pool:
0697     mempool_destroy(snic->req_pool[SNIC_REQ_CACHE_MAX_SGL]);
0698 
0699 err_free_dflt_sgl_pool:
0700     mempool_destroy(snic->req_pool[SNIC_REQ_CACHE_DFLT_SGL]);
0701 
0702 err_free_res:
0703     snic_free_vnic_res(snic);
0704 
0705 err_clear_intr:
0706     snic_clear_intr_mode(snic);
0707 
0708 err_dev_close:
0709     svnic_dev_close(snic->vdev);
0710 
0711 err_vnic_unreg:
0712     svnic_dev_unregister(snic->vdev);
0713 
0714 err_iounmap:
0715     snic_iounmap(snic);
0716 
0717 err_rel_regions:
0718     pci_release_regions(pdev);
0719 
0720 err_pci_disable:
0721     pci_disable_device(pdev);
0722 
0723 err_free_snic:
0724 #ifdef CONFIG_SCSI_SNIC_DEBUG_FS
0725     snic_stats_debugfs_remove(snic);
0726 #endif
0727     scsi_host_put(shost);
0728     pci_set_drvdata(pdev, NULL);
0729 
0730 prob_end:
0731     SNIC_INFO("sNIC device : bus %d: slot %d: fn %d Registration Failed.\n",
0732           pdev->bus->number, PCI_SLOT(pdev->devfn),
0733           PCI_FUNC(pdev->devfn));
0734 
0735     return ret;
0736 } /* end of snic_probe */
0737 
0738 
0739 /*
0740  * snic_remove : invoked on unbinding the interface to cleanup the
0741  * resources allocated in snic_probe on initialization.
0742  */
0743 static void
0744 snic_remove(struct pci_dev *pdev)
0745 {
0746     struct snic *snic = pci_get_drvdata(pdev);
0747     unsigned long flags;
0748 
0749     if (!snic) {
0750         SNIC_INFO("sNIC dev: bus %d slot %d fn %d snic inst is null.\n",
0751               pdev->bus->number, PCI_SLOT(pdev->devfn),
0752               PCI_FUNC(pdev->devfn));
0753 
0754         return;
0755     }
0756 
0757     /*
0758      * Mark state so that the workqueue thread stops forwarding
0759      * received frames and link events. ISR and other threads
0760      * that can queue work items will also stop creating work
0761      * items on the snic workqueue
0762      */
0763     snic_set_state(snic, SNIC_OFFLINE);
0764     spin_lock_irqsave(&snic->snic_lock, flags);
0765     snic->stop_link_events = 1;
0766     spin_unlock_irqrestore(&snic->snic_lock, flags);
0767 
0768     flush_workqueue(snic_glob->event_q);
0769     snic_disc_term(snic);
0770 
0771     spin_lock_irqsave(&snic->snic_lock, flags);
0772     snic->in_remove = 1;
0773     spin_unlock_irqrestore(&snic->snic_lock, flags);
0774 
0775     /*
0776      * This stops the snic device, masks all interrupts, Completed
0777      * CQ entries are drained. Posted WQ/RQ/Copy-WQ entries are
0778      * cleanup
0779      */
0780     snic_cleanup(snic);
0781 
0782     spin_lock_irqsave(&snic_glob->snic_list_lock, flags);
0783     list_del(&snic->list);
0784     spin_unlock_irqrestore(&snic_glob->snic_list_lock, flags);
0785 
0786     snic_tgt_del_all(snic);
0787 #ifdef CONFIG_SCSI_SNIC_DEBUG_FS
0788     snic_stats_debugfs_remove(snic);
0789 #endif
0790     snic_del_host(snic->shost);
0791 
0792     svnic_dev_notify_unset(snic->vdev);
0793     snic_free_intr(snic);
0794     snic_free_vnic_res(snic);
0795     snic_clear_intr_mode(snic);
0796     svnic_dev_close(snic->vdev);
0797     svnic_dev_unregister(snic->vdev);
0798     snic_iounmap(snic);
0799     pci_release_regions(pdev);
0800     pci_disable_device(pdev);
0801     pci_set_drvdata(pdev, NULL);
0802 
0803     /* this frees Scsi_Host and snic memory (continuous chunk) */
0804     scsi_host_put(snic->shost);
0805 } /* end of snic_remove */
0806 
0807 
0808 struct snic_global *snic_glob;
0809 
0810 /*
0811  * snic_global_data_init: Initialize SNIC Global Data
0812  * Notes: All the global lists, variables should be part of global data
0813  * this helps in debugging.
0814  */
0815 static int
0816 snic_global_data_init(void)
0817 {
0818     int ret = 0;
0819     struct kmem_cache *cachep;
0820     ssize_t len = 0;
0821 
0822     snic_glob = kzalloc(sizeof(*snic_glob), GFP_KERNEL);
0823 
0824     if (!snic_glob) {
0825         SNIC_ERR("Failed to allocate Global Context.\n");
0826 
0827         ret = -ENOMEM;
0828         goto gdi_end;
0829     }
0830 
0831 #ifdef CONFIG_SCSI_SNIC_DEBUG_FS
0832     /* Debugfs related Initialization */
0833     /* Create debugfs entries for snic */
0834     snic_debugfs_init();
0835 
0836     /* Trace related Initialization */
0837     /* Allocate memory for trace buffer */
0838     ret = snic_trc_init();
0839     if (ret < 0) {
0840         SNIC_ERR("Trace buffer init failed, SNIC tracing disabled\n");
0841         snic_trc_free();
0842         /* continue even if it fails */
0843     }
0844 
0845 #endif
0846     INIT_LIST_HEAD(&snic_glob->snic_list);
0847     spin_lock_init(&snic_glob->snic_list_lock);
0848 
0849     /* Create a cache for allocation of snic_host_req+default size ESGLs */
0850     len = sizeof(struct snic_req_info);
0851     len += sizeof(struct snic_host_req) + sizeof(struct snic_dflt_sgl);
0852     cachep = kmem_cache_create("snic_req_dfltsgl", len, SNIC_SG_DESC_ALIGN,
0853                    SLAB_HWCACHE_ALIGN, NULL);
0854     if (!cachep) {
0855         SNIC_ERR("Failed to create snic default sgl slab\n");
0856         ret = -ENOMEM;
0857 
0858         goto err_dflt_req_slab;
0859     }
0860     snic_glob->req_cache[SNIC_REQ_CACHE_DFLT_SGL] = cachep;
0861 
0862     /* Create a cache for allocation of max size Extended SGLs */
0863     len = sizeof(struct snic_req_info);
0864     len += sizeof(struct snic_host_req) + sizeof(struct snic_max_sgl);
0865     cachep = kmem_cache_create("snic_req_maxsgl", len, SNIC_SG_DESC_ALIGN,
0866                    SLAB_HWCACHE_ALIGN, NULL);
0867     if (!cachep) {
0868         SNIC_ERR("Failed to create snic max sgl slab\n");
0869         ret = -ENOMEM;
0870 
0871         goto err_max_req_slab;
0872     }
0873     snic_glob->req_cache[SNIC_REQ_CACHE_MAX_SGL] = cachep;
0874 
0875     len = sizeof(struct snic_host_req);
0876     cachep = kmem_cache_create("snic_req_maxsgl", len, SNIC_SG_DESC_ALIGN,
0877                    SLAB_HWCACHE_ALIGN, NULL);
0878     if (!cachep) {
0879         SNIC_ERR("Failed to create snic tm req slab\n");
0880         ret = -ENOMEM;
0881 
0882         goto err_tmreq_slab;
0883     }
0884     snic_glob->req_cache[SNIC_REQ_TM_CACHE] = cachep;
0885 
0886     /* snic_event queue */
0887     snic_glob->event_q = create_singlethread_workqueue("snic_event_wq");
0888     if (!snic_glob->event_q) {
0889         SNIC_ERR("snic event queue create failed\n");
0890         ret = -ENOMEM;
0891 
0892         goto err_eventq;
0893     }
0894 
0895     return ret;
0896 
0897 err_eventq:
0898     kmem_cache_destroy(snic_glob->req_cache[SNIC_REQ_TM_CACHE]);
0899 
0900 err_tmreq_slab:
0901     kmem_cache_destroy(snic_glob->req_cache[SNIC_REQ_CACHE_MAX_SGL]);
0902 
0903 err_max_req_slab:
0904     kmem_cache_destroy(snic_glob->req_cache[SNIC_REQ_CACHE_DFLT_SGL]);
0905 
0906 err_dflt_req_slab:
0907 #ifdef CONFIG_SCSI_SNIC_DEBUG_FS
0908     snic_trc_free();
0909     snic_debugfs_term();
0910 #endif
0911     kfree(snic_glob);
0912     snic_glob = NULL;
0913 
0914 gdi_end:
0915     return ret;
0916 } /* end of snic_glob_init */
0917 
0918 /*
0919  * snic_global_data_cleanup : Frees SNIC Global Data
0920  */
0921 static void
0922 snic_global_data_cleanup(void)
0923 {
0924     SNIC_BUG_ON(snic_glob == NULL);
0925 
0926     destroy_workqueue(snic_glob->event_q);
0927     kmem_cache_destroy(snic_glob->req_cache[SNIC_REQ_TM_CACHE]);
0928     kmem_cache_destroy(snic_glob->req_cache[SNIC_REQ_CACHE_MAX_SGL]);
0929     kmem_cache_destroy(snic_glob->req_cache[SNIC_REQ_CACHE_DFLT_SGL]);
0930 
0931 #ifdef CONFIG_SCSI_SNIC_DEBUG_FS
0932     /* Freeing Trace Resources */
0933     snic_trc_free();
0934 
0935     /* Freeing Debugfs Resources */
0936     snic_debugfs_term();
0937 #endif
0938     kfree(snic_glob);
0939     snic_glob = NULL;
0940 } /* end of snic_glob_cleanup */
0941 
0942 static struct pci_driver snic_driver = {
0943     .name = SNIC_DRV_NAME,
0944     .id_table = snic_id_table,
0945     .probe = snic_probe,
0946     .remove = snic_remove,
0947 };
0948 
0949 static int __init
0950 snic_init_module(void)
0951 {
0952     int ret = 0;
0953 
0954 #ifndef __x86_64__
0955     SNIC_INFO("SNIC Driver is supported only for x86_64 platforms!\n");
0956     add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
0957 #endif
0958 
0959     SNIC_INFO("%s, ver %s\n", SNIC_DRV_DESCRIPTION, SNIC_DRV_VERSION);
0960 
0961     ret = snic_global_data_init();
0962     if (ret) {
0963         SNIC_ERR("Failed to Initialize Global Data.\n");
0964 
0965         return ret;
0966     }
0967 
0968     ret = pci_register_driver(&snic_driver);
0969     if (ret < 0) {
0970         SNIC_ERR("PCI driver register error\n");
0971 
0972         goto err_pci_reg;
0973     }
0974 
0975     return ret;
0976 
0977 err_pci_reg:
0978     snic_global_data_cleanup();
0979 
0980     return ret;
0981 }
0982 
0983 static void __exit
0984 snic_cleanup_module(void)
0985 {
0986     pci_unregister_driver(&snic_driver);
0987     snic_global_data_cleanup();
0988 }
0989 
0990 module_init(snic_init_module);
0991 module_exit(snic_cleanup_module);
0992 
0993 MODULE_LICENSE("GPL v2");
0994 MODULE_DESCRIPTION(SNIC_DRV_DESCRIPTION);
0995 MODULE_VERSION(SNIC_DRV_VERSION);
0996 MODULE_DEVICE_TABLE(pci, snic_id_table);
0997 MODULE_AUTHOR("Narsimhulu Musini <nmusini@cisco.com>, "
0998           "Sesidhar Baddela <sebaddel@cisco.com>");