diff --git a/qla2x00t/qla2x00-target/README b/qla2x00t/qla2x00-target/README index 42312c354..fbfe74519 100644 --- a/qla2x00t/qla2x00-target/README +++ b/qla2x00t/qla2x00-target/README @@ -13,15 +13,16 @@ all necessary callbacks, but it's still capable to work as initiator only. Mode, when a host acts as the initiator and the target simultaneously, is supported as well. -This version is compatible with SCST core version 1.0.0 and higher and -Linux kernel 2.6.26 and higher. Backport patches to kernels earlier than -2.6.26 are welcome. +This version is compatible with SCST core version 1.0.1 and higher and +Linux kernel 2.6.27 and higher. Backport patches to kernels earlier than +2.6.27 are welcome. -The original initiator driver was taken from the kernel 2.6.26. +The original initiator driver was taken from the kernel 2.6.27. -If you need to use this driver on kernels prior 2.6.26, it is +If you need to use this driver on kernels prior 2.6.27, it is recommended to use version 1.0.0.x of this driver, taken from branch -1.0.0.x. +1.0.0.x. For 2.6.26 you can also use version of this driver from SVN +trunk/ revision 577. See also "ToDo" file for list of known issues and unimplemented features. diff --git a/qla2x00t/qla2x00-target/qla2x00t.c b/qla2x00t/qla2x00-target/qla2x00t.c index 3ef2d107e..accfabc64 100644 --- a/qla2x00t/qla2x00-target/qla2x00t.c +++ b/qla2x00t/qla2x00-target/qla2x00t.c @@ -178,7 +178,7 @@ static void __q2t_send_notify_ack(scsi_qla_host_t *ha, /* Send marker if required */ if (tgt_data.issue_marker(ha) != QLA_SUCCESS) { PRINT_ERROR("qla2x00tgt(%ld): __QLA2X00_MARKER() " - "failed", ha->instance); + "failed", ha->host_no); goto out; } @@ -310,7 +310,7 @@ static void q2t_unreg_sess(struct q2t_sess *sess) list_del(&sess->list); PRINT_INFO("qla2x00tgt(%ld): session for loop_id %d deleted", - sess->tgt->ha->instance, sess->loop_id); + sess->tgt->ha->host_no, sess->loop_id); /* * Any commands for this session will be finished regularly, @@ -431,7 +431,7 @@ out: out_err: PRINT_ERROR("qla2x00tgt(%ld): PCI mapping failed: sg_cnt=%d", - prm->tgt->ha->instance, prm->sg_cnt); + prm->tgt->ha->host_no, prm->sg_cnt); res = -1; goto out; } @@ -689,7 +689,7 @@ static int q2t_xmit_response(struct scst_cmd *scst_cmd) TRACE(TRACE_MGMT_MINOR, "qla2x00tgt(%ld): terminating exchange " "for aborted scst_cmd=%p (tag=%lld)", - ha->instance, scst_cmd, scst_cmd_get_tag(scst_cmd)); + ha->host_no, scst_cmd, scst_cmd_get_tag(scst_cmd)); scst_set_delivery_status(scst_cmd, SCST_CMD_DELIVERY_ABORTED); @@ -721,7 +721,7 @@ static int q2t_xmit_response(struct scst_cmd *scst_cmd) if (!is_send_status) { /* ToDo, after it's done in SCST */ PRINT_ERROR("qla2x00tgt(%ld): is_send_status not set: " - "feature not implemented", prm.tgt->ha->instance); + "feature not implemented", prm.tgt->ha->host_no); res = SCST_TGT_RES_FATAL_ERROR; goto out; } @@ -732,12 +732,12 @@ static int q2t_xmit_response(struct scst_cmd *scst_cmd) /* Send marker if required */ if (tgt_data.issue_marker(prm.tgt->ha) != QLA_SUCCESS) { PRINT_ERROR("qla2x00tgt(%ld): __QLA2X00_MARKER() " - "failed", prm.tgt->ha->instance); + "failed", prm.tgt->ha->host_no); res = SCST_TGT_RES_FATAL_ERROR; goto out_unlock; } - TRACE_DBG("CTIO start: ha(%d)", (int) prm.tgt->ha->instance); + TRACE_DBG("CTIO start: ha(%d)", (int) prm.tgt->ha->host_no); if (q2t_has_data(scst_cmd)) { if (q2t_pci_map_calc_cnt(&prm) != 0) { @@ -854,12 +854,12 @@ static int q2t_rdy_to_xfer(struct scst_cmd *scst_cmd) /* Send marker if required */ if (tgt_data.issue_marker(prm.tgt->ha) != QLA_SUCCESS) { PRINT_ERROR("qla2x00tgt(%ld): __QLA2X00_MARKER() " - "failed", prm.tgt->ha->instance); + "failed", prm.tgt->ha->host_no); res = SCST_TGT_RES_FATAL_ERROR; goto out_unlock; } - TRACE_DBG("CTIO_start: ha(%d)", (int) prm.tgt->ha->instance); + TRACE_DBG("CTIO_start: ha(%d)", (int) prm.tgt->ha->host_no); /* Calculate number of entries and segments required */ if (q2t_pci_map_calc_cnt(&prm) != 0) { @@ -906,14 +906,14 @@ static void q2t_send_term_exchange(scsi_qla_host_t *ha, struct q2t_cmd *cmd, /* Send marker if required */ if (tgt_data.issue_marker(ha) != QLA_SUCCESS) { PRINT_ERROR("qla2x00tgt(%ld): __QLA2X00_MARKER() " - "failed", ha->instance); + "failed", ha->host_no); goto out_unlock; } ctio = (ctio_ret_entry_t *)tgt_data.req_pkt(ha); if (ctio == NULL) { PRINT_ERROR("qla2x00tgt(%ld): %s failed: unable to allocate " - "request packet", ha->instance, __func__); + "request packet", ha->host_no, __func__); goto out_unlock; } @@ -1038,19 +1038,19 @@ static void q2t_do_ctio_completion(scsi_qla_host_t *ha, TRACE(TRACE_MGMT_MINOR, "qla2x00tgt(%ld): CTIO with " "status %#x received (LIP_RESET=e, ABORTED=2, " "TARGET_RESET=17, TIMEOUT=b, " - "INVALID_RX_ID=8)", ha->instance, status); + "INVALID_RX_ID=8)", ha->host_no, status); break; case CTIO_PORT_LOGGED_OUT: case CTIO_PORT_UNAVAILABLE: PRINT_INFO("qla2x00tgt(%ld): CTIO with PORT LOGGED " "OUT (29) or PORT UNAVAILABLE (28) status %x " - "received", ha->instance, status); + "received", ha->host_no, status); break; default: PRINT_ERROR("qla2x00tgt(%ld): CTIO with error status " - "0x%x received", ha->instance, status); + "0x%x received", ha->host_no, status); break; } q2t_modify_command_count(ha, 1, 0); @@ -1067,7 +1067,7 @@ static void q2t_do_ctio_completion(scsi_qla_host_t *ha, if (unlikely(scst_cmd == NULL)) { PRINT_INFO("qla2x00tgt(%ld): Suspicious: unable to " "find the command with handle %x", - ha->instance, handle); + ha->host_no, handle); goto out; } if (unlikely(err)) { @@ -1082,7 +1082,7 @@ static void q2t_do_ctio_completion(scsi_qla_host_t *ha, PRINT_INFO("qla2x00tgt(%ld): Suspicious: " "ctio_completion for non-existing session " "(loop_id %d, tag %d)", - ha->instance, loop_id, tag); + ha->host_no, loop_id, tag); goto out; } @@ -1090,7 +1090,7 @@ static void q2t_do_ctio_completion(scsi_qla_host_t *ha, if (scst_cmd == NULL) { PRINT_INFO("qla2x00tgt(%ld): Suspicious: unable to " "find the command with tag %d (loop_id %d)", - ha->instance, tag, loop_id); + ha->host_no, tag, loop_id); goto out; } if (unlikely(err)) { @@ -1139,7 +1139,7 @@ static void q2t_do_ctio_completion(scsi_qla_host_t *ha, goto out_free; } else { PRINT_ERROR("qla2x00tgt(%ld): A command in state (%d) should " - "not return a CTIO complete", ha->instance, cmd->state); + "not return a CTIO complete", ha->host_no, cmd->state); goto out_free; } @@ -1225,7 +1225,7 @@ static int q2t_do_send_cmd_to_scst(scsi_qla_host_t *ha, struct q2t_cmd *cmd) if (cmd->scst_cmd == NULL) { PRINT_ERROR("qla2x00tgt(%ld): scst_rx_cmd() failed for " - "host %ld(%p)", ha->instance, ha->host_no, ha); + "host %ld(%p)", ha->host_no, ha->host_no, ha); res = -EFAULT; goto out; } @@ -1258,7 +1258,7 @@ static int q2t_do_send_cmd_to_scst(scsi_qla_host_t *ha, struct q2t_cmd *cmd) break; default: PRINT_ERROR("qla2x00tgt(%ld): Unknown task code %x, use " - "ORDERED instead", ha->instance, cmd->atio.task_codes); + "ORDERED instead", ha->host_no, cmd->atio.task_codes); cmd->scst_cmd->queue_type = SCST_CMD_QUEUE_ORDERED; break; } @@ -1291,7 +1291,7 @@ static void q2t_alloc_session_done(struct scst_session *scst_sess, unsigned long flags; PRINT_INFO("qla2x00tgt(%ld): Session initialization failed", - ha->instance); + ha->host_no); spin_lock_irqsave(&ha->hardware_lock, flags); q2t_unreg_sess(sess); @@ -1330,7 +1330,7 @@ static char *q2t_find_name(scsi_qla_host_t *ha, int loop_id) if (wwn_found == 0) { TRACE_MGMT_DBG("qla2x00tgt(%ld): Unable to find wwn login for " - "loop id %d", ha->instance, loop_id); + "loop id %d", ha->host_no, loop_id); kfree(wwn_str); wwn_str = NULL; } @@ -1372,8 +1372,8 @@ static int q2t_send_cmd_to_scst(scsi_qla_host_t *ha, atio_entry_t *atio) loop_id = GET_TARGET_ID(ha, atio); pn = (uint16_t *)(((char *)atio)+0x2a); - TRACE_DBG("To SCST instance=%ld l_id=%d tag=%d wwpn=%04x%04x%04x%04x", - ha->instance, loop_id, le16_to_cpu(atio->exchange_id), + TRACE_DBG("To SCST host_no=%ld l_id=%d tag=%d wwpn=%04x%04x%04x%04x", + ha->host_no, loop_id, le16_to_cpu(atio->exchange_id), le16_to_cpu(pn[0]), le16_to_cpu(pn[1]), le16_to_cpu(pn[2]), @@ -1442,7 +1442,7 @@ static int q2t_send_cmd_to_scst(scsi_qla_host_t *ha, atio_entry_t *atio) if (sess->scst_sess == NULL) { PRINT_ERROR("qla2x00tgt(%ld): scst_register_session() failed " - "for host %ld(%p)", ha->instance, ha->host_no, ha); + "for host %ld(%p)", ha->host_no, ha->host_no, ha); res = -EFAULT; goto out_free_sess; } @@ -1492,7 +1492,7 @@ static int q2t_handle_task_mgmt(scsi_qla_host_t *ha, notify_entry_t *iocb) sess = q2t_find_sess_by_lid(tgt, loop_id); if (sess == NULL) { TRACE(TRACE_MGMT, "qla2x00tgt(%ld): task mgmt fn 0x%x for " - "non-existant session", ha->instance, iocb->task_flags); + "non-existant session", ha->host_no, iocb->task_flags); res = -EFAULT; goto out; } @@ -1545,13 +1545,13 @@ static int q2t_handle_task_mgmt(scsi_qla_host_t *ha, notify_entry_t *iocb) default: PRINT_ERROR("qla2x00tgt(%ld): Unknown task mgmt fn 0x%x", - ha->instance, iocb->task_flags); + ha->host_no, iocb->task_flags); break; } if (rc != 0) { PRINT_ERROR("qla2x00tgt(%ld): scst_rx_mgmt_fn_lun() failed: %d", - ha->instance, rc); + ha->host_no, rc); res = -EFAULT; goto out_free; } @@ -1582,7 +1582,7 @@ static int q2t_abort_task(scsi_qla_host_t *ha, notify_entry_t *iocb) sess = q2t_find_sess_by_lid(ha->tgt, loop_id); if (sess == NULL) { TRACE(TRACE_MGMT, "qla2x00tgt(%ld): task abort for unexisting " - "session", ha->instance); + "session", ha->host_no); res = -EFAULT; goto out; } @@ -1601,7 +1601,7 @@ static int q2t_abort_task(scsi_qla_host_t *ha, notify_entry_t *iocb) SCST_ATOMIC, mcmd); if (rc != 0) { PRINT_ERROR("qla2x00tgt(%ld): scst_rx_mgmt_fn_tag() failed: %d", - ha->instance, rc); + ha->host_no, rc); res = -EFAULT; goto out_free; } @@ -1684,7 +1684,7 @@ static void q2t_handle_imm_notify(scsi_qla_host_t *ha, notify_entry_t *iocb) case IMM_NTFY_IOCB_OVERFLOW: PRINT_ERROR("qla2x00tgt(%ld): Cannot provide requested " - "capability (IOCB overflow)", ha->instance); + "capability (IOCB overflow)", ha->host_no); break; case IMM_NTFY_ABORT_TASK: @@ -1721,7 +1721,7 @@ static void q2t_handle_imm_notify(scsi_qla_host_t *ha, notify_entry_t *iocb) case IMM_NTFY_RESOURCE: PRINT_ERROR("qla2x00tgt(%ld): Out of resources, host %ld", - ha->instance, ha->host_no); + ha->host_no, ha->host_no); break; case IMM_NTFY_MSG_RX: @@ -1732,7 +1732,7 @@ static void q2t_handle_imm_notify(scsi_qla_host_t *ha, notify_entry_t *iocb) default: PRINT_ERROR("qla2x00tgt(%ld): Received unknown immediate " - "notify status %x", ha->instance, status); + "notify status %x", ha->host_no, status); break; } @@ -1765,7 +1765,7 @@ static void q2t_response_pkt(scsi_qla_host_t *ha, sts_entry_t *pkt) if (pkt->entry_status != 0) { PRINT_ERROR("qla2x00tgt(%ld): Received response packet %x " - "with error status %x", ha->instance, pkt->entry_type, + "with error status %x", ha->host_no, pkt->entry_type, pkt->entry_status); goto out; } @@ -1775,10 +1775,10 @@ static void q2t_response_pkt(scsi_qla_host_t *ha, sts_entry_t *pkt) if (ha->flags.enable_target_mode && ha->tgt != NULL) { int rc; atio = (atio_entry_t *)pkt; - TRACE_DBG("ACCEPT_TGT_IO instance %ld status %04x " + TRACE_DBG("ACCEPT_TGT_IO host_no %ld status %04x " "lun %04x read/write %d data_length %08x " "target_id %02x exchange_id %04x ", - ha->instance, le16_to_cpu(atio->status), + ha->host_no, le16_to_cpu(atio->status), le16_to_cpu(atio->lun), atio->execution_codes, le32_to_cpu(atio->data_length), @@ -1787,7 +1787,7 @@ static void q2t_response_pkt(scsi_qla_host_t *ha, sts_entry_t *pkt) if (atio->status != __constant_cpu_to_le16(ATIO_CDB_VALID)) { PRINT_ERROR("qla2x00tgt(%ld): ATIO with error " - "status %x received", ha->instance, + "status %x received", ha->host_no, le16_to_cpu(atio->status)); break; } @@ -1806,41 +1806,41 @@ static void q2t_response_pkt(scsi_qla_host_t *ha, sts_entry_t *pkt) PRINT_INFO("qla2x00tgt(%ld): Unable to " "send the command to SCSI target " "mid-level, sending BUSY status", - ha->instance); + ha->host_no); } q2t_send_busy(ha, atio); } } } else if (!ha->tgt->tgt_shutdown) { PRINT_ERROR("qla2x00tgt(%ld): ATIO, but target mode " - "disabled", ha->instance); + "disabled", ha->host_no); } break; case CONTINUE_TGT_IO_TYPE: if (ha->flags.enable_target_mode && ha->tgt != NULL) { ctio_common_entry_t *entry = (ctio_common_entry_t *)pkt; - TRACE_DBG("CONTINUE_TGT_IO: instance %ld", - ha->instance); + TRACE_DBG("CONTINUE_TGT_IO: host_no %ld", + ha->host_no); q2t_do_ctio_completion(ha, entry->handle, le16_to_cpu(entry->status), entry); } else if (!ha->tgt->tgt_shutdown) { PRINT_ERROR("qla2x00tgt(%ld): CTIO, but target mode " - "disabled", ha->instance); + "disabled", ha->host_no); } break; case CTIO_A64_TYPE: if (ha->flags.enable_target_mode && ha->tgt != NULL) { ctio_common_entry_t *entry = (ctio_common_entry_t *)pkt; - TRACE_DBG("CTIO_A64: instance %ld", ha->instance); + TRACE_DBG("CTIO_A64: host_no %ld", ha->host_no); q2t_do_ctio_completion(ha, entry->handle, le16_to_cpu(entry->status), entry); } else if (!ha->tgt->tgt_shutdown) { PRINT_ERROR("qla2x00tgt(%ld): CTIO_A64, but target " - "mode disabled", ha->instance); + "mode disabled", ha->host_no); } break; @@ -1852,7 +1852,7 @@ static void q2t_response_pkt(scsi_qla_host_t *ha, sts_entry_t *pkt) case NOTIFY_ACK_TYPE: if (ha->tgt == NULL) { PRINT_ERROR("qla2x00tgt(%ld): NOTIFY_ACK recieved " - "with NULL tgt", ha->instance); + "with NULL tgt", ha->host_no); } else if (ha->tgt->notify_ack_expected > 0) { nack_entry_t *entry = (nack_entry_t *)pkt; TRACE_DBG("NOTIFY_ACK seq %04x status %x", @@ -1862,12 +1862,12 @@ static void q2t_response_pkt(scsi_qla_host_t *ha, sts_entry_t *pkt) if (entry->status != __constant_cpu_to_le16(NOTIFY_ACK_SUCCESS)) { PRINT_ERROR("qla2x00tgt(%ld): NOTIFY_ACK " - "failed %x", ha->instance, + "failed %x", ha->host_no, le16_to_cpu(entry->status)); } } else { PRINT_ERROR("qla2x00tgt(%ld): Unexpected NOTIFY_ACK " - "received", ha->instance); + "received", ha->host_no); } break; @@ -1888,13 +1888,13 @@ static void q2t_response_pkt(scsi_qla_host_t *ha, sts_entry_t *pkt) tgt->modify_lun_expected--; if (entry->status != MODIFY_LUN_SUCCESS) { PRINT_ERROR("qla2x00tgt(%ld): MODIFY_LUN " - "failed %x", ha->instance, + "failed %x", ha->host_no, entry->status); } tgt->disable_lun_status = entry->status; } else { PRINT_ERROR("qla2x00tgt(%ld): Unexpected MODIFY_LUN " - "received", (ha != NULL) ?ha->instance :-1); + "received", (ha != NULL) ? ha->host_no : -1); } break; @@ -1917,7 +1917,7 @@ static void q2t_response_pkt(scsi_qla_host_t *ha, sts_entry_t *pkt) } else if (entry->status != ENABLE_LUN_SUCCESS) { PRINT_ERROR("qla2x00tgt(%ld): ENABLE_LUN " "failed %x", - ha->instance, entry->status); + ha->host_no, entry->status); ha->flags.enable_target_mode = ~ha->flags.enable_target_mode; } /* else success */ @@ -1927,7 +1927,7 @@ static void q2t_response_pkt(scsi_qla_host_t *ha, sts_entry_t *pkt) default: PRINT_INFO("qla2x00tgt(%ld): Received unknown response pkt " - "type %x", ha->instance, pkt->entry_type); + "type %x", ha->host_no, pkt->entry_type); break; } @@ -2051,7 +2051,7 @@ static void q2t_host_action(scsi_qla_host_t *ha, if (ha->flags.enable_64bit_addressing) { PRINT_INFO("qla2x00tgt(%ld): 64 Bit PCI " - "Addressing Enabled", ha->instance); + "Addressing Enabled", ha->host_no); tgt->tgt_enable_64bit_addr = 1; /* 3 is reserved */ sg_tablesize = @@ -2060,7 +2060,7 @@ static void q2t_host_action(scsi_qla_host_t *ha, tgt->datasegs_per_cont = DATASEGS_PER_CONT64; } else { PRINT_INFO("qla2x00tgt(%ld): Using 32 Bit " - "PCI Addressing", ha->instance); + "PCI Addressing", ha->host_no); sg_tablesize = QLA_MAX_SG32(ha->request_q_length - 3); tgt->datasegs_per_cmd = DATASEGS_PER_COMMAND32; @@ -2076,7 +2076,7 @@ static void q2t_host_action(scsi_qla_host_t *ha, kfree(wwn); if (!tgt->scst_tgt) { PRINT_ERROR("qla2x00tgt(%ld): scst_register() " - "failed for host %ld(%p)", ha->instance, + "failed for host %ld(%p)", ha->host_no, ha->host_no, ha); kfree(tgt); goto out; @@ -2090,7 +2090,7 @@ static void q2t_host_action(scsi_qla_host_t *ha, spin_unlock_irqrestore(&ha->hardware_lock, flags); TRACE_DBG("Enable lun for host %ld(%ld,%p)", - ha->host_no, ha->instance, ha); + ha->host_no, ha->host_no, ha); tgt_data.enable_lun(ha); break; @@ -2113,7 +2113,7 @@ static void q2t_host_action(scsi_qla_host_t *ha, spin_unlock_irqrestore(&ha->hardware_lock, flags); TRACE_DBG("Shutting down host %ld(%ld,%p)", - ha->host_no, ha->instance, ha); + ha->host_no, ha->host_no, ha); scst_unregister(tgt->scst_tgt); /* * Free of tgt happens via callback q2t_target_release diff --git a/qla2x00t/qla_attr.c b/qla2x00t/qla_attr.c index 4e47a6a32..0d987947a 100644 --- a/qla2x00t/qla_attr.c +++ b/qla2x00t/qla_attr.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #ifdef CONFIG_SCSI_QLA2XXX_TARGET @@ -325,7 +326,6 @@ qla2x00_update_portdb(struct device *dev, struct device_attribute *attr, return size; } - static DEVICE_ATTR(port_database, S_IRUGO|S_IWUSR, qla2x00_show_port_database, @@ -340,18 +340,12 @@ qla2x00_sysfs_read_fw_dump(struct kobject *kobj, { struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); - char *rbuf = (char *)ha->fw_dump; if (ha->fw_dump_reading == 0) return 0; - if (off > ha->fw_dump_len) - return 0; - if (off + count > ha->fw_dump_len) - count = ha->fw_dump_len - off; - memcpy(buf, &rbuf[off], count); - - return (count); + return memory_read_from_buffer(buf, count, &off, ha->fw_dump, + ha->fw_dump_len); } static ssize_t @@ -414,20 +408,13 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, { struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); - int size = ha->nvram_size; - char *nvram_cache = ha->nvram; - if (!capable(CAP_SYS_ADMIN) || off > size || count == 0) + if (!capable(CAP_SYS_ADMIN)) return 0; - if (off + count > size) { - size -= off; - count = size; - } /* Read NVRAM data from cache. */ - memcpy(buf, &nvram_cache[off], count); - - return count; + return memory_read_from_buffer(buf, count, &off, ha->nvram, + ha->nvram_size); } static ssize_t @@ -495,14 +482,9 @@ qla2x00_sysfs_read_optrom(struct kobject *kobj, if (ha->optrom_state != QLA_SREADING) return 0; - if (off > ha->optrom_region_size) - return 0; - if (off + count > ha->optrom_region_size) - count = ha->optrom_region_size - off; - memcpy(buf, &ha->optrom_buffer[off], count); - - return count; + return memory_read_from_buffer(buf, count, &off, ha->optrom_buffer, + ha->optrom_region_size); } static ssize_t @@ -694,20 +676,12 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj, { struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); - int size = ha->vpd_size; - char *vpd_cache = ha->vpd; - if (!capable(CAP_SYS_ADMIN) || off > size || count == 0) + if (!capable(CAP_SYS_ADMIN)) return 0; - if (off + count > size) { - size -= off; - count = size; - } /* Read NVRAM data from cache. */ - memcpy(buf, &vpd_cache[off], count); - - return count; + return memory_read_from_buffer(buf, count, &off, ha->vpd, ha->vpd_size); } static ssize_t @@ -877,8 +851,10 @@ qla2x00_serial_num_show(struct device *dev, struct device_attribute *attr, scsi_qla_host_t *ha = shost_priv(class_to_shost(dev)); uint32_t sn; - if (IS_FWI2_CAPABLE(ha)) - return snprintf(buf, PAGE_SIZE, "\n"); + if (IS_FWI2_CAPABLE(ha)) { + qla2xxx_get_vpd_field(ha, "SN", buf, PAGE_SIZE); + return snprintf(buf, PAGE_SIZE, "%s\n", buf); + } sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1; return snprintf(buf, PAGE_SIZE, "%c%05d\n", 'A' + sn / 100000, @@ -1129,6 +1105,16 @@ qla2x00_optrom_fw_version_show(struct device *dev, ha->fw_revision[3]); } +static ssize_t +qla2x00_total_isp_aborts_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + scsi_qla_host_t *ha = shost_priv(class_to_shost(dev)); + + return snprintf(buf, PAGE_SIZE, "%d\n", + ha->qla_stats.total_isp_aborts); +} + static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL); static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL); static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL); @@ -1151,6 +1137,8 @@ static DEVICE_ATTR(optrom_fcode_version, S_IRUGO, qla2x00_optrom_fcode_version_show, NULL); static DEVICE_ATTR(optrom_fw_version, S_IRUGO, qla2x00_optrom_fw_version_show, NULL); +static DEVICE_ATTR(total_isp_aborts, S_IRUGO, qla2x00_total_isp_aborts_show, + NULL); struct device_attribute *qla2x00_host_attrs[] = { &dev_attr_driver_version, @@ -1169,10 +1157,11 @@ struct device_attribute *qla2x00_host_attrs[] = { &dev_attr_optrom_efi_version, &dev_attr_optrom_fcode_version, &dev_attr_optrom_fw_version, + &dev_attr_total_isp_aborts, #ifdef CONFIG_SCSI_QLA2XXX_TARGET - &dev_attr_target_mode_enabled, - &dev_attr_resource_counts, - &dev_attr_port_database, + &dev_attr_target_mode_enabled, + &dev_attr_resource_counts, + &dev_attr_port_database, #endif NULL, }; @@ -1297,26 +1286,50 @@ qla2x00_get_starget_port_id(struct scsi_target *starget) } static void -qla2x00_get_rport_loss_tmo(struct fc_rport *rport) +qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) { - struct Scsi_Host *host = rport_to_shost(rport); - scsi_qla_host_t *ha = shost_priv(host); - - rport->dev_loss_tmo = ha->port_down_retry_count + 5; + if (timeout) + rport->dev_loss_tmo = timeout; + else + rport->dev_loss_tmo = 1; } static void -qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) +qla2x00_dev_loss_tmo_callbk(struct fc_rport *rport) { struct Scsi_Host *host = rport_to_shost(rport); - scsi_qla_host_t *ha = shost_priv(host); + fc_port_t *fcport = *(fc_port_t **)rport->dd_data; - if (timeout) - ha->port_down_retry_count = timeout; - else - ha->port_down_retry_count = 1; + qla2x00_abort_fcport_cmds(fcport); - rport->dev_loss_tmo = ha->port_down_retry_count + 5; + /* + * Transport has effectively 'deleted' the rport, clear + * all local references. + */ + spin_lock_irq(host->host_lock); + fcport->rport = NULL; + *((fc_port_t **)rport->dd_data) = NULL; + spin_unlock_irq(host->host_lock); +} + +static void +qla2x00_terminate_rport_io(struct fc_rport *rport) +{ + fc_port_t *fcport = *(fc_port_t **)rport->dd_data; + + /* + * At this point all fcport's software-states are cleared. Perform any + * final cleanup of firmware resources (PCBs and XCBs). + */ + if (fcport->loop_id != FC_NO_LOOP_ID) { + fcport->ha->isp_ops->fabric_logout(fcport->ha, 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_abort_fcport_cmds(fcport); + scsi_target_unblock(&rport->dev); } static int @@ -1370,6 +1383,7 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) pfc_host_stat->invalid_tx_word_count = stats->inval_xmit_word_cnt; pfc_host_stat->invalid_crc_count = stats->inval_crc_cnt; if (IS_FWI2_CAPABLE(ha)) { + pfc_host_stat->lip_count = stats->lip_cnt; pfc_host_stat->tx_frames = stats->tx_frames; pfc_host_stat->rx_frames = stats->rx_frames; pfc_host_stat->dumped_frames = stats->dumped_frames; @@ -1498,17 +1512,16 @@ vport_create_failed_2: static int qla24xx_vport_delete(struct fc_vport *fc_vport) { - scsi_qla_host_t *ha = shost_priv(fc_vport->shost); scsi_qla_host_t *vha = fc_vport->dd_data; + scsi_qla_host_t *pha = to_qla_parent(vha); + + while (test_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags) || + test_bit(FCPORT_UPDATE_NEEDED, &pha->dpc_flags)) + msleep(1000); qla24xx_disable_vp(vha); qla24xx_deallocate_vp_id(vha); - mutex_lock(&ha->vport_lock); - ha->cur_vport_count--; - clear_bit(vha->vp_idx, ha->vp_idx_map); - mutex_unlock(&ha->vport_lock); - kfree(vha->node_name); kfree(vha->port_name); @@ -1573,11 +1586,12 @@ struct fc_function_template qla2xxx_transport_functions = { .get_starget_port_id = qla2x00_get_starget_port_id, .show_starget_port_id = 1, - .get_rport_dev_loss_tmo = qla2x00_get_rport_loss_tmo, .set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo, .show_rport_dev_loss_tmo = 1, .issue_fc_host_lip = qla2x00_issue_lip, + .dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk, + .terminate_rport_io = qla2x00_terminate_rport_io, .get_fc_host_stats = qla2x00_get_fc_host_stats, .vport_create = qla24xx_vport_create, @@ -1616,11 +1630,12 @@ struct fc_function_template qla2xxx_transport_vport_functions = { .get_starget_port_id = qla2x00_get_starget_port_id, .show_starget_port_id = 1, - .get_rport_dev_loss_tmo = qla2x00_get_rport_loss_tmo, .set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo, .show_rport_dev_loss_tmo = 1, .issue_fc_host_lip = qla2x00_issue_lip, + .dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk, + .terminate_rport_io = qla2x00_terminate_rport_io, .get_fc_host_stats = qla2x00_get_fc_host_stats, }; diff --git a/qla2x00t/qla_dbg.c b/qla2x00t/qla_dbg.c index cbef78576..510ba64bc 100644 --- a/qla2x00t/qla_dbg.c +++ b/qla2x00t/qla_dbg.c @@ -216,7 +216,7 @@ qla24xx_soft_reset(scsi_qla_host_t *ha) static int qla2xxx_dump_ram(scsi_qla_host_t *ha, uint32_t addr, uint16_t *ram, - uint16_t ram_words, void **nxt) + uint32_t ram_words, void **nxt) { int rval; uint32_t cnt, stat, timer, words, idx; diff --git a/qla2x00t/qla_def.h b/qla2x00t/qla_def.h index 6c3498752..8eadc48db 100644 --- a/qla2x00t/qla_def.h +++ b/qla2x00t/qla_def.h @@ -864,7 +864,8 @@ struct link_statistics { uint32_t prim_seq_err_cnt; uint32_t inval_xmit_word_cnt; uint32_t inval_crc_cnt; - uint32_t unused1[0x1b]; + uint32_t lip_cnt; + uint32_t unused1[0x1a]; uint32_t tx_frames; uint32_t rx_frames; uint32_t dumped_frames; @@ -1544,7 +1545,6 @@ typedef struct fc_port { int login_retry; atomic_t port_down_timer; - spinlock_t rport_lock; struct fc_rport *rport, *drport; u32 supported_classes; @@ -2155,6 +2155,10 @@ struct qla_chip_state_84xx { uint32_t gold_fw_version; }; +struct qla_statistics { + uint32_t total_isp_aborts; +}; + /* * Linux Host Adapter structure */ @@ -2166,7 +2170,6 @@ typedef struct scsi_qla_host { struct pci_dev *pdev; unsigned long host_no; - unsigned long instance; volatile struct { uint32_t init_done :1; @@ -2238,6 +2241,7 @@ typedef struct scsi_qla_host { #define REGISTER_FDMI_NEEDED 26 #define FCPORT_UPDATE_NEEDED 27 #define VP_DPC_NEEDED 28 /* wake up for VP dpc handling */ +#define UNLOADING 29 uint32_t device_flags; #define DFLG_LOCAL_DEVICES BIT_0 @@ -2527,7 +2531,7 @@ typedef struct scsi_qla_host { uint8_t model_number[16+1]; #define BINZERO "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" - char *model_desc; + char model_desc[80]; uint8_t adapter_id[16+1]; uint8_t *node_name; @@ -2614,6 +2618,7 @@ typedef struct scsi_qla_host { int cur_vport_count; struct qla_chip_state_84xx *cs84xx; + struct qla_statistics qla_stats; } scsi_qla_host_t; /* Wait type for qla2x00_eh_wait_for_pending_commands() */ diff --git a/qla2x00t/qla_gbl.h b/qla2x00t/qla_gbl.h index 1dbb7fac2..f2fb20361 100644 --- a/qla2x00t/qla_gbl.h +++ b/qla2x00t/qla_gbl.h @@ -66,7 +66,7 @@ extern int ql2xfdmienable; extern int ql2xallocfwdump; extern int ql2xextended_error_logging; extern int ql2xqfullrampup; -extern int num_hosts; +extern int ql2xiidmaenable; extern int qla2x00_loop_reset(scsi_qla_host_t *); extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int); @@ -75,6 +75,8 @@ extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum extern int qla2x00_post_hwe_work(struct scsi_qla_host *, uint16_t , uint16_t, uint16_t, uint16_t); +extern void qla2x00_abort_fcport_cmds(fc_port_t *); + /* * Global Functions in qla_mid.c source file. */ @@ -320,6 +322,7 @@ extern int qla2xxx_hw_event_log(scsi_qla_host_t *, uint16_t , uint16_t, uint16_t, uint16_t); extern void qla2xxx_get_flash_info(scsi_qla_host_t *); +extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t); /* * Global Function Prototypes in qla_dbg.c source file. diff --git a/qla2x00t/qla_gs.c b/qla2x00t/qla_gs.c index 6f783683c..853f1d30d 100644 --- a/qla2x00t/qla_gs.c +++ b/qla2x00t/qla_gs.c @@ -1670,6 +1670,12 @@ qla2x00_fdmi_register(scsi_qla_host_t *ha) { int rval; + if (IS_QLA2100(ha) || IS_QLA2200(ha)) { + DEBUG2(printk("scsi(%ld): FDMI unsupported on " + "ISP2100/ISP2200.\n", ha->host_no)); + return QLA_SUCCESS; + } + rval = qla2x00_mgmt_svr_login(ha); if (rval) return rval; diff --git a/qla2x00t/qla_init.c b/qla2x00t/qla_init.c index 0a4187320..b1a6693f2 100644 --- a/qla2x00t/qla_init.c +++ b/qla2x00t/qla_init.c @@ -344,6 +344,8 @@ static int qla2x00_isp_firmware(scsi_qla_host_t *ha) { int rval; + uint16_t loop_id, topo, sw_cap; + uint8_t domain, area, al_pa; /* Assume loading risc code */ rval = QLA_FUNCTION_FAILED; @@ -355,6 +357,11 @@ qla2x00_isp_firmware(scsi_qla_host_t *ha) /* Verify checksum of loaded RISC code. */ rval = qla2x00_verify_checksum(ha, ha->fw_srisc_address); + if (rval == QLA_SUCCESS) { + /* And, verify we are not in ROM code. */ + rval = qla2x00_get_adapter_id(ha, &loop_id, &al_pa, + &area, &domain, &topo, &sw_cap); + } } if (rval) { @@ -749,7 +756,7 @@ qla24xx_chip_diag(scsi_qla_host_t *ha) /* Perform RISC reset. */ qla24xx_reset_risc(ha); - ha->fw_transfer_size = REQUEST_ENTRY_SIZE * 1024; + ha->fw_transfer_size = REQUEST_ENTRY_SIZE * ha->request_q_length; rval = qla2x00_mbx_reg_test(ha); if (rval) { @@ -795,6 +802,38 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *ha) mem_size = (ha->fw_memory_size - 0x100000 + 1) * sizeof(uint32_t); + /* Allocate memory for Fibre Channel Event Buffer. */ + if (!IS_QLA25XX(ha)) + goto try_eft; + + tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma, + GFP_KERNEL); + if (!tc) { + qla_printk(KERN_WARNING, ha, "Unable to allocate " + "(%d KB) for FCE.\n", FCE_SIZE / 1024); + goto try_eft; + } + + memset(tc, 0, FCE_SIZE); + rval = qla2x00_enable_fce_trace(ha, tc_dma, FCE_NUM_BUFFERS, + ha->fce_mb, &ha->fce_bufs); + if (rval) { + qla_printk(KERN_WARNING, ha, "Unable to initialize " + "FCE (%d).\n", rval); + dma_free_coherent(&ha->pdev->dev, FCE_SIZE, tc, + tc_dma); + ha->flags.fce_enabled = 0; + goto try_eft; + } + + qla_printk(KERN_INFO, ha, "Allocated (%d KB) for FCE...\n", + FCE_SIZE / 1024); + + fce_size = sizeof(struct qla2xxx_fce_chain) + EFT_SIZE; + ha->flags.fce_enabled = 1; + ha->fce_dma = tc_dma; + ha->fce = tc; +try_eft: /* Allocate memory for Extended Trace Buffer. */ tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma, GFP_KERNEL); @@ -820,38 +859,6 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *ha) eft_size = EFT_SIZE; ha->eft_dma = tc_dma; ha->eft = tc; - - /* Allocate memory for Fibre Channel Event Buffer. */ - if (!IS_QLA25XX(ha)) - goto cont_alloc; - - tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma, - GFP_KERNEL); - if (!tc) { - qla_printk(KERN_WARNING, ha, "Unable to allocate " - "(%d KB) for FCE.\n", FCE_SIZE / 1024); - goto cont_alloc; - } - - memset(tc, 0, FCE_SIZE); - rval = qla2x00_enable_fce_trace(ha, tc_dma, FCE_NUM_BUFFERS, - ha->fce_mb, &ha->fce_bufs); - if (rval) { - qla_printk(KERN_WARNING, ha, "Unable to initialize " - "FCE (%d).\n", rval); - dma_free_coherent(&ha->pdev->dev, FCE_SIZE, tc, - tc_dma); - ha->flags.fce_enabled = 0; - goto cont_alloc; - } - - qla_printk(KERN_INFO, ha, "Allocated (%d KB) for FCE...\n", - FCE_SIZE / 1024); - - fce_size = sizeof(struct qla2xxx_fce_chain) + EFT_SIZE; - ha->flags.fce_enabled = 1; - ha->fce_dma = tc_dma; - ha->fce = tc; } cont_alloc: req_q_size = ha->request_q_length * sizeof(request_t); @@ -996,8 +1003,9 @@ qla2x00_setup_chip(scsi_qla_host_t *ha) &ha->fw_attributes, &ha->fw_memory_size); qla2x00_resize_request_q(ha); ha->flags.npiv_supported = 0; - if ((IS_QLA24XX(ha) || IS_QLA25XX(ha)) && - (ha->fw_attributes & BIT_2)) { + if ((IS_QLA24XX(ha) || IS_QLA25XX(ha) || + IS_QLA84XX(ha)) && + (ha->fw_attributes & BIT_2)) { ha->flags.npiv_supported = 1; if ((!ha->max_npiv_vports) || ((ha->max_npiv_vports + 1) % @@ -1528,18 +1536,25 @@ qla2x00_set_model_info(scsi_qla_host_t *ha, uint8_t *model, size_t len, char *de index = (ha->pdev->subsystem_device & 0xff); if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC && index < QLA_MODEL_NAMES) - ha->model_desc = qla2x00_model_name[index * 2 + 1]; + strncpy(ha->model_desc, + qla2x00_model_name[index * 2 + 1], + sizeof(ha->model_desc) - 1); } else { index = (ha->pdev->subsystem_device & 0xff); if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC && index < QLA_MODEL_NAMES) { strcpy(ha->model_number, qla2x00_model_name[index * 2]); - ha->model_desc = qla2x00_model_name[index * 2 + 1]; + strncpy(ha->model_desc, + qla2x00_model_name[index * 2 + 1], + sizeof(ha->model_desc) - 1); } else { strcpy(ha->model_number, def); } } + if (IS_FWI2_CAPABLE(ha)) + qla2xxx_get_vpd_field(ha, "\x82", ha->model_desc, + sizeof(ha->model_desc)); } /* On sparc systems, obtain port and node WWN from firmware @@ -1897,12 +1912,11 @@ qla2x00_rport_del(void *data) { fc_port_t *fcport = data; struct fc_rport *rport; - unsigned long flags; - spin_lock_irqsave(&fcport->rport_lock, flags); + spin_lock_irq(fcport->ha->host->host_lock); rport = fcport->drport; fcport->drport = NULL; - spin_unlock_irqrestore(&fcport->rport_lock, flags); + spin_unlock_irq(fcport->ha->host->host_lock); if (rport) fc_remote_port_delete(rport); } @@ -1931,7 +1945,6 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags) atomic_set(&fcport->state, FCS_UNCONFIGURED); fcport->flags = FCF_RLC_SUPPORT; fcport->supported_classes = FC_COS_UNSPECIFIED; - spin_lock_init(&fcport->rport_lock); return fcport; } @@ -2040,8 +2053,10 @@ qla2x00_configure_loop(scsi_qla_host_t *ha) if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) { if (test_bit(LOCAL_LOOP_UPDATE, &save_flags)) set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); - if (test_bit(RSCN_UPDATE, &save_flags)) + if (test_bit(RSCN_UPDATE, &save_flags)) { + ha->flags.rscn_queue_overflow = 1; set_bit(RSCN_UPDATE, &ha->dpc_flags); + } } return (rval); @@ -2276,28 +2291,24 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport) { struct fc_rport_identifiers rport_ids; struct fc_rport *rport; - unsigned long flags; if (fcport->drport) qla2x00_rport_del(fcport); - if (fcport->rport) - return; rport_ids.node_name = wwn_to_u64(fcport->node_name); rport_ids.port_name = wwn_to_u64(fcport->port_name); rport_ids.port_id = fcport->d_id.b.domain << 16 | fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa; rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; - rport = fc_remote_port_add(ha->host, 0, &rport_ids); + fcport->rport = rport = fc_remote_port_add(ha->host, 0, &rport_ids); if (!rport) { qla_printk(KERN_WARNING, ha, "Unable to allocate fc remote port!\n"); return; } - spin_lock_irqsave(&fcport->rport_lock, flags); - fcport->rport = rport; + spin_lock_irq(fcport->ha->host->host_lock); *((fc_port_t **)rport->dd_data) = fcport; - spin_unlock_irqrestore(&fcport->rport_lock, flags); + spin_unlock_irq(fcport->ha->host->host_lock); rport->supported_classes = fcport->supported_classes; @@ -2601,7 +2612,8 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) } else if (qla2x00_gnn_id(ha, swl) != QLA_SUCCESS) { kfree(swl); swl = NULL; - } else if (qla2x00_gfpn_id(ha, swl) == QLA_SUCCESS) { + } else if (ql2xiidmaenable && + qla2x00_gfpn_id(ha, swl) == QLA_SUCCESS) { qla2x00_gpsc(ha, swl); } } @@ -3256,7 +3268,8 @@ qla2x00_update_fcports(scsi_qla_host_t *ha) /* Go with deferred removal of rport references. */ list_for_each_entry_rcu(fcport, &ha->fcports, list) - if (fcport->drport) + if (fcport->drport && + atomic_read(&fcport->state) != FCS_UNCONFIGURED) qla2x00_rport_del(fcport); } @@ -3275,10 +3288,12 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) { int rval; uint8_t status = 0; + scsi_qla_host_t *vha; if (ha->flags.online) { ha->flags.online = 0; clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + ha->qla_stats.total_isp_aborts++; qla_printk(KERN_INFO, ha, "Performing ISP error recovery - ha= %p.\n", ha); @@ -3288,6 +3303,8 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) if (atomic_read(&ha->loop_state) != LOOP_DOWN) { atomic_set(&ha->loop_state, LOOP_DOWN); qla2x00_mark_all_devices_lost(ha, 0); + list_for_each_entry(vha, &ha->vp_list, vp_list) + qla2x00_mark_all_devices_lost(vha, 0); } else { if (!atomic_read(&ha->loop_down_timer)) atomic_set(&ha->loop_down_timer, @@ -3325,17 +3342,6 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) ha->isp_abort_cnt = 0; clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags); - if (ha->eft) { - memset(ha->eft, 0, EFT_SIZE); - rval = qla2x00_enable_eft_trace(ha, - ha->eft_dma, EFT_NUM_BUFFERS); - if (rval) { - qla_printk(KERN_WARNING, ha, - "Unable to reinitialize EFT " - "(%d).\n", rval); - } - } - if (ha->fce) { ha->flags.fce_enabled = 1; memset(ha->fce, 0, @@ -3350,6 +3356,17 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) ha->flags.fce_enabled = 0; } } + + if (ha->eft) { + memset(ha->eft, 0, EFT_SIZE); + rval = qla2x00_enable_eft_trace(ha, + ha->eft_dma, EFT_NUM_BUFFERS); + if (rval) { + qla_printk(KERN_WARNING, ha, + "Unable to reinitialize EFT " + "(%d).\n", rval); + } + } } else { /* failed the ISP abort */ ha->flags.online = 1; if (test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) { @@ -4068,8 +4085,8 @@ qla2x00_try_to_stop_firmware(scsi_qla_host_t *ha) ret = qla2x00_stop_firmware(ha); for (retries = 5; ret != QLA_SUCCESS && ret != QLA_FUNCTION_TIMEOUT && retries ; retries--) { - qla2x00_reset_chip(ha); - if (qla2x00_chip_diag(ha) != QLA_SUCCESS) + ha->isp_ops->reset_chip(ha); + if (ha->isp_ops->chip_diag(ha) != QLA_SUCCESS) continue; if (qla2x00_setup_chip(ha) != QLA_SUCCESS) continue; @@ -4091,7 +4108,7 @@ qla24xx_configure_vhba(scsi_qla_host_t *ha) rval = qla2x00_fw_ready(ha->parent); if (rval == QLA_SUCCESS) { clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); - qla2x00_marker(ha->parent, 0, 0, MK_SYNC_ALL); + qla2x00_marker(ha, 0, 0, MK_SYNC_ALL); } ha->flags.management_server_logged_in = 0; diff --git a/qla2x00t/qla_iocb.c b/qla2x00t/qla_iocb.c index 3b4a8ef37..2609b26d2 100644 --- a/qla2x00t/qla_iocb.c +++ b/qla2x00t/qla_iocb.c @@ -453,10 +453,11 @@ qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun, { int ret; unsigned long flags = 0; + scsi_qla_host_t *pha = to_qla_parent(ha); - spin_lock_irqsave(&ha->hardware_lock, flags); + spin_lock_irqsave(&pha->hardware_lock, flags); ret = __qla2x00_marker(ha, loop_id, lun, type); - spin_unlock_irqrestore(&ha->hardware_lock, flags); + spin_unlock_irqrestore(&pha->hardware_lock, flags); return (ret); } @@ -671,7 +672,7 @@ qla24xx_start_scsi(srb_t *sp) { int ret, nseg; unsigned long flags; - scsi_qla_host_t *ha; + scsi_qla_host_t *ha, *pha; struct scsi_cmnd *cmd; uint32_t *clr_ptr; uint32_t index; @@ -685,6 +686,7 @@ qla24xx_start_scsi(srb_t *sp) /* Setup device pointers. */ ret = 0; ha = sp->ha; + pha = to_qla_parent(ha); reg = &ha->iobase->isp24; cmd = sp->cmd; /* So we know we haven't pci_map'ed anything yet */ @@ -699,7 +701,7 @@ qla24xx_start_scsi(srb_t *sp) } /* Acquire ring specific lock */ - spin_lock_irqsave(&ha->hardware_lock, flags); + spin_lock_irqsave(&pha->hardware_lock, flags); /* Check for room in outstanding command list. */ handle = ha->current_outstanding_cmd; @@ -794,14 +796,14 @@ qla24xx_start_scsi(srb_t *sp) ha->response_ring_ptr->signature != RESPONSE_PROCESSED) qla24xx_process_response_queue(ha); - spin_unlock_irqrestore(&ha->hardware_lock, flags); + spin_unlock_irqrestore(&pha->hardware_lock, flags); return QLA_SUCCESS; queuing_error: if (tot_dsds) scsi_dma_unmap(cmd); - spin_unlock_irqrestore(&ha->hardware_lock, flags); + spin_unlock_irqrestore(&pha->hardware_lock, flags); return QLA_FUNCTION_FAILED; } diff --git a/qla2x00t/qla_isr.c b/qla2x00t/qla_isr.c index a116fd7f6..9856a7078 100644 --- a/qla2x00t/qla_isr.c +++ b/qla2x00t/qla_isr.c @@ -609,10 +609,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) break; case MBA_PORT_UPDATE: /* Port database update */ - /* Only handle SCNs for our Vport index. */ - if (ha->parent && ha->vp_idx != (mb[3] & 0xff)) - break; - /* * If PORT UPDATE is global (recieved LIP_OCCURED/LIP_RESET * event etc. earlier indicating loop is down) then process @@ -988,11 +984,12 @@ qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t sense_len) sp->request_sense_ptr += sense_len; sp->request_sense_length -= sense_len; if (sp->request_sense_length != 0) - sp->ha->status_srb = sp; + sp->fcport->ha->status_srb = sp; DEBUG5(printk("%s(): Check condition Sense data, scsi(%ld:%d:%d:%d) " - "cmd=%p pid=%ld\n", __func__, sp->ha->host_no, cp->device->channel, - cp->device->id, cp->device->lun, cp, cp->serial_number)); + "cmd=%p pid=%ld\n", __func__, sp->fcport->ha->host_no, + cp->device->channel, cp->device->id, cp->device->lun, cp, + cp->serial_number)); if (sense_len) DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, CMD_ACTUAL_SNSLEN(cp))); @@ -1311,9 +1308,8 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) atomic_read(&fcport->state))); cp->result = DID_BUS_BUSY << 16; - if (atomic_read(&fcport->state) == FCS_ONLINE) { - qla2x00_mark_device_lost(ha, fcport, 1, 1); - } + if (atomic_read(&fcport->state) == FCS_ONLINE) + qla2x00_mark_device_lost(fcport->ha, fcport, 1, 1); break; case CS_RESET: @@ -1356,7 +1352,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) /* Check to see if logout occurred. */ if ((le16_to_cpu(sts->status_flags) & SF_LOGOUT_SENT)) - qla2x00_mark_device_lost(ha, fcport, 1, 1); + qla2x00_mark_device_lost(fcport->ha, fcport, 1, 1); break; default: @@ -1961,7 +1957,6 @@ clear_risc_ints: WRT_REG_WORD(®->isp.hccr, HCCR_CLR_HOST_INT); } spin_unlock_irq(&ha->hardware_lock); - ha->isp_ops->enable_intrs(ha); fail: return ret; diff --git a/qla2x00t/qla_mbx.c b/qla2x00t/qla_mbx.c index 0d2aa33df..7b96e77f5 100644 --- a/qla2x00t/qla_mbx.c +++ b/qla2x00t/qla_mbx.c @@ -918,6 +918,8 @@ qla2x00_get_adapter_id(scsi_qla_host_t *ha, uint16_t *id, uint8_t *al_pa, rval = qla2x00_mailbox_command(ha, mcp); if (mcp->mb[0] == MBS_COMMAND_ERROR) rval = QLA_COMMAND_ERROR; + else if (mcp->mb[0] == MBS_INVALID_COMMAND) + rval = QLA_INVALID_COMMAND; /* Return data. */ *id = mcp->mb[1]; @@ -2165,17 +2167,18 @@ qla24xx_abort_command(scsi_qla_host_t *ha, srb_t *sp) struct abort_entry_24xx *abt; dma_addr_t abt_dma; uint32_t handle; + scsi_qla_host_t *pha = to_qla_parent(ha); DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); fcport = sp->fcport; - spin_lock_irqsave(&ha->hardware_lock, flags); + spin_lock_irqsave(&pha->hardware_lock, flags); for (handle = 1; handle < MAX_OUTSTANDING_COMMANDS; handle++) { - if (ha->outstanding_cmds[handle] == sp) + if (pha->outstanding_cmds[handle] == sp) break; } - spin_unlock_irqrestore(&ha->hardware_lock, flags); + spin_unlock_irqrestore(&pha->hardware_lock, flags); if (handle == MAX_OUTSTANDING_COMMANDS) { /* Command not found. */ return QLA_FUNCTION_FAILED; diff --git a/qla2x00t/qla_mid.c b/qla2x00t/qla_mid.c index 0fd28ac3a..893fc51dc 100644 --- a/qla2x00t/qla_mid.c +++ b/qla2x00t/qla_mid.c @@ -6,7 +6,6 @@ */ #include "qla_def.h" -#include #include #include #include @@ -43,6 +42,7 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha) set_bit(vp_id, ha->vp_idx_map); ha->num_vhosts++; + ha->cur_vport_count++; vha->vp_idx = vp_id; list_add_tail(&vha->vp_list, &ha->vp_list); mutex_unlock(&ha->vport_lock); @@ -58,6 +58,7 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha) mutex_lock(&ha->vport_lock); vp_id = vha->vp_idx; ha->num_vhosts--; + ha->cur_vport_count--; clear_bit(vp_id, ha->vp_idx_map); list_del(&vha->vp_list); mutex_unlock(&ha->vport_lock); @@ -103,8 +104,8 @@ qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha) "loop_id=0x%04x :%x\n", vha->host_no, fcport->loop_id, fcport->vp_idx)); - atomic_set(&fcport->state, FCS_DEVICE_DEAD); qla2x00_mark_device_lost(vha, fcport, 0, 0); + atomic_set(&fcport->state, FCS_UNCONFIGURED); } } @@ -276,7 +277,8 @@ qla2x00_do_dpc_vp(scsi_qla_host_t *vha) clear_bit(RESET_ACTIVE, &vha->dpc_flags); } - if (test_and_clear_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) { + if (atomic_read(&vha->vp_state) == VP_ACTIVE && + test_and_clear_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) { if (!(test_and_set_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags))) { qla2x00_loop_resync(vha); clear_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags); @@ -390,7 +392,6 @@ qla24xx_create_vhost(struct fc_vport *fc_vport) vha->parent = ha; vha->fc_vport = fc_vport; vha->device_flags = 0; - vha->instance = num_hosts; vha->vp_idx = qla24xx_allocate_vp_id(vha); if (vha->vp_idx > ha->max_npiv_vports) { DEBUG15(printk("scsi(%ld): Couldn't allocate vp_id.\n", @@ -428,7 +429,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport) host->max_cmd_len = MAX_CMDSZ; host->max_channel = MAX_BUSES - 1; host->max_lun = MAX_LUNS; - host->unique_id = vha->instance; + host->unique_id = host->host_no; host->max_id = MAX_TARGETS_2200; host->transportt = qla2xxx_transport_vport_template; @@ -436,12 +437,6 @@ qla24xx_create_vhost(struct fc_vport *fc_vport) vha->host_no, vha)); vha->flags.init_done = 1; - num_hosts++; - - mutex_lock(&ha->vport_lock); - set_bit(vha->vp_idx, ha->vp_idx_map); - ha->cur_vport_count++; - mutex_unlock(&ha->vport_lock); return vha; diff --git a/qla2x00t/qla_os.c b/qla2x00t/qla_os.c index 732aaa90c..31091f1c8 100644 --- a/qla2x00t/qla_os.c +++ b/qla2x00t/qla_os.c @@ -31,7 +31,6 @@ char qla2x00_version_str[40]; */ static struct kmem_cache *srb_cachep; -int num_hosts; int ql2xlogintimeout = 20; module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR); MODULE_PARM_DESC(ql2xlogintimeout, @@ -91,6 +90,13 @@ MODULE_PARM_DESC(ql2xqfullrampup, "depth for a device after a queue-full condition has been " "detected. Default is 120 seconds."); +int ql2xiidmaenable=1; +module_param(ql2xiidmaenable, int, S_IRUGO|S_IRUSR); +MODULE_PARM_DESC(ql2xiidmaenable, + "Enables iIDMA settings " + "Default is 1 - perform iIDMA. 0 - no iIDMA."); + + /* * SCSI host template entry points */ @@ -392,7 +398,7 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) } /* Close window on fcport/rport state-transitioning. */ - if (!*(fc_port_t **)rport->dd_data) { + if (fcport->drport) { cmd->result = DID_IMM_RETRY << 16; goto qc_fail_command; } @@ -447,7 +453,7 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) int rval; scsi_qla_host_t *pha = to_qla_parent(ha); - if (unlikely(pci_channel_offline(ha->pdev))) { + if (unlikely(pci_channel_offline(pha->pdev))) { cmd->result = DID_REQUEUE << 16; goto qc24_fail_command; } @@ -459,7 +465,7 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) } /* Close window on fcport/rport state-transitioning. */ - if (!*(fc_port_t **)rport->dd_data) { + if (fcport->drport) { cmd->result = DID_IMM_RETRY << 16; goto qc24_fail_command; } @@ -621,6 +627,40 @@ qla2x00_wait_for_loop_ready(scsi_qla_host_t *ha) return (return_status); } +void +qla2x00_abort_fcport_cmds(fc_port_t *fcport) +{ + int cnt; + unsigned long flags; + srb_t *sp; + scsi_qla_host_t *ha = fcport->ha; + scsi_qla_host_t *pha = to_qla_parent(ha); + + spin_lock_irqsave(&pha->hardware_lock, flags); + for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { + sp = pha->outstanding_cmds[cnt]; + if (!sp) + continue; + if (sp->fcport != fcport) + continue; + + spin_unlock_irqrestore(&pha->hardware_lock, flags); + if (ha->isp_ops->abort_command(ha, sp)) { + DEBUG2(qla_printk(KERN_WARNING, ha, + "Abort failed -- %lx\n", sp->cmd->serial_number)); + } else { + if (qla2x00_eh_wait_on_command(ha, sp->cmd) != + QLA_SUCCESS) + DEBUG2(qla_printk(KERN_WARNING, ha, + "Abort failed while waiting -- %lx\n", + sp->cmd->serial_number)); + + } + spin_lock_irqsave(&pha->hardware_lock, flags); + } + spin_unlock_irqrestore(&pha->hardware_lock, flags); +} + static void qla2x00_block_error_handler(struct scsi_cmnd *cmnd) { @@ -738,7 +778,8 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha, unsigned int t, sp = pha->outstanding_cmds[cnt]; if (!sp) continue; - if (ha->vp_idx != sp->ha->vp_idx) + + if (ha->vp_idx != sp->fcport->ha->vp_idx) continue; match = 0; switch (type) { @@ -1038,9 +1079,7 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *ha, int res) sp = ha->outstanding_cmds[cnt]; if (sp) { ha->outstanding_cmds[cnt] = NULL; - sp->flags = 0; sp->cmd->result = res; - sp->cmd->host_scribble = (unsigned char *)NULL; qla2x00_sp_compl(ha, sp); } } @@ -1071,7 +1110,7 @@ qla2xxx_slave_configure(struct scsi_device *sdev) else scsi_deactivate_tcq(sdev, ha->max_q_depth); - rport->dev_loss_tmo = ha->port_down_retry_count + 5; + rport->dev_loss_tmo = ha->port_down_retry_count; return 0; } @@ -1627,9 +1666,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) } host->can_queue = ha->request_q_length + 128; - /* load the F/W, read paramaters, and init the H/W */ - ha->instance = num_hosts; - spin_lock_init(&ha->dpc_lock); mutex_init(&ha->vport_lock); @@ -1679,7 +1715,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) host->this_id = 255; host->cmd_per_lun = 3; - host->unique_id = ha->instance; + host->unique_id = host->host_no; host->max_cmd_len = MAX_CMDSZ; host->max_channel = MAX_BUSES - 1; host->max_lun = MAX_LUNS; @@ -1700,12 +1736,12 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->flags.init_done = 1; ha->flags.online = 1; - num_hosts++; - ret = scsi_add_host(host, &pdev->dev); if (ret) goto probe_failed; + ha->isp_ops->enable_intrs(ha); + scsi_scan_host(host); qla2x00_alloc_sysfs_attr(ha); @@ -1741,10 +1777,15 @@ probe_out: static void qla2x00_remove_one(struct pci_dev *pdev) { - scsi_qla_host_t *ha; + scsi_qla_host_t *ha, *vha, *temp; ha = pci_get_drvdata(pdev); + list_for_each_entry_safe(vha, temp, &ha->vp_list, vp_list) + fc_vport_terminate(vha->fc_vport); + + set_bit(UNLOADING, &ha->dpc_flags); + #if defined(CONFIG_SCSI_QLA2XXX_TARGET) ha->flags.host_shutting_down = 1; if (qla_target.tgt_host_action != NULL) @@ -1830,27 +1871,22 @@ static inline void qla2x00_schedule_rport_del(struct scsi_qla_host *ha, fc_port_t *fcport, int defer) { - unsigned long flags; struct fc_rport *rport; + scsi_qla_host_t *pha = to_qla_parent(ha); if (!fcport->rport) return; rport = fcport->rport; if (defer) { - spin_lock_irqsave(&fcport->rport_lock, flags); + unsigned long flags; + spin_lock_irqsave(ha->host->host_lock, flags); fcport->drport = rport; - fcport->rport = NULL; - *(fc_port_t **)rport->dd_data = NULL; - spin_unlock_irqrestore(&fcport->rport_lock, flags); - set_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags); - } else { - spin_lock_irqsave(&fcport->rport_lock, flags); - fcport->rport = NULL; - *(fc_port_t **)rport->dd_data = NULL; - spin_unlock_irqrestore(&fcport->rport_lock, flags); + spin_unlock_irqrestore(ha->host->host_lock, flags); + set_bit(FCPORT_UPDATE_NEEDED, &pha->dpc_flags); + qla2xxx_wake_dpc(pha); + } else fc_remote_port_delete(rport); - } } /* @@ -1920,7 +1956,7 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer) scsi_qla_host_t *pha = to_qla_parent(ha); list_for_each_entry_rcu(fcport, &pha->fcports, list) { - if (ha->vp_idx != 0 && ha->vp_idx != fcport->vp_idx) + if (ha->vp_idx != fcport->vp_idx) continue; /* * No point in marking the device as lost, if the device is @@ -1928,17 +1964,10 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer) */ if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD) continue; - if (atomic_read(&fcport->state) == FCS_ONLINE) { - if (defer) - qla2x00_schedule_rport_del(ha, fcport, defer); - else if (ha->vp_idx == fcport->vp_idx) - qla2x00_schedule_rport_del(ha, fcport, defer); - } + if (atomic_read(&fcport->state) == FCS_ONLINE) + qla2x00_schedule_rport_del(ha, fcport, defer); atomic_set(&fcport->state, FCS_DEVICE_LOST); } - - if (defer) - qla2xxx_wake_dpc(ha); } /* @@ -2173,7 +2202,7 @@ qla2x00_alloc_work(struct scsi_qla_host *ha, enum qla_work_type type, static int qla2x00_post_work(struct scsi_qla_host *ha, struct qla_work_evt *e, int locked) { - unsigned long flags; + unsigned long uninitialized_var(flags); scsi_qla_host_t *pha = to_qla_parent(ha); if (!locked) @@ -2330,8 +2359,10 @@ qla2x00_do_dpc(void *data) ha->host_no)); } - if (test_and_clear_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags)) + if (test_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags)) { qla2x00_update_fcports(ha); + clear_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags); + } if (test_and_clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) && (!(test_and_set_bit(RESET_ACTIVE, &ha->dpc_flags)))) { @@ -2444,10 +2475,13 @@ qla2x00_do_dpc(void *data) void qla2xxx_wake_dpc(scsi_qla_host_t *ha) { + struct task_struct *t; unsigned long flags; + spin_lock_irqsave(&ha->dpc_lock, flags); - if (ha->dpc_thread) - wake_up_process(ha->dpc_thread); + t = ha->dpc_thread; + if (!test_bit(UNLOADING, &ha->dpc_flags) && t) + wake_up_process(t); spin_unlock_irqrestore(&ha->dpc_lock, flags); } diff --git a/qla2x00t/qla_sup.c b/qla2x00t/qla_sup.c index 1728ab3cc..1bca74474 100644 --- a/qla2x00t/qla_sup.c +++ b/qla2x00t/qla_sup.c @@ -869,11 +869,9 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, uint32_t i; uint32_t *dwptr; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; - unsigned long flags; ret = QLA_SUCCESS; - spin_lock_irqsave(&ha->hardware_lock, flags); /* Enable flash write. */ WRT_REG_DWORD(®->ctrl_status, RD_REG_DWORD(®->ctrl_status) | CSRX_FLASH_ENABLE); @@ -907,7 +905,6 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, WRT_REG_DWORD(®->ctrl_status, RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE); RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */ - spin_unlock_irqrestore(&ha->hardware_lock, flags); return ret; } @@ -2305,6 +2302,51 @@ qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf) return ret; } +static int +qla2xxx_is_vpd_valid(uint8_t *pos, uint8_t *end) +{ + if (pos >= end || *pos != 0x82) + return 0; + + pos += 3 + pos[1]; + if (pos >= end || *pos != 0x90) + return 0; + + pos += 3 + pos[1]; + if (pos >= end || *pos != 0x78) + return 0; + + return 1; +} + +int +qla2xxx_get_vpd_field(scsi_qla_host_t *ha, char *key, char *str, size_t size) +{ + uint8_t *pos = ha->vpd; + uint8_t *end = pos + ha->vpd_size; + int len = 0; + + if (!IS_FWI2_CAPABLE(ha) || !qla2xxx_is_vpd_valid(pos, end)) + return 0; + + while (pos < end && *pos != 0x78) { + len = (*pos == 0x82) ? pos[1] : pos[2]; + + if (!strncmp(pos, key, strlen(key))) + break; + + if (*pos != 0x90 && *pos != 0x91) + pos += len; + + pos += 3; + } + + if (pos < end - len && *pos != 0x78) + return snprintf(str, size, "%.*s", len, pos + 3); + + return 0; +} + static int qla2xxx_hw_event_store(scsi_qla_host_t *ha, uint32_t *fdata) { diff --git a/qla2x00t/qla_version.h b/qla2x00t/qla_version.h index d058c8862..4160e4caa 100644 --- a/qla2x00t/qla_version.h +++ b/qla2x00t/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.02.01-k4" +#define QLA2XXX_VERSION "8.02.01-k7" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 2