Merge git://www.linux-watchdog.org/linux-watchdog
[pandora-kernel.git] / drivers / scsi / qla4xxx / ql4_init.c
index 42ed5db..3075fba 100644 (file)
@@ -11,9 +11,6 @@
 #include "ql4_dbg.h"
 #include "ql4_inline.h"
 
-static struct ddb_entry *qla4xxx_alloc_ddb(struct scsi_qla_host *ha,
-                                          uint32_t fw_ddb_index);
-
 static void ql4xxx_set_mac_number(struct scsi_qla_host *ha)
 {
        uint32_t value;
@@ -48,41 +45,15 @@ static void ql4xxx_set_mac_number(struct scsi_qla_host *ha)
  * @ha: pointer to host adapter structure.
  * @ddb_entry: pointer to device database entry
  *
- * This routine deallocates and unlinks the specified ddb_entry from the
- * adapter's
+ * This routine marks a DDB entry INVALID
  **/
 void qla4xxx_free_ddb(struct scsi_qla_host *ha,
     struct ddb_entry *ddb_entry)
 {
-       /* Remove device entry from list */
-       list_del_init(&ddb_entry->list);
-
        /* Remove device pointer from index mapping arrays */
        ha->fw_ddb_index_map[ddb_entry->fw_ddb_index] =
                (struct ddb_entry *) INVALID_ENTRY;
        ha->tot_ddbs--;
-
-       /* Free memory and scsi-ml struct for device entry */
-       qla4xxx_destroy_sess(ddb_entry);
-}
-
-/**
- * qla4xxx_free_ddb_list - deallocate all ddbs
- * @ha: pointer to host adapter structure.
- *
- * This routine deallocates and removes all devices on the sppecified adapter.
- **/
-void qla4xxx_free_ddb_list(struct scsi_qla_host *ha)
-{
-       struct list_head *ptr;
-       struct ddb_entry *ddb_entry;
-
-       while (!list_empty(&ha->ddb_list)) {
-               ptr = ha->ddb_list.next;
-               /* Free memory for device entry and remove */
-               ddb_entry = list_entry(ptr, struct ddb_entry, list);
-               qla4xxx_free_ddb(ha, ddb_entry);
-       }
 }
 
 /**
@@ -236,38 +207,44 @@ qla4xxx_wait_for_ip_config(struct scsi_qla_host *ha)
                                    FW_ADDSTATE_DHCPv4_LEASE_ACQUIRED) == 0)) {
                        ipv4_wait = 1;
                }
-               if (((ha->ipv6_addl_options &
-                           IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE) != 0) &&
-                   ((ha->ipv6_link_local_state == IP_ADDRSTATE_ACQUIRING) ||
-                    (ha->ipv6_addr0_state == IP_ADDRSTATE_ACQUIRING) ||
-                    (ha->ipv6_addr1_state == IP_ADDRSTATE_ACQUIRING))) {
+               if (((ha->ip_config.ipv6_addl_options &
+                     IPV6_ADDOPT_NEIGHBOR_DISCOVERY_ADDR_ENABLE) != 0) &&
+                   ((ha->ip_config.ipv6_link_local_state ==
+                     IP_ADDRSTATE_ACQUIRING) ||
+                    (ha->ip_config.ipv6_addr0_state ==
+                     IP_ADDRSTATE_ACQUIRING) ||
+                    (ha->ip_config.ipv6_addr1_state ==
+                     IP_ADDRSTATE_ACQUIRING))) {
 
                        ipv6_wait = 1;
 
-                       if ((ha->ipv6_link_local_state ==
-                                                    IP_ADDRSTATE_PREFERRED) ||
-                           (ha->ipv6_addr0_state == IP_ADDRSTATE_PREFERRED) ||
-                           (ha->ipv6_addr1_state == IP_ADDRSTATE_PREFERRED)) {
+                       if ((ha->ip_config.ipv6_link_local_state ==
+                            IP_ADDRSTATE_PREFERRED) ||
+                           (ha->ip_config.ipv6_addr0_state ==
+                            IP_ADDRSTATE_PREFERRED) ||
+                           (ha->ip_config.ipv6_addr1_state ==
+                            IP_ADDRSTATE_PREFERRED)) {
                                DEBUG2(printk(KERN_INFO "scsi%ld: %s: "
                                              "Preferred IP configured."
                                              " Don't wait!\n", ha->host_no,
                                              __func__));
                                ipv6_wait = 0;
                        }
-                       if (memcmp(&ha->ipv6_default_router_addr, ip_address,
-                               IPv6_ADDR_LEN) == 0) {
+                       if (memcmp(&ha->ip_config.ipv6_default_router_addr,
+                                  ip_address, IPv6_ADDR_LEN) == 0) {
                                DEBUG2(printk(KERN_INFO "scsi%ld: %s: "
                                              "No Router configured. "
                                              "Don't wait!\n", ha->host_no,
                                              __func__));
                                ipv6_wait = 0;
                        }
-                       if ((ha->ipv6_default_router_state ==
-                                               IPV6_RTRSTATE_MANUAL) &&
-                           (ha->ipv6_link_local_state ==
-                                               IP_ADDRSTATE_TENTATIVE) &&
-                           (memcmp(&ha->ipv6_link_local_addr,
-                                   &ha->ipv6_default_router_addr, 4) == 0)) {
+                       if ((ha->ip_config.ipv6_default_router_state ==
+                            IPV6_RTRSTATE_MANUAL) &&
+                           (ha->ip_config.ipv6_link_local_state ==
+                            IP_ADDRSTATE_TENTATIVE) &&
+                           (memcmp(&ha->ip_config.ipv6_link_local_addr,
+                            &ha->ip_config.ipv6_default_router_addr, 4) ==
+                            0)) {
                                DEBUG2(printk("scsi%ld: %s: LinkLocal Router & "
                                        "IP configured. Don't wait!\n",
                                        ha->host_no, __func__));
@@ -279,11 +256,14 @@ qla4xxx_wait_for_ip_config(struct scsi_qla_host *ha)
                                      "IP(s) \"", ha->host_no, __func__));
                        if (ipv4_wait)
                                DEBUG2(printk("IPv4 "));
-                       if (ha->ipv6_link_local_state == IP_ADDRSTATE_ACQUIRING)
+                       if (ha->ip_config.ipv6_link_local_state ==
+                           IP_ADDRSTATE_ACQUIRING)
                                DEBUG2(printk("IPv6LinkLocal "));
-                       if (ha->ipv6_addr0_state == IP_ADDRSTATE_ACQUIRING)
+                       if (ha->ip_config.ipv6_addr0_state ==
+                           IP_ADDRSTATE_ACQUIRING)
                                DEBUG2(printk("IPv6Addr0 "));
-                       if (ha->ipv6_addr1_state == IP_ADDRSTATE_ACQUIRING)
+                       if (ha->ip_config.ipv6_addr1_state ==
+                           IP_ADDRSTATE_ACQUIRING)
                                DEBUG2(printk("IPv6Addr1 "));
                        DEBUG2(printk("\"\n"));
                }
@@ -466,486 +446,19 @@ static int qla4xxx_init_firmware(struct scsi_qla_host *ha)
        return qla4xxx_get_firmware_status(ha);
 }
 
-static struct ddb_entry* qla4xxx_get_ddb_entry(struct scsi_qla_host *ha,
-                                               uint32_t fw_ddb_index,
-                                               uint32_t *new_tgt)
-{
-       struct dev_db_entry *fw_ddb_entry = NULL;
-       dma_addr_t fw_ddb_entry_dma;
-       struct ddb_entry *ddb_entry = NULL;
-       int found = 0;
-       uint32_t device_state;
-
-       *new_tgt = 0;
-       /* Make sure the dma buffer is valid */
-       fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev,
-                                         sizeof(*fw_ddb_entry),
-                                         &fw_ddb_entry_dma, GFP_KERNEL);
-       if (fw_ddb_entry == NULL) {
-               DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n",
-                             ha->host_no, __func__));
-               goto exit_get_ddb_entry_no_free;
-       }
-
-       if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, fw_ddb_entry,
-                                   fw_ddb_entry_dma, NULL, NULL,
-                                   &device_state, NULL, NULL, NULL) ==
-                                   QLA_ERROR) {
-               DEBUG2(printk("scsi%ld: %s: failed get_ddb_entry for "
-                             "fw_ddb_index %d\n", ha->host_no, __func__,
-                             fw_ddb_index));
-               goto exit_get_ddb_entry;
-       }
-
-       /* Allocate DDB if not already allocated. */
-       DEBUG2(printk("scsi%ld: %s: Looking for ddb[%d]\n", ha->host_no,
-                     __func__, fw_ddb_index));
-       list_for_each_entry(ddb_entry, &ha->ddb_list, list) {
-               if ((memcmp(ddb_entry->iscsi_name, fw_ddb_entry->iscsi_name,
-                          ISCSI_NAME_SIZE) == 0) &&
-                       (ddb_entry->tpgt ==
-                               le32_to_cpu(fw_ddb_entry->tgt_portal_grp)) &&
-                       (memcmp(ddb_entry->isid, fw_ddb_entry->isid,
-                               sizeof(ddb_entry->isid)) == 0)) {
-                       found++;
-                       break;
-               }
-       }
-
-       /* if not found allocate new ddb */
-       if (!found) {
-               DEBUG2(printk("scsi%ld: %s: ddb[%d] not found - allocating "
-                             "new ddb\n", ha->host_no, __func__,
-                             fw_ddb_index));
-               *new_tgt = 1;
-               ddb_entry = qla4xxx_alloc_ddb(ha, fw_ddb_index);
-       }
-
-exit_get_ddb_entry:
-       dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), fw_ddb_entry,
-                         fw_ddb_entry_dma);
-
-exit_get_ddb_entry_no_free:
-       return ddb_entry;
-}
-
-/**
- * qla4xxx_update_ddb_entry - update driver's internal ddb
- * @ha: pointer to host adapter structure.
- * @ddb_entry: pointer to device database structure to be filled
- * @fw_ddb_index: index of the ddb entry in fw ddb table
- *
- * This routine updates the driver's internal device database entry
- * with information retrieved from the firmware's device database
- * entry for the specified device. The ddb_entry->fw_ddb_index field
- * must be initialized prior to        calling this routine
- *
- **/
-static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha,
-                                   struct ddb_entry *ddb_entry,
-                                   uint32_t fw_ddb_index)
-{
-       struct dev_db_entry *fw_ddb_entry = NULL;
-       dma_addr_t fw_ddb_entry_dma;
-       int status = QLA_ERROR;
-       uint32_t conn_err;
-
-       if (ddb_entry == NULL) {
-               DEBUG2(printk("scsi%ld: %s: ddb_entry is NULL\n", ha->host_no,
-                             __func__));
-
-               goto exit_update_ddb_no_free;
-       }
-
-       /* Make sure the dma buffer is valid */
-       fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev,
-                                         sizeof(*fw_ddb_entry),
-                                         &fw_ddb_entry_dma, GFP_KERNEL);
-       if (fw_ddb_entry == NULL) {
-               DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n",
-                             ha->host_no, __func__));
-
-               goto exit_update_ddb_no_free;
-       }
-
-       if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, fw_ddb_entry,
-                                   fw_ddb_entry_dma, NULL, NULL,
-                                   &ddb_entry->fw_ddb_device_state, &conn_err,
-                                   &ddb_entry->tcp_source_port_num,
-                                   &ddb_entry->connection_id) ==
-                                   QLA_ERROR) {
-               DEBUG2(printk("scsi%ld: %s: failed get_ddb_entry for "
-                             "fw_ddb_index %d\n", ha->host_no, __func__,
-                             fw_ddb_index));
-
-               goto exit_update_ddb;
-       }
-
-       status = QLA_SUCCESS;
-       ddb_entry->options = le16_to_cpu(fw_ddb_entry->options);
-       ddb_entry->target_session_id = le16_to_cpu(fw_ddb_entry->tsid);
-       ddb_entry->task_mgmt_timeout =
-               le16_to_cpu(fw_ddb_entry->def_timeout);
-       ddb_entry->CmdSn = 0;
-       ddb_entry->exe_throttle = le16_to_cpu(fw_ddb_entry->exec_throttle);
-       ddb_entry->default_relogin_timeout =
-               le16_to_cpu(fw_ddb_entry->def_timeout);
-       ddb_entry->default_time2wait = le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait);
-
-       /* Update index in case it changed */
-       ddb_entry->fw_ddb_index = fw_ddb_index;
-       ha->fw_ddb_index_map[fw_ddb_index] = ddb_entry;
-
-       ddb_entry->port = le16_to_cpu(fw_ddb_entry->port);
-       ddb_entry->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp);
-       memcpy(ddb_entry->isid, fw_ddb_entry->isid, sizeof(ddb_entry->isid));
-
-       memcpy(&ddb_entry->iscsi_name[0], &fw_ddb_entry->iscsi_name[0],
-              min(sizeof(ddb_entry->iscsi_name),
-                  sizeof(fw_ddb_entry->iscsi_name)));
-       memcpy(&ddb_entry->iscsi_alias[0], &fw_ddb_entry->iscsi_alias[0],
-              min(sizeof(ddb_entry->iscsi_alias),
-                  sizeof(fw_ddb_entry->iscsi_alias)));
-       memcpy(&ddb_entry->ip_addr[0], &fw_ddb_entry->ip_addr[0],
-              min(sizeof(ddb_entry->ip_addr), sizeof(fw_ddb_entry->ip_addr)));
-
-       ddb_entry->iscsi_max_burst_len = fw_ddb_entry->iscsi_max_burst_len;
-       ddb_entry->iscsi_max_outsnd_r2t = fw_ddb_entry->iscsi_max_outsnd_r2t;
-       ddb_entry->iscsi_first_burst_len = fw_ddb_entry->iscsi_first_burst_len;
-       ddb_entry->iscsi_max_rcv_data_seg_len =
-                               fw_ddb_entry->iscsi_max_rcv_data_seg_len;
-       ddb_entry->iscsi_max_snd_data_seg_len =
-                               fw_ddb_entry->iscsi_max_snd_data_seg_len;
-
-       if (ddb_entry->options & DDB_OPT_IPV6_DEVICE) {
-               memcpy(&ddb_entry->remote_ipv6_addr,
-                       fw_ddb_entry->ip_addr,
-                       min(sizeof(ddb_entry->remote_ipv6_addr),
-                       sizeof(fw_ddb_entry->ip_addr)));
-               memcpy(&ddb_entry->link_local_ipv6_addr,
-                       fw_ddb_entry->link_local_ipv6_addr,
-                       min(sizeof(ddb_entry->link_local_ipv6_addr),
-                       sizeof(fw_ddb_entry->link_local_ipv6_addr)));
-
-               DEBUG2(ql4_printk(KERN_INFO, ha, "%s: DDB[%d] State %04x"
-                                       " ConnErr %08x IP %pI6 "
-                                       ":%04d \"%s\"\n",
-                                       __func__, fw_ddb_index,
-                                       ddb_entry->fw_ddb_device_state,
-                                       conn_err, fw_ddb_entry->ip_addr,
-                                       le16_to_cpu(fw_ddb_entry->port),
-                                       fw_ddb_entry->iscsi_name));
-       } else
-               DEBUG2(ql4_printk(KERN_INFO, ha, "%s: DDB[%d] State %04x"
-                                       " ConnErr %08x IP %pI4 "
-                                       ":%04d \"%s\"\n",
-                                       __func__, fw_ddb_index,
-                                       ddb_entry->fw_ddb_device_state,
-                                       conn_err, fw_ddb_entry->ip_addr,
-                                       le16_to_cpu(fw_ddb_entry->port),
-                                       fw_ddb_entry->iscsi_name));
-exit_update_ddb:
-       if (fw_ddb_entry)
-               dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
-                                 fw_ddb_entry, fw_ddb_entry_dma);
-
-exit_update_ddb_no_free:
-       return status;
-}
-
-/**
- * qla4xxx_alloc_ddb - allocate device database entry
- * @ha: Pointer to host adapter structure.
- * @fw_ddb_index: Firmware's device database index
- *
- * This routine allocates a ddb_entry, ititializes some values, and
- * inserts it into the ddb list.
- **/
-static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha,
-                                           uint32_t fw_ddb_index)
+static void qla4xxx_set_model_info(struct scsi_qla_host *ha)
 {
-       struct ddb_entry *ddb_entry;
-
-       DEBUG2(printk("scsi%ld: %s: fw_ddb_index [%d]\n", ha->host_no,
-                     __func__, fw_ddb_index));
-
-       ddb_entry = qla4xxx_alloc_sess(ha);
-       if (ddb_entry == NULL) {
-               DEBUG2(printk("scsi%ld: %s: Unable to allocate memory "
-                             "to add fw_ddb_index [%d]\n",
-                             ha->host_no, __func__, fw_ddb_index));
-               return ddb_entry;
-       }
+       uint16_t board_id_string[8];
+       int i;
+       int size = sizeof(ha->nvram->isp4022.boardIdStr);
+       int offset = offsetof(struct eeprom_data, isp4022.boardIdStr) / 2;
 
-       ddb_entry->fw_ddb_index = fw_ddb_index;
-       atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY);
-       atomic_set(&ddb_entry->relogin_timer, 0);
-       atomic_set(&ddb_entry->relogin_retry_count, 0);
-       atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
-       list_add_tail(&ddb_entry->list, &ha->ddb_list);
-       ha->fw_ddb_index_map[fw_ddb_index] = ddb_entry;
-       ha->tot_ddbs++;
-
-       return ddb_entry;
-}
-
-/**
- * qla4_is_relogin_allowed - Are we allowed to login?
- * @ha: Pointer to host adapter structure.
- * @conn_err: Last connection error associated with the ddb
- *
- * This routine tests the given connection error to determine if
- * we are allowed to login.
- **/
-int qla4_is_relogin_allowed(struct scsi_qla_host *ha, uint32_t conn_err)
-{
-       uint32_t err_code, login_rsp_sts_class;
-       int relogin = 1;
-
-       err_code = ((conn_err & 0x00ff0000) >> 16);
-       login_rsp_sts_class = ((conn_err & 0x0000ff00) >> 8);
-       if (err_code == 0x1c || err_code == 0x06) {
-               DEBUG2(ql4_printk(KERN_INFO, ha,
-                   ": conn_err=0x%08x, send target completed"
-                   " or access denied failure\n", conn_err));
-               relogin = 0;
-       }
-       if ((err_code == 0x08) && (login_rsp_sts_class == 0x02)) {
-               /* Login Response PDU returned an error.
-                  Login Response Status in Error Code Detail
-                  indicates login should not be retried.*/
-               DEBUG2(ql4_printk(KERN_INFO, ha,
-                   ": conn_err=0x%08x, do not retry relogin\n",
-                   conn_err));
-               relogin = 0;
+       for (i = 0; i < (size / 2) ; i++) {
+               board_id_string[i] = rd_nvram_word(ha, offset);
+               offset += 1;
        }
 
-       return relogin;
-}
-
-static void qla4xxx_flush_AENS(struct scsi_qla_host *ha)
-{
-       unsigned long wtime;
-
-       /* Flush the 0x8014 AEN from the firmware as a result of
-        * Auto connect. We are basically doing get_firmware_ddb()
-        * to determine whether we need to log back in or not.
-        * Trying to do a set ddb before we have processed 0x8014
-        * will result in another set_ddb() for the same ddb. In other
-        * words there will be stale entries in the aen_q.
-        */
-       wtime = jiffies + (2 * HZ);
-       do {
-               if (qla4xxx_get_firmware_state(ha) == QLA_SUCCESS)
-                       if (ha->firmware_state & (BIT_2 | BIT_0))
-                               return;
-
-               if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags))
-                       qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
-
-               msleep(1000);
-       } while (!time_after_eq(jiffies, wtime));
-}
-
-/**
- * qla4xxx_build_ddb_list - builds driver ddb list
- * @ha: Pointer to host adapter structure.
- *
- * This routine searches for all valid firmware ddb entries and builds
- * an internal ddb list. Ddbs that are considered valid are those with
- * a device state of SESSION_ACTIVE.
- * A relogin (set_ddb) is issued for DDBs that are not online.
- **/
-static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha)
-{
-       int status = QLA_ERROR;
-       uint32_t fw_ddb_index = 0;
-       uint32_t next_fw_ddb_index = 0;
-       uint32_t ddb_state;
-       uint32_t conn_err;
-       struct ddb_entry *ddb_entry;
-       struct dev_db_entry *fw_ddb_entry = NULL;
-       dma_addr_t fw_ddb_entry_dma;
-       uint32_t ipv6_device;
-       uint32_t new_tgt;
-
-       qla4xxx_flush_AENS(ha);
-
-       fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
-                       &fw_ddb_entry_dma, GFP_KERNEL);
-       if (fw_ddb_entry == NULL) {
-               DEBUG2(ql4_printk(KERN_INFO, ha, "%s: DMA alloc failed\n",
-                               __func__));
-
-               goto exit_build_ddb_list_no_free;
-       }
-
-       ql4_printk(KERN_INFO, ha, "Initializing DDBs ...\n");
-       for (fw_ddb_index = 0; fw_ddb_index < MAX_DDB_ENTRIES;
-            fw_ddb_index = next_fw_ddb_index) {
-               /* First, let's see if a device exists here */
-               if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, fw_ddb_entry,
-                                           0, NULL, &next_fw_ddb_index,
-                                           &ddb_state, &conn_err,
-                                           NULL, NULL) ==
-                                           QLA_ERROR) {
-                       DEBUG2(printk("scsi%ld: %s: get_ddb_entry, "
-                                     "fw_ddb_index %d failed", ha->host_no,
-                                     __func__, fw_ddb_index));
-                       goto exit_build_ddb_list;
-               }
-
-               DEBUG2(printk("scsi%ld: %s: Getting DDB[%d] ddbstate=0x%x, "
-                             "next_fw_ddb_index=%d.\n", ha->host_no, __func__,
-                             fw_ddb_index, ddb_state, next_fw_ddb_index));
-
-               /* Issue relogin, if necessary. */
-               if (ddb_state == DDB_DS_SESSION_FAILED ||
-                   ddb_state == DDB_DS_NO_CONNECTION_ACTIVE) {
-                       /* Try and login to device */
-                       DEBUG2(printk("scsi%ld: %s: Login to DDB[%d]\n",
-                                     ha->host_no, __func__, fw_ddb_index));
-                       ipv6_device = le16_to_cpu(fw_ddb_entry->options) &
-                                       DDB_OPT_IPV6_DEVICE;
-                       if (qla4_is_relogin_allowed(ha, conn_err) &&
-                                       ((!ipv6_device &&
-                                         *((uint32_t *)fw_ddb_entry->ip_addr))
-                                        || ipv6_device)) {
-                               qla4xxx_set_ddb_entry(ha, fw_ddb_index, 0);
-                               if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index,
-                                                       NULL, 0, NULL,
-                                                       &next_fw_ddb_index,
-                                                       &ddb_state, &conn_err,
-                                                       NULL, NULL)
-                                               == QLA_ERROR) {
-                                       DEBUG2(printk("scsi%ld: %s:"
-                                               "get_ddb_entry %d failed\n",
-                                               ha->host_no,
-                                               __func__, fw_ddb_index));
-                                       goto exit_build_ddb_list;
-                               }
-                       }
-               }
-
-               if (ddb_state != DDB_DS_SESSION_ACTIVE)
-                       goto next_one;
-               /*
-                * if fw_ddb with session active state found,
-                * add to ddb_list
-                */
-               DEBUG2(printk("scsi%ld: %s: DDB[%d] added to list\n",
-                             ha->host_no, __func__, fw_ddb_index));
-
-               /* Add DDB to internal our ddb list. */
-               ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index, &new_tgt);
-               if (ddb_entry == NULL) {
-                       DEBUG2(printk("scsi%ld: %s: Unable to allocate memory "
-                                     "for device at fw_ddb_index %d\n",
-                                     ha->host_no, __func__, fw_ddb_index));
-                       goto exit_build_ddb_list;
-               }
-               /* Fill in the device structure */
-               if (qla4xxx_update_ddb_entry(ha, ddb_entry, fw_ddb_index) ==
-                   QLA_ERROR) {
-                       ha->fw_ddb_index_map[fw_ddb_index] =
-                               (struct ddb_entry *)INVALID_ENTRY;
-
-                       DEBUG2(printk("scsi%ld: %s: update_ddb_entry failed "
-                                     "for fw_ddb_index %d.\n",
-                                     ha->host_no, __func__, fw_ddb_index));
-                       goto exit_build_ddb_list;
-               }
-
-next_one:
-               /* We know we've reached the last device when
-                * next_fw_ddb_index is 0 */
-               if (next_fw_ddb_index == 0)
-                       break;
-       }
-
-       status = QLA_SUCCESS;
-       ql4_printk(KERN_INFO, ha, "DDB list done..\n");
-
-exit_build_ddb_list:
-       dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), fw_ddb_entry,
-               fw_ddb_entry_dma);
-
-exit_build_ddb_list_no_free:
-       return status;
-}
-
-static int qla4xxx_initialize_ddb_list(struct scsi_qla_host *ha)
-{
-       uint16_t fw_ddb_index;
-       int status = QLA_SUCCESS;
-
-       /* free the ddb list if is not empty */
-       if (!list_empty(&ha->ddb_list))
-               qla4xxx_free_ddb_list(ha);
-
-       for (fw_ddb_index = 0; fw_ddb_index < MAX_DDB_ENTRIES; fw_ddb_index++)
-               ha->fw_ddb_index_map[fw_ddb_index] =
-                   (struct ddb_entry *)INVALID_ENTRY;
-
-       ha->tot_ddbs = 0;
-
-       /* Perform device discovery and build ddb list. */
-       status = qla4xxx_build_ddb_list(ha);
-
-       return status;
-}
-
-/**
- * qla4xxx_reinitialize_ddb_list - update the driver ddb list
- * @ha: pointer to host adapter structure.
- *
- * This routine obtains device information from the F/W database after
- * firmware or adapter resets.  The device table is preserved.
- **/
-int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host *ha)
-{
-       int status = QLA_SUCCESS;
-       struct ddb_entry *ddb_entry, *detemp;
-
-       /* Update the device information for all devices. */
-       list_for_each_entry_safe(ddb_entry, detemp, &ha->ddb_list, list) {
-               qla4xxx_update_ddb_entry(ha, ddb_entry,
-                                        ddb_entry->fw_ddb_index);
-               if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) {
-                       atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
-                       DEBUG2(printk ("scsi%ld: %s: ddb index [%d] marked "
-                                      "ONLINE\n", ha->host_no, __func__,
-                                      ddb_entry->fw_ddb_index));
-                       iscsi_unblock_session(ddb_entry->sess);
-               } else if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE)
-                       qla4xxx_mark_device_missing(ha, ddb_entry);
-       }
-       return status;
-}
-
-/**
- * qla4xxx_relogin_device - re-establish session
- * @ha: Pointer to host adapter structure.
- * @ddb_entry: Pointer to device database entry
- *
- * This routine does a session relogin with the specified device.
- * The ddb entry must be assigned prior to making this call.
- **/
-int qla4xxx_relogin_device(struct scsi_qla_host *ha,
-                          struct ddb_entry * ddb_entry)
-{
-       uint16_t relogin_timer;
-
-       relogin_timer = max(ddb_entry->default_relogin_timeout,
-                           (uint16_t)RELOGIN_TOV);
-       atomic_set(&ddb_entry->relogin_timer, relogin_timer);
-
-       DEBUG2(printk("scsi%ld: Relogin ddb [%d]. TOV=%d\n", ha->host_no,
-                     ddb_entry->fw_ddb_index, relogin_timer));
-
-       qla4xxx_set_ddb_entry(ha, ddb_entry->fw_ddb_index, 0);
-
-       return QLA_SUCCESS;
+       memcpy(ha->model_name, board_id_string, size);
 }
 
 static int qla4xxx_config_nvram(struct scsi_qla_host *ha)
