[SCSI] qla2xxx: Wrong PCIe(2.5Gb/s x8) speed in the kerenel message for ISP82xx.
[deliverable/linux.git] / drivers / scsi / qla2xxx / qla_init.c
index a44653b421612dcb35a302cc74a2ef64b689dd1a..117338da605385075d63794befa94798172a6878 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2011 QLogic Corporation
+ * Copyright (c)  2003-2012 QLogic Corporation
  *
  * See LICENSE.qla2xxx for copyright and licensing details.
  */
@@ -77,7 +77,7 @@ qla2x00_sp_free(void *data, void *ptr)
 
 /* Asynchronous Login/Logout Routines -------------------------------------- */
 
-static inline unsigned long
+unsigned long
 qla2x00_get_async_timeout(struct scsi_qla_host *vha)
 {
        unsigned long tmo;
@@ -429,6 +429,71 @@ qla2x00_async_adisc_done(struct scsi_qla_host *vha, fc_port_t *fcport,
 /*                QLogic ISP2x00 Hardware Support Functions.                */
 /****************************************************************************/
 
+int
+qla83xx_nic_core_fw_load(scsi_qla_host_t *vha)
+{
+       int rval = QLA_SUCCESS;
+       struct qla_hw_data *ha = vha->hw;
+       uint32_t idc_major_ver, idc_minor_ver;
+
+       qla83xx_idc_lock(vha, 0);
+
+       /* SV: TODO: Assign initialization timeout from
+        * flash-info / other param
+        */
+       ha->fcoe_dev_init_timeout = QLA83XX_IDC_INITIALIZATION_TIMEOUT;
+       ha->fcoe_reset_timeout = QLA83XX_IDC_RESET_ACK_TIMEOUT;
+
+       /* Set our fcoe function presence */
+       if (__qla83xx_set_drv_presence(vha) != QLA_SUCCESS) {
+               ql_dbg(ql_dbg_p3p, vha, 0xb077,
+                   "Error while setting DRV-Presence.\n");
+               rval = QLA_FUNCTION_FAILED;
+               goto exit;
+       }
+
+       /* Decide the reset ownership */
+       qla83xx_reset_ownership(vha);
+
+       /*
+        * On first protocol driver load:
+        * Init-Owner: Set IDC-Major-Version and Clear IDC-Lock-Recovery
+        * register.
+        * Others: Check compatibility with current IDC Major version.
+        */
+       qla83xx_rd_reg(vha, QLA83XX_IDC_MAJOR_VERSION, &idc_major_ver);
+       if (ha->flags.nic_core_reset_owner) {
+               /* Set IDC Major version */
+               idc_major_ver = QLA83XX_SUPP_IDC_MAJOR_VERSION;
+               qla83xx_wr_reg(vha, QLA83XX_IDC_MAJOR_VERSION, idc_major_ver);
+
+               /* Clearing IDC-Lock-Recovery register */
+               qla83xx_wr_reg(vha, QLA83XX_IDC_LOCK_RECOVERY, 0);
+       } else if (idc_major_ver != QLA83XX_SUPP_IDC_MAJOR_VERSION) {
+               /*
+                * Clear further IDC participation if we are not compatible with
+                * the current IDC Major Version.
+                */
+               ql_log(ql_log_warn, vha, 0xb07d,
+                   "Failing load, idc_major_ver=%d, expected_major_ver=%d.\n",
+                   idc_major_ver, QLA83XX_SUPP_IDC_MAJOR_VERSION);
+               __qla83xx_clear_drv_presence(vha);
+               rval = QLA_FUNCTION_FAILED;
+               goto exit;
+       }
+       /* Each function sets its supported Minor version. */
+       qla83xx_rd_reg(vha, QLA83XX_IDC_MINOR_VERSION, &idc_minor_ver);
+       idc_minor_ver |= (QLA83XX_SUPP_IDC_MINOR_VERSION << (ha->portnum * 2));
+       qla83xx_wr_reg(vha, QLA83XX_IDC_MINOR_VERSION, idc_minor_ver);
+
+       rval = qla83xx_idc_state_handler(vha);
+
+exit:
+       qla83xx_idc_unlock(vha, 0);
+
+       return rval;
+}
+
 /*
 * qla2x00_initialize_adapter
 *      Initialize board.
@@ -537,6 +602,14 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
                }
        }
 
+       /* Load the NIC Core f/w if we are the first protocol driver. */
+       if (IS_QLA8031(ha)) {
+               rval = qla83xx_nic_core_fw_load(vha);
+               if (rval)
+                       ql_log(ql_log_warn, vha, 0x0124,
+                           "Error in initializing NIC Core f/w.\n");
+       }
+
        if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha))
                qla24xx_read_fcp_prio_cfg(vha);
 
