From 577577da6d197ea3dcf3ee19c4f902fbd3a9390a Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Tue, 2 Dec 2008 00:32:05 -0600 Subject: [SCSI] libiscsi: prepare libiscsi for new offload engines by modifying unsol data code cxgb3i offloads data transfers. It does not offload the entire scsi/iscsi procssing like qla4xxx and it does not offload the iscsi sequence processing like how bnx2i does. cxgb3i relies on iscsi_tcp for the seqeunce handling so this changes how we transfer unsolicitied data by adding a common r2t struct and helpers. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 183 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 122 insertions(+), 61 deletions(-) (limited to 'drivers/scsi/libiscsi.c') diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 3fdee7370ccc..80cbcdce7fa3 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -88,34 +88,47 @@ iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr) } EXPORT_SYMBOL_GPL(iscsi_update_cmdsn); -void iscsi_prep_unsolicit_data_pdu(struct iscsi_task *task, - struct iscsi_data *hdr) +/** + * iscsi_prep_data_out_pdu - initialize Data-Out + * @task: scsi command task + * @r2t: R2T info + * @hdr: iscsi data in pdu + * + * Notes: + * Initialize Data-Out within this R2T sequence and finds + * proper data_offset within this SCSI command. + * + * This function is called with connection lock taken. + **/ +void iscsi_prep_data_out_pdu(struct iscsi_task *task, struct iscsi_r2t_info *r2t, + struct iscsi_data *hdr) { struct iscsi_conn *conn = task->conn; + unsigned int left = r2t->data_length - r2t->sent; + + task->hdr_len = sizeof(struct iscsi_data); memset(hdr, 0, sizeof(struct iscsi_data)); - hdr->ttt = cpu_to_be32(ISCSI_RESERVED_TAG); - hdr->datasn = cpu_to_be32(task->unsol_datasn); - task->unsol_datasn++; + hdr->ttt = r2t->ttt; + hdr->datasn = cpu_to_be32(r2t->datasn); + r2t->datasn++; hdr->opcode = ISCSI_OP_SCSI_DATA_OUT; - memcpy(hdr->lun, task->hdr->lun, sizeof(hdr->lun)); - - hdr->itt = task->hdr->itt; - hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); - hdr->offset = cpu_to_be32(task->unsol_offset); - - if (task->unsol_count > conn->max_xmit_dlength) { + memcpy(hdr->lun, task->lun, sizeof(hdr->lun)); + hdr->itt = task->hdr_itt; + hdr->exp_statsn = r2t->exp_statsn; + hdr->offset = cpu_to_be32(r2t->data_offset + r2t->sent); + if (left > conn->max_xmit_dlength) { hton24(hdr->dlength, conn->max_xmit_dlength); - task->data_count = conn->max_xmit_dlength; - task->unsol_offset += task->data_count; + r2t->data_count = conn->max_xmit_dlength; hdr->flags = 0; } else { - hton24(hdr->dlength, task->unsol_count); - task->data_count = task->unsol_count; + hton24(hdr->dlength, left); + r2t->data_count = left; hdr->flags = ISCSI_FLAG_CMD_FINAL; } + conn->dataout_pdus_cnt++; } -EXPORT_SYMBOL_GPL(iscsi_prep_unsolicit_data_pdu); +EXPORT_SYMBOL_GPL(iscsi_prep_data_out_pdu); static int iscsi_add_hdr(struct iscsi_task *task, unsigned len) { @@ -206,11 +219,17 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) { struct iscsi_conn *conn = task->conn; struct iscsi_session *session = conn->session; - struct iscsi_cmd *hdr = task->hdr; struct scsi_cmnd *sc = task->sc; + struct iscsi_cmd *hdr; unsigned hdrlength, cmd_len; int rc; + rc = conn->session->tt->alloc_pdu(task); + if (rc) + return rc; + hdr = (struct iscsi_cmd *) task->hdr; + memset(hdr, 0, sizeof(*hdr)); + task->hdr_len = 0; rc = iscsi_add_hdr(task, sizeof(*hdr)); if (rc) @@ -218,8 +237,9 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) hdr->opcode = ISCSI_OP_SCSI_CMD; hdr->flags = ISCSI_ATTR_SIMPLE; int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun); - hdr->itt = build_itt(task->itt, session->age); - hdr->cmdsn = cpu_to_be32(session->cmdsn); + memcpy(task->lun, hdr->lun, sizeof(task->lun)); + hdr->itt = task->hdr_itt = build_itt(task->itt, session->age); + hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn); session->cmdsn++; hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); cmd_len = sc->cmd_len; @@ -242,6 +262,8 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) } if (sc->sc_data_direction == DMA_TO_DEVICE) { unsigned out_len = scsi_out(sc)->length; + struct iscsi_r2t_info *r2t = &task->unsol_r2t; + hdr->data_length = cpu_to_be32(out_len); hdr->flags |= ISCSI_FLAG_CMD_WRITE; /* @@ -254,13 +276,11 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) * without R2T ack right after * immediate data * - * r2t_data_count bytes to be sent via R2T ack's + * r2t data_length bytes to be sent via R2T ack's * * pad_count bytes to be sent as zero-padding */ - task->unsol_count = 0; - task->unsol_offset = 0; - task->unsol_datasn = 0; + memset(r2t, 0, sizeof(*r2t)); if (session->imm_data_en) { if (out_len >= session->first_burst) @@ -274,12 +294,14 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) zero_data(hdr->dlength); if (!session->initial_r2t_en) { - task->unsol_count = min(session->first_burst, out_len) - - task->imm_count; - task->unsol_offset = task->imm_count; + r2t->data_length = min(session->first_burst, out_len) - + task->imm_count; + r2t->data_offset = task->imm_count; + r2t->ttt = cpu_to_be32(ISCSI_RESERVED_TAG); + r2t->exp_statsn = cpu_to_be32(conn->exp_statsn); } - if (!task->unsol_count) + if (!task->unsol_r2t.data_length) /* No unsolicit Data-Out's */ hdr->flags |= ISCSI_FLAG_CMD_FINAL; } else { @@ -300,8 +322,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) WARN_ON(hdrlength >= 256); hdr->hlength = hdrlength & 0xFF; - if (conn->session->tt->init_task && - conn->session->tt->init_task(task)) + if (session->tt->init_task && session->tt->init_task(task)) return -EIO; task->state = ISCSI_TASK_RUNNING; @@ -332,6 +353,7 @@ static void iscsi_complete_command(struct iscsi_task *task) struct iscsi_session *session = conn->session; struct scsi_cmnd *sc = task->sc; + session->tt->cleanup_task(task); list_del_init(&task->running); task->state = ISCSI_TASK_COMPLETED; task->sc = NULL; @@ -402,8 +424,6 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_task *task, * the cmd in the sequencing */ conn->session->queued_cmdsn--; - else - conn->session->tt->cleanup_task(conn, task); sc->result = err; if (!scsi_bidi_cmnd(sc)) @@ -423,7 +443,7 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn, struct iscsi_task *task) { struct iscsi_session *session = conn->session; - struct iscsi_hdr *hdr = (struct iscsi_hdr *)task->hdr; + struct iscsi_hdr *hdr = task->hdr; struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr; if (conn->session->state == ISCSI_STATE_LOGGING_OUT) @@ -456,6 +476,7 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn, if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) session->state = ISCSI_STATE_LOGGING_OUT; + task->state = ISCSI_TASK_RUNNING; list_move_tail(&task->running, &conn->mgmt_run_list); debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n", hdr->opcode & ISCSI_OPCODE_MASK, hdr->itt, @@ -505,23 +526,38 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, } else task->data_count = 0; + if (conn->session->tt->alloc_pdu(task)) { + iscsi_conn_printk(KERN_ERR, conn, "Could not allocate " + "pdu for mgmt task.\n"); + goto requeue_task; + } + task->hdr_len = sizeof(struct iscsi_hdr); + memcpy(task->hdr, hdr, sizeof(struct iscsi_hdr)); INIT_LIST_HEAD(&task->running); list_add_tail(&task->running, &conn->mgmtqueue); if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) { - if (iscsi_prep_mgmt_task(conn, task)) { - __iscsi_put_task(task); - return NULL; - } + if (iscsi_prep_mgmt_task(conn, task)) + goto free_task; if (session->tt->xmit_task(task)) - task = NULL; + goto free_task; } else scsi_queue_work(conn->session->host, &conn->xmitwork); return task; + +free_task: + __iscsi_put_task(task); + return NULL; + +requeue_task: + if (task != conn->login_task) + __kfifo_put(session->cmdpool.queue, (void*)&task, + sizeof(void*)); + return NULL; } int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr, @@ -1136,8 +1172,13 @@ check_mgmt: fail_command(conn, conn->task, DID_IMM_RETRY << 16); continue; } - if (iscsi_prep_scsi_cmd_pdu(conn->task)) { - fail_command(conn, conn->task, DID_ABORT << 16); + rc = iscsi_prep_scsi_cmd_pdu(conn->task); + if (rc) { + if (rc == -ENOMEM) { + conn->task = NULL; + goto again; + } else + fail_command(conn, conn->task, DID_ABORT << 16); continue; } rc = iscsi_xmit_task(conn); @@ -1195,6 +1236,26 @@ static void iscsi_xmitworker(struct work_struct *work) } while (rc >= 0 || rc == -EAGAIN); } +static inline struct iscsi_task *iscsi_alloc_task(struct iscsi_conn *conn, + struct scsi_cmnd *sc) +{ + struct iscsi_task *task; + + if (!__kfifo_get(conn->session->cmdpool.queue, + (void *) &task, sizeof(void *))) + return NULL; + + sc->SCp.phase = conn->session->age; + sc->SCp.ptr = (char *) task; + + atomic_set(&task->refcount, 1); + task->state = ISCSI_TASK_PENDING; + task->conn = conn; + task->sc = sc; + INIT_LIST_HEAD(&task->running); + return task; +} + enum { FAILURE_BAD_HOST = 1, FAILURE_SESSION_FAILED, @@ -1281,33 +1342,27 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) goto reject; } - if (!__kfifo_get(session->cmdpool.queue, (void*)&task, - sizeof(void*))) { + task = iscsi_alloc_task(conn, sc); + if (!task) { reason = FAILURE_OOM; goto reject; } - sc->SCp.phase = session->age; - sc->SCp.ptr = (char *)task; - - atomic_set(&task->refcount, 1); - task->state = ISCSI_TASK_PENDING; - task->conn = conn; - task->sc = sc; - INIT_LIST_HEAD(&task->running); list_add_tail(&task->running, &conn->xmitqueue); if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) { - if (iscsi_prep_scsi_cmd_pdu(task)) { - sc->result = DID_ABORT << 16; - sc->scsi_done = NULL; - iscsi_complete_command(task); - goto fault; + reason = iscsi_prep_scsi_cmd_pdu(task); + if (reason) { + if (reason == -ENOMEM) { + reason = FAILURE_OOM; + goto prepd_reject; + } else { + sc->result = DID_ABORT << 16; + goto prepd_fault; + } } if (session->tt->xmit_task(task)) { - sc->scsi_done = NULL; - iscsi_complete_command(task); reason = FAILURE_SESSION_NOT_READY; - goto reject; + goto prepd_reject; } } else scsi_queue_work(session->host, &conn->xmitwork); @@ -1317,12 +1372,18 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) spin_lock(host->host_lock); return 0; +prepd_reject: + sc->scsi_done = NULL; + iscsi_complete_command(task); reject: spin_unlock(&session->lock); debug_scsi("cmd 0x%x rejected (%d)\n", sc->cmnd[0], reason); spin_lock(host->host_lock); return SCSI_MLQUEUE_TARGET_BUSY; +prepd_fault: + sc->scsi_done = NULL; + iscsi_complete_command(task); fault: spin_unlock(&session->lock); debug_scsi("iscsi: cmd 0x%x is not queued (%d)\n", sc->cmnd[0], reason); @@ -1634,9 +1695,9 @@ static void iscsi_prep_abort_task_pdu(struct iscsi_task *task, hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE; hdr->flags = ISCSI_TM_FUNC_ABORT_TASK & ISCSI_FLAG_TM_FUNC_MASK; hdr->flags |= ISCSI_FLAG_CMD_FINAL; - memcpy(hdr->lun, task->hdr->lun, sizeof(hdr->lun)); - hdr->rtt = task->hdr->itt; - hdr->refcmdsn = task->hdr->cmdsn; + memcpy(hdr->lun, task->lun, sizeof(hdr->lun)); + hdr->rtt = task->hdr_itt; + hdr->refcmdsn = task->cmdsn; } int iscsi_eh_abort(struct scsi_cmnd *sc) -- cgit v1.2.3 From cfeb2cf957ca5b4e557b53fb91ccc52f442f6dbe Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Tue, 2 Dec 2008 00:32:09 -0600 Subject: [SCSI] libiscsi: change login data buffer allocation This modifies the login buffer allocation to use __get_free_pages. It will allow drivers that want to send this data with zero copy operations to easily line things up on page boundaries. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/libiscsi.c') diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 80cbcdce7fa3..c1bb74052aed 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -2284,7 +2284,8 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, } spin_unlock_bh(&session->lock); - data = kmalloc(ISCSI_DEF_MAX_RECV_SEG_LEN, GFP_KERNEL); + data = (char *) __get_free_pages(GFP_KERNEL, + get_order(ISCSI_DEF_MAX_RECV_SEG_LEN)); if (!data) goto login_task_data_alloc_fail; conn->login_task->data = conn->data = data; @@ -2355,7 +2356,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) iscsi_suspend_tx(conn); spin_lock_bh(&session->lock); - kfree(conn->data); + free_pages((unsigned long) conn->data, + get_order(ISCSI_DEF_MAX_RECV_SEG_LEN)); kfree(conn->persistent_address); __kfifo_put(session->cmdpool.queue, (void*)&conn->login_task, sizeof(void*)); -- cgit v1.2.3 From 262ef63627977acb7d8dd38c4f0f290bf49fbbfd Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Tue, 2 Dec 2008 00:32:13 -0600 Subject: [SCSI] libiscsi: allow drivers to modify the itt sent to the target bnx2i and cxgb3i need to encode LLD info in the itt so that the firmware/hardware can process the pdu. This patch allows the LLDs to encode info in the task->hdr->itt that they setup in the alloc_pdu callout (any resources that are allocated can be freed with the pdu in the cleanup_task callout). If the LLD encodes info in the itt they should implement a parse_pdu_itt callout. If parse_pdu_itt is not implemented libiscsi will do the right thing for the LLD. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 47 +++++++++++++++++++++++++++---------- include/scsi/libiscsi.h | 5 ++-- include/scsi/scsi_transport_iscsi.h | 3 +++ 3 files changed, 40 insertions(+), 15 deletions(-) (limited to 'drivers/scsi/libiscsi.c') diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index c1bb74052aed..6c4034b1561c 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -222,12 +222,14 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) struct scsi_cmnd *sc = task->sc; struct iscsi_cmd *hdr; unsigned hdrlength, cmd_len; + itt_t itt; int rc; rc = conn->session->tt->alloc_pdu(task); if (rc) return rc; hdr = (struct iscsi_cmd *) task->hdr; + itt = hdr->itt; memset(hdr, 0, sizeof(*hdr)); task->hdr_len = 0; @@ -238,7 +240,11 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) hdr->flags = ISCSI_ATTR_SIMPLE; int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun); memcpy(task->lun, hdr->lun, sizeof(task->lun)); - hdr->itt = task->hdr_itt = build_itt(task->itt, session->age); + if (session->tt->parse_pdu_itt) + hdr->itt = task->hdr_itt = itt; + else + hdr->itt = task->hdr_itt = build_itt(task->itt, + task->conn->session->age); hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn); session->cmdsn++; hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); @@ -457,7 +463,6 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn, */ nop->cmdsn = cpu_to_be32(session->cmdsn); if (hdr->itt != RESERVED_ITT) { - hdr->itt = build_itt(task->itt, session->age); /* * TODO: We always use immediate, so we never hit this. * If we start to send tmfs or nops as non-immediate then @@ -490,6 +495,7 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, { struct iscsi_session *session = conn->session; struct iscsi_task *task; + itt_t itt; if (session->state == ISCSI_STATE_TERMINATE) return NULL; @@ -531,9 +537,18 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, "pdu for mgmt task.\n"); goto requeue_task; } + itt = task->hdr->itt; task->hdr_len = sizeof(struct iscsi_hdr); - memcpy(task->hdr, hdr, sizeof(struct iscsi_hdr)); + + if (hdr->itt != RESERVED_ITT) { + if (session->tt->parse_pdu_itt) + task->hdr->itt = itt; + else + task->hdr->itt = build_itt(task->itt, + task->conn->session->age); + } + INIT_LIST_HEAD(&task->running); list_add_tail(&task->running, &conn->mgmtqueue); @@ -745,7 +760,6 @@ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, { struct iscsi_reject *reject = (struct iscsi_reject *)hdr; struct iscsi_hdr rejected_pdu; - uint32_t itt; conn->exp_statsn = be32_to_cpu(reject->statsn) + 1; @@ -755,10 +769,9 @@ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, if (ntoh24(reject->dlength) >= sizeof(struct iscsi_hdr)) { memcpy(&rejected_pdu, data, sizeof(struct iscsi_hdr)); - itt = get_itt(rejected_pdu.itt); iscsi_conn_printk(KERN_ERR, conn, - "itt 0x%x had pdu (op 0x%x) rejected " - "due to DataDigest error.\n", itt, + "pdu (op 0x%x) rejected " + "due to DataDigest error.\n", rejected_pdu.opcode); } } @@ -778,12 +791,15 @@ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, static struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *conn, itt_t itt) { struct iscsi_session *session = conn->session; - uint32_t i; + int i; if (itt == RESERVED_ITT) return NULL; - i = get_itt(itt); + if (session->tt->parse_pdu_itt) + session->tt->parse_pdu_itt(conn, itt, &i, NULL); + else + i = get_itt(itt); if (i >= session->cmds_max) return NULL; @@ -958,20 +974,25 @@ EXPORT_SYMBOL_GPL(iscsi_complete_pdu); int iscsi_verify_itt(struct iscsi_conn *conn, itt_t itt) { struct iscsi_session *session = conn->session; - uint32_t i; + int age = 0, i = 0; if (itt == RESERVED_ITT) return 0; - if (((__force u32)itt & ISCSI_AGE_MASK) != - (session->age << ISCSI_AGE_SHIFT)) { + if (session->tt->parse_pdu_itt) + session->tt->parse_pdu_itt(conn, itt, &i, &age); + else { + i = get_itt(itt); + age = ((__force u32)itt >> ISCSI_AGE_SHIFT) & ISCSI_AGE_MASK; + } + + if (age != session->age) { iscsi_conn_printk(KERN_ERR, conn, "received itt %x expected session age (%x)\n", (__force u32)itt, session->age); return ISCSI_ERR_BAD_ITT; } - i = get_itt(itt); if (i >= session->cmds_max) { iscsi_conn_printk(KERN_ERR, conn, "received invalid itt index %u (max cmds " diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 51500573c0b8..7360e1916e75 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -30,6 +30,7 @@ #include #include #include +#include struct scsi_transport_template; struct scsi_host_template; @@ -70,12 +71,12 @@ enum { /* Connection suspend "bit" */ #define ISCSI_SUSPEND_BIT 1 -#define ISCSI_ITT_MASK (0x1fff) +#define ISCSI_ITT_MASK 0x1fff #define ISCSI_TOTAL_CMDS_MAX 4096 /* this must be a power of two greater than ISCSI_MGMT_CMDS_MAX */ #define ISCSI_TOTAL_CMDS_MIN 16 #define ISCSI_AGE_SHIFT 28 -#define ISCSI_AGE_MASK (0xf << ISCSI_AGE_SHIFT) +#define ISCSI_AGE_MASK 0xf #define ISCSI_ADDRESS_BUF_LEN 64 diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index c928234c018f..e13cb20f1eae 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -122,6 +122,9 @@ struct iscsi_transport { int (*xmit_pdu) (struct iscsi_task *task); int (*init_pdu) (struct iscsi_task *task, unsigned int offset, unsigned int count); + void (*parse_pdu_itt) (struct iscsi_conn *conn, itt_t itt, + int *index, int *age); + void (*session_recovery_timedout) (struct iscsi_cls_session *session); struct iscsi_endpoint *(*ep_connect) (struct sockaddr *dst_addr, int non_blocking); -- cgit v1.2.3 From 2ff79d52d56eebcffd83e9327b89d7daedf1e897 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Tue, 2 Dec 2008 00:32:14 -0600 Subject: [SCSI] libiscsi: pass opcode into alloc_pdu callout We do not need to allocate a itt for data_out, so this passes the opcode to the alloc_pdu callout. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/infiniband/ulp/iser/iscsi_iser.c | 2 +- drivers/scsi/iscsi_tcp.c | 2 +- drivers/scsi/libiscsi.c | 14 +++++++------- drivers/scsi/libiscsi_tcp.c | 2 +- include/scsi/scsi_transport_iscsi.h | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/scsi/libiscsi.c') diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c index 78bf5e4538cb..12876392516e 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c @@ -119,7 +119,7 @@ error: iscsi_conn_failure(conn, rc); } -static int iscsi_iser_pdu_alloc(struct iscsi_task *task) +static int iscsi_iser_pdu_alloc(struct iscsi_task *task, uint8_t opcode) { struct iscsi_iser_task *iser_task = task->dd_data; diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 07d9eb14721b..de5c9b3e51fb 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -457,7 +457,7 @@ static int iscsi_sw_tcp_pdu_init(struct iscsi_task *task, return 0; } -static int iscsi_sw_tcp_pdu_alloc(struct iscsi_task *task) +static int iscsi_sw_tcp_pdu_alloc(struct iscsi_task *task, uint8_t opcode) { struct iscsi_tcp_task *tcp_task = task->dd_data; diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 6c4034b1561c..ddf53978f0be 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -225,13 +225,18 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) itt_t itt; int rc; - rc = conn->session->tt->alloc_pdu(task); + rc = conn->session->tt->alloc_pdu(task, ISCSI_OP_SCSI_CMD); if (rc) return rc; hdr = (struct iscsi_cmd *) task->hdr; itt = hdr->itt; memset(hdr, 0, sizeof(*hdr)); + if (session->tt->parse_pdu_itt) + hdr->itt = task->hdr_itt = itt; + else + hdr->itt = task->hdr_itt = build_itt(task->itt, + task->conn->session->age); task->hdr_len = 0; rc = iscsi_add_hdr(task, sizeof(*hdr)); if (rc) @@ -240,11 +245,6 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) hdr->flags = ISCSI_ATTR_SIMPLE; int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun); memcpy(task->lun, hdr->lun, sizeof(task->lun)); - if (session->tt->parse_pdu_itt) - hdr->itt = task->hdr_itt = itt; - else - hdr->itt = task->hdr_itt = build_itt(task->itt, - task->conn->session->age); hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn); session->cmdsn++; hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); @@ -532,7 +532,7 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, } else task->data_count = 0; - if (conn->session->tt->alloc_pdu(task)) { + if (conn->session->tt->alloc_pdu(task, hdr->opcode)) { iscsi_conn_printk(KERN_ERR, conn, "Could not allocate " "pdu for mgmt task.\n"); goto requeue_task; diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c index e86508936314..9df6b3436e4a 100644 --- a/drivers/scsi/libiscsi_tcp.c +++ b/drivers/scsi/libiscsi_tcp.c @@ -1021,7 +1021,7 @@ flush: return 0; } - rc = conn->session->tt->alloc_pdu(task); + rc = conn->session->tt->alloc_pdu(task, ISCSI_OP_SCSI_DATA_OUT); if (rc) return rc; iscsi_prep_data_out_pdu(task, r2t, (struct iscsi_data *) task->hdr); diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index e13cb20f1eae..b50aabe2861e 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -118,7 +118,7 @@ struct iscsi_transport { int (*xmit_task) (struct iscsi_task *task); void (*cleanup_task) (struct iscsi_task *task); - int (*alloc_pdu) (struct iscsi_task *task); + int (*alloc_pdu) (struct iscsi_task *task, uint8_t opcode); int (*xmit_pdu) (struct iscsi_task *task); int (*init_pdu) (struct iscsi_task *task, unsigned int offset, unsigned int count); -- cgit v1.2.3 From ae15f80172d95f978b60d40408353943d5bc099b Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Tue, 2 Dec 2008 00:32:15 -0600 Subject: [SCSI] libiscsi: handle init task failures. Mgmt setup used to not fail so we did not have to check the return value. Now with cxgb3i it can so this has us pass up a error. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/libiscsi.c') diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index ddf53978f0be..7225b6e2029e 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -475,8 +475,8 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn, } } - if (session->tt->init_task) - session->tt->init_task(task); + if (session->tt->init_task && session->tt->init_task(task)) + return -EIO; if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) session->state = ISCSI_STATE_LOGGING_OUT; -- cgit v1.2.3