Merge tag 'iwlwifi-for-kalle-2015-04-28' of https://git.kernel.org/pub/scm/linux...
[firefly-linux-kernel-4.4.55.git] / drivers / scsi / lpfc / lpfc_scsi.c
index 4f9222eb22669b6a84f0e5cad891958e6e8c6e22..cb73cf9e9ba5c9a7d16c2b069ef649663cf067f8 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2014 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2015 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -1129,6 +1129,25 @@ lpfc_release_scsi_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb)
        phba->lpfc_release_scsi_buf(phba, psb);
 }
 
+/**
+ * lpfc_fcpcmd_to_iocb - copy the fcp_cmd data into the IOCB
+ * @data: A pointer to the immediate command data portion of the IOCB.
+ * @fcp_cmnd: The FCP Command that is provided by the SCSI layer.
+ *
+ * The routine copies the entire FCP command from @fcp_cmnd to @data while
+ * byte swapping the data to big endian format for transmission on the wire.
+ **/
+static void
+lpfc_fcpcmd_to_iocb(uint8_t *data, struct fcp_cmnd *fcp_cmnd)
+{
+       int i, j;
+
+       for (i = 0, j = 0; i < sizeof(struct fcp_cmnd);
+            i += sizeof(uint32_t), j++) {
+               ((uint32_t *)data)[j] = cpu_to_be32(((uint32_t *)fcp_cmnd)[j]);
+       }
+}
+
 /**
  * lpfc_scsi_prep_dma_buf_s3 - DMA mapping for scsi buffer to SLI3 IF spec
  * @phba: The Hba for which this call is being executed.
@@ -1264,6 +1283,7 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
         * we need to set word 4 of IOCB here
         */
        iocb_cmd->un.fcpi.fcpi_parm = scsi_bufflen(scsi_cmnd);
+       lpfc_fcpcmd_to_iocb(iocb_cmd->unsli3.fcp_ext.icd, fcp_cmnd);
        return 0;
 }
 
@@ -4126,24 +4146,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
        lpfc_release_scsi_buf(phba, lpfc_cmd);
 }
 
-/**
- * lpfc_fcpcmd_to_iocb - copy the fcp_cmd data into the IOCB
- * @data: A pointer to the immediate command data portion of the IOCB.
- * @fcp_cmnd: The FCP Command that is provided by the SCSI layer.
- *
- * The routine copies the entire FCP command from @fcp_cmnd to @data while
- * byte swapping the data to big endian format for transmission on the wire.
- **/
-static void
-lpfc_fcpcmd_to_iocb(uint8_t *data, struct fcp_cmnd *fcp_cmnd)
-{
-       int i, j;
-       for (i = 0, j = 0; i < sizeof(struct fcp_cmnd);
-            i += sizeof(uint32_t), j++) {
-               ((uint32_t *)data)[j] = cpu_to_be32(((uint32_t *)fcp_cmnd)[j]);
-       }
-}
-
 /**
  * lpfc_scsi_prep_cmnd - Wrapper func for convert scsi cmnd to FCP info unit
  * @vport: The virtual port for which this call is being executed.
@@ -4223,9 +4225,6 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd,
                fcp_cmnd->fcpCntl3 = 0;
                phba->fc4ControlRequests++;
        }
-       if (phba->sli_rev == 3 &&
-           !(phba->sli3_options & LPFC_SLI3_BG_ENABLED))
-               lpfc_fcpcmd_to_iocb(iocb_cmd->unsli3.fcp_ext.icd, fcp_cmnd);
        /*
         * Finish initializing those IOCB fields that are independent
         * of the scsi_cmnd request_buffer
@@ -5118,9 +5117,10 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
        int status;
 
        rdata = lpfc_rport_data_from_scsi_device(cmnd->device);
-       if (!rdata) {
+       if (!rdata || !rdata->pnode) {
                lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
-                       "0798 Device Reset rport failure: rdata x%p\n", rdata);
+                                "0798 Device Reset rport failure: rdata x%p\n",
+                                rdata);
                return FAILED;
        }
        pnode = rdata->pnode;
@@ -5202,10 +5202,12 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd)
        if (status == FAILED) {
                lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
                        "0722 Target Reset rport failure: rdata x%p\n", rdata);
-               spin_lock_irq(shost->host_lock);
-               pnode->nlp_flag &= ~NLP_NPR_ADISC;
-               pnode->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
-               spin_unlock_irq(shost->host_lock);
+               if (pnode) {
+                       spin_lock_irq(shost->host_lock);
+                       pnode->nlp_flag &= ~NLP_NPR_ADISC;
+                       pnode->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
+                       spin_unlock_irq(shost->host_lock);
+               }
                lpfc_reset_flush_io_context(vport, tgt_id, lun_id,
                                          LPFC_CTX_TGT);
                return FAST_IO_FAIL;
@@ -5857,6 +5859,31 @@ lpfc_disable_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn,
        return false;
 }
 
+struct scsi_host_template lpfc_template_s3 = {
+       .module                 = THIS_MODULE,
+       .name                   = LPFC_DRIVER_NAME,
+       .info                   = lpfc_info,
+       .queuecommand           = lpfc_queuecommand,
+       .eh_abort_handler       = lpfc_abort_handler,
+       .eh_device_reset_handler = lpfc_device_reset_handler,
+       .eh_target_reset_handler = lpfc_target_reset_handler,
+       .eh_bus_reset_handler   = lpfc_bus_reset_handler,
+       .slave_alloc            = lpfc_slave_alloc,
+       .slave_configure        = lpfc_slave_configure,
+       .slave_destroy          = lpfc_slave_destroy,
+       .scan_finished          = lpfc_scan_finished,
+       .this_id                = -1,
+       .sg_tablesize           = LPFC_DEFAULT_SG_SEG_CNT,
+       .cmd_per_lun            = LPFC_CMD_PER_LUN,
+       .use_clustering         = ENABLE_CLUSTERING,
+       .shost_attrs            = lpfc_hba_attrs,
+       .max_sectors            = 0xFFFF,
+       .vendor_id              = LPFC_NL_VENDOR_ID,
+       .change_queue_depth     = scsi_change_queue_depth,
+       .use_blk_tags           = 1,
+       .track_queue_depth      = 1,
+};
+
 struct scsi_host_template lpfc_template = {
        .module                 = THIS_MODULE,
        .name                   = LPFC_DRIVER_NAME,