@@ -2753,6 +2826,8 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
                if (loop_id > LAST_LOCAL_LOOP_ID)
                        continue;
 
+               memset(new_fcport, 0, sizeof(fc_port_t));
+
                /* Fill in member data. */
                new_fcport->d_id.b.domain = domain;
                new_fcport->d_id.b.area = area;
@@ -3285,7 +3360,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
                         */
                        if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) {
                                fcport->d_id.b24 = new_fcport->d_id.b24;
-                               fcport->loop_id = FC_NO_LOOP_ID;
+                               qla2x00_clear_loop_id(fcport);
                                fcport->flags |= (FCF_FABRIC_DEVICE |
                                    FCF_LOGIN_NEEDED);
                                break;
@@ -3306,7 +3381,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
                                ha->isp_ops->fabric_logout(vha, fcport->loop_id,
                                    fcport->d_id.b.domain, fcport->d_id.b.area,
                                    fcport->d_id.b.al_pa);
-                               fcport->loop_id = FC_NO_LOOP_ID;
+                               qla2x00_clear_loop_id(fcport);
                        }
 
                        break;
@@ -3352,71 +3427,32 @@ int
 qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev)
 {
        int     rval;
-       int     found;
-       fc_port_t *fcport;
-       uint16_t first_loop_id;
        struct qla_hw_data *ha = vha->hw;
-       struct scsi_qla_host *vp;
-       struct scsi_qla_host *tvp;
        unsigned long flags = 0;
 
        rval = QLA_SUCCESS;
 
-       /* Save starting loop ID. */
-       first_loop_id = dev->loop_id;
-
-       for (;;) {
-               /* Skip loop ID if already used by adapter. */
-               if (dev->loop_id == vha->loop_id)
-                       dev->loop_id++;
-
-               /* Skip reserved loop IDs. */
-               while (qla2x00_is_reserved_id(vha, dev->loop_id))
-                       dev->loop_id++;
-
-               /* Reset loop ID if passed the end. */
-               if (dev->loop_id > ha->max_loop_id) {
-                       /* first loop ID. */
-                       dev->loop_id = ha->min_external_loopid;
-               }
-
-               /* Check for loop ID being already in use. */
-               found = 0;
-               fcport = NULL;
-
-               spin_lock_irqsave(&ha->vport_slock, flags);
-               list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
-                       list_for_each_entry(fcport, &vp->vp_fcports, list) {
-                               if (fcport->loop_id == dev->loop_id &&
-                                                               fcport != dev) {
-                                       /* ID possibly in use */
-                                       found++;
-                                       break;
-                               }
-                       }
-                       if (found)
-                               break;
-               }
-               spin_unlock_irqrestore(&ha->vport_slock, flags);
+       spin_lock_irqsave(&ha->vport_slock, flags);
 
-               /* If not in use then it is free to use. */
-               if (!found) {
-                       ql_dbg(ql_dbg_disc, dev->vha, 0x2086,
-                           "Assigning new loopid=%x, portid=%x.\n",
-                           dev->loop_id, dev->d_id.b24);
-                       break;
-               }
+       dev->loop_id = find_first_zero_bit(ha->loop_id_map,
+           LOOPID_MAP_SIZE);
+       if (dev->loop_id >= LOOPID_MAP_SIZE ||
+           qla2x00_is_reserved_id(vha, dev->loop_id)) {
+               dev->loop_id = FC_NO_LOOP_ID;
+               rval = QLA_FUNCTION_FAILED;
+       } else
+               set_bit(dev->loop_id, ha->loop_id_map);
 
-               /* ID in use. Try next value. */
-               dev->loop_id++;
+       spin_unlock_irqrestore(&ha->vport_slock, flags);
 
-               /* If wrap around. No free ID to use. */
-               if (dev->loop_id == first_loop_id) {
-                       dev->loop_id = FC_NO_LOOP_ID;
-                       rval = QLA_FUNCTION_FAILED;
-                       break;
-               }
-       }
+       if (rval == QLA_SUCCESS)
+               ql_dbg(ql_dbg_disc, dev->vha, 0x2086,
+                   "Assigning new loopid=%x, portid=%x.\n",
+                   dev->loop_id, dev->d_id.b24);
+       else
+               ql_log(ql_log_warn, dev->vha, 0x2087,
+                   "No loop_id's available, portid=%x.\n",
+                   dev->d_id.b24);
 
        return (rval);
 }
