|
@@ -35,43 +35,44 @@ static struct kmem_cache *srb_cachep;
|
|
|
int ql4xdisablesysfsboot = 1;
|
|
|
module_param(ql4xdisablesysfsboot, int, S_IRUGO | S_IWUSR);
|
|
|
MODULE_PARM_DESC(ql4xdisablesysfsboot,
|
|
|
- "Set to disable exporting boot targets to sysfs\n"
|
|
|
- " 0 - Export boot targets\n"
|
|
|
- " 1 - Do not export boot targets (Default)");
|
|
|
+ " Set to disable exporting boot targets to sysfs.\n"
|
|
|
+ "\t\t 0 - Export boot targets\n"
|
|
|
+ "\t\t 1 - Do not export boot targets (Default)");
|
|
|
|
|
|
int ql4xdontresethba = 0;
|
|
|
module_param(ql4xdontresethba, int, S_IRUGO | S_IWUSR);
|
|
|
MODULE_PARM_DESC(ql4xdontresethba,
|
|
|
- "Don't reset the HBA for driver recovery \n"
|
|
|
- " 0 - It will reset HBA (Default)\n"
|
|
|
- " 1 - It will NOT reset HBA");
|
|
|
+ " Don't reset the HBA for driver recovery.\n"
|
|
|
+ "\t\t 0 - It will reset HBA (Default)\n"
|
|
|
+ "\t\t 1 - It will NOT reset HBA");
|
|
|
|
|
|
-int ql4xextended_error_logging = 0; /* 0 = off, 1 = log errors */
|
|
|
+int ql4xextended_error_logging;
|
|
|
module_param(ql4xextended_error_logging, int, S_IRUGO | S_IWUSR);
|
|
|
MODULE_PARM_DESC(ql4xextended_error_logging,
|
|
|
- "Option to enable extended error logging, "
|
|
|
- "Default is 0 - no logging, 1 - debug logging");
|
|
|
+ " Option to enable extended error logging.\n"
|
|
|
+ "\t\t 0 - no logging (Default)\n"
|
|
|
+ "\t\t 2 - debug logging");
|
|
|
|
|
|
int ql4xenablemsix = 1;
|
|
|
module_param(ql4xenablemsix, int, S_IRUGO|S_IWUSR);
|
|
|
MODULE_PARM_DESC(ql4xenablemsix,
|
|
|
- "Set to enable MSI or MSI-X interrupt mechanism.\n"
|
|
|
- " 0 = enable INTx interrupt mechanism.\n"
|
|
|
- " 1 = enable MSI-X interrupt mechanism (Default).\n"
|
|
|
- " 2 = enable MSI interrupt mechanism.");
|
|
|
+ " Set to enable MSI or MSI-X interrupt mechanism.\n"
|
|
|
+ "\t\t 0 = enable INTx interrupt mechanism.\n"
|
|
|
+ "\t\t 1 = enable MSI-X interrupt mechanism (Default).\n"
|
|
|
+ "\t\t 2 = enable MSI interrupt mechanism.");
|
|
|
|
|
|
#define QL4_DEF_QDEPTH 32
|
|
|
static int ql4xmaxqdepth = QL4_DEF_QDEPTH;
|
|
|
module_param(ql4xmaxqdepth, int, S_IRUGO | S_IWUSR);
|
|
|
MODULE_PARM_DESC(ql4xmaxqdepth,
|
|
|
- "Maximum queue depth to report for target devices.\n"
|
|
|
- " Default: 32.");
|
|
|
+ " Maximum queue depth to report for target devices.\n"
|
|
|
+ "\t\t Default: 32.");
|
|
|
|
|
|
static int ql4xsess_recovery_tmo = QL4_SESS_RECOVERY_TMO;
|
|
|
module_param(ql4xsess_recovery_tmo, int, S_IRUGO);
|
|
|
MODULE_PARM_DESC(ql4xsess_recovery_tmo,
|
|
|
"Target Session Recovery Timeout.\n"
|
|
|
- " Default: 120 sec.");
|
|
|
+ "\t\t Default: 120 sec.");
|
|
|
|
|
|
static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha);
|
|
|
/*
|
|
@@ -1630,7 +1631,9 @@ void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha,
|
|
|
|
|
|
/* Update timers after login */
|
|
|
ddb_entry->default_relogin_timeout =
|
|
|
- le16_to_cpu(fw_ddb_entry->def_timeout);
|
|
|
+ (le16_to_cpu(fw_ddb_entry->def_timeout) > LOGIN_TOV) &&
|
|
|
+ (le16_to_cpu(fw_ddb_entry->def_timeout) < LOGIN_TOV * 10) ?
|
|
|
+ le16_to_cpu(fw_ddb_entry->def_timeout) : LOGIN_TOV;
|
|
|
ddb_entry->default_time2wait =
|
|
|
le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait);
|
|
|
|
|
@@ -1969,6 +1972,42 @@ mem_alloc_error_exit:
|
|
|
return QLA_ERROR;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * qla4_8xxx_check_temp - Check the ISP82XX temperature.
|
|
|
+ * @ha: adapter block pointer.
|
|
|
+ *
|
|
|
+ * Note: The caller should not hold the idc lock.
|
|
|
+ **/
|
|
|
+static int qla4_8xxx_check_temp(struct scsi_qla_host *ha)
|
|
|
+{
|
|
|
+ uint32_t temp, temp_state, temp_val;
|
|
|
+ int status = QLA_SUCCESS;
|
|
|
+
|
|
|
+ temp = qla4_8xxx_rd_32(ha, CRB_TEMP_STATE);
|
|
|
+
|
|
|
+ temp_state = qla82xx_get_temp_state(temp);
|
|
|
+ temp_val = qla82xx_get_temp_val(temp);
|
|
|
+
|
|
|
+ if (temp_state == QLA82XX_TEMP_PANIC) {
|
|
|
+ ql4_printk(KERN_WARNING, ha, "Device temperature %d degrees C"
|
|
|
+ " exceeds maximum allowed. Hardware has been shut"
|
|
|
+ " down.\n", temp_val);
|
|
|
+ status = QLA_ERROR;
|
|
|
+ } else if (temp_state == QLA82XX_TEMP_WARN) {
|
|
|
+ if (ha->temperature == QLA82XX_TEMP_NORMAL)
|
|
|
+ ql4_printk(KERN_WARNING, ha, "Device temperature %d"
|
|
|
+ " degrees C exceeds operating range."
|
|
|
+ " Immediate action needed.\n", temp_val);
|
|
|
+ } else {
|
|
|
+ if (ha->temperature == QLA82XX_TEMP_WARN)
|
|
|
+ ql4_printk(KERN_INFO, ha, "Device temperature is"
|
|
|
+ " now %d degrees C in normal range.\n",
|
|
|
+ temp_val);
|
|
|
+ }
|
|
|
+ ha->temperature = temp_state;
|
|
|
+ return status;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* qla4_8xxx_check_fw_alive - Check firmware health
|
|
|
* @ha: Pointer to host adapter structure.
|
|
@@ -2040,7 +2079,16 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha)
|
|
|
test_bit(DPC_RESET_HA, &ha->dpc_flags) ||
|
|
|
test_bit(DPC_RETRY_RESET_HA, &ha->dpc_flags))) {
|
|
|
dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
|
|
|
- if (dev_state == QLA82XX_DEV_NEED_RESET &&
|
|
|
+
|
|
|
+ if (qla4_8xxx_check_temp(ha)) {
|
|
|
+ ql4_printk(KERN_INFO, ha, "disabling pause"
|
|
|
+ " transmit on port 0 & 1.\n");
|
|
|
+ qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x98,
|
|
|
+ CRB_NIU_XG_PAUSE_CTL_P0 |
|
|
|
+ CRB_NIU_XG_PAUSE_CTL_P1);
|
|
|
+ set_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags);
|
|
|
+ qla4xxx_wake_dpc(ha);
|
|
|
+ } else if (dev_state == QLA82XX_DEV_NEED_RESET &&
|
|
|
!test_bit(DPC_RESET_HA, &ha->dpc_flags)) {
|
|
|
if (!ql4xdontresethba) {
|
|
|
ql4_printk(KERN_INFO, ha, "%s: HW State: "
|
|
@@ -2057,9 +2105,21 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha)
|
|
|
} else {
|
|
|
/* Check firmware health */
|
|
|
if (qla4_8xxx_check_fw_alive(ha)) {
|
|
|
+ ql4_printk(KERN_INFO, ha, "disabling pause"
|
|
|
+ " transmit on port 0 & 1.\n");
|
|
|
+ qla4_8xxx_wr_32(ha, QLA82XX_CRB_NIU + 0x98,
|
|
|
+ CRB_NIU_XG_PAUSE_CTL_P0 |
|
|
|
+ CRB_NIU_XG_PAUSE_CTL_P1);
|
|
|
halt_status = qla4_8xxx_rd_32(ha,
|
|
|
QLA82XX_PEG_HALT_STATUS1);
|
|
|
|
|
|
+ if (LSW(MSB(halt_status)) == 0x67)
|
|
|
+ ql4_printk(KERN_ERR, ha, "%s:"
|
|
|
+ " Firmware aborted with"
|
|
|
+ " error code 0x00006700."
|
|
|
+ " Device is being reset\n",
|
|
|
+ __func__);
|
|
|
+
|
|
|
/* Since we cannot change dev_state in interrupt
|
|
|
* context, set appropriate DPC flag then wakeup
|
|
|
* DPC */
|
|
@@ -2078,7 +2138,7 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void qla4xxx_check_relogin_flash_ddb(struct iscsi_cls_session *cls_sess)
|
|
|
+static void qla4xxx_check_relogin_flash_ddb(struct iscsi_cls_session *cls_sess)
|
|
|
{
|
|
|
struct iscsi_session *sess;
|
|
|
struct ddb_entry *ddb_entry;
|
|
@@ -3826,16 +3886,14 @@ exit_check:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static void qla4xxx_free_nt_list(struct list_head *list_nt)
|
|
|
+static void qla4xxx_free_ddb_list(struct list_head *list_ddb)
|
|
|
{
|
|
|
- struct qla_ddb_index *nt_ddb_idx, *nt_ddb_idx_tmp;
|
|
|
+ struct qla_ddb_index *ddb_idx, *ddb_idx_tmp;
|
|
|
|
|
|
- /* Free up the normaltargets list */
|
|
|
- list_for_each_entry_safe(nt_ddb_idx, nt_ddb_idx_tmp, list_nt, list) {
|
|
|
- list_del_init(&nt_ddb_idx->list);
|
|
|
- vfree(nt_ddb_idx);
|
|
|
+ list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, list_ddb, list) {
|
|
|
+ list_del_init(&ddb_idx->list);
|
|
|
+ vfree(ddb_idx);
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
|
|
|
static struct iscsi_endpoint *qla4xxx_get_ep_fwdb(struct scsi_qla_host *ha,
|
|
@@ -3884,6 +3942,8 @@ static int qla4xxx_verify_boot_idx(struct scsi_qla_host *ha, uint16_t idx)
|
|
|
static void qla4xxx_setup_flash_ddb_entry(struct scsi_qla_host *ha,
|
|
|
struct ddb_entry *ddb_entry)
|
|
|
{
|
|
|
+ uint16_t def_timeout;
|
|
|
+
|
|
|
ddb_entry->ddb_type = FLASH_DDB;
|
|
|
ddb_entry->fw_ddb_index = INVALID_ENTRY;
|
|
|
ddb_entry->fw_ddb_device_state = DDB_DS_NO_CONNECTION_ACTIVE;
|
|
@@ -3894,9 +3954,10 @@ static void qla4xxx_setup_flash_ddb_entry(struct scsi_qla_host *ha,
|
|
|
atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY);
|
|
|
atomic_set(&ddb_entry->relogin_timer, 0);
|
|
|
atomic_set(&ddb_entry->relogin_retry_count, 0);
|
|
|
-
|
|
|
+ def_timeout = le16_to_cpu(ddb_entry->fw_ddb_entry.def_timeout);
|
|
|
ddb_entry->default_relogin_timeout =
|
|
|
- le16_to_cpu(ddb_entry->fw_ddb_entry.def_timeout);
|
|
|
+ (def_timeout > LOGIN_TOV) && (def_timeout < LOGIN_TOV * 10) ?
|
|
|
+ def_timeout : LOGIN_TOV;
|
|
|
ddb_entry->default_time2wait =
|
|
|
le16_to_cpu(ddb_entry->fw_ddb_entry.iscsi_def_time2wait);
|
|
|
}
|
|
@@ -3934,7 +3995,6 @@ static void qla4xxx_wait_for_ip_configuration(struct scsi_qla_host *ha)
|
|
|
ip_state == IP_ADDRSTATE_DEPRICATED ||
|
|
|
ip_state == IP_ADDRSTATE_DISABLING)
|
|
|
ip_idx[idx] = -1;
|
|
|
-
|
|
|
}
|
|
|
|
|
|
/* Break if all IP states checked */
|
|
@@ -3947,58 +4007,37 @@ static void qla4xxx_wait_for_ip_configuration(struct scsi_qla_host *ha)
|
|
|
} while (time_after(wtime, jiffies));
|
|
|
}
|
|
|
|
|
|
-void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset)
|
|
|
+static void qla4xxx_build_st_list(struct scsi_qla_host *ha,
|
|
|
+ struct list_head *list_st)
|
|
|
{
|
|
|
+ struct qla_ddb_index *st_ddb_idx;
|
|
|
int max_ddbs;
|
|
|
+ int fw_idx_size;
|
|
|
+ struct dev_db_entry *fw_ddb_entry;
|
|
|
+ dma_addr_t fw_ddb_dma;
|
|
|
int ret;
|
|
|
uint32_t idx = 0, next_idx = 0;
|
|
|
uint32_t state = 0, conn_err = 0;
|
|
|
- uint16_t conn_id;
|
|
|
- struct dev_db_entry *fw_ddb_entry;
|
|
|
- struct ddb_entry *ddb_entry = NULL;
|
|
|
- dma_addr_t fw_ddb_dma;
|
|
|
- struct iscsi_cls_session *cls_sess;
|
|
|
- struct iscsi_session *sess;
|
|
|
- struct iscsi_cls_conn *cls_conn;
|
|
|
- struct iscsi_endpoint *ep;
|
|
|
- uint16_t cmds_max = 32, tmo = 0;
|
|
|
- uint32_t initial_cmdsn = 0;
|
|
|
- struct list_head list_st, list_nt; /* List of sendtargets */
|
|
|
- struct qla_ddb_index *st_ddb_idx, *st_ddb_idx_tmp;
|
|
|
- int fw_idx_size;
|
|
|
- unsigned long wtime;
|
|
|
- struct qla_ddb_index *nt_ddb_idx;
|
|
|
-
|
|
|
- if (!test_bit(AF_LINK_UP, &ha->flags)) {
|
|
|
- set_bit(AF_BUILD_DDB_LIST, &ha->flags);
|
|
|
- ha->is_reset = is_reset;
|
|
|
- return;
|
|
|
- }
|
|
|
- max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :
|
|
|
- MAX_DEV_DB_ENTRIES;
|
|
|
+ uint16_t conn_id = 0;
|
|
|
|
|
|
fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL,
|
|
|
&fw_ddb_dma);
|
|
|
if (fw_ddb_entry == NULL) {
|
|
|
DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n"));
|
|
|
- goto exit_ddb_list;
|
|
|
+ goto exit_st_list;
|
|
|
}
|
|
|
|
|
|
- INIT_LIST_HEAD(&list_st);
|
|
|
- INIT_LIST_HEAD(&list_nt);
|
|
|
+ max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :
|
|
|
+ MAX_DEV_DB_ENTRIES;
|
|
|
fw_idx_size = sizeof(struct qla_ddb_index);
|
|
|
|
|
|
for (idx = 0; idx < max_ddbs; idx = next_idx) {
|
|
|
- ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry,
|
|
|
- fw_ddb_dma, NULL,
|
|
|
- &next_idx, &state, &conn_err,
|
|
|
- NULL, &conn_id);
|
|
|
+ ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, fw_ddb_dma,
|
|
|
+ NULL, &next_idx, &state,
|
|
|
+ &conn_err, NULL, &conn_id);
|
|
|
if (ret == QLA_ERROR)
|
|
|
break;
|
|
|
|
|
|
- if (qla4xxx_verify_boot_idx(ha, idx) != QLA_SUCCESS)
|
|
|
- goto continue_next_st;
|
|
|
-
|
|
|
/* Check if ST, add to the list_st */
|
|
|
if (strlen((char *) fw_ddb_entry->iscsi_name) != 0)
|
|
|
goto continue_next_st;
|
|
@@ -4009,59 +4048,155 @@ void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset)
|
|
|
|
|
|
st_ddb_idx->fw_ddb_idx = idx;
|
|
|
|
|
|
- list_add_tail(&st_ddb_idx->list, &list_st);
|
|
|
+ list_add_tail(&st_ddb_idx->list, list_st);
|
|
|
continue_next_st:
|
|
|
if (next_idx == 0)
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- /* Before issuing conn open mbox, ensure all IPs states are configured
|
|
|
- * Note, conn open fails if IPs are not configured
|
|
|
+exit_st_list:
|
|
|
+ if (fw_ddb_entry)
|
|
|
+ dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * qla4xxx_remove_failed_ddb - Remove inactive or failed ddb from list
|
|
|
+ * @ha: pointer to adapter structure
|
|
|
+ * @list_ddb: List from which failed ddb to be removed
|
|
|
+ *
|
|
|
+ * Iterate over the list of DDBs and find and remove DDBs that are either in
|
|
|
+ * no connection active state or failed state
|
|
|
+ **/
|
|
|
+static void qla4xxx_remove_failed_ddb(struct scsi_qla_host *ha,
|
|
|
+ struct list_head *list_ddb)
|
|
|
+{
|
|
|
+ struct qla_ddb_index *ddb_idx, *ddb_idx_tmp;
|
|
|
+ uint32_t next_idx = 0;
|
|
|
+ uint32_t state = 0, conn_err = 0;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, list_ddb, list) {
|
|
|
+ ret = qla4xxx_get_fwddb_entry(ha, ddb_idx->fw_ddb_idx,
|
|
|
+ NULL, 0, NULL, &next_idx, &state,
|
|
|
+ &conn_err, NULL, NULL);
|
|
|
+ if (ret == QLA_ERROR)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (state == DDB_DS_NO_CONNECTION_ACTIVE ||
|
|
|
+ state == DDB_DS_SESSION_FAILED) {
|
|
|
+ list_del_init(&ddb_idx->list);
|
|
|
+ vfree(ddb_idx);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static int qla4xxx_sess_conn_setup(struct scsi_qla_host *ha,
|
|
|
+ struct dev_db_entry *fw_ddb_entry,
|
|
|
+ int is_reset)
|
|
|
+{
|
|
|
+ struct iscsi_cls_session *cls_sess;
|
|
|
+ struct iscsi_session *sess;
|
|
|
+ struct iscsi_cls_conn *cls_conn;
|
|
|
+ struct iscsi_endpoint *ep;
|
|
|
+ uint16_t cmds_max = 32;
|
|
|
+ uint16_t conn_id = 0;
|
|
|
+ uint32_t initial_cmdsn = 0;
|
|
|
+ int ret = QLA_SUCCESS;
|
|
|
+
|
|
|
+ struct ddb_entry *ddb_entry = NULL;
|
|
|
+
|
|
|
+ /* Create session object, with INVALID_ENTRY,
|
|
|
+ * the targer_id would get set when we issue the login
|
|
|
*/
|
|
|
- qla4xxx_wait_for_ip_configuration(ha);
|
|
|
+ cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport, ha->host,
|
|
|
+ cmds_max, sizeof(struct ddb_entry),
|
|
|
+ sizeof(struct ql4_task_data),
|
|
|
+ initial_cmdsn, INVALID_ENTRY);
|
|
|
+ if (!cls_sess) {
|
|
|
+ ret = QLA_ERROR;
|
|
|
+ goto exit_setup;
|
|
|
+ }
|
|
|
|
|
|
- /* Go thru the STs and fire the sendtargets by issuing conn open mbx */
|
|
|
- list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, list) {
|
|
|
- qla4xxx_conn_open(ha, st_ddb_idx->fw_ddb_idx);
|
|
|
+ /*
|
|
|
+ * so calling module_put function to decrement the
|
|
|
+ * reference count.
|
|
|
+ **/
|
|
|
+ module_put(qla4xxx_iscsi_transport.owner);
|
|
|
+ sess = cls_sess->dd_data;
|
|
|
+ ddb_entry = sess->dd_data;
|
|
|
+ ddb_entry->sess = cls_sess;
|
|
|
+
|
|
|
+ cls_sess->recovery_tmo = ql4xsess_recovery_tmo;
|
|
|
+ memcpy(&ddb_entry->fw_ddb_entry, fw_ddb_entry,
|
|
|
+ sizeof(struct dev_db_entry));
|
|
|
+
|
|
|
+ qla4xxx_setup_flash_ddb_entry(ha, ddb_entry);
|
|
|
+
|
|
|
+ cls_conn = iscsi_conn_setup(cls_sess, sizeof(struct qla_conn), conn_id);
|
|
|
+
|
|
|
+ if (!cls_conn) {
|
|
|
+ ret = QLA_ERROR;
|
|
|
+ goto exit_setup;
|
|
|
}
|
|
|
|
|
|
- /* Wait to ensure all sendtargets are done for min 12 sec wait */
|
|
|
- tmo = ((ha->def_timeout < LOGIN_TOV) ? LOGIN_TOV : ha->def_timeout);
|
|
|
- DEBUG2(ql4_printk(KERN_INFO, ha,
|
|
|
- "Default time to wait for build ddb %d\n", tmo));
|
|
|
+ ddb_entry->conn = cls_conn;
|
|
|
|
|
|
- wtime = jiffies + (HZ * tmo);
|
|
|
- do {
|
|
|
- list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st,
|
|
|
- list) {
|
|
|
- ret = qla4xxx_get_fwddb_entry(ha,
|
|
|
- st_ddb_idx->fw_ddb_idx,
|
|
|
- NULL, 0, NULL, &next_idx,
|
|
|
- &state, &conn_err, NULL,
|
|
|
- NULL);
|
|
|
- if (ret == QLA_ERROR)
|
|
|
- continue;
|
|
|
+ /* Setup ep, for displaying attributes in sysfs */
|
|
|
+ ep = qla4xxx_get_ep_fwdb(ha, fw_ddb_entry);
|
|
|
+ if (ep) {
|
|
|
+ ep->conn = cls_conn;
|
|
|
+ cls_conn->ep = ep;
|
|
|
+ } else {
|
|
|
+ DEBUG2(ql4_printk(KERN_ERR, ha, "Unable to get ep\n"));
|
|
|
+ ret = QLA_ERROR;
|
|
|
+ goto exit_setup;
|
|
|
+ }
|
|
|
|
|
|
- if (state == DDB_DS_NO_CONNECTION_ACTIVE ||
|
|
|
- state == DDB_DS_SESSION_FAILED) {
|
|
|
- list_del_init(&st_ddb_idx->list);
|
|
|
- vfree(st_ddb_idx);
|
|
|
- }
|
|
|
- }
|
|
|
- schedule_timeout_uninterruptible(HZ / 10);
|
|
|
- } while (time_after(wtime, jiffies));
|
|
|
+ /* Update sess/conn params */
|
|
|
+ qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess, cls_conn);
|
|
|
|
|
|
- /* Free up the sendtargets list */
|
|
|
- list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, list) {
|
|
|
- list_del_init(&st_ddb_idx->list);
|
|
|
- vfree(st_ddb_idx);
|
|
|
+ if (is_reset == RESET_ADAPTER) {
|
|
|
+ iscsi_block_session(cls_sess);
|
|
|
+ /* Use the relogin path to discover new devices
|
|
|
+ * by short-circuting the logic of setting
|
|
|
+ * timer to relogin - instead set the flags
|
|
|
+ * to initiate login right away.
|
|
|
+ */
|
|
|
+ set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags);
|
|
|
+ set_bit(DF_RELOGIN, &ddb_entry->flags);
|
|
|
}
|
|
|
|
|
|
+exit_setup:
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static void qla4xxx_build_nt_list(struct scsi_qla_host *ha,
|
|
|
+ struct list_head *list_nt, int is_reset)
|
|
|
+{
|
|
|
+ struct dev_db_entry *fw_ddb_entry;
|
|
|
+ dma_addr_t fw_ddb_dma;
|
|
|
+ int max_ddbs;
|
|
|
+ int fw_idx_size;
|
|
|
+ int ret;
|
|
|
+ uint32_t idx = 0, next_idx = 0;
|
|
|
+ uint32_t state = 0, conn_err = 0;
|
|
|
+ uint16_t conn_id = 0;
|
|
|
+ struct qla_ddb_index *nt_ddb_idx;
|
|
|
+
|
|
|
+ fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL,
|
|
|
+ &fw_ddb_dma);
|
|
|
+ if (fw_ddb_entry == NULL) {
|
|
|
+ DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n"));
|
|
|
+ goto exit_nt_list;
|
|
|
+ }
|
|
|
+ max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :
|
|
|
+ MAX_DEV_DB_ENTRIES;
|
|
|
+ fw_idx_size = sizeof(struct qla_ddb_index);
|
|
|
+
|
|
|
for (idx = 0; idx < max_ddbs; idx = next_idx) {
|
|
|
- ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry,
|
|
|
- fw_ddb_dma, NULL,
|
|
|
- &next_idx, &state, &conn_err,
|
|
|
- NULL, &conn_id);
|
|
|
+ ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, fw_ddb_dma,
|
|
|
+ NULL, &next_idx, &state,
|
|
|
+ &conn_err, NULL, &conn_id);
|
|
|
if (ret == QLA_ERROR)
|
|
|
break;
|
|
|
|
|
@@ -4072,107 +4207,113 @@ continue_next_st:
|
|
|
if (strlen((char *) fw_ddb_entry->iscsi_name) == 0)
|
|
|
goto continue_next_nt;
|
|
|
|
|
|
- if (state == DDB_DS_NO_CONNECTION_ACTIVE ||
|
|
|
- state == DDB_DS_SESSION_FAILED) {
|
|
|
- DEBUG2(ql4_printk(KERN_INFO, ha,
|
|
|
- "Adding DDB to session = 0x%x\n",
|
|
|
- idx));
|
|
|
- if (is_reset == INIT_ADAPTER) {
|
|
|
- nt_ddb_idx = vmalloc(fw_idx_size);
|
|
|
- if (!nt_ddb_idx)
|
|
|
- break;
|
|
|
-
|
|
|
- nt_ddb_idx->fw_ddb_idx = idx;
|
|
|
-
|
|
|
- memcpy(&nt_ddb_idx->fw_ddb, fw_ddb_entry,
|
|
|
- sizeof(struct dev_db_entry));
|
|
|
-
|
|
|
- if (qla4xxx_is_flash_ddb_exists(ha, &list_nt,
|
|
|
- fw_ddb_entry) == QLA_SUCCESS) {
|
|
|
- vfree(nt_ddb_idx);
|
|
|
- goto continue_next_nt;
|
|
|
- }
|
|
|
- list_add_tail(&nt_ddb_idx->list, &list_nt);
|
|
|
- } else if (is_reset == RESET_ADAPTER) {
|
|
|
- if (qla4xxx_is_session_exists(ha,
|
|
|
- fw_ddb_entry) == QLA_SUCCESS)
|
|
|
- goto continue_next_nt;
|
|
|
- }
|
|
|
+ if (!(state == DDB_DS_NO_CONNECTION_ACTIVE ||
|
|
|
+ state == DDB_DS_SESSION_FAILED))
|
|
|
+ goto continue_next_nt;
|
|
|
|
|
|
- /* Create session object, with INVALID_ENTRY,
|
|
|
- * the targer_id would get set when we issue the login
|
|
|
- */
|
|
|
- cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport,
|
|
|
- ha->host, cmds_max,
|
|
|
- sizeof(struct ddb_entry),
|
|
|
- sizeof(struct ql4_task_data),
|
|
|
- initial_cmdsn, INVALID_ENTRY);
|
|
|
- if (!cls_sess)
|
|
|
- goto exit_ddb_list;
|
|
|
+ DEBUG2(ql4_printk(KERN_INFO, ha,
|
|
|
+ "Adding DDB to session = 0x%x\n", idx));
|
|
|
+ if (is_reset == INIT_ADAPTER) {
|
|
|
+ nt_ddb_idx = vmalloc(fw_idx_size);
|
|
|
+ if (!nt_ddb_idx)
|
|
|
+ break;
|
|
|
|
|
|
- /*
|
|
|
- * iscsi_session_setup increments the driver reference
|
|
|
- * count which wouldn't let the driver to be unloaded.
|
|
|
- * so calling module_put function to decrement the
|
|
|
- * reference count.
|
|
|
- **/
|
|
|
- module_put(qla4xxx_iscsi_transport.owner);
|
|
|
- sess = cls_sess->dd_data;
|
|
|
- ddb_entry = sess->dd_data;
|
|
|
- ddb_entry->sess = cls_sess;
|
|
|
+ nt_ddb_idx->fw_ddb_idx = idx;
|
|
|
|
|
|
- cls_sess->recovery_tmo = ql4xsess_recovery_tmo;
|
|
|
- memcpy(&ddb_entry->fw_ddb_entry, fw_ddb_entry,
|
|
|
+ memcpy(&nt_ddb_idx->fw_ddb, fw_ddb_entry,
|
|
|
sizeof(struct dev_db_entry));
|
|
|
|
|
|
- qla4xxx_setup_flash_ddb_entry(ha, ddb_entry);
|
|
|
-
|
|
|
- cls_conn = iscsi_conn_setup(cls_sess,
|
|
|
- sizeof(struct qla_conn),
|
|
|
- conn_id);
|
|
|
- if (!cls_conn)
|
|
|
- goto exit_ddb_list;
|
|
|
-
|
|
|
- ddb_entry->conn = cls_conn;
|
|
|
-
|
|
|
- /* Setup ep, for displaying attributes in sysfs */
|
|
|
- ep = qla4xxx_get_ep_fwdb(ha, fw_ddb_entry);
|
|
|
- if (ep) {
|
|
|
- ep->conn = cls_conn;
|
|
|
- cls_conn->ep = ep;
|
|
|
- } else {
|
|
|
- DEBUG2(ql4_printk(KERN_ERR, ha,
|
|
|
- "Unable to get ep\n"));
|
|
|
- }
|
|
|
-
|
|
|
- /* Update sess/conn params */
|
|
|
- qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess,
|
|
|
- cls_conn);
|
|
|
-
|
|
|
- if (is_reset == RESET_ADAPTER) {
|
|
|
- iscsi_block_session(cls_sess);
|
|
|
- /* Use the relogin path to discover new devices
|
|
|
- * by short-circuting the logic of setting
|
|
|
- * timer to relogin - instead set the flags
|
|
|
- * to initiate login right away.
|
|
|
- */
|
|
|
- set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags);
|
|
|
- set_bit(DF_RELOGIN, &ddb_entry->flags);
|
|
|
+ if (qla4xxx_is_flash_ddb_exists(ha, list_nt,
|
|
|
+ fw_ddb_entry) == QLA_SUCCESS) {
|
|
|
+ vfree(nt_ddb_idx);
|
|
|
+ goto continue_next_nt;
|
|
|
}
|
|
|
+ list_add_tail(&nt_ddb_idx->list, list_nt);
|
|
|
+ } else if (is_reset == RESET_ADAPTER) {
|
|
|
+ if (qla4xxx_is_session_exists(ha, fw_ddb_entry) ==
|
|
|
+ QLA_SUCCESS)
|
|
|
+ goto continue_next_nt;
|
|
|
}
|
|
|
+
|
|
|
+ ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, is_reset);
|
|
|
+ if (ret == QLA_ERROR)
|
|
|
+ goto exit_nt_list;
|
|
|
+
|
|
|
continue_next_nt:
|
|
|
if (next_idx == 0)
|
|
|
break;
|
|
|
}
|
|
|
-exit_ddb_list:
|
|
|
- qla4xxx_free_nt_list(&list_nt);
|
|
|
+
|
|
|
+exit_nt_list:
|
|
|
if (fw_ddb_entry)
|
|
|
dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * qla4xxx_build_ddb_list - Build ddb list and setup sessions
|
|
|
+ * @ha: pointer to adapter structure
|
|
|
+ * @is_reset: Is this init path or reset path
|
|
|
+ *
|
|
|
+ * Create a list of sendtargets (st) from firmware DDBs, issue send targets
|
|
|
+ * using connection open, then create the list of normal targets (nt)
|
|
|
+ * from firmware DDBs. Based on the list of nt setup session and connection
|
|
|
+ * objects.
|
|
|
+ **/
|
|
|
+void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset)
|
|
|
+{
|
|
|
+ uint16_t tmo = 0;
|
|
|
+ struct list_head list_st, list_nt;
|
|
|
+ struct qla_ddb_index *st_ddb_idx, *st_ddb_idx_tmp;
|
|
|
+ unsigned long wtime;
|
|
|
+
|
|
|
+ if (!test_bit(AF_LINK_UP, &ha->flags)) {
|
|
|
+ set_bit(AF_BUILD_DDB_LIST, &ha->flags);
|
|
|
+ ha->is_reset = is_reset;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ INIT_LIST_HEAD(&list_st);
|
|
|
+ INIT_LIST_HEAD(&list_nt);
|
|
|
+
|
|
|
+ qla4xxx_build_st_list(ha, &list_st);
|
|
|
+
|
|
|
+ /* Before issuing conn open mbox, ensure all IPs states are configured
|
|
|
+ * Note, conn open fails if IPs are not configured
|
|
|
+ */
|
|
|
+ qla4xxx_wait_for_ip_configuration(ha);
|
|
|
+
|
|
|
+ /* Go thru the STs and fire the sendtargets by issuing conn open mbx */
|
|
|
+ list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, list) {
|
|
|
+ qla4xxx_conn_open(ha, st_ddb_idx->fw_ddb_idx);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Wait to ensure all sendtargets are done for min 12 sec wait */
|
|
|
+ tmo = ((ha->def_timeout > LOGIN_TOV) &&
|
|
|
+ (ha->def_timeout < LOGIN_TOV * 10) ?
|
|
|
+ ha->def_timeout : LOGIN_TOV);
|
|
|
+
|
|
|
+ DEBUG2(ql4_printk(KERN_INFO, ha,
|
|
|
+ "Default time to wait for build ddb %d\n", tmo));
|
|
|
+
|
|
|
+ wtime = jiffies + (HZ * tmo);
|
|
|
+ do {
|
|
|
+ if (list_empty(&list_st))
|
|
|
+ break;
|
|
|
+
|
|
|
+ qla4xxx_remove_failed_ddb(ha, &list_st);
|
|
|
+ schedule_timeout_uninterruptible(HZ / 10);
|
|
|
+ } while (time_after(wtime, jiffies));
|
|
|
+
|
|
|
+ /* Free up the sendtargets list */
|
|
|
+ qla4xxx_free_ddb_list(&list_st);
|
|
|
+
|
|
|
+ qla4xxx_build_nt_list(ha, &list_nt, is_reset);
|
|
|
+
|
|
|
+ qla4xxx_free_ddb_list(&list_nt);
|
|
|
|
|
|
qla4xxx_free_ddb_index(ha);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
/**
|
|
|
* qla4xxx_probe_adapter - callback function to probe HBA
|
|
|
* @pdev: pointer to pci_dev structure
|