@@ -983,6 +496,12 @@ static int qla4xxx_config_nvram(struct scsi_qla_host *ha)
                else
                        return QLA_ERROR;
        }
+
+       if (is_qla4022(ha) || is_qla4032(ha))
+               qla4xxx_set_model_info(ha);
+       else
+               strcpy(ha->model_name, "QLA4010");
+
        DEBUG(printk("scsi%ld: %s: Setting extHwConfig to 0xFFFF%04x\n",
                     ha->host_no, __func__, extHwConfig.Asuint32_t));
 
@@ -1246,23 +765,56 @@ int qla4xxx_start_firmware(struct scsi_qla_host *ha)
        }
        return status;
 }
+/**
+ * qla4xxx_free_ddb_index - Free DDBs reserved by firmware
+ * @ha: pointer to adapter structure
+ *
+ * Since firmware is not running in autoconnect mode the DDB indices should
+ * be freed so that when login happens from user space there are free DDB
+ * indices available.
+ **/
+static void qla4xxx_free_ddb_index(struct scsi_qla_host *ha)
+{
+       int max_ddbs;
+       int ret;
+       uint32_t idx = 0, next_idx = 0;
+       uint32_t state = 0, conn_err = 0;
+
+       max_ddbs =  is_qla40XX(ha) ? MAX_PRST_DEV_DB_ENTRIES :
+                                    MAX_DEV_DB_ENTRIES;
+
+       for (idx = 0; idx < max_ddbs; idx = next_idx) {
+               ret = qla4xxx_get_fwddb_entry(ha, 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) {
+                       DEBUG2(ql4_printk(KERN_INFO, ha,
+                                         "Freeing DDB index = 0x%x\n", idx));
+                       ret = qla4xxx_clear_ddb_entry(ha, idx);
+                       if (ret == QLA_ERROR)
+                               ql4_printk(KERN_ERR, ha,
+                                          "Unable to clear DDB index = "
+                                          "0x%x\n", idx);
+               }
+               if (next_idx == 0)
+                       break;
+       }
+}
 
 
 /**
  * qla4xxx_initialize_adapter - initiailizes hba
  * @ha: Pointer to host adapter structure.
- * @renew_ddb_list: Indicates what to do with the adapter's ddb list
- *     after adapter recovery has completed.
- *     0=preserve ddb list, 1=destroy and rebuild ddb list
  *
  * This routine parforms all of the steps necessary to initialize the adapter.
  *
  **/
