diff options
Diffstat (limited to 'drivers/scsi/libiscsi.c')
-rw-r--r-- | drivers/scsi/libiscsi.c | 236 |
1 files changed, 160 insertions, 76 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 3fdee7370ccc..7225b6e2029e 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) | |||
88 | } | 88 | } |
89 | EXPORT_SYMBOL_GPL(iscsi_update_cmdsn); | 89 | EXPORT_SYMBOL_GPL(iscsi_update_cmdsn); |
90 | 90 | ||
91 | void iscsi_prep_unsolicit_data_pdu(struct iscsi_task *task, | 91 | /** |
92 | struct iscsi_data *hdr) | 92 | * iscsi_prep_data_out_pdu - initialize Data-Out |
93 | * @task: scsi command task | ||
94 | * @r2t: R2T info | ||
95 | * @hdr: iscsi data in pdu | ||
96 | * | ||
97 | * Notes: | ||
98 | * Initialize Data-Out within this R2T sequence and finds | ||
99 | * proper data_offset within this SCSI command. | ||
100 | * | ||
101 | * This function is called with connection lock taken. | ||
102 | **/ | ||
103 | void iscsi_prep_data_out_pdu(struct iscsi_task *task, struct iscsi_r2t_info *r2t, | ||
104 | struct iscsi_data *hdr) | ||
93 | { | 105 | { |
94 | struct iscsi_conn *conn = task->conn; | 106 | struct iscsi_conn *conn = task->conn; |
107 | unsigned int left = r2t->data_length - r2t->sent; | ||
108 | |||
109 | task->hdr_len = sizeof(struct iscsi_data); | ||
95 | 110 | ||
96 | memset(hdr, 0, sizeof(struct iscsi_data)); | 111 | memset(hdr, 0, sizeof(struct iscsi_data)); |
97 | hdr->ttt = cpu_to_be32(ISCSI_RESERVED_TAG); | 112 | hdr->ttt = r2t->ttt; |
98 | hdr->datasn = cpu_to_be32(task->unsol_datasn); | 113 | hdr->datasn = cpu_to_be32(r2t->datasn); |
99 | task->unsol_datasn++; | 114 | r2t->datasn++; |
100 | hdr->opcode = ISCSI_OP_SCSI_DATA_OUT; | 115 | hdr->opcode = ISCSI_OP_SCSI_DATA_OUT; |
101 | memcpy(hdr->lun, task->hdr->lun, sizeof(hdr->lun)); | 116 | memcpy(hdr->lun, task->lun, sizeof(hdr->lun)); |
102 | 117 | hdr->itt = task->hdr_itt; | |
103 | hdr->itt = task->hdr->itt; | 118 | hdr->exp_statsn = r2t->exp_statsn; |
104 | hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); | 119 | hdr->offset = cpu_to_be32(r2t->data_offset + r2t->sent); |
105 | hdr->offset = cpu_to_be32(task->unsol_offset); | 120 | if (left > conn->max_xmit_dlength) { |
106 | |||
107 | if (task->unsol_count > conn->max_xmit_dlength) { | ||
108 | hton24(hdr->dlength, conn->max_xmit_dlength); | 121 | hton24(hdr->dlength, conn->max_xmit_dlength); |
109 | task->data_count = conn->max_xmit_dlength; | 122 | r2t->data_count = conn->max_xmit_dlength; |
110 | task->unsol_offset += task->data_count; | ||
111 | hdr->flags = 0; | 123 | hdr->flags = 0; |
112 | } else { | 124 | } else { |
113 | hton24(hdr->dlength, task->unsol_count); | 125 | hton24(hdr->dlength, left); |
114 | task->data_count = task->unsol_count; | 126 | r2t->data_count = left; |
115 | hdr->flags = ISCSI_FLAG_CMD_FINAL; | 127 | hdr->flags = ISCSI_FLAG_CMD_FINAL; |
116 | } | 128 | } |
129 | conn->dataout_pdus_cnt++; | ||
117 | } | 130 | } |
118 | EXPORT_SYMBOL_GPL(iscsi_prep_unsolicit_data_pdu); | 131 | EXPORT_SYMBOL_GPL(iscsi_prep_data_out_pdu); |
119 | 132 | ||
120 | static int iscsi_add_hdr(struct iscsi_task *task, unsigned len) | 133 | static int iscsi_add_hdr(struct iscsi_task *task, unsigned len) |
121 | { | 134 | { |
@@ -206,11 +219,24 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) | |||
206 | { | 219 | { |
207 | struct iscsi_conn *conn = task->conn; | 220 | struct iscsi_conn *conn = task->conn; |
208 | struct iscsi_session *session = conn->session; | 221 | struct iscsi_session *session = conn->session; |
209 | struct iscsi_cmd *hdr = task->hdr; | ||
210 | struct scsi_cmnd *sc = task->sc; | 222 | struct scsi_cmnd *sc = task->sc; |
223 | struct iscsi_cmd *hdr; | ||
211 | unsigned hdrlength, cmd_len; | 224 | unsigned hdrlength, cmd_len; |
225 | itt_t itt; | ||
212 | int rc; | 226 | int rc; |
213 | 227 | ||
228 | rc = conn->session->tt->alloc_pdu(task, ISCSI_OP_SCSI_CMD); | ||
229 | if (rc) | ||
230 | return rc; | ||
231 | hdr = (struct iscsi_cmd *) task->hdr; | ||
232 | itt = hdr->itt; | ||
233 | memset(hdr, 0, sizeof(*hdr)); | ||
234 | |||
235 | if (session->tt->parse_pdu_itt) | ||
236 | hdr->itt = task->hdr_itt = itt; | ||
237 | else | ||
238 | hdr->itt = task->hdr_itt = build_itt(task->itt, | ||
239 | task->conn->session->age); | ||
214 | task->hdr_len = 0; | 240 | task->hdr_len = 0; |
215 | rc = iscsi_add_hdr(task, sizeof(*hdr)); | 241 | rc = iscsi_add_hdr(task, sizeof(*hdr)); |
216 | if (rc) | 242 | if (rc) |
@@ -218,8 +244,8 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) | |||
218 | hdr->opcode = ISCSI_OP_SCSI_CMD; | 244 | hdr->opcode = ISCSI_OP_SCSI_CMD; |
219 | hdr->flags = ISCSI_ATTR_SIMPLE; | 245 | hdr->flags = ISCSI_ATTR_SIMPLE; |
220 | int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun); | 246 | int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun); |
221 | hdr->itt = build_itt(task->itt, session->age); | 247 | memcpy(task->lun, hdr->lun, sizeof(task->lun)); |
222 | hdr->cmdsn = cpu_to_be32(session->cmdsn); | 248 | hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn); |
223 | session->cmdsn++; | 249 | session->cmdsn++; |
224 | hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); | 250 | hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); |
225 | cmd_len = sc->cmd_len; | 251 | cmd_len = sc->cmd_len; |
@@ -242,6 +268,8 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) | |||
242 | } | 268 | } |
243 | if (sc->sc_data_direction == DMA_TO_DEVICE) { | 269 | if (sc->sc_data_direction == DMA_TO_DEVICE) { |
244 | unsigned out_len = scsi_out(sc)->length; | 270 | unsigned out_len = scsi_out(sc)->length; |
271 | struct iscsi_r2t_info *r2t = &task->unsol_r2t; | ||
272 | |||
245 | hdr->data_length = cpu_to_be32(out_len); | 273 | hdr->data_length = cpu_to_be32(out_len); |
246 | hdr->flags |= ISCSI_FLAG_CMD_WRITE; | 274 | hdr->flags |= ISCSI_FLAG_CMD_WRITE; |
247 | /* | 275 | /* |
@@ -254,13 +282,11 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) | |||
254 | * without R2T ack right after | 282 | * without R2T ack right after |
255 | * immediate data | 283 | * immediate data |
256 | * | 284 | * |
257 | * r2t_data_count bytes to be sent via R2T ack's | 285 | * r2t data_length bytes to be sent via R2T ack's |
258 | * | 286 | * |
259 | * pad_count bytes to be sent as zero-padding | 287 | * pad_count bytes to be sent as zero-padding |
260 | */ | 288 | */ |
261 | task->unsol_count = 0; | 289 | memset(r2t, 0, sizeof(*r2t)); |
262 | task->unsol_offset = 0; | ||
263 | task->unsol_datasn = 0; | ||
264 | 290 | ||
265 | if (session->imm_data_en) { | 291 | if (session->imm_data_en) { |
266 | if (out_len >= session->first_burst) | 292 | if (out_len >= session->first_burst) |
@@ -274,12 +300,14 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) | |||
274 | zero_data(hdr->dlength); | 300 | zero_data(hdr->dlength); |
275 | 301 | ||
276 | if (!session->initial_r2t_en) { | 302 | if (!session->initial_r2t_en) { |
277 | task->unsol_count = min(session->first_burst, out_len) | 303 | r2t->data_length = min(session->first_burst, out_len) - |
278 | - task->imm_count; | 304 | task->imm_count; |
279 | task->unsol_offset = task->imm_count; | 305 | r2t->data_offset = task->imm_count; |
306 | r2t->ttt = cpu_to_be32(ISCSI_RESERVED_TAG); | ||
307 | r2t->exp_statsn = cpu_to_be32(conn->exp_statsn); | ||
280 | } | 308 | } |
281 | 309 | ||
282 | if (!task->unsol_count) | 310 | if (!task->unsol_r2t.data_length) |
283 | /* No unsolicit Data-Out's */ | 311 | /* No unsolicit Data-Out's */ |
284 | hdr->flags |= ISCSI_FLAG_CMD_FINAL; | 312 | hdr->flags |= ISCSI_FLAG_CMD_FINAL; |
285 | } else { | 313 | } else { |
@@ -300,8 +328,7 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) | |||
300 | WARN_ON(hdrlength >= 256); | 328 | WARN_ON(hdrlength >= 256); |
301 | hdr->hlength = hdrlength & 0xFF; | 329 | hdr->hlength = hdrlength & 0xFF; |
302 | 330 | ||
303 | if (conn->session->tt->init_task && | 331 | if (session->tt->init_task && session->tt->init_task(task)) |
304 | conn->session->tt->init_task(task)) | ||
305 | return -EIO; | 332 | return -EIO; |
306 | 333 | ||
307 | task->state = ISCSI_TASK_RUNNING; | 334 | task->state = ISCSI_TASK_RUNNING; |
@@ -332,6 +359,7 @@ static void iscsi_complete_command(struct iscsi_task *task) | |||
332 | struct iscsi_session *session = conn->session; | 359 | struct iscsi_session *session = conn->session; |
333 | struct scsi_cmnd *sc = task->sc; | 360 | struct scsi_cmnd *sc = task->sc; |
334 | 361 | ||
362 | session->tt->cleanup_task(task); | ||
335 | list_del_init(&task->running); | 363 | list_del_init(&task->running); |
336 | task->state = ISCSI_TASK_COMPLETED; | 364 | task->state = ISCSI_TASK_COMPLETED; |
337 | task->sc = NULL; | 365 | task->sc = NULL; |
@@ -402,8 +430,6 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_task *task, | |||
402 | * the cmd in the sequencing | 430 | * the cmd in the sequencing |
403 | */ | 431 | */ |
404 | conn->session->queued_cmdsn--; | 432 | conn->session->queued_cmdsn--; |
405 | else | ||
406 | conn->session->tt->cleanup_task(conn, task); | ||
407 | 433 | ||
408 | sc->result = err; | 434 | sc->result = err; |
409 | if (!scsi_bidi_cmnd(sc)) | 435 | if (!scsi_bidi_cmnd(sc)) |
@@ -423,7 +449,7 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn, | |||
423 | struct iscsi_task *task) | 449 | struct iscsi_task *task) |
424 | { | 450 | { |
425 | struct iscsi_session *session = conn->session; | 451 | struct iscsi_session *session = conn->session; |
426 | struct iscsi_hdr *hdr = (struct iscsi_hdr *)task->hdr; | 452 | struct iscsi_hdr *hdr = task->hdr; |
427 | struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr; | 453 | struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr; |
428 | 454 | ||
429 | if (conn->session->state == ISCSI_STATE_LOGGING_OUT) | 455 | if (conn->session->state == ISCSI_STATE_LOGGING_OUT) |
@@ -437,7 +463,6 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn, | |||
437 | */ | 463 | */ |
438 | nop->cmdsn = cpu_to_be32(session->cmdsn); | 464 | nop->cmdsn = cpu_to_be32(session->cmdsn); |
439 | if (hdr->itt != RESERVED_ITT) { | 465 | if (hdr->itt != RESERVED_ITT) { |
440 | hdr->itt = build_itt(task->itt, session->age); | ||
441 | /* | 466 | /* |
442 | * TODO: We always use immediate, so we never hit this. | 467 | * TODO: We always use immediate, so we never hit this. |
443 | * If we start to send tmfs or nops as non-immediate then | 468 | * If we start to send tmfs or nops as non-immediate then |
@@ -450,12 +475,13 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn, | |||
450 | } | 475 | } |
451 | } | 476 | } |
452 | 477 | ||
453 | if (session->tt->init_task) | 478 | if (session->tt->init_task && session->tt->init_task(task)) |
454 | session->tt->init_task(task); | 479 | return -EIO; |
455 | 480 | ||
456 | if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) | 481 | if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) |
457 | session->state = ISCSI_STATE_LOGGING_OUT; | 482 | session->state = ISCSI_STATE_LOGGING_OUT; |
458 | 483 | ||
484 | task->state = ISCSI_TASK_RUNNING; | ||
459 | list_move_tail(&task->running, &conn->mgmt_run_list); | 485 | list_move_tail(&task->running, &conn->mgmt_run_list); |
460 | debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n", | 486 | debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n", |
461 | hdr->opcode & ISCSI_OPCODE_MASK, hdr->itt, | 487 | hdr->opcode & ISCSI_OPCODE_MASK, hdr->itt, |
@@ -469,6 +495,7 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
469 | { | 495 | { |
470 | struct iscsi_session *session = conn->session; | 496 | struct iscsi_session *session = conn->session; |
471 | struct iscsi_task *task; | 497 | struct iscsi_task *task; |
498 | itt_t itt; | ||
472 | 499 | ||
473 | if (session->state == ISCSI_STATE_TERMINATE) | 500 | if (session->state == ISCSI_STATE_TERMINATE) |
474 | return NULL; | 501 | return NULL; |
@@ -505,23 +532,47 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
505 | } else | 532 | } else |
506 | task->data_count = 0; | 533 | task->data_count = 0; |
507 | 534 | ||
535 | if (conn->session->tt->alloc_pdu(task, hdr->opcode)) { | ||
536 | iscsi_conn_printk(KERN_ERR, conn, "Could not allocate " | ||
537 | "pdu for mgmt task.\n"); | ||
538 | goto requeue_task; | ||
539 | } | ||
540 | itt = task->hdr->itt; | ||
541 | task->hdr_len = sizeof(struct iscsi_hdr); | ||
508 | memcpy(task->hdr, hdr, sizeof(struct iscsi_hdr)); | 542 | memcpy(task->hdr, hdr, sizeof(struct iscsi_hdr)); |
543 | |||
544 | if (hdr->itt != RESERVED_ITT) { | ||
545 | if (session->tt->parse_pdu_itt) | ||
546 | task->hdr->itt = itt; | ||
547 | else | ||
548 | task->hdr->itt = build_itt(task->itt, | ||
549 | task->conn->session->age); | ||
550 | } | ||
551 | |||
509 | INIT_LIST_HEAD(&task->running); | 552 | INIT_LIST_HEAD(&task->running); |
510 | list_add_tail(&task->running, &conn->mgmtqueue); | 553 | list_add_tail(&task->running, &conn->mgmtqueue); |
511 | 554 | ||
512 | if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) { | 555 | if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) { |
513 | if (iscsi_prep_mgmt_task(conn, task)) { | 556 | if (iscsi_prep_mgmt_task(conn, task)) |
514 | __iscsi_put_task(task); | 557 | goto free_task; |
515 | return NULL; | ||
516 | } | ||
517 | 558 | ||
518 | if (session->tt->xmit_task(task)) | 559 | if (session->tt->xmit_task(task)) |
519 | task = NULL; | 560 | goto free_task; |
520 | 561 | ||
521 | } else | 562 | } else |
522 | scsi_queue_work(conn->session->host, &conn->xmitwork); | 563 | scsi_queue_work(conn->session->host, &conn->xmitwork); |
523 | 564 | ||
524 | return task; | 565 | return task; |
566 | |||
567 | free_task: | ||
568 | __iscsi_put_task(task); | ||
569 | return NULL; | ||
570 | |||
571 | requeue_task: | ||
572 | if (task != conn->login_task) | ||
573 | __kfifo_put(session->cmdpool.queue, (void*)&task, | ||
574 | sizeof(void*)); | ||
575 | return NULL; | ||
525 | } | 576 | } |
526 | 577 | ||
527 | int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr, | 578 | int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr, |
@@ -709,7 +760,6 @@ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
709 | { | 760 | { |
710 | struct iscsi_reject *reject = (struct iscsi_reject *)hdr; | 761 | struct iscsi_reject *reject = (struct iscsi_reject *)hdr; |
711 | struct iscsi_hdr rejected_pdu; | 762 | struct iscsi_hdr rejected_pdu; |
712 | uint32_t itt; | ||
713 | 763 | ||
714 | conn->exp_statsn = be32_to_cpu(reject->statsn) + 1; | 764 | conn->exp_statsn = be32_to_cpu(reject->statsn) + 1; |
715 | 765 | ||
@@ -719,10 +769,9 @@ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
719 | 769 | ||
720 | if (ntoh24(reject->dlength) >= sizeof(struct iscsi_hdr)) { | 770 | if (ntoh24(reject->dlength) >= sizeof(struct iscsi_hdr)) { |
721 | memcpy(&rejected_pdu, data, sizeof(struct iscsi_hdr)); | 771 | memcpy(&rejected_pdu, data, sizeof(struct iscsi_hdr)); |
722 | itt = get_itt(rejected_pdu.itt); | ||
723 | iscsi_conn_printk(KERN_ERR, conn, | 772 | iscsi_conn_printk(KERN_ERR, conn, |
724 | "itt 0x%x had pdu (op 0x%x) rejected " | 773 | "pdu (op 0x%x) rejected " |
725 | "due to DataDigest error.\n", itt, | 774 | "due to DataDigest error.\n", |
726 | rejected_pdu.opcode); | 775 | rejected_pdu.opcode); |
727 | } | 776 | } |
728 | } | 777 | } |
@@ -742,12 +791,15 @@ static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
742 | static struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *conn, itt_t itt) | 791 | static struct iscsi_task *iscsi_itt_to_task(struct iscsi_conn *conn, itt_t itt) |
743 | { | 792 | { |
744 | struct iscsi_session *session = conn->session; | 793 | struct iscsi_session *session = conn->session; |
745 | uint32_t i; | 794 | int i; |
746 | 795 | ||
747 | if (itt == RESERVED_ITT) | 796 | if (itt == RESERVED_ITT) |
748 | return NULL; | 797 | return NULL; |
749 | 798 | ||
750 | i = get_itt(itt); | 799 | if (session->tt->parse_pdu_itt) |
800 | session->tt->parse_pdu_itt(conn, itt, &i, NULL); | ||
801 | else | ||
802 | i = get_itt(itt); | ||
751 | if (i >= session->cmds_max) | 803 | if (i >= session->cmds_max) |
752 | return NULL; | 804 | return NULL; |
753 | 805 | ||
@@ -922,20 +974,25 @@ EXPORT_SYMBOL_GPL(iscsi_complete_pdu); | |||
922 | int iscsi_verify_itt(struct iscsi_conn *conn, itt_t itt) | 974 | int iscsi_verify_itt(struct iscsi_conn *conn, itt_t itt) |
923 | { | 975 | { |
924 | struct iscsi_session *session = conn->session; | 976 | struct iscsi_session *session = conn->session; |
925 | uint32_t i; | 977 | int age = 0, i = 0; |
926 | 978 | ||
927 | if (itt == RESERVED_ITT) | 979 | if (itt == RESERVED_ITT) |
928 | return 0; | 980 | return 0; |
929 | 981 | ||
930 | if (((__force u32)itt & ISCSI_AGE_MASK) != | 982 | if (session->tt->parse_pdu_itt) |
931 | (session->age << ISCSI_AGE_SHIFT)) { | 983 | session->tt->parse_pdu_itt(conn, itt, &i, &age); |
984 | else { | ||
985 | i = get_itt(itt); | ||
986 | age = ((__force u32)itt >> ISCSI_AGE_SHIFT) & ISCSI_AGE_MASK; | ||
987 | } | ||
988 | |||
989 | if (age != session->age) { | ||
932 | iscsi_conn_printk(KERN_ERR, conn, | 990 | iscsi_conn_printk(KERN_ERR, conn, |
933 | "received itt %x expected session age (%x)\n", | 991 | "received itt %x expected session age (%x)\n", |
934 | (__force u32)itt, session->age); | 992 | (__force u32)itt, session->age); |
935 | return ISCSI_ERR_BAD_ITT; | 993 | return ISCSI_ERR_BAD_ITT; |
936 | } | 994 | } |
937 | 995 | ||
938 | i = get_itt(itt); | ||
939 | if (i >= session->cmds_max) { | 996 | if (i >= session->cmds_max) { |
940 | iscsi_conn_printk(KERN_ERR, conn, | 997 | iscsi_conn_printk(KERN_ERR, conn, |
941 | "received invalid itt index %u (max cmds " | 998 | "received invalid itt index %u (max cmds " |
@@ -1136,8 +1193,13 @@ check_mgmt: | |||
1136 | fail_command(conn, conn->task, DID_IMM_RETRY << 16); | 1193 | fail_command(conn, conn->task, DID_IMM_RETRY << 16); |
1137 | continue; | 1194 | continue; |
1138 | } | 1195 | } |
1139 | if (iscsi_prep_scsi_cmd_pdu(conn->task)) { | 1196 | rc = iscsi_prep_scsi_cmd_pdu(conn->task); |
1140 | fail_command(conn, conn->task, DID_ABORT << 16); | 1197 | if (rc) { |
1198 | if (rc == -ENOMEM) { | ||
1199 | conn->task = NULL; | ||
1200 | goto again; | ||
1201 | } else | ||
1202 | fail_command(conn, conn->task, DID_ABORT << 16); | ||
1141 | continue; | 1203 | continue; |
1142 | } | 1204 | } |
1143 | rc = iscsi_xmit_task(conn); | 1205 | rc = iscsi_xmit_task(conn); |
@@ -1195,6 +1257,26 @@ static void iscsi_xmitworker(struct work_struct *work) | |||
1195 | } while (rc >= 0 || rc == -EAGAIN); | 1257 | } while (rc >= 0 || rc == -EAGAIN); |
1196 | } | 1258 | } |
1197 | 1259 | ||
1260 | static inline struct iscsi_task *iscsi_alloc_task(struct iscsi_conn *conn, | ||
1261 | struct scsi_cmnd *sc) | ||
1262 | { | ||
1263 | struct iscsi_task *task; | ||
1264 | |||
1265 | if (!__kfifo_get(conn->session->cmdpool.queue, | ||
1266 | (void *) &task, sizeof(void *))) | ||
1267 | return NULL; | ||
1268 | |||
1269 | sc->SCp.phase = conn->session->age; | ||
1270 | sc->SCp.ptr = (char *) task; | ||
1271 | |||
1272 | atomic_set(&task->refcount, 1); | ||
1273 | task->state = ISCSI_TASK_PENDING; | ||
1274 | task->conn = conn; | ||
1275 | task->sc = sc; | ||
1276 | INIT_LIST_HEAD(&task->running); | ||
1277 | return task; | ||
1278 | } | ||
1279 | |||
1198 | enum { | 1280 | enum { |
1199 | FAILURE_BAD_HOST = 1, | 1281 | FAILURE_BAD_HOST = 1, |
1200 | FAILURE_SESSION_FAILED, | 1282 | FAILURE_SESSION_FAILED, |
@@ -1281,33 +1363,27 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1281 | goto reject; | 1363 | goto reject; |
1282 | } | 1364 | } |
1283 | 1365 | ||
1284 | if (!__kfifo_get(session->cmdpool.queue, (void*)&task, | 1366 | task = iscsi_alloc_task(conn, sc); |
1285 | sizeof(void*))) { | 1367 | if (!task) { |
1286 | reason = FAILURE_OOM; | 1368 | reason = FAILURE_OOM; |
1287 | goto reject; | 1369 | goto reject; |
1288 | } | 1370 | } |
1289 | sc->SCp.phase = session->age; | ||
1290 | sc->SCp.ptr = (char *)task; | ||
1291 | |||
1292 | atomic_set(&task->refcount, 1); | ||
1293 | task->state = ISCSI_TASK_PENDING; | ||
1294 | task->conn = conn; | ||
1295 | task->sc = sc; | ||
1296 | INIT_LIST_HEAD(&task->running); | ||
1297 | list_add_tail(&task->running, &conn->xmitqueue); | 1371 | list_add_tail(&task->running, &conn->xmitqueue); |
1298 | 1372 | ||
1299 | if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) { | 1373 | if (session->tt->caps & CAP_DATA_PATH_OFFLOAD) { |
1300 | if (iscsi_prep_scsi_cmd_pdu(task)) { | 1374 | reason = iscsi_prep_scsi_cmd_pdu(task); |
1301 | sc->result = DID_ABORT << 16; | 1375 | if (reason) { |
1302 | sc->scsi_done = NULL; | 1376 | if (reason == -ENOMEM) { |
1303 | iscsi_complete_command(task); | 1377 | reason = FAILURE_OOM; |
1304 | goto fault; | 1378 | goto prepd_reject; |
1379 | } else { | ||
1380 | sc->result = DID_ABORT << 16; | ||
1381 | goto prepd_fault; | ||
1382 | } | ||
1305 | } | 1383 | } |
1306 | if (session->tt->xmit_task(task)) { | 1384 | if (session->tt->xmit_task(task)) { |
1307 | sc->scsi_done = NULL; | ||
1308 | iscsi_complete_command(task); | ||
1309 | reason = FAILURE_SESSION_NOT_READY; | 1385 | reason = FAILURE_SESSION_NOT_READY; |
1310 | goto reject; | 1386 | goto prepd_reject; |
1311 | } | 1387 | } |
1312 | } else | 1388 | } else |
1313 | scsi_queue_work(session->host, &conn->xmitwork); | 1389 | scsi_queue_work(session->host, &conn->xmitwork); |
@@ -1317,12 +1393,18 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1317 | spin_lock(host->host_lock); | 1393 | spin_lock(host->host_lock); |
1318 | return 0; | 1394 | return 0; |
1319 | 1395 | ||
1396 | prepd_reject: | ||
1397 | sc->scsi_done = NULL; | ||
1398 | iscsi_complete_command(task); | ||
1320 | reject: | 1399 | reject: |
1321 | spin_unlock(&session->lock); | 1400 | spin_unlock(&session->lock); |
1322 | debug_scsi("cmd 0x%x rejected (%d)\n", sc->cmnd[0], reason); | 1401 | debug_scsi("cmd 0x%x rejected (%d)\n", sc->cmnd[0], reason); |
1323 | spin_lock(host->host_lock); | 1402 | spin_lock(host->host_lock); |
1324 | return SCSI_MLQUEUE_TARGET_BUSY; | 1403 | return SCSI_MLQUEUE_TARGET_BUSY; |
1325 | 1404 | ||
1405 | prepd_fault: | ||
1406 | sc->scsi_done = NULL; | ||
1407 | iscsi_complete_command(task); | ||
1326 | fault: | 1408 | fault: |
1327 | spin_unlock(&session->lock); | 1409 | spin_unlock(&session->lock); |
1328 | debug_scsi("iscsi: cmd 0x%x is not queued (%d)\n", sc->cmnd[0], reason); | 1410 | debug_scsi("iscsi: cmd 0x%x is not queued (%d)\n", sc->cmnd[0], reason); |
@@ -1634,9 +1716,9 @@ static void iscsi_prep_abort_task_pdu(struct iscsi_task *task, | |||
1634 | hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE; | 1716 | hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE; |
1635 | hdr->flags = ISCSI_TM_FUNC_ABORT_TASK & ISCSI_FLAG_TM_FUNC_MASK; | 1717 | hdr->flags = ISCSI_TM_FUNC_ABORT_TASK & ISCSI_FLAG_TM_FUNC_MASK; |
1636 | hdr->flags |= ISCSI_FLAG_CMD_FINAL; | 1718 | hdr->flags |= ISCSI_FLAG_CMD_FINAL; |
1637 | memcpy(hdr->lun, task->hdr->lun, sizeof(hdr->lun)); | 1719 | memcpy(hdr->lun, task->lun, sizeof(hdr->lun)); |
1638 | hdr->rtt = task->hdr->itt; | 1720 | hdr->rtt = task->hdr_itt; |
1639 | hdr->refcmdsn = task->hdr->cmdsn; | 1721 | hdr->refcmdsn = task->cmdsn; |
1640 | } | 1722 | } |
1641 | 1723 | ||
1642 | int iscsi_eh_abort(struct scsi_cmnd *sc) | 1724 | int iscsi_eh_abort(struct scsi_cmnd *sc) |
@@ -2223,7 +2305,8 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, | |||
2223 | } | 2305 | } |
2224 | spin_unlock_bh(&session->lock); | 2306 | spin_unlock_bh(&session->lock); |
2225 | 2307 | ||
2226 | data = kmalloc(ISCSI_DEF_MAX_RECV_SEG_LEN, GFP_KERNEL); | 2308 | data = (char *) __get_free_pages(GFP_KERNEL, |
2309 | get_order(ISCSI_DEF_MAX_RECV_SEG_LEN)); | ||
2227 | if (!data) | 2310 | if (!data) |
2228 | goto login_task_data_alloc_fail; | 2311 | goto login_task_data_alloc_fail; |
2229 | conn->login_task->data = conn->data = data; | 2312 | conn->login_task->data = conn->data = data; |
@@ -2294,7 +2377,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) | |||
2294 | iscsi_suspend_tx(conn); | 2377 | iscsi_suspend_tx(conn); |
2295 | 2378 | ||
2296 | spin_lock_bh(&session->lock); | 2379 | spin_lock_bh(&session->lock); |
2297 | kfree(conn->data); | 2380 | free_pages((unsigned long) conn->data, |
2381 | get_order(ISCSI_DEF_MAX_RECV_SEG_LEN)); | ||
2298 | kfree(conn->persistent_address); | 2382 | kfree(conn->persistent_address); |
2299 | __kfifo_put(session->cmdpool.queue, (void*)&conn->login_task, | 2383 | __kfifo_put(session->cmdpool.queue, (void*)&conn->login_task, |
2300 | sizeof(void*)); | 2384 | sizeof(void*)); |