]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blobdiff - src/patches/suse-2.6.27.31/patches.drivers/lpfc-8.2.8.3-update
Imported linux-2.6.27.39 suse/xen patches.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.drivers / lpfc-8.2.8.3-update
diff --git a/src/patches/suse-2.6.27.31/patches.drivers/lpfc-8.2.8.3-update b/src/patches/suse-2.6.27.31/patches.drivers/lpfc-8.2.8.3-update
deleted file mode 100644 (file)
index e4b57fd..0000000
+++ /dev/null
@@ -1,1355 +0,0 @@
-From: Jamie Wellnitz <jamie.wellnitz@emulex.com>
-Subject: Update lpfc to 8.2.8.3
-References: bnc#420767
-    
-This patch updates the SLES 11 inbox lpfc driver to 8.2.8.3 which has several
-changes, mainly bugfixes:
-    
-  * Changed version number to 8.2.8.3
-  * Resolved uninitialized node access (CR 83287)
-  * Fixed failing ioctl commands (CR 83850)
-  * Cosmetic coding style clean up
-  * Fix echotest failure when NPIV is enabled (CR 75009)
-  * Fixed Port busy events
-  * Back out slow vports fix (CR 83103)
-  * Added a vendor unique RSCN event to send entire payload to mgmt application
-  * Fixed internal loopback Hornet hardware (CR 83323)
-  * Fixed sysfs write handler for mailbox interface (CR 83674)
-  * Implement driver support for Power Management Suspend/Resume operations (CR
-  74378)
-  * Changed version number to 8.2.8.2
-  * Added data structures required for new events.
-  * Streamlined interrupt enable/disable logic into helper routines
-  * Fixed incorrect decrement of cmd_pending count. (CR 83286)
-  * Fixed internal and external loopback on Hornet. (CR 83323)
-  * Removed unnecessary sleeps during HBA initialization. (CR 82846)
-  * Fixed RSCN address format not handled properly. (CR 82252)
-  * Fixed unload driver with vports locks up driver (CR 83334)
-  * Avoid polling HBA Error Attention when HBA's PCI channel is offline
-    
-Signed-off-by: Jamie Wellnitz <jamie.wellnitz@emulex.com>
-Signed-off-by: Hannes Reinecke <hare@suse.de>
-
-diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
-index 273aa4f..8e94902 100644
---- a/drivers/scsi/lpfc/lpfc_attr.c
-+++ b/drivers/scsi/lpfc/lpfc_attr.c
-@@ -3531,9 +3531,6 @@ sysfs_mbox_write(struct kobject *kobj, struct bin_attribute *bin_attr,
-       uint8_t *ext;
-       uint32_t size;
--      if ((count + off) > MAILBOX_CMD_SIZE)
--              return -ERANGE;
--
-       if (off % 4 ||  count % 4 || (unsigned long)buf % 4)
-               return -EINVAL;
-diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
-index 0c90479..a93c555 100644
---- a/drivers/scsi/lpfc/lpfc_crtn.h
-+++ b/drivers/scsi/lpfc/lpfc_crtn.h
-@@ -323,11 +323,10 @@ void lpfc_fabric_abort_nport(struct lpfc_nodelist *);
- void lpfc_fabric_abort_hba(struct lpfc_hba *);
- void lpfc_fabric_block_timeout(unsigned long);
- void lpfc_unblock_fabric_iocbs(struct lpfc_hba *);
--void lpfc_adjust_queue_depth(struct lpfc_hba *);
-+void lpfc_rampdown_queue_depth(struct lpfc_hba *);
- void lpfc_ramp_down_queue_handler(struct lpfc_hba *);
- void lpfc_ramp_up_queue_handler(struct lpfc_hba *);
- void lpfc_scsi_dev_block(struct lpfc_hba *);
--void lpfc_scsi_dev_rescan(struct lpfc_hba *);
- void
- lpfc_send_els_failure_event(struct lpfc_hba *, struct lpfc_iocbq *,
-diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
-index bce59ec..a95815e 100644
---- a/drivers/scsi/lpfc/lpfc_els.c
-+++ b/drivers/scsi/lpfc/lpfc_els.c
-@@ -224,7 +224,11 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
-               /* For ELS_REQUEST64_CR, use the VPI by default */
-               icmd->ulpContext = vport->vpi;
-               icmd->ulpCt_h = 0;
--              icmd->ulpCt_l = 1;
-+              /* The CT field must be 0=INVALID_RPI for the ECHO cmd */
-+              if (elscmd == ELS_CMD_ECHO)
-+                      icmd->ulpCt_l = 0; /* context = invalid RPI */
-+              else
-+                      icmd->ulpCt_l = 1; /* context = VPI */
-       }
-       bpl = (struct ulp_bde64 *) pbuflist->virt;
-@@ -2504,6 +2508,15 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
-       case IOSTAT_LOCAL_REJECT:
-               switch ((irsp->un.ulpWord[4] & 0xff)) {
-               case IOERR_LOOP_OPEN_FAILURE:
-+                      if (cmd == ELS_CMD_FLOGI) {
-+                              if (PCI_DEVICE_ID_HORNET ==
-+                                      phba->pcidev->device) {
-+                                      phba->fc_topology = TOPOLOGY_LOOP;
-+                                      phba->pport->fc_myDID = 0;
-+                                      phba->alpa_map[0] = 0;
-+                                      phba->alpa_map[1] = 0;
-+                              }
-+                      }
-                       if (cmd == ELS_CMD_PLOGI && cmdiocb->retry == 0)
-                               delay = 1000;
-                       retry = 1;
-@@ -3870,27 +3883,21 @@ lpfc_rscn_payload_check(struct lpfc_vport *vport, uint32_t did)
-               while (payload_len) {
-                       rscn_did.un.word = be32_to_cpu(*lp++);
-                       payload_len -= sizeof(uint32_t);
--                      switch (rscn_did.un.b.resv) {
--                      case 0: /* Single N_Port ID effected */
-+                      switch (rscn_did.un.b.resv & RSCN_ADDRESS_FORMAT_MASK) {
-+                      case RSCN_ADDRESS_FORMAT_PORT:
-                               if (ns_did.un.word == rscn_did.un.word)
-                                       goto return_did_out;
-                               break;
--                      case 1: /* Whole N_Port Area effected */
-+                      case RSCN_ADDRESS_FORMAT_AREA:
-                               if ((ns_did.un.b.domain == rscn_did.un.b.domain)
-                                   && (ns_did.un.b.area == rscn_did.un.b.area))
-                                       goto return_did_out;
-                               break;
--                      case 2: /* Whole N_Port Domain effected */
-+                      case RSCN_ADDRESS_FORMAT_DOMAIN:
-                               if (ns_did.un.b.domain == rscn_did.un.b.domain)
-                                       goto return_did_out;
-                               break;
--                      default:
--                              /* Unknown Identifier in RSCN node */
--                              lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
--                                               "0217 Unknown Identifier in "
--                                               "RSCN payload Data: x%x\n",
--                                               rscn_did.un.word);
--                      case 3: /* Whole Fabric effected */
-+                      case RSCN_ADDRESS_FORMAT_FABRIC:
-                               goto return_did_out;
-                       }
-               }
-@@ -3934,6 +3941,49 @@ lpfc_rscn_recovery_check(struct lpfc_vport *vport)
- }
- /**
-+ * lpfc_send_rscn_event: Send an RSCN event to management application.
-+ * @vport: pointer to a host virtual N_Port data structure.
-+ * @cmdiocb: pointer to lpfc command iocb data structure.
-+ *
-+ * lpfc_send_rscn_event sends an RSCN netlink event to management
-+ * applications.
-+ */
-+static void
-+lpfc_send_rscn_event(struct lpfc_vport *vport,
-+              struct lpfc_iocbq *cmdiocb)
-+{
-+      struct lpfc_dmabuf *pcmd;
-+      struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-+      uint32_t *payload_ptr;
-+      uint32_t payload_len;
-+      struct lpfc_rscn_event_header *rscn_event_data;
-+
-+      pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
-+      payload_ptr = (uint32_t *) pcmd->virt;
-+      payload_len = be32_to_cpu(*payload_ptr & ~ELS_CMD_MASK);
-+
-+      rscn_event_data = kmalloc(sizeof(struct lpfc_rscn_event_header) +
-+              payload_len, GFP_KERNEL);
-+      if (!rscn_event_data) {
-+              lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
-+                      "0147 Failed to allocate memory for RSCN event\n");
-+              return;
-+      }
-+      rscn_event_data->event_type = FC_REG_RSCN_EVENT;
-+      rscn_event_data->payload_length = payload_len;
-+      memcpy(rscn_event_data->rscn_payload, payload_ptr,
-+              payload_len);
-+
-+      fc_host_post_vendor_event(shost,
-+              fc_get_event_number(),
-+              sizeof(struct lpfc_els_event_header) + payload_len,
-+              (char *)rscn_event_data,
-+              LPFC_NL_VENDOR_ID);
-+
-+      kfree(rscn_event_data);
-+}
-+
-+/**
-  * lpfc_els_rcv_rscn: Process an unsolicited rscn iocb.
-  * @vport: pointer to a host virtual N_Port data structure.
-  * @cmdiocb: pointer to lpfc command iocb data structure.
-@@ -3980,6 +4030,10 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
-                        "0214 RSCN received Data: x%x x%x x%x x%x\n",
-                        vport->fc_flag, payload_len, *lp,
-                        vport->fc_rscn_id_cnt);
-+
-+      /* Send an RSCN event to the management application */
-+      lpfc_send_rscn_event(vport, cmdiocb);
-+
-       for (i = 0; i < payload_len/sizeof(uint32_t); i++)
-               fc_host_post_event(shost, fc_get_event_number(),
-                       FCH_EVT_RSCN, lp[i]);
-@@ -5532,7 +5586,7 @@ lpfc_send_els_failure_event(struct lpfc_hba *phba,
-                       fc_get_event_number(),
-                       sizeof(lsrjt_event),
-                       (char *)&lsrjt_event,
--                      SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
-+                      LPFC_NL_VENDOR_ID);
-               return;
-       }
-       if ((rspiocbp->iocb.ulpStatus == IOSTAT_NPORT_BSY) ||
-@@ -5550,7 +5604,7 @@ lpfc_send_els_failure_event(struct lpfc_hba *phba,
-                       fc_get_event_number(),
-                       sizeof(fabric_event),
-                       (char *)&fabric_event,
--                      SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
-+                      LPFC_NL_VENDOR_ID);
-               return;
-       }
-@@ -5568,32 +5622,68 @@ lpfc_send_els_failure_event(struct lpfc_hba *phba,
- static void
- lpfc_send_els_event(struct lpfc_vport *vport,
-                   struct lpfc_nodelist *ndlp,
--                  uint32_t cmd)
-+                  uint32_t *payload)
- {
--      struct lpfc_els_event_header els_data;
-+      struct lpfc_els_event_header *els_data = NULL;
-+      struct lpfc_logo_event *logo_data = NULL;
-       struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
--      els_data.event_type = FC_REG_ELS_EVENT;
--      switch (cmd) {
-+      if (*payload == ELS_CMD_LOGO) {
-+              logo_data = kmalloc(sizeof(struct lpfc_logo_event), GFP_KERNEL);
-+              if (!logo_data) {
-+                      lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
-+                              "0148 Failed to allocate memory "
-+                              "for LOGO event\n");
-+                      return;
-+              }
-+              els_data = &logo_data->header;
-+      } else {
-+              els_data = kmalloc(sizeof(struct lpfc_els_event_header),
-+                      GFP_KERNEL);
-+              if (!els_data) {
-+                      lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
-+                              "0149 Failed to allocate memory "
-+                              "for ELS event\n");
-+                      return;
-+              }
-+      }
-+      els_data->event_type = FC_REG_ELS_EVENT;
-+      switch (*payload) {
-       case ELS_CMD_PLOGI:
--              els_data.subcategory = LPFC_EVENT_PLOGI_RCV;
-+              els_data->subcategory = LPFC_EVENT_PLOGI_RCV;
-               break;
-       case ELS_CMD_PRLO:
--              els_data.subcategory = LPFC_EVENT_PRLO_RCV;
-+              els_data->subcategory = LPFC_EVENT_PRLO_RCV;
-               break;
-       case ELS_CMD_ADISC:
--              els_data.subcategory = LPFC_EVENT_ADISC_RCV;
-+              els_data->subcategory = LPFC_EVENT_ADISC_RCV;
-+              break;
-+      case ELS_CMD_LOGO:
-+              els_data->subcategory = LPFC_EVENT_LOGO_RCV;
-+              /* Copy the WWPN in the LOGO payload */
-+              memcpy(logo_data->logo_wwpn, &payload[2],
-+                      sizeof(struct lpfc_name));
-               break;
-       default:
-               return;
-       }
--      memcpy(els_data.wwpn, &ndlp->nlp_portname, sizeof(struct lpfc_name));
--      memcpy(els_data.wwnn, &ndlp->nlp_nodename, sizeof(struct lpfc_name));
--      fc_host_post_vendor_event(shost,
--              fc_get_event_number(),
--              sizeof(els_data),
--              (char *)&els_data,
--              SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
-+      memcpy(els_data->wwpn, &ndlp->nlp_portname, sizeof(struct lpfc_name));
-+      memcpy(els_data->wwnn, &ndlp->nlp_nodename, sizeof(struct lpfc_name));
-+      if (*payload == ELS_CMD_LOGO) {
-+              fc_host_post_vendor_event(shost,
-+                      fc_get_event_number(),
-+                      sizeof(struct lpfc_logo_event),
-+                      (char *)logo_data,
-+                      LPFC_NL_VENDOR_ID);
-+              kfree(logo_data);
-+      } else {
-+              fc_host_post_vendor_event(shost,
-+                      fc_get_event_number(),
-+                      sizeof(struct lpfc_els_event_header),
-+                      (char *)els_data,
-+                      LPFC_NL_VENDOR_ID);
-+              kfree(els_data);
-+      }
-       return;
- }
-@@ -5700,7 +5790,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
-               phba->fc_stat.elsRcvPLOGI++;
-               ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp);
--              lpfc_send_els_event(vport, ndlp, cmd);
-+              lpfc_send_els_event(vport, ndlp, payload);
-               if (vport->port_state < LPFC_DISC_AUTH) {
-                       if (!(phba->pport->fc_flag & FC_PT2PT) ||
-                               (phba->pport->fc_flag & FC_PT2PT_PLOGI)) {
-@@ -5738,6 +5828,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
-                       did, vport->port_state, ndlp->nlp_flag);
-               phba->fc_stat.elsRcvLOGO++;
-+              lpfc_send_els_event(vport, ndlp, payload);
-               if (vport->port_state < LPFC_DISC_AUTH) {
-                       rjt_err = LSRJT_UNABLE_TPC;
-                       break;
-@@ -5750,7 +5841,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
-                       did, vport->port_state, ndlp->nlp_flag);
-               phba->fc_stat.elsRcvPRLO++;
--              lpfc_send_els_event(vport, ndlp, cmd);
-+              lpfc_send_els_event(vport, ndlp, payload);
-               if (vport->port_state < LPFC_DISC_AUTH) {
-                       rjt_err = LSRJT_UNABLE_TPC;
-                       break;
-@@ -5768,7 +5859,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
-                       "RCV ADISC:       did:x%x/ste:x%x flg:x%x",
-                       did, vport->port_state, ndlp->nlp_flag);
--              lpfc_send_els_event(vport, ndlp, cmd);
-+              lpfc_send_els_event(vport, ndlp, payload);
-               phba->fc_stat.elsRcvADISC++;
-               if (vport->port_state < LPFC_DISC_AUTH) {
-                       rjt_err = LSRJT_UNABLE_TPC;
-diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
-index 3d825ff..502a9a5 100644
---- a/drivers/scsi/lpfc/lpfc_hbadisc.c
-+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
-@@ -391,7 +391,7 @@ lpfc_send_fastpath_evt(struct lpfc_hba *phba,
-                       evt_data_size = sizeof(fast_evt_data->un.
-                               read_check_error);
-               } else if ((evt_sub_category == LPFC_EVENT_FABRIC_BUSY) ||
--                      (evt_sub_category == IOSTAT_NPORT_BSY)) {
-+                      (evt_sub_category == LPFC_EVENT_PORT_BUSY)) {
-                       evt_data = (char *) &fast_evt_data->un.fabric_evt;
-                       evt_data_size = sizeof(fast_evt_data->un.fabric_evt);
-               } else {
-@@ -428,7 +428,7 @@ lpfc_send_fastpath_evt(struct lpfc_hba *phba,
-               fc_get_event_number(),
-               evt_data_size,
-               evt_data,
--              SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
-+              LPFC_NL_VENDOR_ID);
-       lpfc_free_fast_evt(phba, fast_evt_data);
-       return;
-@@ -635,20 +635,25 @@ lpfc_do_work(void *p)
-       set_user_nice(current, -20);
-       phba->data_flags = 0;
--      while (1) {
-+      while (!kthread_should_stop()) {
-               /* wait and check worker queue activities */
-               rc = wait_event_interruptible(phba->work_waitq,
-                                       (test_and_clear_bit(LPFC_DATA_READY,
-                                                           &phba->data_flags)
-                                        || kthread_should_stop()));
--              BUG_ON(rc);
--
--              if (kthread_should_stop())
-+              /* Signal wakeup shall terminate the worker thread */
-+              if (rc) {
-+                      lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-+                                      "0433 Wakeup on signal: rc=x%x\n", rc);
-                       break;
-+              }
-               /* Attend pending lpfc data processing */
-               lpfc_work_done(phba);
-       }
-+      phba->worker_thread = NULL;
-+      lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-+                      "0432 Worker thread stopped.\n");
-       return 0;
- }
-@@ -1895,6 +1900,36 @@ lpfc_disable_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
-       lpfc_nlp_state_cleanup(vport, ndlp, ndlp->nlp_state,
-                               NLP_STE_UNUSED_NODE);
- }
-+/**
-+ * lpfc_initialize_node: Initialize all fields of node object.
-+ * @vport: Pointer to Virtual Port object.
-+ * @ndlp: Pointer to FC node object.
-+ * @did: FC_ID of the node.
-+ *    This function is always called when node object need to
-+ * be initialized. It initializes all the fields of the node
-+ * object.
-+ **/
-+static inline void
-+lpfc_initialize_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-+      uint32_t did)
-+{
-+      INIT_LIST_HEAD(&ndlp->els_retry_evt.evt_listp);
-+      INIT_LIST_HEAD(&ndlp->dev_loss_evt.evt_listp);
-+      INIT_LIST_HEAD(&ndlp->els_reauth_evt.evt_listp);
-+      init_timer(&ndlp->nlp_delayfunc);
-+      ndlp->nlp_delayfunc.function = lpfc_els_retry_delay;
-+      ndlp->nlp_delayfunc.data = (unsigned long)ndlp;
-+      init_timer(&ndlp->nlp_reauth_tmr);
-+      ndlp->nlp_reauth_tmr.function = lpfc_reauth_node;
-+      ndlp->nlp_reauth_tmr.data = (unsigned long)ndlp;
-+      ndlp->nlp_DID = did;
-+      ndlp->vport = vport;
-+      ndlp->nlp_sid = NLP_NO_SID;
-+      kref_init(&ndlp->kref);
-+      NLP_INT_NODE_ACT(ndlp);
-+      atomic_set(&ndlp->cmd_pending, 0);
-+      ndlp->cmd_qdepth = LPFC_MAX_TGT_QDEPTH;
-+}
- struct lpfc_nodelist *
- lpfc_enable_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-@@ -1935,21 +1970,7 @@ lpfc_enable_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-       /* re-initialize ndlp except of ndlp linked list pointer */
-       memset((((char *)ndlp) + sizeof (struct list_head)), 0,
-               sizeof (struct lpfc_nodelist) - sizeof (struct list_head));
--      INIT_LIST_HEAD(&ndlp->els_retry_evt.evt_listp);
--      INIT_LIST_HEAD(&ndlp->dev_loss_evt.evt_listp);
--      INIT_LIST_HEAD(&ndlp->els_reauth_evt.evt_listp);
--      init_timer(&ndlp->nlp_delayfunc);
--      ndlp->nlp_delayfunc.function = lpfc_els_retry_delay;
--      ndlp->nlp_delayfunc.data = (unsigned long)ndlp;
--      init_timer(&ndlp->nlp_reauth_tmr);
--      ndlp->nlp_reauth_tmr.function = lpfc_reauth_node;
--      ndlp->nlp_reauth_tmr.data = (unsigned long)ndlp;
--      ndlp->nlp_DID = did;
--      ndlp->vport = vport;
--      ndlp->nlp_sid = NLP_NO_SID;
--      /* ndlp management re-initialize */
--      kref_init(&ndlp->kref);
--      NLP_INT_NODE_ACT(ndlp);
-+      lpfc_initialize_node(vport, ndlp, did);
-       spin_unlock_irqrestore(&phba->ndlp_lock, flags);
-@@ -2561,7 +2582,8 @@ lpfc_disc_list_loopmap(struct lpfc_vport *vport)
-                       alpa = lpfcAlpaArray[index];
-                       if ((vport->fc_myDID & 0xff) == alpa)
-                               continue;
--                      lpfc_setup_disc_node(vport, alpa);
-+                      if (!(phba->link_flag & LS_LOOPBACK_MODE))
-+                              lpfc_setup_disc_node(vport, alpa);
-               }
-       }
-       return;
-@@ -3204,23 +3226,8 @@ lpfc_nlp_init(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
-             uint32_t did)
- {
-       memset(ndlp, 0, sizeof (struct lpfc_nodelist));
--      INIT_LIST_HEAD(&ndlp->els_retry_evt.evt_listp);
--      INIT_LIST_HEAD(&ndlp->dev_loss_evt.evt_listp);
--      INIT_LIST_HEAD(&ndlp->els_reauth_evt.evt_listp);
--      init_timer(&ndlp->nlp_delayfunc);
--      ndlp->nlp_delayfunc.function = lpfc_els_retry_delay;
--      ndlp->nlp_delayfunc.data = (unsigned long)ndlp;
--      init_timer(&ndlp->nlp_reauth_tmr);
--      ndlp->nlp_reauth_tmr.function = lpfc_reauth_node;
--      ndlp->nlp_reauth_tmr.data = (unsigned long)ndlp;
--      ndlp->nlp_DID = did;
--      ndlp->vport = vport;
--      ndlp->nlp_sid = NLP_NO_SID;
-+      lpfc_initialize_node(vport, ndlp, did);
-       INIT_LIST_HEAD(&ndlp->nlp_listp);
--      kref_init(&ndlp->kref);
--      NLP_INT_NODE_ACT(ndlp);
--      atomic_set(&ndlp->cmd_pending, 0);
--      ndlp->cmd_qdepth = LPFC_MAX_TGT_QDEPTH;
-       lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_NODE,
-               "node init:       did:x%x",
-diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
-index 9fc50ef..90d0c5a 100644
---- a/drivers/scsi/lpfc/lpfc_hw.h
-+++ b/drivers/scsi/lpfc/lpfc_hw.h
-@@ -66,6 +66,9 @@
- #define BUF_SZ_4K             4096
-+/* vendor ID used in SCSI netlink calls */
-+#define LPFC_NL_VENDOR_ID (SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX)
-+
- /* Common Transport structures and definitions */
- union CtRevisionId {
-@@ -891,6 +894,12 @@ typedef struct _D_ID {            /* Structure is in Big Endian format */
-       } un;
- } D_ID;
-+#define RSCN_ADDRESS_FORMAT_PORT      0x0
-+#define RSCN_ADDRESS_FORMAT_AREA      0x1
-+#define RSCN_ADDRESS_FORMAT_DOMAIN    0x2
-+#define RSCN_ADDRESS_FORMAT_FABRIC    0x3
-+#define RSCN_ADDRESS_FORMAT_MASK      0x3
-+
- /*
-  *  Structure to define all ELS Payload types
-  */
-diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
-index c19c631..c0ea4fc 100644
---- a/drivers/scsi/lpfc/lpfc_init.c
-+++ b/drivers/scsi/lpfc/lpfc_init.c
-@@ -879,8 +879,7 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
-       fc_host_post_vendor_event(shost, fc_get_event_number(),
-                                 sizeof(board_event),
-                                 (char *) &board_event,
--                                SCSI_NL_VID_TYPE_PCI
--                                | PCI_VENDOR_ID_EMULEX);
-+                                LPFC_NL_VENDOR_ID);
-       if (phba->work_hs & HS_FFER6) {
-               /* Re-establishing Link */
-@@ -2383,6 +2382,98 @@ lpfc_disable_msix(struct lpfc_hba *phba)
- }
- /**
-+ * lpfc_enable_intr: Enable device interrupt.
-+ * @phba: pointer to lpfc hba data structure.
-+ *
-+ * This routine is invoked to enable device interrupt and associate driver's
-+ * interrupt handler(s) to interrupt vector(s). Depends on the interrupt
-+ * mode configured to the driver, the driver will try to fallback from the
-+ * configured interrupt mode to an interrupt mode which is supported by the
-+ * platform, kernel, and device in the order of: MSI-X -> MSI -> IRQ.
-+ *
-+ * Return codes
-+ *   0 - sucessful
-+ *   other values - error
-+ **/
-+static int
-+lpfc_enable_intr(struct lpfc_hba *phba)
-+{
-+      int retval = 0;
-+
-+      /* Starting point of configuring interrupt method */
-+      phba->intr_type = NONE;
-+
-+      if (phba->cfg_use_msi == 2) {
-+              /* Need to issue conf_port mbox cmd before conf_msi mbox cmd */
-+              retval = lpfc_sli_config_port(phba, 3);
-+              if (retval)
-+                      lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-+                              "0478 Firmware not capable of SLI 3 mode.\n");
-+              else {
-+                      lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-+                              "0479 Firmware capable of SLI 3 mode.\n");
-+                      /* Now, try to enable MSI-X interrupt mode */
-+                      retval = lpfc_enable_msix(phba);
-+                      if (!retval) {
-+                              phba->intr_type = MSIX;
-+                              lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-+                                              "0480 enable MSI-X mode.\n");
-+                      }
-+              }
-+      }
-+
-+      /* Fallback to MSI if MSI-X initialization failed */
-+      if (phba->cfg_use_msi >= 1 && phba->intr_type == NONE) {
-+              retval = pci_enable_msi(phba->pcidev);
-+              if (!retval) {
-+                      phba->intr_type = MSI;
-+                      lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-+                                      "0481 enable MSI mode.\n");
-+              } else
-+                      lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-+                                      "0470 enable IRQ mode.\n");
-+      }
-+
-+      /* MSI-X is the only case the doesn't need to call request_irq */
-+      if (phba->intr_type != MSIX) {
-+              retval = request_irq(phba->pcidev->irq, lpfc_intr_handler,
-+                                   IRQF_SHARED, LPFC_DRIVER_NAME, phba);
-+              if (retval) {
-+                      if (phba->intr_type == MSI)
-+                              pci_disable_msi(phba->pcidev);
-+                      lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-+                                      "0471 Enable interrupt handler "
-+                                      "failed\n");
-+              } else if (phba->intr_type != MSI)
-+                      phba->intr_type = INTx;
-+      }
-+
-+      return retval;
-+}
-+
-+/**
-+ * lpfc_disable_intr: Disable device interrupt.
-+ * @phba: pointer to lpfc hba data structure.
-+ *
-+ * This routine is invoked to disable device interrupt and disassociate the
-+ * driver's interrupt handler(s) from interrupt vector(s). Depending on the
-+ * interrupt mode, the driver will release the interrupt vector(s) for the
-+ * message signaled interrupt.
-+ **/
-+static void
-+lpfc_disable_intr(struct lpfc_hba *phba)
-+{
-+      if (phba->intr_type == MSIX)
-+              lpfc_disable_msix(phba);
-+      else {
-+              free_irq(phba->pcidev->irq, phba);
-+              if (phba->intr_type == MSI)
-+                      pci_disable_msi(phba->pcidev);
-+      }
-+      return;
-+}
-+
-+/**
-  * lpfc_pci_probe_one: lpfc PCI probe func to register device to PCI subsystem.
-  * @pdev: pointer to PCI device
-  * @pid: pointer to PCI device identifier
-@@ -2634,7 +2725,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
-       lpfc_debugfs_initialize(vport);
-       pci_set_drvdata(pdev, shost);
--      phba->intr_type = NONE;
-       phba->MBslimaddr = phba->slim_memmap_p;
-       phba->HAregaddr = phba->ctrl_regs_memmap_p + HA_REG_OFFSET;
-@@ -2643,48 +2733,11 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
-       phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET;
-       /* Configure and enable interrupt */
--      if (phba->cfg_use_msi == 2) {
--              /* Need to issue conf_port mbox cmd before conf_msi mbox cmd */
--              error = lpfc_sli_config_port(phba, 3);
--              if (error)
--                      lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
--                              "0427 Firmware not capable of SLI 3 mode.\n");
--              else {
--                      lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
--                              "0426 Firmware capable of SLI 3 mode.\n");
--                      /* Now, try to enable MSI-X interrupt mode */
--                      error = lpfc_enable_msix(phba);
--                      if (!error) {
--                              phba->intr_type = MSIX;
--                              lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
--                                              "0430 enable MSI-X mode.\n");
--                      }
--              }
--      }
--
--      /* Fallback to MSI if MSI-X initialization failed */
--      if (phba->cfg_use_msi >= 1 && phba->intr_type == NONE) {
--              retval = pci_enable_msi(phba->pcidev);
--              if (!retval) {
--                      phba->intr_type = MSI;
--                      lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
--                                      "0473 enable MSI mode.\n");
--              } else
--                      lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
--                                      "0452 enable IRQ mode.\n");
--      }
--
--      /* MSI-X is the only case the doesn't need to call request_irq */
--      if (phba->intr_type != MSIX) {
--              retval = request_irq(phba->pcidev->irq, lpfc_intr_handler,
--                                   IRQF_SHARED, LPFC_DRIVER_NAME, phba);
--              if (retval) {
--                      lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0451 Enable "
--                                      "interrupt handler failed\n");
--                      error = retval;
--                      goto out_disable_msi;
--              } else if (phba->intr_type != MSI)
--                      phba->intr_type = INTx;
-+      error = lpfc_enable_intr(phba);
-+      if (error) {
-+              lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-+                              "0426 Failed to enable interrupt.\n");
-+              goto out_destroy_port;
-       }
-       phba->dfc_host = lpfcdfc_host_add(pdev, shost, phba);
-@@ -2731,7 +2784,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
-       fc_host_post_vendor_event(shost, fc_get_event_number(),
-               sizeof(adapter_event),
-               (char *) &adapter_event,
--              SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
-+              LPFC_NL_VENDOR_ID);
-       scsi_scan_host(shost);
-@@ -2747,15 +2800,8 @@ out_free_irq:
-               lpfcdfc_host_del(phba->dfc_host);
-       lpfc_stop_phba_timers(phba);
-       phba->pport->work_port_events = 0;
--
--      if (phba->intr_type == MSIX)
--              lpfc_disable_msix(phba);
--      else
--              free_irq(phba->pcidev->irq, phba);
--
--out_disable_msi:
--      if (phba->intr_type == MSI)
--              pci_disable_msi(phba->pcidev);
-+      lpfc_disable_intr(phba);
-+out_destroy_port:
-       destroy_port(vport);
- out_kthread_stop:
-       kthread_stop(phba->worker_thread);
-@@ -2796,7 +2842,7 @@ out:
-  * @pdev: pointer to PCI device
-  *
-  * This routine is to be registered to the kernel's PCI subsystem. When an
-- * Emulex HBA is removed from PCI bus. It perform all the necessary cleanup
-+ * Emulex HBA is removed from PCI bus, it performs all the necessary cleanup
-  * for the HBA device to be removed from the PCI subsystem properly.
-  **/
- static void __devexit
-@@ -2804,12 +2850,11 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
- {
-       struct Scsi_Host  *shost = pci_get_drvdata(pdev);
-       struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
-+      struct lpfc_vport **vports;
-       struct lpfc_hba   *phba = vport->phba;
-+      int i;
-       int bars = pci_select_bars(pdev, IORESOURCE_MEM);
--      /* In case PCI channel permanently disabled, rescan SCSI devices */
--      if (pdev->error_state == pci_channel_io_perm_failure)
--              lpfc_scsi_dev_rescan(phba);
-       lpfcdfc_host_del(phba->dfc_host);
-       phba->dfc_host = NULL;
-@@ -2822,6 +2867,14 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
-       kthread_stop(phba->worker_thread);
-+      /* Release all the vports against this physical port */
-+      vports = lpfc_create_vport_work_array(phba);
-+      if (vports != NULL)
-+              for (i = 1; i <= phba->max_vpi && vports[i] != NULL; i++)
-+                      fc_vport_terminate(vports[i]->fc_vport);
-+      lpfc_destroy_vport_work_array(phba, vports);
-+
-+      /* Remove FC host and then SCSI host with the physical port */
-       fc_remove_host(shost);
-       scsi_remove_host(shost);
-       lpfc_cleanup(vport);
-@@ -2841,13 +2894,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
-       lpfc_debugfs_terminate(vport);
--      if (phba->intr_type == MSIX)
--              lpfc_disable_msix(phba);
--      else {
--              free_irq(phba->pcidev->irq, phba);
--              if (phba->intr_type == MSI)
--                      pci_disable_msi(phba->pcidev);
--      }
-+      /* Disable interrupt */
-+      lpfc_disable_intr(phba);
-       pci_set_drvdata(pdev, NULL);
-       scsi_host_put(shost);
-@@ -2879,6 +2927,111 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
- }
- /**
-+ * lpfc_pci_suspend_one: lpfc PCI func to suspend device for power management.
-+ * @pdev: pointer to PCI device
-+ * @msg: power management message
-+ *
-+ * This routine is to be registered to the kernel's PCI subsystem to support
-+ * system Power Management (PM). When PM invokes this method, it quiesces the
-+ * device by stopping the driver's worker thread for the device, turning off
-+ * device's interrupt and DMA, and bring the device offline. Note that as the
-+ * driver implements the minimum PM requirements to a power-aware driver's PM
-+ * support for suspend/resume -- all the possible PM messages (SUSPEND,
-+ * HIBERNATE, FREEZE) to the suspend() method call will be treated as SUSPEND
-+ * and the driver will fully reinitialize its device during resume() method
-+ * call, the driver will set device to PCI_D3hot state in PCI config space
-+ * instead of setting it according to the @msg provided by the PM.
-+ *
-+ * Return code
-+ *   0 - driver suspended the device
-+ *   Error otherwise
-+ **/
-+static int
-+lpfc_pci_suspend_one(struct pci_dev *pdev, pm_message_t msg)
-+{
-+      struct Scsi_Host *shost = pci_get_drvdata(pdev);
-+      struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
-+
-+      lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-+                      "0473 PCI device Power Management suspend.\n");
-+
-+      /* Bring down the device */
-+      lpfc_offline_prep(phba);
-+      lpfc_offline(phba);
-+      kthread_stop(phba->worker_thread);
-+
-+      /* Disable interrupt from device */
-+      lpfc_disable_intr(phba);
-+
-+      /* Save device state to PCI config space */
-+      pci_save_state(pdev);
-+      pci_set_power_state(pdev, PCI_D3hot);
-+
-+      return 0;
-+}
-+
-+/**
-+ * lpfc_pci_resume_one: lpfc PCI func to resume device for power management.
-+ * @pdev: pointer to PCI device
-+ *
-+ * This routine is to be registered to the kernel's PCI subsystem to support
-+ * system Power Management (PM). When PM invokes this method, it restores
-+ * the device's PCI config space state and fully reinitializes the device
-+ * and brings it online. Note that as the driver implements the minimum PM
-+ * requirements to a power-aware driver's PM for suspend/resume -- all
-+ * the possible PM messages (SUSPEND, HIBERNATE, FREEZE) to the suspend()
-+ * method call will be treated as SUSPEND and the driver will fully
-+ * reinitialize its device during resume() method call, the device will be
-+ * set to PCI_D0 directly in PCI config space before restoring the state.
-+ *
-+ * Return code
-+ *   0 - driver suspended the device
-+ *   Error otherwise
-+ **/
-+static int
-+lpfc_pci_resume_one(struct pci_dev *pdev)
-+{
-+      struct Scsi_Host *shost = pci_get_drvdata(pdev);
-+      struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
-+      int error;
-+
-+      lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-+                      "0452 PCI device Power Management resume.\n");
-+
-+      /* Restore device state from PCI config space */
-+      pci_set_power_state(pdev, PCI_D0);
-+      pci_restore_state(pdev);
-+      if (pdev->is_busmaster)
-+              pci_set_master(pdev);
-+
-+      /* Startup the kernel thread for this host adapter. */
-+      phba->worker_thread = kthread_run(lpfc_do_work, phba,
-+                                      "lpfc_worker_%d", phba->brd_no);
-+      if (IS_ERR(phba->worker_thread)) {
-+              error = PTR_ERR(phba->worker_thread);
-+              lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-+                              "0434 PM resume failed to start worker "
-+                              "thread: error=x%x.\n", error);
-+              return error;
-+      }
-+
-+      /* Enable interrupt from device */
-+      error = lpfc_enable_intr(phba);
-+      if (error) {
-+              lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-+                              "0430 PM resume Failed to enable interrupt: "
-+                              "error=x%x.\n", error);
-+              return error;
-+      }
-+
-+      /* Restart HBA and bring it online */
-+      lpfc_sli_brdrestart(phba);
-+      lpfc_online(phba);
-+
-+      return 0;
-+}
-+
-+/**
-  * lpfc_io_error_detected: Driver method for handling PCI I/O error detected.
-  * @pdev: pointer to PCI device.
-  * @state: the current PCI connection state.
-@@ -2921,13 +3074,8 @@ static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev,
-       pring = &psli->ring[psli->fcp_ring];
-       lpfc_sli_abort_iocb_ring(phba, pring);
--      if (phba->intr_type == MSIX)
--              lpfc_disable_msix(phba);
--      else {
--              free_irq(phba->pcidev->irq, phba);
--              if (phba->intr_type == MSI)
--                      pci_disable_msi(phba->pcidev);
--      }
-+      /* Disable interrupt */
-+      lpfc_disable_intr(phba);
-       /* Request a slot reset. */
-       return PCI_ERS_RESULT_NEED_RESET;
-@@ -2955,7 +3103,7 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
-       struct Scsi_Host *shost = pci_get_drvdata(pdev);
-       struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
-       struct lpfc_sli *psli = &phba->sli;
--      int error, retval;
-+      int error;
-       dev_printk(KERN_INFO, &pdev->dev, "recovering from a slot reset.\n");
-       if (pci_enable_device_mem(pdev)) {
-@@ -2971,48 +3119,12 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
-       spin_unlock_irq(&phba->hbalock);
-       /* Enable configured interrupt method */
--      phba->intr_type = NONE;
--      if (phba->cfg_use_msi == 2) {
--              /* Need to issue conf_port mbox cmd before conf_msi mbox cmd */
--              error = lpfc_sli_config_port(phba, 3);
--              if (error)
--                      lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
--                              "0478 Firmware not capable of SLI 3 mode.\n");
--              else {
--                      lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
--                              "0479 Firmware capable of SLI 3 mode.\n");
--                      /* Now, try to enable MSI-X interrupt mode */
--                      error = lpfc_enable_msix(phba);
--                      if (!error) {
--                              phba->intr_type = MSIX;
--                              lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
--                                              "0480 enable MSI-X mode.\n");
--                      }
--              }
--      }
--
--      /* Fallback to MSI if MSI-X initialization failed */
--      if (phba->cfg_use_msi >= 1 && phba->intr_type == NONE) {
--              retval = pci_enable_msi(phba->pcidev);
--              if (!retval) {
--                      phba->intr_type = MSI;
--                      lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
--                                      "0481 enable MSI mode.\n");
--              } else
--                      lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
--                                      "0470 enable IRQ mode.\n");
--      }
--
--      /* MSI-X is the only case the doesn't need to call request_irq */
--      if (phba->intr_type != MSIX) {
--              retval = request_irq(phba->pcidev->irq, lpfc_intr_handler,
--                                   IRQF_SHARED, LPFC_DRIVER_NAME, phba);
--              if (retval) {
--                      lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
--                                      "0471 Enable interrupt handler "
--                                      "failed\n");
--              } else if (phba->intr_type != MSI)
--                      phba->intr_type = INTx;
-+      error = lpfc_enable_intr(phba);
-+      if (error) {
-+              lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-+                              "0427 Cannot re-enable interrupt after "
-+                              "slot reset.\n");
-+              return PCI_ERS_RESULT_DISCONNECT;
-       }
-       /* Take device offline; this will perform cleanup */
-@@ -3130,6 +3242,8 @@ static struct pci_driver lpfc_driver = {
-       .id_table       = lpfc_id_table,
-       .probe          = lpfc_pci_probe_one,
-       .remove         = __devexit_p(lpfc_pci_remove_one),
-+      .suspend        = lpfc_pci_suspend_one,
-+      .resume         = lpfc_pci_resume_one,
-       .err_handler    = &lpfc_err_handler,
- };
-diff --git a/drivers/scsi/lpfc/lpfc_ioctl.c b/drivers/scsi/lpfc/lpfc_ioctl.c
-index 242bed3..e80d157 100644
---- a/drivers/scsi/lpfc/lpfc_ioctl.c
-+++ b/drivers/scsi/lpfc/lpfc_ioctl.c
-@@ -828,10 +828,10 @@ lpfc_ioctl_send_mgmt_cmd(struct lpfc_hba * phba,
-               rc = EIO;
- send_mgmt_cmd_free_outdmp:
--      spin_lock_irq(shost->host_lock);
-       dfc_cmd_data_free(phba, outdmp);
- send_mgmt_cmd_free_indmp:
-       dfc_cmd_data_free(phba, indmp);
-+      spin_lock_irq(shost->host_lock);
- send_mgmt_cmd_free_bmpvirt:
-       lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
- send_mgmt_cmd_free_bmp:
-@@ -2069,14 +2069,14 @@ __dfc_cmd_data_alloc(struct lpfc_hba * phba,
-                                       cnt)) {
-                                       goto out;
-                               }
--
-+                      bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64;
-                       pci_dma_sync_single_for_device(phba->pcidev,
-                               dmp->dma.phys, LPFC_BPL_SIZE, PCI_DMA_TODEVICE);
--              } else
-+              } else {
-                       memset((uint8_t *)dmp->dma.virt, 0, cnt);
--              bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64;
--
-+                      bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64I;
-+              }
-               /* build buffer ptr list for IOCB */
-               bpl->addrLow = le32_to_cpu(putPaddrLow(dmp->dma.phys));
-               bpl->addrHigh = le32_to_cpu(putPaddrHigh(dmp->dma.phys));
-diff --git a/drivers/scsi/lpfc/lpfc_menlo.c b/drivers/scsi/lpfc/lpfc_menlo.c
-index 60d3df8..aa36c16 100644
---- a/drivers/scsi/lpfc/lpfc_menlo.c
-+++ b/drivers/scsi/lpfc/lpfc_menlo.c
-@@ -42,6 +42,7 @@
- #include "lpfc_vport.h"
- #define MENLO_CMD_FW_DOWNLOAD                   0x00000002
-+#define MENLO_CMD_LOOPBACK                    0x00000014
- static void lpfc_menlo_iocb_timeout_cmpl(struct lpfc_hba *,
-                       struct lpfc_iocbq *, struct lpfc_iocbq *);
-@@ -686,6 +687,16 @@ lpfc_menlo_write(struct lpfc_hba *phba,
-               } else
-                       memcpy((uint8_t *) mlast->dma.virt, buf, count);
-+              if (sysfs_menlo->cmdhdr.cmd == MENLO_CMD_LOOPBACK) {
-+                      if (mlast) {
-+                              tmpptr = (uint32_t *)mlast->dma.virt;
-+                              if (*(tmpptr+2))
-+                                      phba->link_flag |= LS_LOOPBACK_MODE;
-+                              else
-+                                      phba->link_flag &= ~LS_LOOPBACK_MODE;
-+                      }
-+              }
-+
-               if (sysfs_menlo->cmdhdr.cmd == MENLO_CMD_FW_DOWNLOAD
-                       && genreq->offset < hdr_offset) {
-                       if (sysfs_menlo->cr.indmp
-diff --git a/drivers/scsi/lpfc/lpfc_nl.h b/drivers/scsi/lpfc/lpfc_nl.h
-index 1accb5a..991ad53 100644
---- a/drivers/scsi/lpfc/lpfc_nl.h
-+++ b/drivers/scsi/lpfc/lpfc_nl.h
-@@ -52,6 +52,13 @@
-  * The payload sent via the fc transport is one-way driver->application.
-  */
-+/* RSCN event header */
-+struct lpfc_rscn_event_header {
-+      uint32_t event_type;
-+      uint32_t payload_length; /* RSCN data length in bytes */
-+      uint32_t rscn_payload[];
-+};
-+
- /* els event header */
- struct lpfc_els_event_header {
-       uint32_t event_type;
-@@ -65,6 +72,7 @@ struct lpfc_els_event_header {
- #define LPFC_EVENT_PRLO_RCV           0x02
- #define LPFC_EVENT_ADISC_RCV          0x04
- #define LPFC_EVENT_LSRJT_RCV          0x08
-+#define LPFC_EVENT_LOGO_RCV           0x10
- /* special els lsrjt event */
- struct lpfc_lsrjt_event {
-@@ -74,6 +82,11 @@ struct lpfc_lsrjt_event {
-       uint32_t explanation;
- };
-+/* special els logo event */
-+struct lpfc_logo_event {
-+      struct lpfc_els_event_header header;
-+      uint8_t logo_wwpn[8];
-+};
- /* fabric event header */
- struct lpfc_fabric_event_header {
-@@ -125,6 +138,7 @@ struct lpfc_scsi_varqueuedepth_event {
- /* special case scsi check condition event */
- struct lpfc_scsi_check_condition_event {
-       struct lpfc_scsi_event_header scsi_event;
-+      uint8_t opcode;
-       uint8_t sense_key;
-       uint8_t asc;
-       uint8_t ascq;
-diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
-index a116875..a7ea952 100644
---- a/drivers/scsi/lpfc/lpfc_scsi.c
-+++ b/drivers/scsi/lpfc/lpfc_scsi.c
-@@ -147,12 +147,19 @@ lpfc_send_sdev_queuedepth_change_event(struct lpfc_hba *phba,
-       return;
- }
--/*
-- * This function is called with no lock held when there is a resource
-- * error in driver or in firmware.
-- */
-+/**
-+ * lpfc_rampdown_queue_depth: Post RAMP_DOWN_QUEUE event to worker thread.
-+ * @phba: The Hba for which this call is being executed.
-+ *
-+ * This routine is called when there is resource error in driver or firmware.
-+ * This routine posts WORKER_RAMP_DOWN_QUEUE event for @phba. This routine
-+ * posts at most 1 event each second. This routine wakes up worker thread of
-+ * @phba to process WORKER_RAM_DOWN_EVENT event.
-+ *
-+ * This routine should be called with no lock held.
-+ **/
- void
--lpfc_adjust_queue_depth(struct lpfc_hba *phba)
-+lpfc_rampdown_queue_depth(struct lpfc_hba *phba)
- {
-       unsigned long flags;
-       uint32_t evt_posted;
-@@ -335,22 +342,6 @@ lpfc_scsi_dev_block(struct lpfc_hba *phba)
-       lpfc_destroy_vport_work_array(phba, vports);
- }
--void
--lpfc_scsi_dev_rescan(struct lpfc_hba *phba)
--{
--      struct lpfc_vport **vports;
--      struct Scsi_Host  *shost;
--      int i;
--
--      vports = lpfc_create_vport_work_array(phba);
--      if (vports != NULL)
--              for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
--                      shost = lpfc_shost_from_vport(vports[i]);
--                      scsi_scan_host(shost);
--              }
--      lpfc_destroy_vport_work_array(phba, vports);
--}
--
- /*
-  * This routine allocates a scsi buffer, which contains all the necessary
-  * information needed to initiate a SCSI I/O.  The non-DMAable buffer region
-@@ -861,7 +852,8 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
-       lpfc_cmd->result = pIocbOut->iocb.un.ulpWord[4];
-       lpfc_cmd->status = pIocbOut->iocb.ulpStatus;
--      atomic_dec(&pnode->cmd_pending);
-+      if (pnode && NLP_CHK_NODE_ACT(pnode))
-+              atomic_dec(&pnode->cmd_pending);
-       if (lpfc_cmd->status) {
-               if (lpfc_cmd->status == IOSTAT_LOCAL_REJECT &&
-@@ -951,23 +943,31 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
-          time_after(jiffies, lpfc_cmd->start_time +
-               msecs_to_jiffies(vport->cfg_max_scsicmpl_time))) {
-               spin_lock_irqsave(sdev->host->host_lock, flags);
--              if ((pnode->cmd_qdepth > atomic_read(&pnode->cmd_pending) &&
--                  (atomic_read(&pnode->cmd_pending) > LPFC_MIN_TGT_QDEPTH) &&
--                  ((cmd->cmnd[0] == READ_10) || (cmd->cmnd[0] == WRITE_10))))
--                      pnode->cmd_qdepth = atomic_read(&pnode->cmd_pending);
--
--              pnode->last_change_time = jiffies;
-+              if (pnode && NLP_CHK_NODE_ACT(pnode)) {
-+                      if (pnode->cmd_qdepth >
-+                              atomic_read(&pnode->cmd_pending) &&
-+                              (atomic_read(&pnode->cmd_pending) >
-+                              LPFC_MIN_TGT_QDEPTH) &&
-+                              ((cmd->cmnd[0] == READ_10) ||
-+                              (cmd->cmnd[0] == WRITE_10)))
-+                              pnode->cmd_qdepth =
-+                                      atomic_read(&pnode->cmd_pending);
-+
-+                      pnode->last_change_time = jiffies;
-+              }
-               spin_unlock_irqrestore(sdev->host->host_lock, flags);
--      } else if ((pnode->cmd_qdepth < LPFC_MAX_TGT_QDEPTH) &&
-+      } else if (pnode && NLP_CHK_NODE_ACT(pnode)) {
-+              if ((pnode->cmd_qdepth < LPFC_MAX_TGT_QDEPTH) &&
-                  time_after(jiffies, pnode->last_change_time +
--                      msecs_to_jiffies(LPFC_TGTQ_INTERVAL))) {
--              spin_lock_irqsave(sdev->host->host_lock, flags);
--              pnode->cmd_qdepth += pnode->cmd_qdepth *
--                      LPFC_TGTQ_RAMPUP_PCENT / 100;
--              if (pnode->cmd_qdepth > LPFC_MAX_TGT_QDEPTH)
--                      pnode->cmd_qdepth = LPFC_MAX_TGT_QDEPTH;
--              pnode->last_change_time = jiffies;
--              spin_unlock_irqrestore(sdev->host->host_lock, flags);
-+                            msecs_to_jiffies(LPFC_TGTQ_INTERVAL))) {
-+                      spin_lock_irqsave(sdev->host->host_lock, flags);
-+                      pnode->cmd_qdepth += pnode->cmd_qdepth *
-+                              LPFC_TGTQ_RAMPUP_PCENT / 100;
-+                      if (pnode->cmd_qdepth > LPFC_MAX_TGT_QDEPTH)
-+                              pnode->cmd_qdepth = LPFC_MAX_TGT_QDEPTH;
-+                      pnode->last_change_time = jiffies;
-+                      spin_unlock_irqrestore(sdev->host->host_lock, flags);
-+              }
-       }
-       lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
-@@ -1363,13 +1363,13 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
-               cmnd->result = ScsiResult(DID_TRANSPORT_DISRUPTED, 0);
-               goto out_fail_command;
-       }
--
--      if (atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth)
-+      if (vport->cfg_max_scsicmpl_time &&
-+              (atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth))
-               goto out_host_busy;
-       lpfc_cmd = lpfc_get_scsi_buf(phba);
-       if (lpfc_cmd == NULL) {
--              lpfc_adjust_queue_depth(phba);
-+              lpfc_rampdown_queue_depth(phba);
-               lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
-                                "0707 driver's buffer pool is empty, "
-@@ -1397,9 +1397,10 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
-       atomic_inc(&ndlp->cmd_pending);
-       err = lpfc_sli_issue_iocb(phba, &phba->sli.ring[psli->fcp_ring],
-                                 &lpfc_cmd->cur_iocbq, SLI_IOCB_RET_IOCB);
--      if (err)
-+      if (err) {
-+              atomic_dec(&ndlp->cmd_pending);
-               goto out_host_busy_free_buf;
--
-+      }
-       if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
-               lpfc_sli_poll_fcp_ring(phba);
-               if (phba->cfg_poll & DISABLE_FCP_RING_INT)
-@@ -1409,7 +1410,6 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
-       return 0;
-  out_host_busy_free_buf:
--      atomic_dec(&ndlp->cmd_pending);
-       lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
-       lpfc_release_scsi_buf(phba, lpfc_cmd);
-  out_host_busy:
-@@ -1575,7 +1575,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
-               fc_get_event_number(),
-               sizeof(scsi_event),
-               (char *)&scsi_event,
--              SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
-+              LPFC_NL_VENDOR_ID);
-       if (!rdata || pnode->nlp_state != NLP_STE_MAPPED_NODE) {
-               lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP,
-@@ -1672,7 +1672,7 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
-               fc_get_event_number(),
-               sizeof(scsi_event),
-               (char *)&scsi_event,
--              SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
-+              LPFC_NL_VENDOR_ID);
-       lpfc_block_error_handler(cmnd);
-       /*
-diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
-index d4341df..ac78493 100644
---- a/drivers/scsi/lpfc/lpfc_sli.c
-+++ b/drivers/scsi/lpfc/lpfc_sli.c
-@@ -1985,7 +1985,7 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba,
-                       if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
-                               (irsp->un.ulpWord[4] == IOERR_NO_RESOURCES)) {
-                               spin_unlock_irqrestore(&phba->hbalock, iflag);
--                              lpfc_adjust_queue_depth(phba);
-+                              lpfc_rampdown_queue_depth(phba);
-                               spin_lock_irqsave(&phba->hbalock, iflag);
-                       }
-@@ -2228,7 +2228,7 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba,
-                       if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
-                            (irsp->un.ulpWord[4] == IOERR_NO_RESOURCES)) {
-                               spin_unlock_irqrestore(&phba->hbalock, iflag);
--                              lpfc_adjust_queue_depth(phba);
-+                              lpfc_rampdown_queue_depth(phba);
-                               spin_lock_irqsave(&phba->hbalock, iflag);
-                       }
-@@ -2793,7 +2793,6 @@ lpfc_sli_brdrestart(struct lpfc_hba *phba)
- {
-       MAILBOX_t *mb;
-       struct lpfc_sli *psli;
--      uint16_t skip_post;
-       volatile uint32_t word0;
-       void __iomem *to_slim;
-@@ -2818,13 +2817,10 @@ lpfc_sli_brdrestart(struct lpfc_hba *phba)
-       readl(to_slim); /* flush */
-       /* Only skip post after fc_ffinit is completed */
--      if (phba->pport->port_state) {
--              skip_post = 1;
-+      if (phba->pport->port_state)
-               word0 = 1;      /* This is really setting up word1 */
--      } else {
--              skip_post = 0;
-+      else
-               word0 = 0;      /* This is really setting up word1 */
--      }
-       to_slim = phba->MBslimaddr + sizeof (uint32_t);
-       writel(*(uint32_t *) mb, to_slim);
-       readl(to_slim); /* flush */
-@@ -2838,10 +2834,8 @@ lpfc_sli_brdrestart(struct lpfc_hba *phba)
-       memset(&psli->lnk_stat_offsets, 0, sizeof(psli->lnk_stat_offsets));
-       psli->stats_start = get_seconds();
--      if (skip_post)
--              mdelay(100);
--      else
--              mdelay(2000);
-+      /* Give the INITFF and Post time to settle. */
-+      mdelay(100);
-       lpfc_hba_down_post(phba);
-@@ -3087,7 +3081,6 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode)
-               spin_unlock_irq(&phba->hbalock);
-               phba->pport->port_state = LPFC_VPORT_UNKNOWN;
-               lpfc_sli_brdrestart(phba);
--              msleep(2500);
-               rc = lpfc_sli_chipset_init(phba);
-               if (rc)
-                       break;
-@@ -4041,7 +4034,7 @@ lpfc_sli_async_event_handler(struct lpfc_hba * phba,
-       shost = lpfc_shost_from_vport(phba->pport);
-       fc_host_post_vendor_event(shost, fc_get_event_number(),
-               sizeof(temp_event_data), (char *) &temp_event_data,
--              SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
-+              LPFC_NL_VENDOR_ID);
- }
-@@ -5220,6 +5213,10 @@ lpfc_sli_check_eratt(struct lpfc_hba *phba)
- {
-       uint32_t ha_copy;
-+      /* If PCI channel is offline, don't process it */
-+      if (unlikely(pci_channel_offline(phba->pcidev)))
-+              return 0;
-+
-       /* If somebody is waiting to handle an eratt, don't process it
-        * here. The brdkill function will do this.
-        */
-diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
-index 899a337..a42cef2 100644
---- a/drivers/scsi/lpfc/lpfc_version.h
-+++ b/drivers/scsi/lpfc/lpfc_version.h
-@@ -18,7 +18,7 @@
-  * included with this package.                                     *
-  *******************************************************************/
--#define LPFC_DRIVER_VERSION "8.2.8.1"
-+#define LPFC_DRIVER_VERSION "8.2.8.3"
- #define LPFC_DRIVER_NAME              "lpfc"
- #define LPFC_SP_DRIVER_HANDLER_NAME   "lpfc:sp"
-diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c
-index 8761840..c3a3f6e 100644
---- a/drivers/scsi/lpfc/lpfc_vport.c
-+++ b/drivers/scsi/lpfc/lpfc_vport.c
-@@ -605,6 +605,8 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
-       spin_unlock_irq(&phba->hbalock);
-       kfree(vport->vname);
-       lpfc_debugfs_terminate(vport);
-+
-+      /* Remove FC host and then SCSI host with the vport */
-       fc_remove_host(lpfc_shost_from_vport(vport));
-       scsi_remove_host(lpfc_shost_from_vport(vport));
-@@ -689,8 +691,6 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
-               }
-               vport->unreg_vpi_cmpl = VPORT_INVAL;
-               timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
--              if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
--                      goto skip_logo;
-               if (!lpfc_issue_els_npiv_logo(vport, ndlp))
-                       while (vport->unreg_vpi_cmpl == VPORT_INVAL && timeout)
-                               timeout = schedule_timeout(timeout);