-int qla4xxx_initialize_adapter(struct scsi_qla_host *ha,
-                              uint8_t renew_ddb_list)
+int qla4xxx_initialize_adapter(struct scsi_qla_host *ha)
 {
        int status = QLA_ERROR;
-       int8_t ip_address[IP_ADDR_LEN] = {0} ;
 
        ha->eeprom_cmd_data = 0;
 
@@ -1288,47 +840,8 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha,
        if (status == QLA_ERROR)
                goto exit_init_hba;
 
-       /*
-        * FW is waiting to get an IP address from DHCP server: Skip building
-        * the ddb_list and wait for DHCP lease acquired aen to come in
-        * followed by 0x8014 aen" to trigger the tgt discovery process.
-        */
-       if (ha->firmware_state & FW_STATE_CONFIGURING_IP)
-               goto exit_init_online;
-
-       /* Skip device discovery if ip and subnet is zero */
-       if (memcmp(ha->ip_address, ip_address, IP_ADDR_LEN) == 0 ||
-           memcmp(ha->subnet_mask, ip_address, IP_ADDR_LEN) == 0)
-               goto exit_init_online;
+       qla4xxx_free_ddb_index(ha);
 
-       if (renew_ddb_list == PRESERVE_DDB_LIST) {
-               /*
-                * We want to preserve lun states (i.e. suspended, etc.)
-                * for recovery initiated by the driver.  So just update
-                * the device states for the existing ddb_list.
-                */
-               qla4xxx_reinitialize_ddb_list(ha);
-       } else if (renew_ddb_list == REBUILD_DDB_LIST) {
-               /*
-                * We want to build the ddb_list from scratch during
-                * driver initialization and recovery initiated by the
-                * INT_HBA_RESET IOCTL.
-                */
-               status = qla4xxx_initialize_ddb_list(ha);
-               if (status == QLA_ERROR) {
-                       DEBUG2(printk("%s(%ld) Error occurred during build"
-                                     "ddb list\n", __func__, ha->host_no));
-                       goto exit_init_hba;
-               }
-
-       }
-       if (!ha->tot_ddbs) {
-               DEBUG2(printk("scsi%ld: Failed to initialize devices or none "
-                             "present in Firmware device database\n",
-                             ha->host_no));
-       }
-
-exit_init_online:
        set_bit(AF_ONLINE, &ha->flags);
 exit_init_hba:
        if (is_qla8022(ha) && (status == QLA_ERROR)) {
@@ -1342,61 +855,6 @@ exit_init_hba:
        return status;
 }
 
-/**
- * qla4xxx_add_device_dynamically - ddb addition due to an AEN
- * @ha:  Pointer to host adapter structure.
- * @fw_ddb_index:  Firmware's device database index
- *
- * This routine processes adds a device as a result of an 8014h AEN.
- **/
-static void qla4xxx_add_device_dynamically(struct scsi_qla_host *ha,
-                                          uint32_t fw_ddb_index)
-{
-       struct ddb_entry * ddb_entry;
-       uint32_t new_tgt;
-
-       /* First allocate a device structure */
-       ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index, &new_tgt);
-       if (ddb_entry == NULL) {
-               DEBUG2(printk(KERN_WARNING
-                             "scsi%ld: Unable to allocate memory to add "
-                             "fw_ddb_index %d\n", ha->host_no, fw_ddb_index));
-               return;
-       }
-
-       if (!new_tgt && (ddb_entry->fw_ddb_index != fw_ddb_index)) {
-               /* Target has been bound to a new fw_ddb_index */
-               qla4xxx_free_ddb(ha, ddb_entry);
-               ddb_entry = qla4xxx_alloc_ddb(ha, fw_ddb_index);
-               if (ddb_entry == NULL) {
-                       DEBUG2(printk(KERN_WARNING
-                               "scsi%ld: Unable to allocate memory"
-                               " to add fw_ddb_index %d\n",
-                               ha->host_no, fw_ddb_index));
-                       return;
-               }
-       }
-       if (qla4xxx_update_ddb_entry(ha, ddb_entry, fw_ddb_index) ==
-                                   QLA_ERROR) {
-               ha->fw_ddb_index_map[fw_ddb_index] =
-                                       (struct ddb_entry *)INVALID_ENTRY;
-               DEBUG2(printk(KERN_WARNING
-                             "scsi%ld: failed to add new device at index "
-                             "[%d]\n Unable to retrieve fw ddb entry\n",
-                             ha->host_no, fw_ddb_index));
-               qla4xxx_free_ddb(ha, ddb_entry);
-               return;
-       }
-
-       if (qla4xxx_add_sess(ddb_entry)) {
-               DEBUG2(printk(KERN_WARNING
-                             "scsi%ld: failed to add new device at index "
-                             "[%d]\n Unable to add connection and session\n",
-                             ha->host_no, fw_ddb_index));
-               qla4xxx_free_ddb(ha, ddb_entry);
-       }
-}
-
 /**
  * qla4xxx_process_ddb_changed - process ddb state change
  * @ha - Pointer to host adapter structure.
@@ -1409,88 +867,94 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
                uint32_t state, uint32_t conn_err)
 {
        struct ddb_entry * ddb_entry;
+       uint32_t old_fw_ddb_device_state;
+       int status = QLA_ERROR;
 
        /* check for out of range index */
        if (fw_ddb_index >= MAX_DDB_ENTRIES)
