]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 31 May 2012 19:02:41 +0000 (12:02 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 31 May 2012 19:02:41 +0000 (12:02 -0700)
Pull final round of SCSI updates from James Bottomley:
 "This is primarily another round of driver updates (bnx2fc, qla2xxx,
  qla4xxx) including the target mode driver for qla2xxx.  We've also got
  a couple of regression fixes (async scanning, broken this merge window
  and a fix to a long standing break in the scsi_wait_scan module)."

* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (45 commits)
  [SCSI] fix scsi_wait_scan
  [SCSI] fix async probe regression
  [SCSI] be2iscsi: fix dma free size mismatch regression
  [SCSI] qla4xxx: Update driver version to 5.02.00-k17
  [SCSI] qla4xxx: Capture minidump for ISP82XX on firmware failure
  [SCSI] qla4xxx: Add change_queue_depth API support
  [SCSI] qla4xxx: Fix clear ddb mbx command failure issue.
  [SCSI] qla4xxx: Fix kernel panic during discovery logout.
  [SCSI] qla4xxx: Correct early completion of pending mbox.
  [SCSI] fcoe, bnx2fc, libfcoe: SW FCoE and bnx2fc use FCoE Syfs
  [SCSI] libfcoe: Add fcoe_sysfs
  [SCSI] bnx2fc: Allocate fcoe_ctlr with bnx2fc_interface, not as a member
  [SCSI] fcoe: Allocate fcoe_ctlr with fcoe_interface, not as a member
  [SCSI] Fix dm-multipath starvation when scsi host is busy
  [SCSI] ufs: fix potential NULL pointer dereferencing error in ufshcd_prove.
  [SCSI] qla2xxx: don't free pool that wasn't allocated
  [SCSI] mptfusion: unlock on error in mpt_config()
  [SCSI] tcm_qla2xxx: Add >= 24xx series fabric module for target-core
  [SCSI] qla2xxx: Add LLD target-mode infrastructure for >= 24xx series
  [SCSI] Revert "qla2xxx: During loopdown perform Diagnostic loopback."
  ...

1  2 
drivers/scsi/qla2xxx/qla_os.c

index c9c56a8427f3e1d36c2a1c14764a4d4860a782d9,9c50a8505f0706837158018f50af18c95f0f6826..6d1d873a20e2f8997ead5ecadd2e30a183d92c6c
  #include <linux/mutex.h>
  #include <linux/kobject.h>
  #include <linux/slab.h>
  #include <scsi/scsi_tcq.h>
  #include <scsi/scsicam.h>
  #include <scsi/scsi_transport.h>
  #include <scsi/scsi_transport_fc.h>
  
+ #include "qla_target.h"
  /*
   * Driver version
   */
@@@ -40,6 -41,12 +41,12 @@@ static struct kmem_cache *ctx_cachep
   */
  int ql_errlev = ql_log_all;
  
+ int ql2xenableclass2;
+ module_param(ql2xenableclass2, int, S_IRUGO|S_IRUSR);
+ MODULE_PARM_DESC(ql2xenableclass2,
+               "Specify if Class 2 operations are supported from the very "
+               "beginning. Default is 0 - class 2 not supported.");
  int ql2xlogintimeout = 20;
  module_param(ql2xlogintimeout, int, S_IRUGO);
  MODULE_PARM_DESC(ql2xlogintimeout,
@@@ -255,6 -262,8 +262,8 @@@ struct scsi_host_template qla2xxx_drive
  
        .max_sectors            = 0xFFFF,
        .shost_attrs            = qla2x00_host_attrs,
+       .supported_mode         = MODE_INITIATOR,
  };
  
  static struct scsi_transport_template *qla2xxx_transport_template = NULL;
