Update to initiator driver from 2.6.27

git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@578 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2008-11-20 18:58:53 +00:00
parent d908081912
commit e54c3872bc
15 changed files with 389 additions and 271 deletions

View File

@@ -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.

View File

@@ -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

View File

@@ -9,6 +9,7 @@
#include <linux/kthread.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
#include <linux/delay.h>
#include <linux/version.h>
#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,
};

View File

@@ -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;

View File

@@ -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() */

View File

@@ -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.

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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(&reg->isp.hccr, HCCR_CLR_HOST_INT);
}
spin_unlock_irq(&ha->hardware_lock);
ha->isp_ops->enable_intrs(ha);
fail:
return ret;

View File

@@ -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;

View File

@@ -6,7 +6,6 @@
*/
#include "qla_def.h"
#include <linux/version.h>
#include <linux/moduleparam.h>
#include <linux/vmalloc.h>
#include <linux/smp_lock.h>
@@ -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;

View File

@@ -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);
}

View File

@@ -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(&reg->ctrl_status,
RD_REG_DWORD(&reg->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(&reg->ctrl_status,
RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
RD_REG_DWORD(&reg->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)
{

View File

@@ -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