-               return QLA_ERROR;
+               goto exit_ddb_event;
 
        /* Get the corresponging ddb entry */
        ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, fw_ddb_index);
        /* Device does not currently exist in our database. */
        if (ddb_entry == NULL) {
-               if (state == DDB_DS_SESSION_ACTIVE)
-                       qla4xxx_add_device_dynamically(ha, fw_ddb_index);
-               return QLA_SUCCESS;
+               ql4_printk(KERN_ERR, ha, "%s: No ddb_entry at FW index [%d]\n",
+                          __func__, fw_ddb_index);
+
+               if (state == DDB_DS_NO_CONNECTION_ACTIVE)
+                       clear_bit(fw_ddb_index, ha->ddb_idx_map);
+
+               goto exit_ddb_event;
        }
 
-       /* Device already exists in our database. */
-       DEBUG2(printk("scsi%ld: %s DDB - old state= 0x%x, new state=0x%x for "
-                     "index [%d]\n", ha->host_no, __func__,
-                     ddb_entry->fw_ddb_device_state, state, fw_ddb_index));
+       old_fw_ddb_device_state = ddb_entry->fw_ddb_device_state;
+       DEBUG2(ql4_printk(KERN_INFO, ha,
+                         "%s: DDB - old state = 0x%x, new state = 0x%x for "
+                         "index [%d]\n", __func__,
+                         ddb_entry->fw_ddb_device_state, state, fw_ddb_index));
 
        ddb_entry->fw_ddb_device_state = state;