@@@ -306,7 -315,8 +315,8 @@@ static void qla2x00_free_fw_dump(struc
  static void qla2x00_mem_free(struct qla_hw_data *);
  
  /* -------------------------------------------------------------------------- */
- static int qla2x00_alloc_queues(struct qla_hw_data *ha)
+ static int qla2x00_alloc_queues(struct qla_hw_data *ha, struct req_que *req,
+                               struct rsp_que *rsp)
  {
        scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
        ha->req_q_map = kzalloc(sizeof(struct req_que *) * ha->max_req_queues,
                    "Unable to allocate memory for response queue ptrs.\n");
                goto fail_rsp_map;
        }
+       /*
+        * Make sure we record at least the request and response queue zero in
+        * case we need to free them if part of the probe fails.
+        */
+       ha->rsp_q_map[0] = rsp;
+       ha->req_q_map[0] = req;
        set_bit(0, ha->rsp_qid_map);
        set_bit(0, ha->req_qid_map);
        return 1;
@@@ -642,12 -658,12 +658,12 @@@ qla2xxx_queuecommand(struct Scsi_Host *
  
        if (ha->flags.eeh_busy) {
                if (ha->flags.pci_channel_io_perm_failure) {
-                       ql_dbg(ql_dbg_io, vha, 0x3001,
+                       ql_dbg(ql_dbg_aer, vha, 0x9010,
                            "PCI Channel IO permanent failure, exiting "
                            "cmd=%p.\n", cmd);
                        cmd->result = DID_NO_CONNECT << 16;
                } else {
-                       ql_dbg(ql_dbg_io, vha, 0x3002,
+                       ql_dbg(ql_dbg_aer, vha, 0x9011,
                            "EEH_Busy, Requeuing the cmd=%p.\n", cmd);
                        cmd->result = DID_REQUEUE << 16;
                }
        rval = fc_remote_port_chkready(rport);
        if (rval) {
                cmd->result = rval;
-               ql_dbg(ql_dbg_io, vha, 0x3003,
+               ql_dbg(ql_dbg_io + ql_dbg_verbose, vha, 0x3003,
                    "fc_remote_port_chkready failed for cmd=%p, rval=0x%x.\n",
                    cmd, rval);
                goto qc24_fail_command;
@@@ -1136,7 -1152,7 +1152,7 @@@ qla2xxx_eh_bus_reset(struct scsi_cmnd *
        ret = FAILED;
  
        ql_log(ql_log_info, vha, 0x8012,
-           "BUS RESET ISSUED nexus=%ld:%d%d.\n", vha->host_no, id, lun);
+           "BUS RESET ISSUED nexus=%ld:%d:%d.\n", vha->host_no, id, lun);
  
        if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
                ql_log(ql_log_fatal, vha, 0x8013,
@@@ -2180,6 -2196,7 +2196,7 @@@ qla2x00_probe_one(struct pci_dev *pdev
        ql_dbg_pci(ql_dbg_init, pdev, 0x000a,
            "Memory allocated for ha=%p.\n", ha);
        ha->pdev = pdev;
+       ha->tgt.enable_class_2 = ql2xenableclass2;
  
        /* Clear our data area */
        ha->bars = bars;
                ha->mbx_count = MAILBOX_REGISTER_COUNT;
                req_length = REQUEST_ENTRY_CNT_24XX;
                rsp_length = RESPONSE_ENTRY_CNT_2300;
+               ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX;
                ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
                ha->init_cb_size = sizeof(struct mid_init_cb_24xx);
                ha->gid_list_info_size = 8;
                ha->mbx_count = MAILBOX_REGISTER_COUNT;
                req_length = REQUEST_ENTRY_CNT_24XX;
                rsp_length = RESPONSE_ENTRY_CNT_2300;
+               ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX;
                ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
                ha->init_cb_size = sizeof(struct mid_init_cb_24xx);
                ha->gid_list_info_size = 8;
            host->max_cmd_len, host->max_channel, host->max_lun,
            host->transportt, sht->vendor_id);
  
+ que_init:
+       /* Alloc arrays of request and response ring ptrs */
+       if (!qla2x00_alloc_queues(ha, req, rsp)) {
+               ql_log(ql_log_fatal, base_vha, 0x003d,
+                   "Failed to allocate memory for queue pointers..."
+                   "aborting.\n");
+               goto probe_init_failed;
+       }
+       qlt_probe_one_stage1(base_vha, ha);
        /* Set up the irqs */
        ret = qla2x00_request_irqs(ha, rsp);
        if (ret)
  
        pci_save_state(pdev);
  
-       /* Alloc arrays of request and response ring ptrs */
- que_init:
-       if (!qla2x00_alloc_queues(ha)) {
-               ql_log(ql_log_fatal, base_vha, 0x003d,
-                   "Failed to allocate memory for queue pointers.. aborting.\n");
-               goto probe_init_failed;
-       }
-       ha->rsp_q_map[0] = rsp;
-       ha->req_q_map[0] = req;
+       /* Assign back pointers */
        rsp->req = req;
        req->rsp = rsp;
-       set_bit(0, ha->req_qid_map);
-       set_bit(0, ha->rsp_qid_map);
        /* FWI2-capable only. */
        req->req_q_in = &ha->iobase->isp24.req_q_in;
        req->req_q_out = &ha->iobase->isp24.req_q_out;
        ql_dbg(ql_dbg_init, base_vha, 0x00ee,
            "DPC thread started successfully.\n");
  
+       /*
+        * If we're not coming up in initiator mode, we might sit for
+        * a while without waking up the dpc thread, which leads to a
+        * stuck process warning.  So just kick the dpc once here and
+        * let the kthread start (and go back to sleep in qla2x00_do_dpc).
+        */
+       qla2xxx_wake_dpc(base_vha);
  skip_dpc:
        list_add_tail(&base_vha->list, &ha->vp_list);
        base_vha->host->irq = ha->pdev->irq;
        ql_dbg(ql_dbg_init, base_vha, 0x00f2,
            "Init done and hba is online.\n");
  
-       scsi_scan_host(host);
+       if (qla_ini_mode_enabled(base_vha))
+               scsi_scan_host(host);
+       else
+               ql_dbg(ql_dbg_init, base_vha, 0x0122,
+                       "skipping scsi_scan_host() for non-initiator port\n");
  
        qla2x00_alloc_sysfs_attr(base_vha);
  
            base_vha->host_no,
            ha->isp_ops->fw_version_str(base_vha, fw_str));
  
+       qlt_add_target(ha, base_vha);
        return 0;
  
  probe_init_failed:
        qla2x00_free_req_que(ha, req);
+       ha->req_q_map[0] = NULL;
+       clear_bit(0, ha->req_qid_map);
        qla2x00_free_rsp_que(ha, rsp);
+       ha->rsp_q_map[0] = NULL;
+       clear_bit(0, ha->rsp_qid_map);
        ha->max_req_queues = ha->max_rsp_queues = 0;
  
  probe_failed:
@@@ -2620,6 -2658,22 +2658,22 @@@ probe_out
        return ret;
  }
  
+ static void
+ qla2x00_stop_dpc_thread(scsi_qla_host_t *vha)
+ {
+       struct qla_hw_data *ha = vha->hw;
+       struct task_struct *t = ha->dpc_thread;
+       if (ha->dpc_thread == NULL)
+               return;
+       /*
+        * qla2xxx_wake_dpc checks for ->dpc_thread
+        * so we need to zero it out.
+        */
+       ha->dpc_thread = NULL;
+       kthread_stop(t);
+ }
  static void
  qla2x00_shutdown(struct pci_dev *pdev)
  {
@@@ -2663,9 -2717,18 +2717,18 @@@ qla2x00_remove_one(struct pci_dev *pdev
        struct qla_hw_data  *ha;
        unsigned long flags;
  
+       /*
+        * If the PCI device is disabled that means that probe failed and any
+        * resources should be have cleaned up on probe exit.
+        */
+       if (!atomic_read(&pdev->enable_cnt))
+               return;
        base_vha = pci_get_drvdata(pdev);
        ha = base_vha->hw;
  
+       ha->flags.host_shutting_down = 1;
        mutex_lock(&ha->vport_lock);
        while (ha->cur_vport_count) {
                struct Scsi_Host *scsi_host;
                ha->dpc_thread = NULL;
                kthread_stop(t);
        }
+       qlt_remove_target(ha, base_vha);
  
        qla2x00_free_sysfs_attr(base_vha);
  
@@@ -2770,17 -2834,7 +2834,7 @@@ qla2x00_free_device(scsi_qla_host_t *vh
        if (vha->timer_active)
                qla2x00_stop_timer(vha);
  
-       /* Kill the kernel thread for this host */
-       if (ha->dpc_thread) {
-               struct task_struct *t = ha->dpc_thread;
-               /*
-                * qla2xxx_wake_dpc checks for ->dpc_thread
-                * so we need to zero it out.
-                */
-               ha->dpc_thread = NULL;
-               kthread_stop(t);
-       }
+       qla2x00_stop_dpc_thread(vha);
  
        qla25xx_delete_queues(vha);
  
@@@ -2842,8 -2896,10 +2896,10 @@@ qla2x00_schedule_rport_del(struct scsi_
                spin_unlock_irqrestore(vha->host->host_lock, flags);
                set_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags);
                qla2xxx_wake_dpc(base_vha);
-       } else
+       } else {
                fc_remote_port_delete(rport);
+               qlt_fc_port_deleted(vha, fcport);
+       }
  }
  
  /*
@@@ -2859,7 -2915,7 +2915,7 @@@ void qla2x00_mark_device_lost(scsi_qla_
      int do_login, int defer)
  {
        if (atomic_read(&fcport->state) == FCS_ONLINE &&
-           vha->vp_idx == fcport->vp_idx) {
+           vha->vp_idx == fcport->vha->vp_idx) {
                qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST);
                qla2x00_schedule_rport_del(vha, fcport, defer);
        }
@@@ -2908,7 -2964,7 +2964,7 @@@ qla2x00_mark_all_devices_lost(scsi_qla_
        fc_port_t *fcport;
  
        list_for_each_entry(fcport, &vha->vp_fcports, list) {
-               if (vha->vp_idx != 0 && vha->vp_idx != fcport->vp_idx)
+               if (vha->vp_idx != 0 && vha->vp_idx != fcport->vha->vp_idx)
                        continue;
  
                /*
                        qla2x00_set_fcport_state(fcport, FCS_DEVICE_LOST);
                        if (defer)
                                qla2x00_schedule_rport_del(vha, fcport, defer);
-                       else if (vha->vp_idx == fcport->vp_idx)
+                       else if (vha->vp_idx == fcport->vha->vp_idx)
                                qla2x00_schedule_rport_del(vha, fcport, defer);
                }
        }
@@@ -2946,10 -3002,13 +3002,13 @@@ qla2x00_mem_alloc(struct qla_hw_data *h
        if (!ha->init_cb)
                goto fail;
  
+       if (qlt_mem_alloc(ha) < 0)
+               goto fail_free_init_cb;
        ha->gid_list = dma_alloc_coherent(&ha->pdev->dev,
                qla2x00_gid_list_size(ha), &ha->gid_list_dma, GFP_KERNEL);
        if (!ha->gid_list)
-               goto fail_free_init_cb;
+               goto fail_free_tgt_mem;
  
        ha->srb_mempool = mempool_create_slab_pool(SRB_MIN_REQ, srb_cachep);
        if (!ha->srb_mempool)
@@@ -3167,6 -3226,8 +3226,8 @@@ fail_free_gid_list
        ha->gid_list_dma);
        ha->gid_list = NULL;
        ha->gid_list_dma = 0;
+ fail_free_tgt_mem:
+       qlt_mem_free(ha);
  fail_free_init_cb:
        dma_free_coherent(&ha->pdev->dev, ha->init_cb_size, ha->init_cb,
        ha->init_cb_dma);
@@@ -3282,6 -3343,8 +3343,8 @@@ qla2x00_mem_free(struct qla_hw_data *ha
        if (ha->ctx_mempool)
                mempool_destroy(ha->ctx_mempool);
  
+       qlt_mem_free(ha);
        if (ha->init_cb)
                dma_free_coherent(&ha->pdev->dev, ha->init_cb_size,
                        ha->init_cb, ha->init_cb_dma);
  
        ha->gid_list = NULL;
        ha->gid_list_dma = 0;
+       ha->tgt.atio_ring = NULL;
+       ha->tgt.atio_dma = 0;
+       ha->tgt.tgt_vp_map = NULL;
  }
  
  struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
@@@ -3671,10 -3738,9 +3738,9 @@@ qla2x00_do_dpc(void *data
  
                ha->dpc_active = 1;
  
-               ql_dbg(ql_dbg_dpc, base_vha, 0x4001,
-                   "DPC handler waking up.\n");
-               ql_dbg(ql_dbg_dpc, base_vha, 0x4002,
-                   "dpc_flags=0x%lx.\n", base_vha->dpc_flags);
+               ql_dbg(ql_dbg_dpc + ql_dbg_verbose, base_vha, 0x4001,
+                   "DPC handler waking up, dpc_flags=0x%lx.\n",
+                   base_vha->dpc_flags);
  
                qla2x00_do_work(base_vha);
  
                        clear_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags);
                }
  
+               if (test_bit(SCR_PENDING, &base_vha->dpc_flags)) {
+                       int ret;
+                       ret = qla2x00_send_change_request(base_vha, 0x3, 0);
+                       if (ret != QLA_SUCCESS)
+                               ql_log(ql_log_warn, base_vha, 0x121,
+                                   "Failed to enable receiving of RSCN "
+                                   "requests: 0x%x.\n", ret);
+                       clear_bit(SCR_PENDING, &base_vha->dpc_flags);
+               }
                if (test_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags)) {
                        ql_dbg(ql_dbg_dpc, base_vha, 0x4009,
                            "Quiescence mode scheduled.\n");
@@@ -4122,7 -4198,8 +4198,7 @@@ qla2x00_release_firmware(void
  
        mutex_lock(&qla_fw_lock);
        for (idx = 0; idx < FW_BLOBS; idx++)
 -              if (qla_fw_blobs[idx].fw)
 -                      release_firmware(qla_fw_blobs[idx].fw);
 +              release_firmware(qla_fw_blobs[idx].fw);
        mutex_unlock(&qla_fw_lock);
  }
  
@@@ -4457,6 -4534,21 +4533,21 @@@ qla2x00_module_init(void
                return -ENOMEM;
        }
  
+       /* Initialize target kmem_cache and mem_pools */
+       ret = qlt_init();
+       if (ret < 0) {
+               kmem_cache_destroy(srb_cachep);
+               return ret;
+       } else if (ret > 0) {
+               /*
+                * If initiator mode is explictly disabled by qlt_init(),
+                * prevent scsi_transport_fc.c:fc_scsi_scan_rport() from
+                * performing scsi_scan_target() during LOOP UP event.
+                */
+               qla2xxx_transport_functions.disable_target_scan = 1;
+               qla2xxx_transport_vport_functions.disable_target_scan = 1;
+       }
        /* Derive version string. */
        strcpy(qla2x00_version_str, QLA2XXX_VERSION);
        if (ql2xextended_error_logging)
                kmem_cache_destroy(srb_cachep);
                ql_log(ql_log_fatal, NULL, 0x0002,
                    "fc_attach_transport failed...Failing load!.\n");
+               qlt_exit();
                return -ENODEV;
        }
  
            fc_attach_transport(&qla2xxx_transport_vport_functions);
        if (!qla2xxx_transport_vport_template) {
                kmem_cache_destroy(srb_cachep);
+               qlt_exit();
                fc_release_transport(qla2xxx_transport_template);
                ql_log(ql_log_fatal, NULL, 0x0004,
                    "fc_attach_transport vport failed...Failing load!.\n");
        ret = pci_register_driver(&qla2xxx_pci_driver);
        if (ret) {
                kmem_cache_destroy(srb_cachep);
+               qlt_exit();
                fc_release_transport(qla2xxx_transport_template);
                fc_release_transport(qla2xxx_transport_vport_template);
                ql_log(ql_log_fatal, NULL, 0x0006,
@@@ -4511,6 -4606,7 +4605,7 @@@ qla2x00_module_exit(void
        pci_unregister_driver(&qla2xxx_pci_driver);
        qla2x00_release_firmware();
        kmem_cache_destroy(srb_cachep);
+       qlt_exit();
        if (ctx_cachep)
                kmem_cache_destroy(ctx_cachep);
        fc_release_transport(qla2xxx_transport_template);