* [PATCH]qla4xxx:Add support for Async Message PDUs
@ 2008-04-18 20:44 David C Somayajulu
2008-04-22 16:20 ` Mike Christie
0 siblings, 1 reply; 13+ messages in thread
From: David C Somayajulu @ 2008-04-18 20:44 UTC (permalink / raw)
To: linux-scsi; +Cc: michaelc, David Somayajulu, David Wagner
The following patch adds support for Async Message PDUs. It also has minor clean up mainly removing references to iSNS.
Signed-off-by: David C Somayajulu <david.somayajulu@qlogic.com>
---
drivers/scsi/qla4xxx/ql4_def.h | 8 ++
drivers/scsi/qla4xxx/ql4_fw.h | 39 +++++++----
drivers/scsi/qla4xxx/ql4_glbl.h | 4 +
drivers/scsi/qla4xxx/ql4_isr.c | 23 ++++++
drivers/scsi/qla4xxx/ql4_mbx.c | 48 ++++++++++++-
drivers/scsi/qla4xxx/ql4_os.c | 137 +++++++++++++++++++++++++++++++++++-
drivers/scsi/qla4xxx/ql4_version.h | 2 +-
7 files changed, 244 insertions(+), 17 deletions(-)
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
index d6be076..12b5623 100644
--- a/drivers/scsi/qla4xxx/ql4_def.h
+++ b/drivers/scsi/qla4xxx/ql4_def.h
@@ -296,6 +296,7 @@ struct scsi_qla_host {
#define DPC_ISNS_RESTART 7 /* 0x00000080 */
#define DPC_AEN 9 /* 0x00000200 */
#define DPC_GET_DHCP_IP_ADDR 15 /* 0x00008000 */
+#define DPC_ASYNC_MSG_PDU 16 /* 0x00010000 */
struct Scsi_Host *host; /* pointer to host data */
uint32_t tot_ddbs;
@@ -434,7 +435,14 @@ struct scsi_qla_host {
/* Map ddb_list entry by FW ddb index */
struct ddb_entry *fw_ddb_index_map[MAX_DDB_ENTRIES];
+ struct list_head async_iocb_list;
+ dma_addr_t gen_req_rsp_iocb_dma;
+ void *gen_req_rsp_iocb;
+};
+struct async_msg_pdu_iocb {
+ struct list_head list;
+ uint8_t iocb[0x40];
};
static inline int is_qla4010(struct scsi_qla_host *ha)
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
index 1b667a7..5023f6f 100644
--- a/drivers/scsi/qla4xxx/ql4_fw.h
+++ b/drivers/scsi/qla4xxx/ql4_fw.h
@@ -227,8 +227,8 @@ union external_hw_config_reg {
#define MBOX_CMD_READ_FLASH 0x0026
#define MBOX_CMD_CLEAR_DATABASE_ENTRY 0x0031
#define MBOX_CMD_CONN_CLOSE_SESS_LOGOUT 0x0056
-#define LOGOUT_OPTION_CLOSE_SESSION 0x01
-#define LOGOUT_OPTION_RELOGIN 0x02
+#define LOGOUT_OPTION_CLOSE_SESSION 0x02
+#define LOGOUT_OPTION_RESET 0x04
#define MBOX_CMD_EXECUTE_IOCB_A64 0x005A
#define MBOX_CMD_INITIALIZE_FIRMWARE 0x0060
#define MBOX_CMD_GET_INIT_FW_CTRL_BLOCK 0x0061
@@ -576,13 +576,14 @@ struct conn_event_log_entry {
/* IOCB header structure */
struct qla4_header {
uint8_t entryType;
-#define ET_STATUS 0x03
-#define ET_MARKER 0x04
-#define ET_CONT_T1 0x0A
-#define ET_STATUS_CONTINUATION 0x10
-#define ET_CMND_T3 0x19
-#define ET_PASSTHRU0 0x3A
-#define ET_PASSTHRU_STATUS 0x3C
+#define ET_STATUS 0x03
+#define ET_MARKER 0x04
+#define ET_CONT_T1 0x0A
+#define ET_STATUS_CONTINUATION 0x10
+#define ET_CMND_T3 0x19
+#define ET_ASYNC_PDU 0x37
+#define ET_PASSTHRU0 0x3A
+#define ET_PASSTHRU_STATUS 0x3C
uint8_t entryStatus;
uint8_t systemDefined;
@@ -691,6 +692,18 @@ struct qla4_marker_entry {
uint64_t reserved6; /* 38-3F */
};
+/* Asynchronous PDU IOCB structure */
+struct async_pdu_iocb {
+ struct qla4_header hdr; /* 00-02 */
+ uint32_t async_pdu_handle; /* 03-06 */
+ uint16_t target_id; /* 07-08 */
+ uint16_t status; /* 09-0A */
+#define ASYNC_PDU_IOCB_STS_OK 0x01
+
+ uint32_t rsrvd; /* 0B-0F */
+ uint8_t iscsi_pdu_hdr[48]; /* 10-3F */
+};
+
/* Status entry structure*/
struct status_entry {
struct qla4_header hdr; /* 00-03 */
@@ -738,11 +751,8 @@ struct passthru0 {
uint32_t handle; /* 04-07 */
uint16_t target; /* 08-09 */
uint16_t connectionID; /* 0A-0B */
-#define ISNS_DEFAULT_SERVER_CONN_ID ((uint16_t)0x8000)
-
uint16_t controlFlags; /* 0C-0D */
-#define PT_FLAG_ETHERNET_FRAME 0x8000
-#define PT_FLAG_ISNS_PDU 0x8000
+#define PT_FLAG_ISCSI_PDU 0x1000
#define PT_FLAG_SEND_BUFFER 0x0200
#define PT_FLAG_WAIT_4_RESPONSE 0x0100
@@ -752,7 +762,8 @@ struct passthru0 {
struct data_seg_a64 outDataSeg64; /* 10-1B */
uint32_t res1; /* 1C-1F */
struct data_seg_a64 inDataSeg64; /* 20-2B */
- uint8_t res2[20]; /* 2C-3F */
+ uint8_t res2[16]; /* 2C-3B */
+ uint32_t async_pdu_handle;
};
struct passthru_status {
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
index 96ebfb0..7542996 100644
--- a/drivers/scsi/qla4xxx/ql4_glbl.h
+++ b/drivers/scsi/qla4xxx/ql4_glbl.h
@@ -31,6 +31,10 @@ int qla4xxx_reset_target(struct scsi_qla
struct ddb_entry * ddb_entry);
int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr,
uint32_t offset, uint32_t len);
+int qla4xxx_issue_iocb(struct scsi_qla_host * ha, uint32_t comp_offset,
+ dma_addr_t phys_addr);
+int qla4xxx_conn_close_sess_logout(struct scsi_qla_host * ha,
+ uint16_t fw_ddb_index, uint16_t connection_id, uint16_t option);
int qla4xxx_get_firmware_status(struct scsi_qla_host * ha);
int qla4xxx_get_firmware_state(struct scsi_qla_host * ha);
int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha);
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c
index a91a57c..77b2f65 100644
--- a/drivers/scsi/qla4xxx/ql4_isr.c
+++ b/drivers/scsi/qla4xxx/ql4_isr.c
@@ -9,6 +9,7 @@
#include "ql4_glbl.h"
#include "ql4_dbg.h"
#include "ql4_inline.h"
+#include <scsi/iscsi_proto.h>
/**
* qla4xxx_status_entry - processes status IOCBs
@@ -285,6 +286,9 @@ static void qla4xxx_process_response_que
uint32_t count = 0;
struct srb *srb = NULL;
struct status_entry *sts_entry;
+ struct async_pdu_iocb *apdu;
+ struct iscsi_hdr *pdu_hdr;
+ struct async_msg_pdu_iocb *apdu_iocb;
/* Process all responses from response queue */
while ((ha->response_in =
@@ -315,6 +319,25 @@ static void qla4xxx_process_response_que
case ET_PASSTHRU_STATUS:
break;
+ case ET_ASYNC_PDU:
+ apdu = (struct async_pdu_iocb *)sts_entry;
+ if (apdu->status != ASYNC_PDU_IOCB_STS_OK)
+ break;
+
+ pdu_hdr = (struct iscsi_hdr *)apdu->iscsi_pdu_hdr;
+ if (pdu_hdr->hlength || pdu_hdr->dlength[0] ||
+ pdu_hdr->dlength[1] || pdu_hdr->dlength[2]){
+ apdu_iocb = vmalloc(sizeof (struct async_msg_pdu_iocb));
+ if (apdu_iocb) {
+ memcpy(apdu_iocb->iocb, apdu,
+ sizeof(struct async_pdu_iocb));
+ list_add_tail(&apdu_iocb->list,
+ &ha->async_iocb_list);
+ set_bit(DPC_ASYNC_MSG_PDU, &ha->dpc_flags);
+ }
+ }
+ break;
+
case ET_STATUS_CONTINUATION:
/* Just throw away the status continuation entries */
DEBUG2(printk("scsi%ld: %s: Status Continuation entry "
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index c577d79..75bcf2b 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -862,7 +862,6 @@ static int qla4xxx_req_ddb_entry(struct
return QLA_SUCCESS;
}
-
int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port)
{
struct dev_db_entry *fw_ddb_entry;
@@ -915,3 +914,50 @@ qla4xxx_send_tgts_exit:
return ret_val;
}
+int
+qla4xxx_issue_iocb(struct scsi_qla_host * ha, uint32_t comp_offset,
+ dma_addr_t phys_addr)
+{
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+ int status;
+
+ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+ memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+ mbox_cmd[0] = MBOX_CMD_EXECUTE_IOCB_A64;
+ mbox_cmd[1] = comp_offset;
+ mbox_cmd[2] = LSDW(phys_addr);
+ mbox_cmd[3] = MSDW(phys_addr);
+
+ status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
+ &mbox_sts[0]);
+ return status;
+}
+
+int qla4xxx_conn_close_sess_logout(struct scsi_qla_host * ha,
+ uint16_t fw_ddb_index, uint16_t connection_id, uint16_t option)
+{
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+
+ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+ memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+ mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
+ mbox_cmd[1] = fw_ddb_index;
+ mbox_cmd[2] = connection_id;
+ mbox_cmd[3] = LOGOUT_OPTION_RESET;
+
+ if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],
+ &mbox_sts[0]) != QLA_SUCCESS) {
+ DEBUG2(printk("scsi%ld: %s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT "
+ "option %04x failed sts %04X %04X",
+ ha->host_no, __func__,
+ option, mbox_sts[0], mbox_sts[1]));
+ if (mbox_sts[0] == 0x4005)
+ DEBUG2(printk("%s reason %04X\n", __func__,
+ mbox_sts[1]));
+ }
+ return QLA_SUCCESS;
+}
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 0c78694..b6cc961 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -8,6 +8,8 @@
#include <scsi/scsi_tcq.h>
#include <scsi/scsicam.h>
+#include <scsi/iscsi_proto.h>
+#include <scsi/scsi_eh.h>
#include "ql4_def.h"
#include "ql4_version.h"
@@ -482,10 +484,24 @@ qc_fail_command:
**/
static void qla4xxx_mem_free(struct scsi_qla_host *ha)
{
+ struct list_head *ptr;
+ struct async_msg_pdu_iocb *apdu_iocb;
+
if (ha->queues)
dma_free_coherent(&ha->pdev->dev, ha->queues_len, ha->queues,
ha->queues_dma);
+ if (ha->gen_req_rsp_iocb)
+ dma_free_coherent(&ha->pdev->dev, PAGE_SIZE,
+ ha->gen_req_rsp_iocb, ha->gen_req_rsp_iocb_dma);
+
+ while (!list_empty(&ha->async_iocb_list)){
+ ptr = ha->async_iocb_list.next;
+ apdu_iocb = list_entry(ptr, struct async_msg_pdu_iocb, list);
+ list_del_init(&apdu_iocb->list);
+ vfree(apdu_iocb);
+ }
+
ha->queues_len = 0;
ha->queues = NULL;
ha->queues_dma = 0;
@@ -570,6 +586,14 @@ static int qla4xxx_mem_alloc(struct scsi
goto mem_alloc_error_exit;
}
+ ha->gen_req_rsp_iocb = dma_alloc_coherent(&ha->pdev->dev, PAGE_SIZE,
+ &ha->gen_req_rsp_iocb_dma, GFP_KERNEL);
+ if (ha->gen_req_rsp_iocb == NULL){
+ dev_warn(&ha->pdev->dev,
+ "Memory Allocation failed - gen_req_rsp_iocb.\n");
+
+ goto mem_alloc_error_exit;
+ }
return QLA_SUCCESS;
@@ -668,7 +692,8 @@ static void qla4xxx_timer(struct scsi_ql
test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags) ||
test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) ||
test_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags) ||
- test_bit(DPC_AEN, &ha->dpc_flags)) &&
+ test_bit(DPC_AEN, &ha->dpc_flags) ||
+ test_bit(DPC_ASYNC_MSG_PDU, &ha->dpc_flags)) &&
ha->dpc_thread) {
DEBUG2(printk("scsi%ld: %s: scheduling dpc routine"
" - dpc flags = 0x%lx\n",
@@ -985,6 +1010,102 @@ static int qla4xxx_recover_adapter(struc
return status;
}
+/*
+ * qla4xxx_async_iocbs - processes ASYNC PDU IOCBS, if they are greater in
+ * length than 48 bytes (i.e., more than just the iscsi header). Used for
+ * unsolicited pdus received from target.
+ */
+static void qla4xxx_async_iocbs(struct scsi_qla_host *ha,
+ struct async_msg_pdu_iocb *amsg_pdu_iocb)
+{
+ struct iscsi_hdr *hdr;
+ struct async_pdu_iocb *apdu;
+ uint32_t len;
+ void *buf_addr;
+ dma_addr_t buf_addr_dma;
+ uint32_t offset;
+ struct passthru0 *pthru0_iocb;
+ struct scsi_sense_hdr sshdr;
+ struct ddb_entry *ddb_entry = NULL;
+ uint8_t using_prealloc = 1;
+ uint8_t async_event_type;
+
+ apdu = (struct async_pdu_iocb *)amsg_pdu_iocb->iocb;
+ hdr = (struct iscsi_hdr *)apdu->iscsi_pdu_hdr;
+ len = hdr->hlength + hdr->dlength[2] +
+ (hdr->dlength[1]<<8) + (hdr->dlength[0]<<16);
+
+ offset = sizeof (struct passthru0) + sizeof (struct passthru_status);
+ if (len <= (PAGE_SIZE - offset)) {
+ buf_addr_dma = ha->gen_req_rsp_iocb_dma + offset;
+ buf_addr = (uint8_t *)ha->gen_req_rsp_iocb + offset;
+ } else {
+ using_prealloc = 0;
+ buf_addr = dma_alloc_coherent(&ha->pdev->dev, len,
+ &buf_addr_dma, GFP_KERNEL);
+ if (!buf_addr) {
+ dev_info(&ha->pdev->dev,
+ "%s: dma_alloc_coherent failed\n", __func__);
+ return;
+ }
+ }
+ /* Create the pass-thru0 iocb */
+ pthru0_iocb = ha->gen_req_rsp_iocb;
+ memset(pthru0_iocb, 0, offset);
+
+ pthru0_iocb->hdr.entryType = ET_PASSTHRU0;
+ pthru0_iocb->controlFlags =
+ cpu_to_le16(PT_FLAG_ISCSI_PDU | PT_FLAG_WAIT_4_RESPONSE);
+ pthru0_iocb->timeout = cpu_to_le16(PT_DEFAULT_TIMEOUT);
+ pthru0_iocb->inDataSeg64.base.addrHigh =
+ cpu_to_le32(MSDW(buf_addr_dma));
+ pthru0_iocb->inDataSeg64.base.addrLow =
+ cpu_to_le32(LSDW(buf_addr_dma));
+ pthru0_iocb->inDataSeg64.count = cpu_to_le32(len);
+
+ if (qla4xxx_issue_iocb(ha, sizeof(struct passthru0),
+ ha->gen_req_rsp_iocb_dma) != QLA_SUCCESS) {
+ dev_info(&ha->pdev->dev,
+ "%s: qla4xxx_issue_iocb failed\n", __func__);
+ goto exit_async_pdu_iocb;
+ }
+
+ async_event_type = ((struct iscsi_async *)hdr)->async_event;
+ ddb_entry = ha->fw_ddb_index_map[apdu->target_id];
+
+ if (ddb_entry == NULL)
+ goto exit_async_pdu_iocb;
+
+ switch (async_event_type) {
+ case ISCSI_ASYNC_MSG_SCSI_EVENT:
+ if (!scsi_normalize_sense((uint8_t *)buf_addr, len, &sshdr)) {
+ dev_info(&ha->pdev->dev,
+ "%s: scsi_normalize_sense failed\n", __func__);
+ break;
+ }
+ if (sshdr.asc == 0x3f && sshdr.ascq == 0x0e) {
+ scsi_scan_target(&ddb_entry->sess->dev, 0,
+ ddb_entry->sess->target_id, SCAN_WILD_CARD, 0);
+ }
+ break;
+ case ISCSI_ASYNC_MSG_REQUEST_LOGOUT:
+ qla4xxx_conn_close_sess_logout(ha, apdu->target_id,0,0);
+ break;
+ default:
+ dev_info(&ha->pdev->dev,
+ "%s: async msg event 0x%x not processed\n",
+ __func__, async_event_type);
+ break;
+ };
+
+exit_async_pdu_iocb:
+ if (!using_prealloc)
+ dma_free_coherent(&ha->pdev->dev, len,
+ buf_addr, buf_addr_dma);
+
+ return;
+}
+
/**
* qla4xxx_do_dpc - dpc routine
* @data: in our case pointer to adapter structure
@@ -1001,6 +1122,7 @@ static void qla4xxx_do_dpc(struct work_s
struct scsi_qla_host *ha =
container_of(work, struct scsi_qla_host, dpc_work);
struct ddb_entry *ddb_entry, *dtemp;
+ struct async_msg_pdu_iocb *apdu_iocb, *apdu_iocb_tmp;
int status = QLA_ERROR;
DEBUG2(printk("scsi%ld: %s: DPC handler waking up."
@@ -1076,6 +1198,18 @@ static void qla4xxx_do_dpc(struct work_s
}
}
}
+ /* Check for ASYNC PDU IOCBs */
+ if (adapter_up(ha) &&
+ test_bit(DPC_ASYNC_MSG_PDU, &ha->dpc_flags)) {
+
+ list_for_each_entry_safe(apdu_iocb, apdu_iocb_tmp,
+ &ha->async_iocb_list, list) {
+ qla4xxx_async_iocbs(ha, apdu_iocb);
+ list_del_init(&apdu_iocb->list);
+ vfree(apdu_iocb);
+ }
+ clear_bit(DPC_ASYNC_MSG_PDU, &ha->dpc_flags);
+ }
}
/**
@@ -1229,6 +1363,7 @@ static int __devinit qla4xxx_probe_adapt
/* Initialize lists and spinlocks. */
INIT_LIST_HEAD(&ha->ddb_list);
INIT_LIST_HEAD(&ha->free_srb_q);
+ INIT_LIST_HEAD(&ha->async_iocb_list);
mutex_init(&ha->mbox_sem);
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h
index ab984cb..6980cb2 100644
--- a/drivers/scsi/qla4xxx/ql4_version.h
+++ b/drivers/scsi/qla4xxx/ql4_version.h
@@ -5,5 +5,5 @@
* See LICENSE.qla4xxx for copyright and licensing details.
*/
-#define QLA4XXX_DRIVER_VERSION "5.01.00-k8"
+#define QLA4XXX_DRIVER_VERSION "5.01.00-k9"
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH]qla4xxx:Add support for Async Message PDUs
2008-04-18 20:44 [PATCH]qla4xxx:Add support for Async Message PDUs David C Somayajulu
@ 2008-04-22 16:20 ` Mike Christie
2008-04-24 16:01 ` David C Somayajulu
0 siblings, 1 reply; 13+ messages in thread
From: Mike Christie @ 2008-04-22 16:20 UTC (permalink / raw)
To: David C Somayajulu; +Cc: linux-scsi, David Wagner
David C Somayajulu wrote:
> +int qla4xxx_conn_close_sess_logout(struct scsi_qla_host * ha,
> + uint16_t fw_ddb_index, uint16_t connection_id, uint16_t option)
> +{
> + uint32_t mbox_cmd[MBOX_REG_COUNT];
> + uint32_t mbox_sts[MBOX_REG_COUNT];
> +
> + memset(&mbox_cmd, 0, sizeof(mbox_cmd));
> + memset(&mbox_sts, 0, sizeof(mbox_sts));
> +
> + mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
> + mbox_cmd[1] = fw_ddb_index;
> + mbox_cmd[2] = connection_id;
> + mbox_cmd[3] = LOGOUT_OPTION_RESET;
> +
> + if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],
> + &mbox_sts[0]) != QLA_SUCCESS) {
> + DEBUG2(printk("scsi%ld: %s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT "
> + "option %04x failed sts %04X %04X",
> + ha->host_no, __func__,
> + option, mbox_sts[0], mbox_sts[1]));
> + if (mbox_sts[0] == 0x4005)
> + DEBUG2(printk("%s reason %04X\n", __func__,
> + mbox_sts[1]));
> + }
> + return QLA_SUCCESS;
Does this logout function logout a session and stop it from being logged
back in, or does it logout the session then the firmware tries to log
back in?
> +/*
> + * qla4xxx_async_iocbs - processes ASYNC PDU IOCBS, if they are greater in
> + * length than 48 bytes (i.e., more than just the iscsi header). Used for
> + * unsolicited pdus received from target.
> + */
> +static void qla4xxx_async_iocbs(struct scsi_qla_host *ha,
> + struct async_msg_pdu_iocb *amsg_pdu_iocb)
> +{
> + struct iscsi_hdr *hdr;
> + struct async_pdu_iocb *apdu;
> + uint32_t len;
> + void *buf_addr;
> + dma_addr_t buf_addr_dma;
> + uint32_t offset;
> + struct passthru0 *pthru0_iocb;
> + struct scsi_sense_hdr sshdr;
> + struct ddb_entry *ddb_entry = NULL;
> + uint8_t using_prealloc = 1;
> + uint8_t async_event_type;
> +
> + apdu = (struct async_pdu_iocb *)amsg_pdu_iocb->iocb;
> + hdr = (struct iscsi_hdr *)apdu->iscsi_pdu_hdr;
> + len = hdr->hlength + hdr->dlength[2] +
> + (hdr->dlength[1]<<8) + (hdr->dlength[0]<<16);
> +
> + offset = sizeof (struct passthru0) + sizeof (struct passthru_status);
> + if (len <= (PAGE_SIZE - offset)) {
> + buf_addr_dma = ha->gen_req_rsp_iocb_dma + offset;
> + buf_addr = (uint8_t *)ha->gen_req_rsp_iocb + offset;
> + } else {
> + using_prealloc = 0;
> + buf_addr = dma_alloc_coherent(&ha->pdev->dev, len,
> + &buf_addr_dma, GFP_KERNEL);
> + if (!buf_addr) {
> + dev_info(&ha->pdev->dev,
> + "%s: dma_alloc_coherent failed\n", __func__);
> + return;
> + }
> + }
> + /* Create the pass-thru0 iocb */
> + pthru0_iocb = ha->gen_req_rsp_iocb;
> + memset(pthru0_iocb, 0, offset);
> +
> + pthru0_iocb->hdr.entryType = ET_PASSTHRU0;
> + pthru0_iocb->controlFlags =
> + cpu_to_le16(PT_FLAG_ISCSI_PDU | PT_FLAG_WAIT_4_RESPONSE);
> + pthru0_iocb->timeout = cpu_to_le16(PT_DEFAULT_TIMEOUT);
> + pthru0_iocb->inDataSeg64.base.addrHigh =
> + cpu_to_le32(MSDW(buf_addr_dma));
> + pthru0_iocb->inDataSeg64.base.addrLow =
> + cpu_to_le32(LSDW(buf_addr_dma));
> + pthru0_iocb->inDataSeg64.count = cpu_to_le32(len);
> +
> + if (qla4xxx_issue_iocb(ha, sizeof(struct passthru0),
> + ha->gen_req_rsp_iocb_dma) != QLA_SUCCESS) {
> + dev_info(&ha->pdev->dev,
> + "%s: qla4xxx_issue_iocb failed\n", __func__);
> + goto exit_async_pdu_iocb;
> + }
> +
> + async_event_type = ((struct iscsi_async *)hdr)->async_event;
> + ddb_entry = ha->fw_ddb_index_map[apdu->target_id];
> +
> + if (ddb_entry == NULL)
> + goto exit_async_pdu_iocb;
> +
> + switch (async_event_type) {
> + case ISCSI_ASYNC_MSG_SCSI_EVENT:
> + if (!scsi_normalize_sense((uint8_t *)buf_addr, len, &sshdr)) {
> + dev_info(&ha->pdev->dev,
> + "%s: scsi_normalize_sense failed\n", __func__);
> + break;
> + }
> + if (sshdr.asc == 0x3f && sshdr.ascq == 0x0e) {
> + scsi_scan_target(&ddb_entry->sess->dev, 0,
> + ddb_entry->sess->target_id, SCAN_WILD_CARD, 0);
>
I do not think you can call scsi_scan_target from your dpc thread. If
there was a problem that the the dpc thread needed to recover the
session or host for it would not be able to because the scsi_scan_target
call would be blocked on the recovery of that host or session.
You need to modify scsi_transport_iscsi.c:session->scan_work related
code to be able to be called from _iscsi_unblock_session and from some
new function that just checks the state and scans the session.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH]qla4xxx:Add support for Async Message PDUs
2008-04-22 16:20 ` Mike Christie
@ 2008-04-24 16:01 ` David C Somayajulu
2008-04-24 16:40 ` Mike Christie
0 siblings, 1 reply; 13+ messages in thread
From: David C Somayajulu @ 2008-04-24 16:01 UTC (permalink / raw)
To: Mike Christie; +Cc: linux-scsi, David Wagner
On Tue, 2008-04-22 at 11:20 -0500, Mike Christie wrote:
> David C Somayajulu wrote:
> > +int qla4xxx_conn_close_sess_logout(struct scsi_qla_host * ha,
> > + uint16_t fw_ddb_index, uint16_t connection_id, uint16_t option)
> > +{
> > + uint32_t mbox_cmd[MBOX_REG_COUNT];
> > + uint32_t mbox_sts[MBOX_REG_COUNT];
> > +
> > + memset(&mbox_cmd, 0, sizeof(mbox_cmd));
> > + memset(&mbox_sts, 0, sizeof(mbox_sts));
> > +
> > + mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
> > + mbox_cmd[1] = fw_ddb_index;
> > + mbox_cmd[2] = connection_id;
> > + mbox_cmd[3] = LOGOUT_OPTION_RESET;
> > +
> > + if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],
> > + &mbox_sts[0]) != QLA_SUCCESS) {
> > + DEBUG2(printk("scsi%ld: %s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT "
> > + "option %04x failed sts %04X %04X",
> > + ha->host_no, __func__,
> > + option, mbox_sts[0], mbox_sts[1]));
> > + if (mbox_sts[0] == 0x4005)
> > + DEBUG2(printk("%s reason %04X\n", __func__,
> > + mbox_sts[1]));
> > + }
> > + return QLA_SUCCESS;
>
>
> Does this logout function logout a session and stop it from being logged
> back in, or does it logout the session then the firmware tries to log
> back in?
Once the session is logged out, it stays in that state till the user
initiates a login. The firmware does not automatically try to login
again.
>
>
> > +/*
> > + * qla4xxx_async_iocbs - processes ASYNC PDU IOCBS, if they are greater in
> > + * length than 48 bytes (i.e., more than just the iscsi header). Used for
> > + * unsolicited pdus received from target.
> > + */
> > +static void qla4xxx_async_iocbs(struct scsi_qla_host *ha,
> > + struct async_msg_pdu_iocb *amsg_pdu_iocb)
> > +{
> > + struct iscsi_hdr *hdr;
> > + struct async_pdu_iocb *apdu;
> > + uint32_t len;
> > + void *buf_addr;
> > + dma_addr_t buf_addr_dma;
> > + uint32_t offset;
> > + struct passthru0 *pthru0_iocb;
> > + struct scsi_sense_hdr sshdr;
> > + struct ddb_entry *ddb_entry = NULL;
> > + uint8_t using_prealloc = 1;
> > + uint8_t async_event_type;
> > +
> > + apdu = (struct async_pdu_iocb *)amsg_pdu_iocb->iocb;
> > + hdr = (struct iscsi_hdr *)apdu->iscsi_pdu_hdr;
> > + len = hdr->hlength + hdr->dlength[2] +
> > + (hdr->dlength[1]<<8) + (hdr->dlength[0]<<16);
> > +
> > + offset = sizeof (struct passthru0) + sizeof (struct passthru_status);
> > + if (len <= (PAGE_SIZE - offset)) {
> > + buf_addr_dma = ha->gen_req_rsp_iocb_dma + offset;
> > + buf_addr = (uint8_t *)ha->gen_req_rsp_iocb + offset;
> > + } else {
> > + using_prealloc = 0;
> > + buf_addr = dma_alloc_coherent(&ha->pdev->dev, len,
> > + &buf_addr_dma, GFP_KERNEL);
> > + if (!buf_addr) {
> > + dev_info(&ha->pdev->dev,
> > + "%s: dma_alloc_coherent failed\n", __func__);
> > + return;
> > + }
> > + }
> > + /* Create the pass-thru0 iocb */
> > + pthru0_iocb = ha->gen_req_rsp_iocb;
> > + memset(pthru0_iocb, 0, offset);
> > +
> > + pthru0_iocb->hdr.entryType = ET_PASSTHRU0;
> > + pthru0_iocb->controlFlags =
> > + cpu_to_le16(PT_FLAG_ISCSI_PDU | PT_FLAG_WAIT_4_RESPONSE);
> > + pthru0_iocb->timeout = cpu_to_le16(PT_DEFAULT_TIMEOUT);
> > + pthru0_iocb->inDataSeg64.base.addrHigh =
> > + cpu_to_le32(MSDW(buf_addr_dma));
> > + pthru0_iocb->inDataSeg64.base.addrLow =
> > + cpu_to_le32(LSDW(buf_addr_dma));
> > + pthru0_iocb->inDataSeg64.count = cpu_to_le32(len);
> > +
> > + if (qla4xxx_issue_iocb(ha, sizeof(struct passthru0),
> > + ha->gen_req_rsp_iocb_dma) != QLA_SUCCESS) {
> > + dev_info(&ha->pdev->dev,
> > + "%s: qla4xxx_issue_iocb failed\n", __func__);
> > + goto exit_async_pdu_iocb;
> > + }
> > +
> > + async_event_type = ((struct iscsi_async *)hdr)->async_event;
> > + ddb_entry = ha->fw_ddb_index_map[apdu->target_id];
> > +
> > + if (ddb_entry == NULL)
> > + goto exit_async_pdu_iocb;
> > +
> > + switch (async_event_type) {
> > + case ISCSI_ASYNC_MSG_SCSI_EVENT:
> > + if (!scsi_normalize_sense((uint8_t *)buf_addr, len, &sshdr)) {
> > + dev_info(&ha->pdev->dev,
> > + "%s: scsi_normalize_sense failed\n", __func__);
> > + break;
> > + }
> > + if (sshdr.asc == 0x3f && sshdr.ascq == 0x0e) {
> > + scsi_scan_target(&ddb_entry->sess->dev, 0,
> > + ddb_entry->sess->target_id, SCAN_WILD_CARD, 0);
> >
>
> I do not think you can call scsi_scan_target from your dpc thread. If
> there was a problem that the the dpc thread needed to recover the
> session or host for it would not be able to because the scsi_scan_target
> call would be blocked on the recovery of that host or session.
>
> You need to modify scsi_transport_iscsi.c:session->scan_work related
> code to be able to be called from _iscsi_unblock_session and from some
> new function that just checks the state and scans the session.
O.K. Mike I will look into this.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH]qla4xxx:Add support for Async Message PDUs
2008-04-24 16:01 ` David C Somayajulu
@ 2008-04-24 16:40 ` Mike Christie
2008-04-24 19:42 ` David C Somayajulu
2008-04-25 19:23 ` David C Somayajulu
0 siblings, 2 replies; 13+ messages in thread
From: Mike Christie @ 2008-04-24 16:40 UTC (permalink / raw)
To: David C Somayajulu; +Cc: linux-scsi, David Wagner
David C Somayajulu wrote:
> On Tue, 2008-04-22 at 11:20 -0500, Mike Christie wrote:
>> David C Somayajulu wrote:
>>> +int qla4xxx_conn_close_sess_logout(struct scsi_qla_host * ha,
>>> + uint16_t fw_ddb_index, uint16_t connection_id, uint16_t option)
>>> +{
>>> + uint32_t mbox_cmd[MBOX_REG_COUNT];
>>> + uint32_t mbox_sts[MBOX_REG_COUNT];
>>> +
>>> + memset(&mbox_cmd, 0, sizeof(mbox_cmd));
>>> + memset(&mbox_sts, 0, sizeof(mbox_sts));
>>> +
>>> + mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
>>> + mbox_cmd[1] = fw_ddb_index;
>>> + mbox_cmd[2] = connection_id;
>>> + mbox_cmd[3] = LOGOUT_OPTION_RESET;
>>> +
>>> + if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],
>>> + &mbox_sts[0]) != QLA_SUCCESS) {
>>> + DEBUG2(printk("scsi%ld: %s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT "
>>> + "option %04x failed sts %04X %04X",
>>> + ha->host_no, __func__,
>>> + option, mbox_sts[0], mbox_sts[1]));
>>> + if (mbox_sts[0] == 0x4005)
>>> + DEBUG2(printk("%s reason %04X\n", __func__,
>>> + mbox_sts[1]));
>>> + }
>>> + return QLA_SUCCESS;
>>
>> Does this logout function logout a session and stop it from being logged
>> back in, or does it logout the session then the firmware tries to log
>> back in?
> Once the session is logged out, it stays in that state till the user
> initiates a login. The firmware does not automatically try to login
> again.
I think we want to login in this case. Did you guys test with this
Equalogic boxes, or what boxes did you try that send a logout request
and always do not want you to relogin?
EQL boxes have that magic target load balancing, where if they detect a
problem the box will send the async logout request. It then expects the
initiator to try a relogin, and at that time it will use the login
redirect feature to send us to a new portal.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH]qla4xxx:Add support for Async Message PDUs
2008-04-24 16:40 ` Mike Christie
@ 2008-04-24 19:42 ` David C Somayajulu
2008-04-25 19:23 ` David C Somayajulu
1 sibling, 0 replies; 13+ messages in thread
From: David C Somayajulu @ 2008-04-24 19:42 UTC (permalink / raw)
To: Mike Christie; +Cc: linux-scsi, David Wagner
On Thu, 2008-04-24 at 11:40 -0500, Mike Christie wrote:
> David C Somayajulu wrote:
> > On Tue, 2008-04-22 at 11:20 -0500, Mike Christie wrote:
> >> David C Somayajulu wrote:
> >>> +int qla4xxx_conn_close_sess_logout(struct scsi_qla_host * ha,
> >>> + uint16_t fw_ddb_index, uint16_t connection_id, uint16_t option)
> >>> +{
> >>> + uint32_t mbox_cmd[MBOX_REG_COUNT];
> >>> + uint32_t mbox_sts[MBOX_REG_COUNT];
> >>> +
> >>> + memset(&mbox_cmd, 0, sizeof(mbox_cmd));
> >>> + memset(&mbox_sts, 0, sizeof(mbox_sts));
> >>> +
> >>> + mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
> >>> + mbox_cmd[1] = fw_ddb_index;
> >>> + mbox_cmd[2] = connection_id;
> >>> + mbox_cmd[3] = LOGOUT_OPTION_RESET;
> >>> +
> >>> + if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],
> >>> + &mbox_sts[0]) != QLA_SUCCESS) {
> >>> + DEBUG2(printk("scsi%ld: %s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT "
> >>> + "option %04x failed sts %04X %04X",
> >>> + ha->host_no, __func__,
> >>> + option, mbox_sts[0], mbox_sts[1]));
> >>> + if (mbox_sts[0] == 0x4005)
> >>> + DEBUG2(printk("%s reason %04X\n", __func__,
> >>> + mbox_sts[1]));
> >>> + }
> >>> + return QLA_SUCCESS;
> >>
> >> Does this logout function logout a session and stop it from being logged
> >> back in, or does it logout the session then the firmware tries to log
> >> back in?
> > Once the session is logged out, it stays in that state till the user
> > initiates a login. The firmware does not automatically try to login
> > again.
>
> I think we want to login in this case. Did you guys test with this
> Equalogic boxes, or what boxes did you try that send a logout request
> and always do not want you to relogin?
>
> EQL boxes have that magic target load balancing, where if they detect a
> problem the box will send the async logout request. It then expects the
> initiator to try a relogin, and at that time it will use the login
> redirect feature to send us to a new portal.
I did not use Equal Logic. Will check it out.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH]qla4xxx:Add support for Async Message PDUs
2008-04-24 16:40 ` Mike Christie
2008-04-24 19:42 ` David C Somayajulu
@ 2008-04-25 19:23 ` David C Somayajulu
2008-04-26 16:42 ` Mike Christie
1 sibling, 1 reply; 13+ messages in thread
From: David C Somayajulu @ 2008-04-25 19:23 UTC (permalink / raw)
To: Mike Christie; +Cc: linux-scsi, David Wagner, David Somayajulu
On Thu, 2008-04-24 at 11:40 -0500, Mike Christie wrote:
> David C Somayajulu wrote:
> > On Tue, 2008-04-22 at 11:20 -0500, Mike Christie wrote:
> >> David C Somayajulu wrote:
> >>> +int qla4xxx_conn_close_sess_logout(struct scsi_qla_host * ha,
> >>> + uint16_t fw_ddb_index, uint16_t connection_id, uint16_t option)
> >>> +{
> >>> + uint32_t mbox_cmd[MBOX_REG_COUNT];
> >>> + uint32_t mbox_sts[MBOX_REG_COUNT];
> >>> +
> >>> + memset(&mbox_cmd, 0, sizeof(mbox_cmd));
> >>> + memset(&mbox_sts, 0, sizeof(mbox_sts));
> >>> +
> >>> + mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
> >>> + mbox_cmd[1] = fw_ddb_index;
> >>> + mbox_cmd[2] = connection_id;
> >>> + mbox_cmd[3] = LOGOUT_OPTION_RESET;
> >>> +
> >>> + if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],
> >>> + &mbox_sts[0]) != QLA_SUCCESS) {
> >>> + DEBUG2(printk("scsi%ld: %s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT "
> >>> + "option %04x failed sts %04X %04X",
> >>> + ha->host_no, __func__,
> >>> + option, mbox_sts[0], mbox_sts[1]));
> >>> + if (mbox_sts[0] == 0x4005)
> >>> + DEBUG2(printk("%s reason %04X\n", __func__,
> >>> + mbox_sts[1]));
> >>> + }
> >>> + return QLA_SUCCESS;
> >>
> >> Does this logout function logout a session and stop it from being logged
> >> back in, or does it logout the session then the firmware tries to log
> >> back in?
> > Once the session is logged out, it stays in that state till the user
> > initiates a login. The firmware does not automatically try to login
> > again.
>
> I think we want to login in this case. Did you guys test with this
> Equalogic boxes, or what boxes did you try that send a logout request
> and always do not want you to relogin?
>
> EQL boxes have that magic target load balancing, where if they detect a
> problem the box will send the async logout request. It then expects the
> initiator to try a relogin, and at that time it will use the login
> redirect feature to send us to a new portal.
Mike, you are correct. Async Logout is for recovery (stated in RFC5048).
I have since confirmed with one of the storage vendors as well. I am
trying to see if there is a Time2Wait (seconds) type thing the initiator
needs to honor before it does the re-login. I will repost the patch.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH]qla4xxx:Add support for Async Message PDUs
2008-04-25 19:23 ` David C Somayajulu
@ 2008-04-26 16:42 ` Mike Christie
2008-04-28 15:39 ` David C Somayajulu
2008-04-30 18:35 ` [PATCH]qla4xxx:Add support for Async Message PDUs [REPOST with fixes] David C Somayajulu
0 siblings, 2 replies; 13+ messages in thread
From: Mike Christie @ 2008-04-26 16:42 UTC (permalink / raw)
To: David C Somayajulu; +Cc: linux-scsi, David Wagner
David C Somayajulu wrote:
> On Thu, 2008-04-24 at 11:40 -0500, Mike Christie wrote:
>> David C Somayajulu wrote:
>>> On Tue, 2008-04-22 at 11:20 -0500, Mike Christie wrote:
>>>> David C Somayajulu wrote:
>>>>> +int qla4xxx_conn_close_sess_logout(struct scsi_qla_host * ha,
>>>>> + uint16_t fw_ddb_index, uint16_t connection_id, uint16_t option)
>>>>> +{
>>>>> + uint32_t mbox_cmd[MBOX_REG_COUNT];
>>>>> + uint32_t mbox_sts[MBOX_REG_COUNT];
>>>>> +
>>>>> + memset(&mbox_cmd, 0, sizeof(mbox_cmd));
>>>>> + memset(&mbox_sts, 0, sizeof(mbox_sts));
>>>>> +
>>>>> + mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
>>>>> + mbox_cmd[1] = fw_ddb_index;
>>>>> + mbox_cmd[2] = connection_id;
>>>>> + mbox_cmd[3] = LOGOUT_OPTION_RESET;
>>>>> +
>>>>> + if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],
>>>>> + &mbox_sts[0]) != QLA_SUCCESS) {
>>>>> + DEBUG2(printk("scsi%ld: %s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT "
>>>>> + "option %04x failed sts %04X %04X",
>>>>> + ha->host_no, __func__,
>>>>> + option, mbox_sts[0], mbox_sts[1]));
>>>>> + if (mbox_sts[0] == 0x4005)
>>>>> + DEBUG2(printk("%s reason %04X\n", __func__,
>>>>> + mbox_sts[1]));
>>>>> + }
>>>>> + return QLA_SUCCESS;
>>>> Does this logout function logout a session and stop it from being logged
>>>> back in, or does it logout the session then the firmware tries to log
>>>> back in?
>>> Once the session is logged out, it stays in that state till the user
>>> initiates a login. The firmware does not automatically try to login
>>> again.
>> I think we want to login in this case. Did you guys test with this
>> Equalogic boxes, or what boxes did you try that send a logout request
>> and always do not want you to relogin?
>>
>> EQL boxes have that magic target load balancing, where if they detect a
>> problem the box will send the async logout request. It then expects the
>> initiator to try a relogin, and at that time it will use the login
>> redirect feature to send us to a new portal.
> Mike, you are correct. Async Logout is for recovery (stated in RFC5048).
> I have since confirmed with one of the storage vendors as well. I am
> trying to see if there is a Time2Wait (seconds) type thing the initiator
> needs to honor before it does the re-login. I will repost the patch.
There is. I think in the dropping connections related asyn pdus there is
a time2wait value, and with the logout request asyn pdu, you will get a
time2wait in the logout response.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH]qla4xxx:Add support for Async Message PDUs
2008-04-26 16:42 ` Mike Christie
@ 2008-04-28 15:39 ` David C Somayajulu
2008-04-30 18:35 ` [PATCH]qla4xxx:Add support for Async Message PDUs [REPOST with fixes] David C Somayajulu
1 sibling, 0 replies; 13+ messages in thread
From: David C Somayajulu @ 2008-04-28 15:39 UTC (permalink / raw)
To: Mike Christie; +Cc: linux-scsi, David Wagner
On Sat, 2008-04-26 at 11:42 -0500, Mike Christie wrote:
> David C Somayajulu wrote:
> > On Thu, 2008-04-24 at 11:40 -0500, Mike Christie wrote:
> >> David C Somayajulu wrote:
> >>> On Tue, 2008-04-22 at 11:20 -0500, Mike Christie wrote:
> >>>> David C Somayajulu wrote:
> >>>>> +int qla4xxx_conn_close_sess_logout(struct scsi_qla_host * ha,
> >>>>> + uint16_t fw_ddb_index, uint16_t connection_id, uint16_t option)
> >>>>> +{
> >>>>> + uint32_t mbox_cmd[MBOX_REG_COUNT];
> >>>>> + uint32_t mbox_sts[MBOX_REG_COUNT];
> >>>>> +
> >>>>> + memset(&mbox_cmd, 0, sizeof(mbox_cmd));
> >>>>> + memset(&mbox_sts, 0, sizeof(mbox_sts));
> >>>>> +
> >>>>> + mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
> >>>>> + mbox_cmd[1] = fw_ddb_index;
> >>>>> + mbox_cmd[2] = connection_id;
> >>>>> + mbox_cmd[3] = LOGOUT_OPTION_RESET;
> >>>>> +
> >>>>> + if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],
> >>>>> + &mbox_sts[0]) != QLA_SUCCESS) {
> >>>>> + DEBUG2(printk("scsi%ld: %s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT "
> >>>>> + "option %04x failed sts %04X %04X",
> >>>>> + ha->host_no, __func__,
> >>>>> + option, mbox_sts[0], mbox_sts[1]));
> >>>>> + if (mbox_sts[0] == 0x4005)
> >>>>> + DEBUG2(printk("%s reason %04X\n", __func__,
> >>>>> + mbox_sts[1]));
> >>>>> + }
> >>>>> + return QLA_SUCCESS;
> >>>> Does this logout function logout a session and stop it from being logged
> >>>> back in, or does it logout the session then the firmware tries to log
> >>>> back in?
> >>> Once the session is logged out, it stays in that state till the user
> >>> initiates a login. The firmware does not automatically try to login
> >>> again.
> >> I think we want to login in this case. Did you guys test with this
> >> Equalogic boxes, or what boxes did you try that send a logout request
> >> and always do not want you to relogin?
> >>
> >> EQL boxes have that magic target load balancing, where if they detect a
> >> problem the box will send the async logout request. It then expects the
> >> initiator to try a relogin, and at that time it will use the login
> >> redirect feature to send us to a new portal.
> > Mike, you are correct. Async Logout is for recovery (stated in RFC5048).
> > I have since confirmed with one of the storage vendors as well. I am
> > trying to see if there is a Time2Wait (seconds) type thing the initiator
> > needs to honor before it does the re-login. I will repost the patch.
>
> There is. I think in the dropping connections related asyn pdus there is
> a time2wait value, and with the logout request asyn pdu, you will get a
> time2wait in the logout response.
The time2wait you are referring to is the time the Target waits for the
Logout from the Initiator before if shuts down the connection on its
own. It appears that there is no time2wait for the relogin.
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH]qla4xxx:Add support for Async Message PDUs [REPOST with fixes]
2008-04-26 16:42 ` Mike Christie
2008-04-28 15:39 ` David C Somayajulu
@ 2008-04-30 18:35 ` David C Somayajulu
2008-04-30 19:23 ` Mike Christie
1 sibling, 1 reply; 13+ messages in thread
From: David C Somayajulu @ 2008-04-30 18:35 UTC (permalink / raw)
To: linux-scsi; +Cc: Mike Christie, David Wagner, david.somayajulu
This patch contains the following after incorporating the fixes from the feedback received:
1. when hba completion status is good, check for iscsi transport errors (underflow/overflow) prior to checking the scsi status
2. New firmware requires that one marker iocb be issued for each task management command. The patch issues marker iocb immediately following a LUN or Target reset.
Signed-off-by: David C Somayajulu <david.somayajulu@qlogic.com>
----
drivers/scsi/qla4xxx/ql4_def.h | 8 ++
drivers/scsi/qla4xxx/ql4_fw.h | 39 ++++++----
drivers/scsi/qla4xxx/ql4_glbl.h | 4 +
drivers/scsi/qla4xxx/ql4_isr.c | 23 ++++++
drivers/scsi/qla4xxx/ql4_mbx.c | 48 ++++++++++++-
drivers/scsi/qla4xxx/ql4_os.c | 146 +++++++++++++++++++++++++++++++++++-
drivers/scsi/qla4xxx/ql4_version.h | 2 +-
7 files changed, 253 insertions(+), 17 deletions(-)
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
index d6be076..12b5623 100644
--- a/drivers/scsi/qla4xxx/ql4_def.h
+++ b/drivers/scsi/qla4xxx/ql4_def.h
@@ -296,6 +296,7 @@ struct scsi_qla_host {
#define DPC_ISNS_RESTART 7 /* 0x00000080 */
#define DPC_AEN 9 /* 0x00000200 */
#define DPC_GET_DHCP_IP_ADDR 15 /* 0x00008000 */
+#define DPC_ASYNC_MSG_PDU 16 /* 0x00010000 */
struct Scsi_Host *host; /* pointer to host data */
uint32_t tot_ddbs;
@@ -434,7 +435,14 @@ struct scsi_qla_host {
/* Map ddb_list entry by FW ddb index */
struct ddb_entry *fw_ddb_index_map[MAX_DDB_ENTRIES];
+ struct list_head async_iocb_list;
+ dma_addr_t gen_req_rsp_iocb_dma;
+ void *gen_req_rsp_iocb;
+};
+struct async_msg_pdu_iocb {
+ struct list_head list;
+ uint8_t iocb[0x40];
};
static inline int is_qla4010(struct scsi_qla_host *ha)
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h
index 1b667a7..5023f6f 100644
--- a/drivers/scsi/qla4xxx/ql4_fw.h
+++ b/drivers/scsi/qla4xxx/ql4_fw.h
@@ -227,8 +227,8 @@ union external_hw_config_reg {
#define MBOX_CMD_READ_FLASH 0x0026
#define MBOX_CMD_CLEAR_DATABASE_ENTRY 0x0031
#define MBOX_CMD_CONN_CLOSE_SESS_LOGOUT 0x0056
-#define LOGOUT_OPTION_CLOSE_SESSION 0x01
-#define LOGOUT_OPTION_RELOGIN 0x02
+#define LOGOUT_OPTION_CLOSE_SESSION 0x02
+#define LOGOUT_OPTION_RESET 0x04
#define MBOX_CMD_EXECUTE_IOCB_A64 0x005A
#define MBOX_CMD_INITIALIZE_FIRMWARE 0x0060
#define MBOX_CMD_GET_INIT_FW_CTRL_BLOCK 0x0061
@@ -576,13 +576,14 @@ struct conn_event_log_entry {
/* IOCB header structure */
struct qla4_header {
uint8_t entryType;
-#define ET_STATUS 0x03
-#define ET_MARKER 0x04
-#define ET_CONT_T1 0x0A
-#define ET_STATUS_CONTINUATION 0x10
-#define ET_CMND_T3 0x19
-#define ET_PASSTHRU0 0x3A
-#define ET_PASSTHRU_STATUS 0x3C
+#define ET_STATUS 0x03
+#define ET_MARKER 0x04
+#define ET_CONT_T1 0x0A
+#define ET_STATUS_CONTINUATION 0x10
+#define ET_CMND_T3 0x19
+#define ET_ASYNC_PDU 0x37
+#define ET_PASSTHRU0 0x3A
+#define ET_PASSTHRU_STATUS 0x3C
uint8_t entryStatus;
uint8_t systemDefined;
@@ -691,6 +692,18 @@ struct qla4_marker_entry {
uint64_t reserved6; /* 38-3F */
};
+/* Asynchronous PDU IOCB structure */
+struct async_pdu_iocb {
+ struct qla4_header hdr; /* 00-02 */
+ uint32_t async_pdu_handle; /* 03-06 */
+ uint16_t target_id; /* 07-08 */
+ uint16_t status; /* 09-0A */
+#define ASYNC_PDU_IOCB_STS_OK 0x01
+
+ uint32_t rsrvd; /* 0B-0F */
+ uint8_t iscsi_pdu_hdr[48]; /* 10-3F */
+};
+
/* Status entry structure*/
struct status_entry {
struct qla4_header hdr; /* 00-03 */
@@ -738,11 +751,8 @@ struct passthru0 {
uint32_t handle; /* 04-07 */
uint16_t target; /* 08-09 */
uint16_t connectionID; /* 0A-0B */
-#define ISNS_DEFAULT_SERVER_CONN_ID ((uint16_t)0x8000)
-
uint16_t controlFlags; /* 0C-0D */
-#define PT_FLAG_ETHERNET_FRAME 0x8000
-#define PT_FLAG_ISNS_PDU 0x8000
+#define PT_FLAG_ISCSI_PDU 0x1000
#define PT_FLAG_SEND_BUFFER 0x0200
#define PT_FLAG_WAIT_4_RESPONSE 0x0100
@@ -752,7 +762,8 @@ struct passthru0 {
struct data_seg_a64 outDataSeg64; /* 10-1B */
uint32_t res1; /* 1C-1F */
struct data_seg_a64 inDataSeg64; /* 20-2B */
- uint8_t res2[20]; /* 2C-3F */
+ uint8_t res2[16]; /* 2C-3B */
+ uint32_t async_pdu_handle;
};
struct passthru_status {
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
index 96ebfb0..7542996 100644
--- a/drivers/scsi/qla4xxx/ql4_glbl.h
+++ b/drivers/scsi/qla4xxx/ql4_glbl.h
@@ -31,6 +31,10 @@ int qla4xxx_reset_target(struct scsi_qla
struct ddb_entry * ddb_entry);
int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr,
uint32_t offset, uint32_t len);
+int qla4xxx_issue_iocb(struct scsi_qla_host * ha, uint32_t comp_offset,
+ dma_addr_t phys_addr);
+int qla4xxx_conn_close_sess_logout(struct scsi_qla_host * ha,
+ uint16_t fw_ddb_index, uint16_t connection_id, uint16_t option);
int qla4xxx_get_firmware_status(struct scsi_qla_host * ha);
int qla4xxx_get_firmware_state(struct scsi_qla_host * ha);
int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha);
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c
index a91a57c..77b2f65 100644
--- a/drivers/scsi/qla4xxx/ql4_isr.c
+++ b/drivers/scsi/qla4xxx/ql4_isr.c
@@ -9,6 +9,7 @@
#include "ql4_glbl.h"
#include "ql4_dbg.h"
#include "ql4_inline.h"
+#include <scsi/iscsi_proto.h>
/**
* qla4xxx_status_entry - processes status IOCBs
@@ -285,6 +286,9 @@ static void qla4xxx_process_response_que
uint32_t count = 0;
struct srb *srb = NULL;
struct status_entry *sts_entry;
+ struct async_pdu_iocb *apdu;
+ struct iscsi_hdr *pdu_hdr;
+ struct async_msg_pdu_iocb *apdu_iocb;
/* Process all responses from response queue */
while ((ha->response_in =
@@ -315,6 +319,25 @@ static void qla4xxx_process_response_que
case ET_PASSTHRU_STATUS:
break;
+ case ET_ASYNC_PDU:
+ apdu = (struct async_pdu_iocb *)sts_entry;
+ if (apdu->status != ASYNC_PDU_IOCB_STS_OK)
+ break;
+
+ pdu_hdr = (struct iscsi_hdr *)apdu->iscsi_pdu_hdr;
+ if (pdu_hdr->hlength || pdu_hdr->dlength[0] ||
+ pdu_hdr->dlength[1] || pdu_hdr->dlength[2]){
+ apdu_iocb = vmalloc(sizeof (struct async_msg_pdu_iocb));
+ if (apdu_iocb) {
+ memcpy(apdu_iocb->iocb, apdu,
+ sizeof(struct async_pdu_iocb));
+ list_add_tail(&apdu_iocb->list,
+ &ha->async_iocb_list);
+ set_bit(DPC_ASYNC_MSG_PDU, &ha->dpc_flags);
+ }
+ }
+ break;
+
case ET_STATUS_CONTINUATION:
/* Just throw away the status continuation entries */
DEBUG2(printk("scsi%ld: %s: Status Continuation entry "
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c
index c577d79..75bcf2b 100644
--- a/drivers/scsi/qla4xxx/ql4_mbx.c
+++ b/drivers/scsi/qla4xxx/ql4_mbx.c
@@ -862,7 +862,6 @@ static int qla4xxx_req_ddb_entry(struct
return QLA_SUCCESS;
}
-
int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port)
{
struct dev_db_entry *fw_ddb_entry;
@@ -915,3 +914,50 @@ qla4xxx_send_tgts_exit:
return ret_val;
}
+int
+qla4xxx_issue_iocb(struct scsi_qla_host * ha, uint32_t comp_offset,
+ dma_addr_t phys_addr)
+{
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+ int status;
+
+ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+ memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+ mbox_cmd[0] = MBOX_CMD_EXECUTE_IOCB_A64;
+ mbox_cmd[1] = comp_offset;
+ mbox_cmd[2] = LSDW(phys_addr);
+ mbox_cmd[3] = MSDW(phys_addr);
+
+ status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
+ &mbox_sts[0]);
+ return status;
+}
+
+int qla4xxx_conn_close_sess_logout(struct scsi_qla_host * ha,
+ uint16_t fw_ddb_index, uint16_t connection_id, uint16_t option)
+{
+ uint32_t mbox_cmd[MBOX_REG_COUNT];
+ uint32_t mbox_sts[MBOX_REG_COUNT];
+
+ memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+ memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+ mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT;
+ mbox_cmd[1] = fw_ddb_index;
+ mbox_cmd[2] = connection_id;
+ mbox_cmd[3] = LOGOUT_OPTION_RESET;
+
+ if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0],
+ &mbox_sts[0]) != QLA_SUCCESS) {
+ DEBUG2(printk("scsi%ld: %s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT "
+ "option %04x failed sts %04X %04X",
+ ha->host_no, __func__,
+ option, mbox_sts[0], mbox_sts[1]));
+ if (mbox_sts[0] == 0x4005)
+ DEBUG2(printk("%s reason %04X\n", __func__,
+ mbox_sts[1]));
+ }
+ return QLA_SUCCESS;
+}
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 0c78694..0540302 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -8,6 +8,8 @@
#include <scsi/scsi_tcq.h>
#include <scsi/scsicam.h>
+#include <scsi/iscsi_proto.h>
+#include <scsi/scsi_eh.h>
#include "ql4_def.h"
#include "ql4_version.h"
@@ -482,10 +484,24 @@ qc_fail_command:
**/
static void qla4xxx_mem_free(struct scsi_qla_host *ha)
{
+ struct list_head *ptr;
+ struct async_msg_pdu_iocb *apdu_iocb;
+
if (ha->queues)
dma_free_coherent(&ha->pdev->dev, ha->queues_len, ha->queues,
ha->queues_dma);
+ if (ha->gen_req_rsp_iocb)
+ dma_free_coherent(&ha->pdev->dev, PAGE_SIZE,
+ ha->gen_req_rsp_iocb, ha->gen_req_rsp_iocb_dma);
+
+ while (!list_empty(&ha->async_iocb_list)){
+ ptr = ha->async_iocb_list.next;
+ apdu_iocb = list_entry(ptr, struct async_msg_pdu_iocb, list);
+ list_del_init(&apdu_iocb->list);
+ vfree(apdu_iocb);
+ }
+
ha->queues_len = 0;
ha->queues = NULL;
ha->queues_dma = 0;
@@ -570,6 +586,14 @@ static int qla4xxx_mem_alloc(struct scsi
goto mem_alloc_error_exit;
}
+ ha->gen_req_rsp_iocb = dma_alloc_coherent(&ha->pdev->dev, PAGE_SIZE,
+ &ha->gen_req_rsp_iocb_dma, GFP_KERNEL);
+ if (ha->gen_req_rsp_iocb == NULL){
+ dev_warn(&ha->pdev->dev,
+ "Memory Allocation failed - gen_req_rsp_iocb.\n");
+
+ goto mem_alloc_error_exit;
+ }
return QLA_SUCCESS;
@@ -668,7 +692,8 @@ static void qla4xxx_timer(struct scsi_ql
test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags) ||
test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) ||
test_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags) ||
- test_bit(DPC_AEN, &ha->dpc_flags)) &&
+ test_bit(DPC_AEN, &ha->dpc_flags) ||
+ test_bit(DPC_ASYNC_MSG_PDU, &ha->dpc_flags)) &&
ha->dpc_thread) {
DEBUG2(printk("scsi%ld: %s: scheduling dpc routine"
" - dpc flags = 0x%lx\n",
@@ -985,6 +1010,111 @@ static int qla4xxx_recover_adapter(struc
return status;
}
+/*
+ * qla4xxx_async_iocbs - processes ASYNC PDU IOCBS, if they are greater in
+ * length than 48 bytes (i.e., more than just the iscsi header). Used for
+ * unsolicited pdus received from target.
+ */
+static void qla4xxx_async_iocbs(struct scsi_qla_host *ha,
+ struct async_msg_pdu_iocb *amsg_pdu_iocb)
+{
+ struct iscsi_hdr *hdr;
+ struct async_pdu_iocb *apdu;
+ uint32_t len;
+ void *buf_addr;
+ dma_addr_t buf_addr_dma;
+ uint32_t offset;
+ struct passthru0 *pthru0_iocb;
+ struct scsi_sense_hdr sshdr;
+ struct ddb_entry *ddb_entry = NULL;
+ uint8_t using_prealloc = 1;
+ uint8_t async_event_type;
+
+ apdu = (struct async_pdu_iocb *)amsg_pdu_iocb->iocb;
+ hdr = (struct iscsi_hdr *)apdu->iscsi_pdu_hdr;
+ len = hdr->hlength + hdr->dlength[2] +
+ (hdr->dlength[1]<<8) + (hdr->dlength[0]<<16);
+
+ offset = sizeof (struct passthru0) + sizeof (struct passthru_status);
+ if (len <= (PAGE_SIZE - offset)) {
+ buf_addr_dma = ha->gen_req_rsp_iocb_dma + offset;
+ buf_addr = (uint8_t *)ha->gen_req_rsp_iocb + offset;
+ } else {
+ using_prealloc = 0;
+ buf_addr = dma_alloc_coherent(&ha->pdev->dev, len,
+ &buf_addr_dma, GFP_KERNEL);
+ if (!buf_addr) {
+ dev_info(&ha->pdev->dev,
+ "%s: dma_alloc_coherent failed\n", __func__);
+ return;
+ }
+ }
+ /* Create the pass-thru0 iocb */
+ pthru0_iocb = ha->gen_req_rsp_iocb;
+ memset(pthru0_iocb, 0, offset);
+
+ pthru0_iocb->hdr.entryType = ET_PASSTHRU0;
+ pthru0_iocb->hdr.entryCount = 1;
+ pthru0_iocb->target = cpu_to_le16(apdu->target_id);
+ pthru0_iocb->controlFlags =
+ cpu_to_le16(PT_FLAG_ISCSI_PDU | PT_FLAG_WAIT_4_RESPONSE);
+ pthru0_iocb->timeout = cpu_to_le16(PT_DEFAULT_TIMEOUT);
+ pthru0_iocb->inDataSeg64.base.addrHigh =
+ cpu_to_le32(MSDW(buf_addr_dma));
+ pthru0_iocb->inDataSeg64.base.addrLow =
+ cpu_to_le32(LSDW(buf_addr_dma));
+ pthru0_iocb->inDataSeg64.count = cpu_to_le32(len);
+ pthru0_iocb->async_pdu_handle = cpu_to_le32(apdu->async_pdu_handle);
+
+ if (qla4xxx_issue_iocb(ha, sizeof(struct passthru0),
+ ha->gen_req_rsp_iocb_dma) != QLA_SUCCESS) {
+ dev_info(&ha->pdev->dev,
+ "%s: qla4xxx_issue_iocb failed\n", __func__);
+ goto exit_async_pdu_iocb;
+ }
+
+ async_event_type = ((struct iscsi_async *)hdr)->async_event;
+ ddb_entry = ha->fw_ddb_index_map[apdu->target_id];
+
+ if (ddb_entry == NULL)
+ goto exit_async_pdu_iocb;
+
+ switch (async_event_type) {
+ case ISCSI_ASYNC_MSG_SCSI_EVENT:
+ if (!scsi_normalize_sense((uint8_t *)buf_addr, len, &sshdr)) {
+ dev_info(&ha->pdev->dev,
+ "%s: scsi_normalize_sense failed\n", __func__);
+ break;
+ }
+ if (sshdr.asc == 0x3f && sshdr.ascq == 0x0e) {
+ /* induce rescan */
+ iscsi_block_session(ddb_entry->sess);
+ iscsi_unblock_session(ddb_entry->sess);
+ }
+ break;
+ case ISCSI_ASYNC_MSG_REQUEST_LOGOUT:
+ qla4xxx_conn_close_sess_logout(ha, apdu->target_id,0,0);
+ iscsi_block_session(ddb_entry->sess);
+
+ /* Re-establish session */
+ qla4xxx_set_ddb_entry(ha, ddb_entry->fw_ddb_index, 0);
+ /* Session gets unblocked due to AEN at session establishment */
+ break;
+ default:
+ dev_info(&ha->pdev->dev,
+ "%s: async msg event 0x%x not processed\n",
+ __func__, async_event_type);
+ break;
+ };
+
+exit_async_pdu_iocb:
+ if (!using_prealloc)
+ dma_free_coherent(&ha->pdev->dev, len,
+ buf_addr, buf_addr_dma);
+
+ return;
+}
+
/**
* qla4xxx_do_dpc - dpc routine
* @data: in our case pointer to adapter structure
@@ -1001,6 +1131,7 @@ static void qla4xxx_do_dpc(struct work_s
struct scsi_qla_host *ha =
container_of(work, struct scsi_qla_host, dpc_work);
struct ddb_entry *ddb_entry, *dtemp;
+ struct async_msg_pdu_iocb *apdu_iocb, *apdu_iocb_tmp;
int status = QLA_ERROR;
DEBUG2(printk("scsi%ld: %s: DPC handler waking up."
@@ -1076,6 +1207,18 @@ static void qla4xxx_do_dpc(struct work_s
}
}
}
+ /* Check for ASYNC PDU IOCBs */
+ if (adapter_up(ha) &&
+ test_bit(DPC_ASYNC_MSG_PDU, &ha->dpc_flags)) {
+
+ list_for_each_entry_safe(apdu_iocb, apdu_iocb_tmp,
+ &ha->async_iocb_list, list) {
+ qla4xxx_async_iocbs(ha, apdu_iocb);
+ list_del_init(&apdu_iocb->list);
+ vfree(apdu_iocb);
+ }
+ clear_bit(DPC_ASYNC_MSG_PDU, &ha->dpc_flags);
+ }
}
/**
@@ -1229,6 +1372,7 @@ static int __devinit qla4xxx_probe_adapt
/* Initialize lists and spinlocks. */
INIT_LIST_HEAD(&ha->ddb_list);
INIT_LIST_HEAD(&ha->free_srb_q);
+ INIT_LIST_HEAD(&ha->async_iocb_list);
mutex_init(&ha->mbox_sem);
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h
index ab984cb..6980cb2 100644
--- a/drivers/scsi/qla4xxx/ql4_version.h
+++ b/drivers/scsi/qla4xxx/ql4_version.h
@@ -5,5 +5,5 @@
* See LICENSE.qla4xxx for copyright and licensing details.
*/
-#define QLA4XXX_DRIVER_VERSION "5.01.00-k8"
+#define QLA4XXX_DRIVER_VERSION "5.01.00-k9"
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH]qla4xxx:Add support for Async Message PDUs [REPOST with fixes]
2008-04-30 18:35 ` [PATCH]qla4xxx:Add support for Async Message PDUs [REPOST with fixes] David C Somayajulu
@ 2008-04-30 19:23 ` Mike Christie
2008-04-30 19:36 ` Mike Christie
0 siblings, 1 reply; 13+ messages in thread
From: Mike Christie @ 2008-04-30 19:23 UTC (permalink / raw)
To: David C Somayajulu; +Cc: linux-scsi, David Wagner
David C Somayajulu wrote:
> + }
> + if (sshdr.asc == 0x3f && sshdr.ascq == 0x0e) {
> + /* induce rescan */
> + iscsi_block_session(ddb_entry->sess);
> + iscsi_unblock_session(ddb_entry->sess);
> + }
I think I was wrong off list. We could actually just call
iscsi_unblock_session, but we do not know the state of the session do
we? If we got a event that indicated the session was failed could we
have a block queued up and this would reverse it by accident?
I was thinking that because qla4xxx_process_aen is called before this we
could just check the ddb state, but we can call iscsi_block_session from
the interrupt handler to queue up a block so I think that could race
with the unblock call here.
I think you really just want to separate that code. It might also be
better to make a more generic framework. If we got this in the scsi
command sense we want to rescan too. And the problem is that celerra or
centerra and cisco mds will send the iscsi asyn pdu, but netapp and
other boxes do not (probably even across EMC boxes we will not see the
same thing :( ). These other boxes send the sense in the scsi command,
so eventually we have to handle it both places to make our masters happy :)
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH]qla4xxx:Add support for Async Message PDUs [REPOST with fixes]
2008-04-30 19:23 ` Mike Christie
@ 2008-04-30 19:36 ` Mike Christie
2008-05-01 0:36 ` David C Somayajulu
0 siblings, 1 reply; 13+ messages in thread
From: Mike Christie @ 2008-04-30 19:36 UTC (permalink / raw)
To: David C Somayajulu; +Cc: linux-scsi, David Wagner
Mike Christie wrote:
> David C Somayajulu wrote:
>> + }
>> + if (sshdr.asc == 0x3f && sshdr.ascq == 0x0e) {
>> + /* induce rescan */
>> + iscsi_block_session(ddb_entry->sess);
>> + iscsi_unblock_session(ddb_entry->sess);
>> + }
>
> I think I was wrong off list. We could actually just call
> iscsi_unblock_session, but we do not know the state of the session do
> we? If we got a event that indicated the session was failed could we
> have a block queued up and this would reverse it by accident?
>
> I was thinking that because qla4xxx_process_aen is called before this we
> could just check the ddb state, but we can call iscsi_block_session from
> the interrupt handler to queue up a block so I think that could race
> with the unblock call here.
Maybe to handle the race we do not want to call qla4xxx_mark_device_busy
when we get SCS_TIMEOUT. If we get a ddb aen then could we just wait for
that and all those events would be serialized through the dpc thread?
What does SCS_TIMEOUT mean?
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH]qla4xxx:Add support for Async Message PDUs [REPOST with fixes]
2008-04-30 19:36 ` Mike Christie
@ 2008-05-01 0:36 ` David C Somayajulu
2008-05-01 14:59 ` Mike Christie
0 siblings, 1 reply; 13+ messages in thread
From: David C Somayajulu @ 2008-05-01 0:36 UTC (permalink / raw)
To: Mike Christie; +Cc: linux-scsi, David Wagner
On Wed, 2008-04-30 at 14:36 -0500, Mike Christie wrote:
> Mike Christie wrote:
> > David C Somayajulu wrote:
> >> + }
> >> + if (sshdr.asc == 0x3f && sshdr.ascq == 0x0e) {
> >> + /* induce rescan */
> >> + iscsi_block_session(ddb_entry->sess);
> >> + iscsi_unblock_session(ddb_entry->sess);
> >> + }
> >
> > I think I was wrong off list. We could actually just call
> > iscsi_unblock_session, but we do not know the state of the session do
> > we? If we got a event that indicated the session was failed could we
> > have a block queued up and this would reverse it by accident?
> >
> > I was thinking that because qla4xxx_process_aen is called before this we
> > could just check the ddb state, but we can call iscsi_block_session from
> > the interrupt handler to queue up a block so I think that could race
> > with the unblock call here.
>
> Maybe to handle the race we do not want to call qla4xxx_mark_device_busy
> when we get SCS_TIMEOUT. If we get a ddb aen then could we just wait for
> that and all those events would be serialized through the dpc thread?
>
> What does SCS_TIMEOUT mean?
I think the driver on receiving the Async Message PDU of type
ISCSI_ASYNC_MSG_SCSI_EVENT, should first retrieve the DDB state. If the
session is still not active, it should block it. If the DDB state
indicates the session is active, then call iscsi_unblock_session() if
rescan is needed. What do you think of this solution ?
SCS_TIMEOUT is generated when there is a transport layer timeout for one
of the PDUs issued as result of an IOCB.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH]qla4xxx:Add support for Async Message PDUs [REPOST with fixes]
2008-05-01 0:36 ` David C Somayajulu
@ 2008-05-01 14:59 ` Mike Christie
0 siblings, 0 replies; 13+ messages in thread
From: Mike Christie @ 2008-05-01 14:59 UTC (permalink / raw)
To: David C Somayajulu; +Cc: linux-scsi, David Wagner
David C Somayajulu wrote:
> On Wed, 2008-04-30 at 14:36 -0500, Mike Christie wrote:
>> Mike Christie wrote:
>>> David C Somayajulu wrote:
>>>> + }
>>>> + if (sshdr.asc == 0x3f && sshdr.ascq == 0x0e) {
>>>> + /* induce rescan */
>>>> + iscsi_block_session(ddb_entry->sess);
>>>> + iscsi_unblock_session(ddb_entry->sess);
>>>> + }
>>> I think I was wrong off list. We could actually just call
>>> iscsi_unblock_session, but we do not know the state of the session do
>>> we? If we got a event that indicated the session was failed could we
>>> have a block queued up and this would reverse it by accident?
>>>
>>> I was thinking that because qla4xxx_process_aen is called before this we
>>> could just check the ddb state, but we can call iscsi_block_session from
>>> the interrupt handler to queue up a block so I think that could race
>>> with the unblock call here.
>> Maybe to handle the race we do not want to call qla4xxx_mark_device_busy
>> when we get SCS_TIMEOUT. If we get a ddb aen then could we just wait for
>> that and all those events would be serialized through the dpc thread?
>>
>> What does SCS_TIMEOUT mean?
> I think the driver on receiving the Async Message PDU of type
> ISCSI_ASYNC_MSG_SCSI_EVENT, should first retrieve the DDB state. If the
> session is still not active, it should block it. If the DDB state
You should not need to block it though. qla4xxx_process_aen will have
done this already when it set the ddb state, wouldn't it? I am saying if
the ddb state indicates that it is not active then the session should be
in the blocked state by the time we get to handling the iscsi async event.
> indicates the session is active, then call iscsi_unblock_session() if
> rescan is needed. What do you think of this solution ?
>
> SCS_TIMEOUT is generated when there is a transport layer timeout for one
> of the PDUs issued as result of an IOCB.
>
Do you need some locking or something then? If the dpc thread is about
to check the ddb state to handle the iscsi async pdu like we said above,
then we get a SCS_TIMEOUT, could the dpc thread read the ddb state and
see a good ddb state, then the SCS_TIMEOUT handling would set the state
to DDB_STATE_MISSING and queue a block. The dpc thread would then queue
a unblock early?
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2008-05-01 14:59 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-04-18 20:44 [PATCH]qla4xxx:Add support for Async Message PDUs David C Somayajulu
2008-04-22 16:20 ` Mike Christie
2008-04-24 16:01 ` David C Somayajulu
2008-04-24 16:40 ` Mike Christie
2008-04-24 19:42 ` David C Somayajulu
2008-04-25 19:23 ` David C Somayajulu
2008-04-26 16:42 ` Mike Christie
2008-04-28 15:39 ` David C Somayajulu
2008-04-30 18:35 ` [PATCH]qla4xxx:Add support for Async Message PDUs [REPOST with fixes] David C Somayajulu
2008-04-30 19:23 ` Mike Christie
2008-04-30 19:36 ` Mike Christie
2008-05-01 0:36 ` David C Somayajulu
2008-05-01 14:59 ` Mike Christie
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).