-       /* Device is back online. */
-       if ((ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) &&
-          (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE)) {
-               atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
-               atomic_set(&ddb_entry->relogin_retry_count, 0);
-               atomic_set(&ddb_entry->relogin_timer, 0);
-               clear_bit(DF_RELOGIN, &ddb_entry->flags);
-               iscsi_unblock_session(ddb_entry->sess);
-               iscsi_session_event(ddb_entry->sess,
-                                   ISCSI_KEVENT_CREATE_SESSION);
-               /*
-                * Change the lun state to READY in case the lun TIMEOUT before
-                * the device came back.
-                */
-       } else if (ddb_entry->fw_ddb_device_state != DDB_DS_SESSION_ACTIVE) {
-               /* Device went away, mark device missing */
-               if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE) {
-                       DEBUG2(ql4_printk(KERN_INFO, ha, "%s mark missing "
-                                       "ddb_entry 0x%p sess 0x%p conn 0x%p\n",
-                                       __func__, ddb_entry,
-                                       ddb_entry->sess, ddb_entry->conn));
-                       qla4xxx_mark_device_missing(ha, ddb_entry);
-               }
 
-               /*
-                * Relogin if device state changed to a not active state.
-                * However, do not relogin if a RELOGIN is in process, or
-                * we are not allowed to relogin to this DDB.
-                */
-               if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_FAILED &&
-                   !test_bit(DF_RELOGIN, &ddb_entry->flags) &&
-                   qla4_is_relogin_allowed(ha, conn_err)) {
+       switch (old_fw_ddb_device_state) {
+       case DDB_DS_LOGIN_IN_PROCESS:
+               switch (state) {
+               case DDB_DS_SESSION_ACTIVE:
+               case DDB_DS_DISCOVERY:
+                       iscsi_conn_start(ddb_entry->conn);
+                       iscsi_conn_login_event(ddb_entry->conn,
+                                              ISCSI_CONN_STATE_LOGGED_IN);
+                       qla4xxx_update_session_conn_param(ha, ddb_entry);
+                       status = QLA_SUCCESS;
+                       break;
+               case DDB_DS_SESSION_FAILED:
+               case DDB_DS_NO_CONNECTION_ACTIVE:
+                       iscsi_conn_login_event(ddb_entry->conn,
+                                              ISCSI_CONN_STATE_FREE);
+                       status = QLA_SUCCESS;
+                       break;
+               }
+               break;
+       case DDB_DS_SESSION_ACTIVE:
+               switch (state) {
+               case DDB_DS_SESSION_FAILED:
                        /*
-                        * This triggers a relogin.  After the relogin_timer
-                        * expires, the relogin gets scheduled.  We must wait a
-                        * minimum amount of time since receiving an 0x8014 AEN
-                        * with failed device_state or a logout response before
-                        * we can issue another relogin.
+                        * iscsi_session failure  will cause userspace to
+                        * stop the connection which in turn would block the
+                        * iscsi_session and start relogin
                         */
-                       /* Firmware pads this timeout: (time2wait +1).
-                        * Driver retry to login should be longer than F/W.
-                        * Otherwise F/W will fail
-                        * set_ddb() mbx cmd with 0x4005 since it still
-                        * counting down its time2wait.
-                        */
-                       atomic_set(&ddb_entry->relogin_timer, 0);
-                       atomic_set(&ddb_entry->retry_relogin_timer,
-                                  ddb_entry->default_time2wait + 4);
-                       DEBUG(printk("scsi%ld: %s: ddb[%d] "
-                           "initiate relogin after %d seconds\n",
-                           ha->host_no, __func__,
-                           ddb_entry->fw_ddb_index,
-                           ddb_entry->default_time2wait + 4));
-               } else {
-                       DEBUG(printk("scsi%ld: %s: ddb[%d] "
-                           "relogin not initiated, state = %d, "
-                           "ddb_entry->flags = 0x%lx\n",
-                           ha->host_no, __func__,
-                           ddb_entry->fw_ddb_index,
-                           ddb_entry->fw_ddb_device_state,
-                           ddb_entry->flags));
+                       iscsi_session_failure(ddb_entry->sess->dd_data,
+                                             ISCSI_ERR_CONN_FAILED);
+                       status = QLA_SUCCESS;
+                       break;
+               case DDB_DS_NO_CONNECTION_ACTIVE:
+                       clear_bit(fw_ddb_index, ha->ddb_idx_map);
+                       status = QLA_SUCCESS;
+                       break;
+               }
+               break;
+       case DDB_DS_SESSION_FAILED:
+               switch (state) {
+               case DDB_DS_SESSION_ACTIVE:
+               case DDB_DS_DISCOVERY:
+                       iscsi_conn_start(ddb_entry->conn);
+                       iscsi_conn_login_event(ddb_entry->conn,
+                                              ISCSI_CONN_STATE_LOGGED_IN);
+                       qla4xxx_update_session_conn_param(ha, ddb_entry);
+                       status = QLA_SUCCESS;
+                       break;
+               case DDB_DS_SESSION_FAILED:
+                       iscsi_session_failure(ddb_entry->sess->dd_data,
+                                             ISCSI_ERR_CONN_FAILED);
+                       status = QLA_SUCCESS;
+                       break;
                }
+               break;
+       default:
+               DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Unknown Event\n",
+                               __func__));
+               break;
        }
-       return QLA_SUCCESS;
+
+exit_ddb_event:
+       return status;
 }