@@ -3616,7 +3652,7 @@ qla2x00_fabric_login(scsi_qla_host_t *vha, fc_port_t *fcport,
                        ha->isp_ops->fabric_logout(vha, fcport->loop_id,
                            fcport->d_id.b.domain, fcport->d_id.b.area,
                            fcport->d_id.b.al_pa);
-                       fcport->loop_id = FC_NO_LOOP_ID;
+                       qla2x00_clear_loop_id(fcport);
                        fcport->login_retry = 0;
 
                        rval = 3;
@@ -3775,8 +3811,363 @@ qla2x00_update_fcports(scsi_qla_host_t *base_vha)
        spin_unlock_irqrestore(&ha->vport_slock, flags);
 }
 
+/* Assumes idc_lock always held on entry */
+void
+qla83xx_reset_ownership(scsi_qla_host_t *vha)
+{
+       struct qla_hw_data *ha = vha->hw;
+       uint32_t drv_presence, drv_presence_mask;
+       uint32_t dev_part_info1, dev_part_info2, class_type;
+       uint32_t class_type_mask = 0x3;
+       uint16_t fcoe_other_function = 0xffff, i;
+
+       qla83xx_rd_reg(vha, QLA83XX_IDC_DRV_PRESENCE, &drv_presence);
+
+       qla83xx_rd_reg(vha, QLA83XX_DEV_PARTINFO1, &dev_part_info1);
+       qla83xx_rd_reg(vha, QLA83XX_DEV_PARTINFO2, &dev_part_info2);
+       for (i = 0; i < 8; i++) {
+               class_type = ((dev_part_info1 >> (i * 4)) & class_type_mask);
+               if ((class_type == QLA83XX_CLASS_TYPE_FCOE) &&
+                   (i != ha->portnum)) {
+                       fcoe_other_function = i;
+                       break;
+               }
+       }
+       if (fcoe_other_function == 0xffff) {
+               for (i = 0; i < 8; i++) {
+                       class_type = ((dev_part_info2 >> (i * 4)) &
+                           class_type_mask);
+                       if ((class_type == QLA83XX_CLASS_TYPE_FCOE) &&
+                           ((i + 8) != ha->portnum)) {
+                               fcoe_other_function = i + 8;
+                               break;
+                       }
+               }
+       }
+       /*
+        * Prepare drv-presence mask based on fcoe functions present.
+        * However consider only valid physical fcoe function numbers (0-15).
+        */
+       drv_presence_mask = ~((1 << (ha->portnum)) |
+                       ((fcoe_other_function == 0xffff) ?
+                        0 : (1 << (fcoe_other_function))));
+
+       /* We are the reset owner iff:
+        *    - No other protocol drivers present.
+        *    - This is the lowest among fcoe functions. */
+       if (!(drv_presence & drv_presence_mask) &&
+                       (ha->portnum < fcoe_other_function)) {
+               ql_dbg(ql_dbg_p3p, vha, 0xb07f,
+                   "This host is Reset owner.\n");
+               ha->flags.nic_core_reset_owner = 1;
+       }
+}
+
+int
+__qla83xx_set_drv_ack(scsi_qla_host_t *vha)
+{
+       int rval = QLA_SUCCESS;
+       struct qla_hw_data *ha = vha->hw;
+       uint32_t drv_ack;
+
+       rval = qla83xx_rd_reg(vha, QLA83XX_IDC_DRIVER_ACK, &drv_ack);
+       if (rval == QLA_SUCCESS) {
+               drv_ack |= (1 << ha->portnum);
+               rval = qla83xx_wr_reg(vha, QLA83XX_IDC_DRIVER_ACK, drv_ack);
+       }
+
+       return rval;
+}
+
+int
+qla83xx_set_drv_ack(scsi_qla_host_t *vha)
+{
+       int rval = QLA_SUCCESS;
+
+       qla83xx_idc_lock(vha, 0);
+       rval = __qla83xx_set_drv_ack(vha);
+       qla83xx_idc_unlock(vha, 0);
+
+       return rval;
+}
+
+int
+__qla83xx_clear_drv_ack(scsi_qla_host_t *vha)
+{
+       int rval = QLA_SUCCESS;
+       struct qla_hw_data *ha = vha->hw;
+       uint32_t drv_ack;
+
+       rval = qla83xx_rd_reg(vha, QLA83XX_IDC_DRIVER_ACK, &drv_ack);
+       if (rval == QLA_SUCCESS) {
+               drv_ack &= ~(1 << ha->portnum);
+               rval = qla83xx_wr_reg(vha, QLA83XX_IDC_DRIVER_ACK, drv_ack);
+       }
+
+       return rval;
+}
+
+int
+qla83xx_clear_drv_ack(scsi_qla_host_t *vha)
+{
+       int rval = QLA_SUCCESS;
+
+       qla83xx_idc_lock(vha, 0);
+       rval = __qla83xx_clear_drv_ack(vha);
+       qla83xx_idc_unlock(vha, 0);
+
+       return rval;
+}
+
+const char *
+qla83xx_dev_state_to_string(uint32_t dev_state)
+{
+       switch (dev_state) {
+       case QLA8XXX_DEV_COLD:
+               return "COLD/RE-INIT";
+       case QLA8XXX_DEV_INITIALIZING:
+               return "INITIALIZING";
+       case QLA8XXX_DEV_READY:
+               return "READY";
+       case QLA8XXX_DEV_NEED_RESET:
+               return "NEED RESET";
+       case QLA8XXX_DEV_NEED_QUIESCENT:
+               return "NEED QUIESCENT";
+       case QLA8XXX_DEV_FAILED:
+               return "FAILED";
+       case QLA8XXX_DEV_QUIESCENT:
+               return "QUIESCENT";
+       default:
+               return "Unknown";
+       }
+}
+
+/* Assumes idc-lock always held on entry */
+void
+qla83xx_idc_audit(scsi_qla_host_t *vha, int audit_type)
+{
+       struct qla_hw_data *ha = vha->hw;
+       uint32_t idc_audit_reg = 0, duration_secs = 0;
+
+       switch (audit_type) {
+       case IDC_AUDIT_TIMESTAMP:
+               ha->idc_audit_ts = (jiffies_to_msecs(jiffies) / 1000);
+               idc_audit_reg = (ha->portnum) |
+                   (IDC_AUDIT_TIMESTAMP << 7) | (ha->idc_audit_ts << 8);
+               qla83xx_wr_reg(vha, QLA83XX_IDC_AUDIT, idc_audit_reg);
+               break;
+
+       case IDC_AUDIT_COMPLETION:
+               duration_secs = ((jiffies_to_msecs(jiffies) -
+                   jiffies_to_msecs(ha->idc_audit_ts)) / 1000);
+               idc_audit_reg = (ha->portnum) |
+                   (IDC_AUDIT_COMPLETION << 7) | (duration_secs << 8);
+               qla83xx_wr_reg(vha, QLA83XX_IDC_AUDIT, idc_audit_reg);
+               break;
+
+       default:
+               ql_log(ql_log_warn, vha, 0xb078,
+                   "Invalid audit type specified.\n");
+               break;
+       }
+}
+
+/* Assumes idc_lock always held on entry */
+int
+qla83xx_initiating_reset(scsi_qla_host_t *vha)
+{
+       struct qla_hw_data *ha = vha->hw;
+       uint32_t  idc_control, dev_state;
+
+       __qla83xx_get_idc_control(vha, &idc_control);
+       if ((idc_control & QLA83XX_IDC_RESET_DISABLED)) {
+               ql_log(ql_log_info, vha, 0xb080,
+                   "NIC Core reset has been disabled. idc-control=0x%x\n",
+                   idc_control);
+               return QLA_FUNCTION_FAILED;
+       }
+
+       /* Set NEED-RESET iff in READY state and we are the reset-owner */
+       qla83xx_rd_reg(vha, QLA83XX_IDC_DEV_STATE, &dev_state);
+       if (ha->flags.nic_core_reset_owner && dev_state == QLA8XXX_DEV_READY) {
+               qla83xx_wr_reg(vha, QLA83XX_IDC_DEV_STATE,
+                   QLA8XXX_DEV_NEED_RESET);
+               ql_log(ql_log_info, vha, 0xb056, "HW State: NEED RESET.\n");
+               qla83xx_idc_audit(vha, IDC_AUDIT_TIMESTAMP);
+       } else {
+               const char *state = qla83xx_dev_state_to_string(dev_state);
+               ql_log(ql_log_info, vha, 0xb057, "HW State: %s.\n", state);
+
+               /* SV: XXX: Is timeout required here? */
+               /* Wait for IDC state change READY -> NEED_RESET */
+               while (dev_state == QLA8XXX_DEV_READY) {
+                       qla83xx_idc_unlock(vha, 0);
+                       msleep(200);
+                       qla83xx_idc_lock(vha, 0);
+                       qla83xx_rd_reg(vha, QLA83XX_IDC_DEV_STATE, &dev_state);
+               }
+       }
+
+       /* Send IDC ack by writing to drv-ack register */
+       __qla83xx_set_drv_ack(vha);
+
+       return QLA_SUCCESS;
+}
+
+int
+__qla83xx_set_idc_control(scsi_qla_host_t *vha, uint32_t idc_control)
+{
+       return qla83xx_wr_reg(vha, QLA83XX_IDC_CONTROL, idc_control);
+}
+
+int
+qla83xx_set_idc_control(scsi_qla_host_t *vha, uint32_t idc_control)
+{
+       int rval = QLA_SUCCESS;
+
+       qla83xx_idc_lock(vha, 0);
+       rval = __qla83xx_set_idc_control(vha, idc_control);
+       qla83xx_idc_unlock(vha, 0);
+
+       return rval;
+}
+
+int
+__qla83xx_get_idc_control(scsi_qla_host_t *vha, uint32_t *idc_control)
+{
+       return qla83xx_rd_reg(vha, QLA83XX_IDC_CONTROL, idc_control);
+}
+
+int
+qla83xx_get_idc_control(scsi_qla_host_t *vha, uint32_t *idc_control)
+{
+       int rval = QLA_SUCCESS;
+
+       qla83xx_idc_lock(vha, 0);
+       rval = __qla83xx_get_idc_control(vha, idc_control);
+       qla83xx_idc_unlock(vha, 0);
+
+       return rval;
+}
+
+int
+qla83xx_check_driver_presence(scsi_qla_host_t *vha)
+{
+       uint32_t drv_presence = 0;
+       struct qla_hw_data *ha = vha->hw;
+
+       qla83xx_rd_reg(vha, QLA83XX_IDC_DRV_PRESENCE, &drv_presence);
+       if (drv_presence & (1 << ha->portnum))
+               return QLA_SUCCESS;
+       else
+               return QLA_TEST_FAILED;
+}
+
+int
+qla83xx_nic_core_reset(scsi_qla_host_t *vha)
+{
+       int rval = QLA_SUCCESS;
+       struct qla_hw_data *ha = vha->hw;
+
+       ql_dbg(ql_dbg_p3p, vha, 0xb058,
+           "Entered  %s().\n", __func__);
+
+       if (vha->device_flags & DFLG_DEV_FAILED) {
+               ql_log(ql_log_warn, vha, 0xb059,
+                   "Device in unrecoverable FAILED state.\n");
+               return QLA_FUNCTION_FAILED;
+       }
+
+       qla83xx_idc_lock(vha, 0);
+
+       if (qla83xx_check_driver_presence(vha) != QLA_SUCCESS) {
+               ql_log(ql_log_warn, vha, 0xb05a,
+                   "Function=0x%x has been removed from IDC participation.\n",
+                   ha->portnum);
+               rval = QLA_FUNCTION_FAILED;
+               goto exit;
+       }
+
+       qla83xx_reset_ownership(vha);
+
+       rval = qla83xx_initiating_reset(vha);
+
+       /*
+        * Perform reset if we are the reset-owner,
+        * else wait till IDC state changes to READY/FAILED.
+        */
+       if (rval == QLA_SUCCESS) {
+               rval = qla83xx_idc_state_handler(vha);
+
+               if (rval == QLA_SUCCESS)
+                       ha->flags.nic_core_hung = 0;
+               __qla83xx_clear_drv_ack(vha);
+       }
+
+exit:
+       qla83xx_idc_unlock(vha, 0);
+
+       ql_dbg(ql_dbg_p3p, vha, 0xb05b, "Exiting %s.\n", __func__);
+
+       return rval;
+}
+
+int
+qla2xxx_mctp_dump(scsi_qla_host_t *vha)
+{
+       struct qla_hw_data *ha = vha->hw;
+       int rval = QLA_FUNCTION_FAILED;
+
+       if (!IS_MCTP_CAPABLE(ha)) {
+               /* This message can be removed from the final version */
+               ql_log(ql_log_info, vha, 0x506d,
+                   "This board is not MCTP capable\n");
+               return rval;
+       }
+
+       if (!ha->mctp_dump) {
+               ha->mctp_dump = dma_alloc_coherent(&ha->pdev->dev,
+                   MCTP_DUMP_SIZE, &ha->mctp_dump_dma, GFP_KERNEL);
+
+               if (!ha->mctp_dump) {
+                       ql_log(ql_log_warn, vha, 0x506e,
+                           "Failed to allocate memory for mctp dump\n");
+                       return rval;
+               }
+       }
+
+#define MCTP_DUMP_STR_ADDR     0x00000000
+       rval = qla2x00_dump_mctp_data(vha, ha->mctp_dump_dma,
+           MCTP_DUMP_STR_ADDR, MCTP_DUMP_SIZE/4);
+       if (rval != QLA_SUCCESS) {
+               ql_log(ql_log_warn, vha, 0x506f,
+                   "Failed to capture mctp dump\n");
+       } else {
+               ql_log(ql_log_info, vha, 0x5070,
+                   "Mctp dump capture for host (%ld/%p).\n",
+                   vha->host_no, ha->mctp_dump);
+               ha->mctp_dumped = 1;
+       }
+
+       if (!ha->flags.nic_core_reset_hdlr_active) {
+               ha->flags.nic_core_reset_hdlr_active = 1;
+               rval = qla83xx_restart_nic_firmware(vha);
+               if (rval)
+                       /* NIC Core reset failed. */
+                       ql_log(ql_log_warn, vha, 0x5071,
+                           "Failed to restart nic firmware\n");
+               else
+                       ql_dbg(ql_dbg_p3p, vha, 0xb084,
+                           "Restarted NIC firmware successfully.\n");
+               ha->flags.nic_core_reset_hdlr_active = 0;
+       }
+
+       return rval;
+
+}
+
 /*
-* qla82xx_quiescent_state_cleanup
+* qla2x00_quiesce_io
 * Description: This function will block the new I/Os
 *              Its not aborting any I/Os as context
 *              is not destroyed during quiescence
@@ -3784,20 +4175,20 @@ qla2x00_update_fcports(scsi_qla_host_t *base_vha)
 * return   : void
 */
 void
