999 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2// Copyright 2014 Cisco Systems, Inc. All rights reserved.3 4#include <linux/module.h>5#include <linux/mempool.h>6#include <linux/string.h>7#include <linux/slab.h>8#include <linux/errno.h>9#include <linux/init.h>10#include <linux/pci.h>11#include <linux/skbuff.h>12#include <linux/interrupt.h>13#include <linux/spinlock.h>14#include <linux/workqueue.h>15#include <scsi/scsi_host.h>16#include <scsi/scsi_tcq.h>17 18#include "snic.h"19#include "snic_fwint.h"20 21#define PCI_DEVICE_ID_CISCO_SNIC 0x004622 23/* Supported devices by snic module */24static struct pci_device_id snic_id_table[] = {25 {PCI_DEVICE(0x1137, PCI_DEVICE_ID_CISCO_SNIC) },26 { 0, } /* end of table */27};28 29unsigned int snic_log_level = 0x0;30module_param(snic_log_level, int, S_IRUGO|S_IWUSR);31MODULE_PARM_DESC(snic_log_level, "bitmask for snic logging levels");32 33#ifdef CONFIG_SCSI_SNIC_DEBUG_FS34unsigned int snic_trace_max_pages = 16;35module_param(snic_trace_max_pages, uint, S_IRUGO|S_IWUSR);36MODULE_PARM_DESC(snic_trace_max_pages,37 "Total allocated memory pages for snic trace buffer");38 39#endif40unsigned int snic_max_qdepth = SNIC_DFLT_QUEUE_DEPTH;41module_param(snic_max_qdepth, uint, S_IRUGO | S_IWUSR);42MODULE_PARM_DESC(snic_max_qdepth, "Queue depth to report for each LUN");43 44/*45 * snic_slave_alloc : callback function to SCSI Mid Layer, called on46 * scsi device initialization.47 */48static int49snic_slave_alloc(struct scsi_device *sdev)50{51 struct snic_tgt *tgt = starget_to_tgt(scsi_target(sdev));52 53 if (!tgt || snic_tgt_chkready(tgt))54 return -ENXIO;55 56 return 0;57}58 59/*60 * snic_slave_configure : callback function to SCSI Mid Layer, called on61 * scsi device initialization.62 */63static int64snic_slave_configure(struct scsi_device *sdev)65{66 struct snic *snic = shost_priv(sdev->host);67 u32 qdepth = 0, max_ios = 0;68 int tmo = SNIC_DFLT_CMD_TIMEOUT * HZ;69 70 /* Set Queue Depth */71 max_ios = snic_max_qdepth;72 qdepth = min_t(u32, max_ios, SNIC_MAX_QUEUE_DEPTH);73 scsi_change_queue_depth(sdev, qdepth);74 75 if (snic->fwinfo.io_tmo > 1)76 tmo = snic->fwinfo.io_tmo * HZ;77 78 /* FW requires extended timeouts */79 blk_queue_rq_timeout(sdev->request_queue, tmo);80 81 return 0;82}83 84static int85snic_change_queue_depth(struct scsi_device *sdev, int qdepth)86{87 struct snic *snic = shost_priv(sdev->host);88 int qsz = 0;89 90 qsz = min_t(u32, qdepth, SNIC_MAX_QUEUE_DEPTH);91 if (qsz < sdev->queue_depth)92 atomic64_inc(&snic->s_stats.misc.qsz_rampdown);93 else if (qsz > sdev->queue_depth)94 atomic64_inc(&snic->s_stats.misc.qsz_rampup);95 96 atomic64_set(&snic->s_stats.misc.last_qsz, sdev->queue_depth);97 98 scsi_change_queue_depth(sdev, qsz);99 100 return sdev->queue_depth;101}102 103static const struct scsi_host_template snic_host_template = {104 .module = THIS_MODULE,105 .name = SNIC_DRV_NAME,106 .queuecommand = snic_queuecommand,107 .eh_abort_handler = snic_abort_cmd,108 .eh_device_reset_handler = snic_device_reset,109 .eh_host_reset_handler = snic_host_reset,110 .slave_alloc = snic_slave_alloc,111 .slave_configure = snic_slave_configure,112 .change_queue_depth = snic_change_queue_depth,113 .this_id = -1,114 .cmd_per_lun = SNIC_DFLT_QUEUE_DEPTH,115 .can_queue = SNIC_MAX_IO_REQ,116 .sg_tablesize = SNIC_MAX_SG_DESC_CNT,117 .max_sectors = 0x800,118 .shost_groups = snic_host_groups,119 .track_queue_depth = 1,120 .cmd_size = sizeof(struct snic_internal_io_state),121 .proc_name = "snic_scsi",122};123 124/*125 * snic_handle_link_event : Handles link events such as link up/down/error126 */127void128snic_handle_link_event(struct snic *snic)129{130 unsigned long flags;131 132 spin_lock_irqsave(&snic->snic_lock, flags);133 if (snic->stop_link_events) {134 spin_unlock_irqrestore(&snic->snic_lock, flags);135 136 return;137 }138 spin_unlock_irqrestore(&snic->snic_lock, flags);139 140 queue_work(snic_glob->event_q, &snic->link_work);141} /* end of snic_handle_link_event */142 143/*144 * snic_notify_set : sets notification area145 * This notification area is to receive events from fw146 * Note: snic supports only MSIX interrupts, in which we can just call147 * svnic_dev_notify_set directly148 */149static int150snic_notify_set(struct snic *snic)151{152 int ret = 0;153 enum vnic_dev_intr_mode intr_mode;154 155 intr_mode = svnic_dev_get_intr_mode(snic->vdev);156 157 if (intr_mode == VNIC_DEV_INTR_MODE_MSIX) {158 ret = svnic_dev_notify_set(snic->vdev, SNIC_MSIX_ERR_NOTIFY);159 } else {160 SNIC_HOST_ERR(snic->shost,161 "Interrupt mode should be setup before devcmd notify set %d\n",162 intr_mode);163 ret = -1;164 }165 166 return ret;167} /* end of snic_notify_set */168 169/*170 * snic_dev_wait : polls vnic open status.171 */172static int173snic_dev_wait(struct vnic_dev *vdev,174 int (*start)(struct vnic_dev *, int),175 int (*finished)(struct vnic_dev *, int *),176 int arg)177{178 unsigned long time;179 int ret, done;180 int retry_cnt = 0;181 182 ret = start(vdev, arg);183 if (ret)184 return ret;185 186 /*187 * Wait for func to complete...2 seconds max.188 *189 * Sometimes schedule_timeout_uninterruptible take long time190 * to wakeup, which results skipping retry. The retry counter191 * ensures to retry at least two times.192 */193 time = jiffies + (HZ * 2);194 do {195 ret = finished(vdev, &done);196 if (ret)197 return ret;198 199 if (done)200 return 0;201 schedule_timeout_uninterruptible(HZ/10);202 ++retry_cnt;203 } while (time_after(time, jiffies) || (retry_cnt < 3));204 205 return -ETIMEDOUT;206} /* end of snic_dev_wait */207 208/*209 * snic_cleanup: called by snic_remove210 * Stops the snic device, masks all interrupts, Completed CQ entries are211 * drained. Posted WQ/RQ/Copy-WQ entries are cleanup212 */213static int214snic_cleanup(struct snic *snic)215{216 unsigned int i;217 int ret;218 219 svnic_dev_disable(snic->vdev);220 for (i = 0; i < snic->intr_count; i++)221 svnic_intr_mask(&snic->intr[i]);222 223 for (i = 0; i < snic->wq_count; i++) {224 ret = svnic_wq_disable(&snic->wq[i]);225 if (ret)226 return ret;227 }228 229 /* Clean up completed IOs */230 snic_fwcq_cmpl_handler(snic, -1);231 232 snic_wq_cmpl_handler(snic, -1);233 234 /* Clean up the IOs that have not completed */235 for (i = 0; i < snic->wq_count; i++)236 svnic_wq_clean(&snic->wq[i], snic_free_wq_buf);237 238 for (i = 0; i < snic->cq_count; i++)239 svnic_cq_clean(&snic->cq[i]);240 241 for (i = 0; i < snic->intr_count; i++)242 svnic_intr_clean(&snic->intr[i]);243 244 /* Cleanup snic specific requests */245 snic_free_all_untagged_reqs(snic);246 247 /* Cleanup Pending SCSI commands */248 snic_shutdown_scsi_cleanup(snic);249 250 for (i = 0; i < SNIC_REQ_MAX_CACHES; i++)251 mempool_destroy(snic->req_pool[i]);252 253 return 0;254} /* end of snic_cleanup */255 256 257static void258snic_iounmap(struct snic *snic)259{260 if (snic->bar0.vaddr)261 iounmap(snic->bar0.vaddr);262}263 264/*265 * snic_vdev_open_done : polls for svnic_dev_open cmd completion.266 */267static int268snic_vdev_open_done(struct vnic_dev *vdev, int *done)269{270 struct snic *snic = svnic_dev_priv(vdev);271 int ret;272 int nretries = 5;273 274 do {275 ret = svnic_dev_open_done(vdev, done);276 if (ret == 0)277 break;278 279 SNIC_HOST_INFO(snic->shost, "VNIC_DEV_OPEN Timedout.\n");280 } while (nretries--);281 282 return ret;283} /* end of snic_vdev_open_done */284 285/*286 * snic_add_host : registers scsi host with ML287 */288static int289snic_add_host(struct Scsi_Host *shost, struct pci_dev *pdev)290{291 int ret = 0;292 293 ret = scsi_add_host(shost, &pdev->dev);294 if (ret) {295 SNIC_HOST_ERR(shost,296 "snic: scsi_add_host failed. %d\n",297 ret);298 299 return ret;300 }301 302 SNIC_BUG_ON(shost->work_q != NULL);303 shost->work_q = alloc_ordered_workqueue("scsi_wq_%d", WQ_MEM_RECLAIM,304 shost->host_no);305 if (!shost->work_q) {306 SNIC_HOST_ERR(shost, "Failed to Create ScsiHost wq.\n");307 308 ret = -ENOMEM;309 }310 311 return ret;312} /* end of snic_add_host */313 314static void315snic_del_host(struct Scsi_Host *shost)316{317 if (!shost->work_q)318 return;319 320 destroy_workqueue(shost->work_q);321 shost->work_q = NULL;322 scsi_remove_host(shost);323}324 325int326snic_get_state(struct snic *snic)327{328 return atomic_read(&snic->state);329}330 331void332snic_set_state(struct snic *snic, enum snic_state state)333{334 SNIC_HOST_INFO(snic->shost, "snic state change from %s to %s\n",335 snic_state_to_str(snic_get_state(snic)),336 snic_state_to_str(state));337 338 atomic_set(&snic->state, state);339}340 341/*342 * snic_probe : Initialize the snic interface.343 */344static int345snic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)346{347 struct Scsi_Host *shost;348 struct snic *snic;349 mempool_t *pool;350 unsigned long flags;351 u32 max_ios = 0;352 int ret, i;353 354 /* Device Information */355 SNIC_INFO("snic device %4x:%4x:%4x:%4x: ",356 pdev->vendor, pdev->device, pdev->subsystem_vendor,357 pdev->subsystem_device);358 359 SNIC_INFO("snic device bus %x: slot %x: fn %x\n",360 pdev->bus->number, PCI_SLOT(pdev->devfn),361 PCI_FUNC(pdev->devfn));362 363 /*364 * Allocate SCSI Host and setup association between host, and snic365 */366 shost = scsi_host_alloc(&snic_host_template, sizeof(struct snic));367 if (!shost) {368 SNIC_ERR("Unable to alloc scsi_host\n");369 ret = -ENOMEM;370 371 goto prob_end;372 }373 snic = shost_priv(shost);374 snic->shost = shost;375 376 snprintf(snic->name, sizeof(snic->name) - 1, "%s%d", SNIC_DRV_NAME,377 shost->host_no);378 379 SNIC_HOST_INFO(shost,380 "snic%d = %p shost = %p device bus %x: slot %x: fn %x\n",381 shost->host_no, snic, shost, pdev->bus->number,382 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));383#ifdef CONFIG_SCSI_SNIC_DEBUG_FS384 /* Per snic debugfs init */385 snic_stats_debugfs_init(snic);386#endif387 388 /* Setup PCI Resources */389 pci_set_drvdata(pdev, snic);390 snic->pdev = pdev;391 392 ret = pci_enable_device(pdev);393 if (ret) {394 SNIC_HOST_ERR(shost,395 "Cannot enable PCI Resources, aborting : %d\n",396 ret);397 398 goto err_free_snic;399 }400 401 ret = pci_request_regions(pdev, SNIC_DRV_NAME);402 if (ret) {403 SNIC_HOST_ERR(shost,404 "Cannot obtain PCI Resources, aborting : %d\n",405 ret);406 407 goto err_pci_disable;408 }409 410 pci_set_master(pdev);411 412 /*413 * Query PCI Controller on system for DMA addressing414 * limitation for the device. Try 43-bit first, and415 * fail to 32-bit.416 */417 ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(43));418 if (ret) {419 ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));420 if (ret) {421 SNIC_HOST_ERR(shost,422 "No Usable DMA Configuration, aborting %d\n",423 ret);424 goto err_rel_regions;425 }426 }427 428 /* Map vNIC resources from BAR0 */429 if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {430 SNIC_HOST_ERR(shost, "BAR0 not memory mappable aborting.\n");431 432 ret = -ENODEV;433 goto err_rel_regions;434 }435 436 snic->bar0.vaddr = pci_iomap(pdev, 0, 0);437 if (!snic->bar0.vaddr) {438 SNIC_HOST_ERR(shost,439 "Cannot memory map BAR0 res hdr aborting.\n");440 441 ret = -ENODEV;442 goto err_rel_regions;443 }444 445 snic->bar0.bus_addr = pci_resource_start(pdev, 0);446 snic->bar0.len = pci_resource_len(pdev, 0);447 SNIC_BUG_ON(snic->bar0.bus_addr == 0);448 449 /* Devcmd2 Resource Allocation and Initialization */450 snic->vdev = svnic_dev_alloc_discover(NULL, snic, pdev, &snic->bar0, 1);451 if (!snic->vdev) {452 SNIC_HOST_ERR(shost, "vNIC Resource Discovery Failed.\n");453 454 ret = -ENODEV;455 goto err_iounmap;456 }457 458 ret = svnic_dev_cmd_init(snic->vdev, 0);459 if (ret) {460 SNIC_HOST_INFO(shost, "Devcmd2 Init Failed. err = %d\n", ret);461 462 goto err_vnic_unreg;463 }464 465 ret = snic_dev_wait(snic->vdev, svnic_dev_open, snic_vdev_open_done, 0);466 if (ret) {467 SNIC_HOST_ERR(shost,468 "vNIC dev open failed, aborting. %d\n",469 ret);470 471 goto err_vnic_unreg;472 }473 474 ret = svnic_dev_init(snic->vdev, 0);475 if (ret) {476 SNIC_HOST_ERR(shost,477 "vNIC dev init failed. aborting. %d\n",478 ret);479 480 goto err_dev_close;481 }482 483 /* Get vNIC information */484 ret = snic_get_vnic_config(snic);485 if (ret) {486 SNIC_HOST_ERR(shost,487 "Get vNIC configuration failed, aborting. %d\n",488 ret);489 490 goto err_dev_close;491 }492 493 /* Configure Maximum Outstanding IO reqs */494 max_ios = snic->config.io_throttle_count;495 if (max_ios != SNIC_UCSM_DFLT_THROTTLE_CNT_BLD)496 shost->can_queue = min_t(u32, SNIC_MAX_IO_REQ,497 max_t(u32, SNIC_MIN_IO_REQ, max_ios));498 499 snic->max_tag_id = shost->can_queue;500 501 shost->max_lun = snic->config.luns_per_tgt;502 shost->max_id = SNIC_MAX_TARGET;503 504 shost->max_cmd_len = MAX_COMMAND_SIZE; /*defined in scsi_cmnd.h*/505 506 snic_get_res_counts(snic);507 508 /*509 * Assumption: Only MSIx is supported510 */511 ret = snic_set_intr_mode(snic);512 if (ret) {513 SNIC_HOST_ERR(shost,514 "Failed to set intr mode aborting. %d\n",515 ret);516 517 goto err_dev_close;518 }519 520 ret = snic_alloc_vnic_res(snic);521 if (ret) {522 SNIC_HOST_ERR(shost,523 "Failed to alloc vNIC resources aborting. %d\n",524 ret);525 526 goto err_clear_intr;527 }528 529 /* Initialize specific lists */530 INIT_LIST_HEAD(&snic->list);531 532 /*533 * spl_cmd_list for maintaining snic specific cmds534 * such as EXCH_VER_REQ, REPORT_TARGETS etc535 */536 INIT_LIST_HEAD(&snic->spl_cmd_list);537 spin_lock_init(&snic->spl_cmd_lock);538 539 /* initialize all snic locks */540 spin_lock_init(&snic->snic_lock);541 542 for (i = 0; i < SNIC_WQ_MAX; i++)543 spin_lock_init(&snic->wq_lock[i]);544 545 for (i = 0; i < SNIC_IO_LOCKS; i++)546 spin_lock_init(&snic->io_req_lock[i]);547 548 pool = mempool_create_slab_pool(2,549 snic_glob->req_cache[SNIC_REQ_CACHE_DFLT_SGL]);550 if (!pool) {551 SNIC_HOST_ERR(shost, "dflt sgl pool creation failed\n");552 553 ret = -ENOMEM;554 goto err_free_res;555 }556 557 snic->req_pool[SNIC_REQ_CACHE_DFLT_SGL] = pool;558 559 pool = mempool_create_slab_pool(2,560 snic_glob->req_cache[SNIC_REQ_CACHE_MAX_SGL]);561 if (!pool) {562 SNIC_HOST_ERR(shost, "max sgl pool creation failed\n");563 564 ret = -ENOMEM;565 goto err_free_dflt_sgl_pool;566 }567 568 snic->req_pool[SNIC_REQ_CACHE_MAX_SGL] = pool;569 570 pool = mempool_create_slab_pool(2,571 snic_glob->req_cache[SNIC_REQ_TM_CACHE]);572 if (!pool) {573 SNIC_HOST_ERR(shost, "snic tmreq info pool creation failed.\n");574 575 ret = -ENOMEM;576 goto err_free_max_sgl_pool;577 }578 579 snic->req_pool[SNIC_REQ_TM_CACHE] = pool;580 581 /* Initialize snic state */582 atomic_set(&snic->state, SNIC_INIT);583 584 atomic_set(&snic->ios_inflight, 0);585 586 /* Setup notification buffer area */587 ret = snic_notify_set(snic);588 if (ret) {589 SNIC_HOST_ERR(shost,590 "Failed to alloc notify buffer aborting. %d\n",591 ret);592 593 goto err_free_tmreq_pool;594 }595 596 spin_lock_irqsave(&snic_glob->snic_list_lock, flags);597 list_add_tail(&snic->list, &snic_glob->snic_list);598 spin_unlock_irqrestore(&snic_glob->snic_list_lock, flags);599 600 snic_disc_init(&snic->disc);601 INIT_WORK(&snic->tgt_work, snic_handle_tgt_disc);602 INIT_WORK(&snic->disc_work, snic_handle_disc);603 INIT_WORK(&snic->link_work, snic_handle_link);604 605 /* Enable all queues */606 for (i = 0; i < snic->wq_count; i++)607 svnic_wq_enable(&snic->wq[i]);608 609 ret = svnic_dev_enable_wait(snic->vdev);610 if (ret) {611 SNIC_HOST_ERR(shost,612 "vNIC dev enable failed w/ error %d\n",613 ret);614 615 goto err_vdev_enable;616 }617 618 ret = snic_request_intr(snic);619 if (ret) {620 SNIC_HOST_ERR(shost, "Unable to request irq. %d\n", ret);621 622 goto err_req_intr;623 }624 625 for (i = 0; i < snic->intr_count; i++)626 svnic_intr_unmask(&snic->intr[i]);627 628 /* Get snic params */629 ret = snic_get_conf(snic);630 if (ret) {631 SNIC_HOST_ERR(shost,632 "Failed to get snic io config from FW w err %d\n",633 ret);634 635 goto err_get_conf;636 }637 638 /*639 * Initialization done with PCI system, hardware, firmware.640 * Add shost to SCSI641 */642 ret = snic_add_host(shost, pdev);643 if (ret) {644 SNIC_HOST_ERR(shost,645 "Adding scsi host Failed ... exiting. %d\n",646 ret);647 648 goto err_get_conf;649 }650 651 snic_set_state(snic, SNIC_ONLINE);652 653 ret = snic_disc_start(snic);654 if (ret) {655 SNIC_HOST_ERR(shost, "snic_probe:Discovery Failed w err = %d\n",656 ret);657 658 goto err_get_conf;659 }660 661 SNIC_HOST_INFO(shost, "SNIC Device Probe Successful.\n");662 663 return 0;664 665err_get_conf:666 snic_free_all_untagged_reqs(snic);667 668 for (i = 0; i < snic->intr_count; i++)669 svnic_intr_mask(&snic->intr[i]);670 671 snic_free_intr(snic);672 673err_req_intr:674 svnic_dev_disable(snic->vdev);675 676err_vdev_enable:677 svnic_dev_notify_unset(snic->vdev);678 679 for (i = 0; i < snic->wq_count; i++) {680 int rc = 0;681 682 rc = svnic_wq_disable(&snic->wq[i]);683 if (rc) {684 SNIC_HOST_ERR(shost,685 "WQ Disable Failed w/ err = %d\n", rc);686 687 break;688 }689 }690 snic_del_host(snic->shost);691 692err_free_tmreq_pool:693 mempool_destroy(snic->req_pool[SNIC_REQ_TM_CACHE]);694 695err_free_max_sgl_pool:696 mempool_destroy(snic->req_pool[SNIC_REQ_CACHE_MAX_SGL]);697 698err_free_dflt_sgl_pool:699 mempool_destroy(snic->req_pool[SNIC_REQ_CACHE_DFLT_SGL]);700 701err_free_res:702 snic_free_vnic_res(snic);703 704err_clear_intr:705 snic_clear_intr_mode(snic);706 707err_dev_close:708 svnic_dev_close(snic->vdev);709 710err_vnic_unreg:711 svnic_dev_unregister(snic->vdev);712 713err_iounmap:714 snic_iounmap(snic);715 716err_rel_regions:717 pci_release_regions(pdev);718 719err_pci_disable:720 pci_disable_device(pdev);721 722err_free_snic:723#ifdef CONFIG_SCSI_SNIC_DEBUG_FS724 snic_stats_debugfs_remove(snic);725#endif726 scsi_host_put(shost);727 pci_set_drvdata(pdev, NULL);728 729prob_end:730 SNIC_INFO("sNIC device : bus %d: slot %d: fn %d Registration Failed.\n",731 pdev->bus->number, PCI_SLOT(pdev->devfn),732 PCI_FUNC(pdev->devfn));733 734 return ret;735} /* end of snic_probe */736 737 738/*739 * snic_remove : invoked on unbinding the interface to cleanup the740 * resources allocated in snic_probe on initialization.741 */742static void743snic_remove(struct pci_dev *pdev)744{745 struct snic *snic = pci_get_drvdata(pdev);746 unsigned long flags;747 748 if (!snic) {749 SNIC_INFO("sNIC dev: bus %d slot %d fn %d snic inst is null.\n",750 pdev->bus->number, PCI_SLOT(pdev->devfn),751 PCI_FUNC(pdev->devfn));752 753 return;754 }755 756 /*757 * Mark state so that the workqueue thread stops forwarding758 * received frames and link events. ISR and other threads759 * that can queue work items will also stop creating work760 * items on the snic workqueue761 */762 snic_set_state(snic, SNIC_OFFLINE);763 spin_lock_irqsave(&snic->snic_lock, flags);764 snic->stop_link_events = 1;765 spin_unlock_irqrestore(&snic->snic_lock, flags);766 767 flush_workqueue(snic_glob->event_q);768 snic_disc_term(snic);769 770 spin_lock_irqsave(&snic->snic_lock, flags);771 snic->in_remove = 1;772 spin_unlock_irqrestore(&snic->snic_lock, flags);773 774 /*775 * This stops the snic device, masks all interrupts, Completed776 * CQ entries are drained. Posted WQ/RQ/Copy-WQ entries are777 * cleanup778 */779 snic_cleanup(snic);780 781 spin_lock_irqsave(&snic_glob->snic_list_lock, flags);782 list_del(&snic->list);783 spin_unlock_irqrestore(&snic_glob->snic_list_lock, flags);784 785 snic_tgt_del_all(snic);786#ifdef CONFIG_SCSI_SNIC_DEBUG_FS787 snic_stats_debugfs_remove(snic);788#endif789 snic_del_host(snic->shost);790 791 svnic_dev_notify_unset(snic->vdev);792 snic_free_intr(snic);793 snic_free_vnic_res(snic);794 snic_clear_intr_mode(snic);795 svnic_dev_close(snic->vdev);796 svnic_dev_unregister(snic->vdev);797 snic_iounmap(snic);798 pci_release_regions(pdev);799 pci_disable_device(pdev);800 pci_set_drvdata(pdev, NULL);801 802 /* this frees Scsi_Host and snic memory (continuous chunk) */803 scsi_host_put(snic->shost);804} /* end of snic_remove */805 806 807struct snic_global *snic_glob;808 809/*810 * snic_global_data_init: Initialize SNIC Global Data811 * Notes: All the global lists, variables should be part of global data812 * this helps in debugging.813 */814static int815snic_global_data_init(void)816{817 int ret = 0;818 struct kmem_cache *cachep;819 ssize_t len = 0;820 821 snic_glob = kzalloc(sizeof(*snic_glob), GFP_KERNEL);822 823 if (!snic_glob) {824 SNIC_ERR("Failed to allocate Global Context.\n");825 826 ret = -ENOMEM;827 goto gdi_end;828 }829 830#ifdef CONFIG_SCSI_SNIC_DEBUG_FS831 /* Debugfs related Initialization */832 /* Create debugfs entries for snic */833 snic_debugfs_init();834 835 /* Trace related Initialization */836 /* Allocate memory for trace buffer */837 ret = snic_trc_init();838 if (ret < 0) {839 SNIC_ERR("Trace buffer init failed, SNIC tracing disabled\n");840 snic_trc_free();841 /* continue even if it fails */842 }843 844#endif845 INIT_LIST_HEAD(&snic_glob->snic_list);846 spin_lock_init(&snic_glob->snic_list_lock);847 848 /* Create a cache for allocation of snic_host_req+default size ESGLs */849 len = sizeof(struct snic_req_info);850 len += sizeof(struct snic_host_req) + sizeof(struct snic_dflt_sgl);851 cachep = kmem_cache_create("snic_req_dfltsgl", len, SNIC_SG_DESC_ALIGN,852 SLAB_HWCACHE_ALIGN, NULL);853 if (!cachep) {854 SNIC_ERR("Failed to create snic default sgl slab\n");855 ret = -ENOMEM;856 857 goto err_dflt_req_slab;858 }859 snic_glob->req_cache[SNIC_REQ_CACHE_DFLT_SGL] = cachep;860 861 /* Create a cache for allocation of max size Extended SGLs */862 len = sizeof(struct snic_req_info);863 len += sizeof(struct snic_host_req) + sizeof(struct snic_max_sgl);864 cachep = kmem_cache_create("snic_req_maxsgl", len, SNIC_SG_DESC_ALIGN,865 SLAB_HWCACHE_ALIGN, NULL);866 if (!cachep) {867 SNIC_ERR("Failed to create snic max sgl slab\n");868 ret = -ENOMEM;869 870 goto err_max_req_slab;871 }872 snic_glob->req_cache[SNIC_REQ_CACHE_MAX_SGL] = cachep;873 874 len = sizeof(struct snic_host_req);875 cachep = kmem_cache_create("snic_req_tm", len, SNIC_SG_DESC_ALIGN,876 SLAB_HWCACHE_ALIGN, NULL);877 if (!cachep) {878 SNIC_ERR("Failed to create snic tm req slab\n");879 ret = -ENOMEM;880 881 goto err_tmreq_slab;882 }883 snic_glob->req_cache[SNIC_REQ_TM_CACHE] = cachep;884 885 /* snic_event queue */886 snic_glob->event_q =887 alloc_ordered_workqueue("%s", WQ_MEM_RECLAIM, "snic_event_wq");888 if (!snic_glob->event_q) {889 SNIC_ERR("snic event queue create failed\n");890 ret = -ENOMEM;891 892 goto err_eventq;893 }894 895 return ret;896 897err_eventq:898 kmem_cache_destroy(snic_glob->req_cache[SNIC_REQ_TM_CACHE]);899 900err_tmreq_slab:901 kmem_cache_destroy(snic_glob->req_cache[SNIC_REQ_CACHE_MAX_SGL]);902 903err_max_req_slab:904 kmem_cache_destroy(snic_glob->req_cache[SNIC_REQ_CACHE_DFLT_SGL]);905 906err_dflt_req_slab:907#ifdef CONFIG_SCSI_SNIC_DEBUG_FS908 snic_trc_free();909 snic_debugfs_term();910#endif911 kfree(snic_glob);912 snic_glob = NULL;913 914gdi_end:915 return ret;916} /* end of snic_glob_init */917 918/*919 * snic_global_data_cleanup : Frees SNIC Global Data920 */921static void922snic_global_data_cleanup(void)923{924 SNIC_BUG_ON(snic_glob == NULL);925 926 destroy_workqueue(snic_glob->event_q);927 kmem_cache_destroy(snic_glob->req_cache[SNIC_REQ_TM_CACHE]);928 kmem_cache_destroy(snic_glob->req_cache[SNIC_REQ_CACHE_MAX_SGL]);929 kmem_cache_destroy(snic_glob->req_cache[SNIC_REQ_CACHE_DFLT_SGL]);930 931#ifdef CONFIG_SCSI_SNIC_DEBUG_FS932 /* Freeing Trace Resources */933 snic_trc_free();934 935 /* Freeing Debugfs Resources */936 snic_debugfs_term();937#endif938 kfree(snic_glob);939 snic_glob = NULL;940} /* end of snic_glob_cleanup */941 942static struct pci_driver snic_driver = {943 .name = SNIC_DRV_NAME,944 .id_table = snic_id_table,945 .probe = snic_probe,946 .remove = snic_remove,947};948 949static int __init950snic_init_module(void)951{952 int ret = 0;953 954#ifndef __x86_64__955 SNIC_INFO("SNIC Driver is supported only for x86_64 platforms!\n");956 add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);957#endif958 959 SNIC_INFO("%s, ver %s\n", SNIC_DRV_DESCRIPTION, SNIC_DRV_VERSION);960 961 ret = snic_global_data_init();962 if (ret) {963 SNIC_ERR("Failed to Initialize Global Data.\n");964 965 return ret;966 }967 968 ret = pci_register_driver(&snic_driver);969 if (ret < 0) {970 SNIC_ERR("PCI driver register error\n");971 972 goto err_pci_reg;973 }974 975 return ret;976 977err_pci_reg:978 snic_global_data_cleanup();979 980 return ret;981}982 983static void __exit984snic_cleanup_module(void)985{986 pci_unregister_driver(&snic_driver);987 snic_global_data_cleanup();988}989 990module_init(snic_init_module);991module_exit(snic_cleanup_module);992 993MODULE_LICENSE("GPL v2");994MODULE_DESCRIPTION(SNIC_DRV_DESCRIPTION);995MODULE_VERSION(SNIC_DRV_VERSION);996MODULE_DEVICE_TABLE(pci, snic_id_table);997MODULE_AUTHOR("Narsimhulu Musini <nmusini@cisco.com>, "998 "Sesidhar Baddela <sebaddel@cisco.com>");999