-qla82xx_quiescent_state_cleanup(scsi_qla_host_t *vha)
+qla2x00_quiesce_io(scsi_qla_host_t *vha)
 {
        struct qla_hw_data *ha = vha->hw;
        struct scsi_qla_host *vp;
 
-       ql_dbg(ql_dbg_p3p, vha, 0xb002,
-           "Performing ISP error recovery - ha=%p.\n", ha);
+       ql_dbg(ql_dbg_dpc, vha, 0x401d,
+           "Quiescing I/O - ha=%p.\n", ha);
 
        atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
        if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
                atomic_set(&vha->loop_state, LOOP_DOWN);
                qla2x00_mark_all_devices_lost(vha, 0);
                list_for_each_entry(vp, &ha->vp_list, list)
-                       qla2x00_mark_all_devices_lost(vha, 0);
+                       qla2x00_mark_all_devices_lost(vp, 0);
        } else {
                if (!atomic_read(&vha->loop_down_timer))
                        atomic_set(&vha->loop_down_timer,
@@ -3913,6 +4304,14 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
        if (vha->flags.online) {
                qla2x00_abort_isp_cleanup(vha);
 
+               if (IS_QLA8031(ha)) {
+                       ql_dbg(ql_dbg_p3p, vha, 0xb05c,
+                           "Clearing fcoe driver presence.\n");
+                       if (qla83xx_clear_drv_presence(vha) != QLA_SUCCESS)
+                               ql_dbg(ql_dbg_p3p, vha, 0xb073,
+                                   "Error while clearing DRV-Presence.\n");
+               }
+
                if (unlikely(pci_channel_offline(ha->pdev) &&
                    ha->flags.pci_channel_io_perm_failure)) {
                        clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
@@ -4021,6 +4420,13 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
                }
                spin_unlock_irqrestore(&ha->vport_slock, flags);
 
+               if (IS_QLA8031(ha)) {
+                       ql_dbg(ql_dbg_p3p, vha, 0xb05d,
+                           "Setting back fcoe driver presence.\n");
+                       if (qla83xx_set_drv_presence(vha) != QLA_SUCCESS)
+                               ql_dbg(ql_dbg_p3p, vha, 0xb074,
+                                   "Error while setting DRV-Presence.\n");
+               }
        } else {
                ql_log(ql_log_warn, vha, 0x8023, "%s **** FAILED ****.\n",
                       __func__);
This page took 0.030517 seconds and 5 git commands to generate.