diff options
Diffstat (limited to 'drivers/scsi/bnx2i')
-rw-r--r-- | drivers/scsi/bnx2i/bnx2i.h | 2 | ||||
-rw-r--r-- | drivers/scsi/bnx2i/bnx2i_hwi.c | 63 | ||||
-rw-r--r-- | drivers/scsi/bnx2i/bnx2i_init.c | 62 | ||||
-rw-r--r-- | drivers/scsi/bnx2i/bnx2i_iscsi.c | 15 |
4 files changed, 81 insertions, 61 deletions
diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h index 00c033511cbf..b6345d91bb66 100644 --- a/drivers/scsi/bnx2i/bnx2i.h +++ b/drivers/scsi/bnx2i/bnx2i.h | |||
@@ -753,7 +753,7 @@ extern int bnx2i_send_iscsi_tmf(struct bnx2i_conn *conn, | |||
753 | extern int bnx2i_send_iscsi_scsicmd(struct bnx2i_conn *conn, | 753 | extern int bnx2i_send_iscsi_scsicmd(struct bnx2i_conn *conn, |
754 | struct bnx2i_cmd *cmnd); | 754 | struct bnx2i_cmd *cmnd); |
755 | extern int bnx2i_send_iscsi_nopout(struct bnx2i_conn *conn, | 755 | extern int bnx2i_send_iscsi_nopout(struct bnx2i_conn *conn, |
756 | struct iscsi_task *mtask, u32 ttt, | 756 | struct iscsi_task *mtask, |
757 | char *datap, int data_len, int unsol); | 757 | char *datap, int data_len, int unsol); |
758 | extern int bnx2i_send_iscsi_logout(struct bnx2i_conn *conn, | 758 | extern int bnx2i_send_iscsi_logout(struct bnx2i_conn *conn, |
759 | struct iscsi_task *mtask); | 759 | struct iscsi_task *mtask); |
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c index d23fc256d585..90cef716b796 100644 --- a/drivers/scsi/bnx2i/bnx2i_hwi.c +++ b/drivers/scsi/bnx2i/bnx2i_hwi.c | |||
@@ -385,7 +385,6 @@ int bnx2i_send_iscsi_tmf(struct bnx2i_conn *bnx2i_conn, | |||
385 | struct bnx2i_cmd *bnx2i_cmd; | 385 | struct bnx2i_cmd *bnx2i_cmd; |
386 | struct bnx2i_tmf_request *tmfabort_wqe; | 386 | struct bnx2i_tmf_request *tmfabort_wqe; |
387 | u32 dword; | 387 | u32 dword; |
388 | u32 scsi_lun[2]; | ||
389 | 388 | ||
390 | bnx2i_cmd = (struct bnx2i_cmd *)mtask->dd_data; | 389 | bnx2i_cmd = (struct bnx2i_cmd *)mtask->dd_data; |
391 | tmfabort_hdr = (struct iscsi_tm *)mtask->hdr; | 390 | tmfabort_hdr = (struct iscsi_tm *)mtask->hdr; |
@@ -393,38 +392,41 @@ int bnx2i_send_iscsi_tmf(struct bnx2i_conn *bnx2i_conn, | |||
393 | bnx2i_conn->ep->qp.sq_prod_qe; | 392 | bnx2i_conn->ep->qp.sq_prod_qe; |
394 | 393 | ||
395 | tmfabort_wqe->op_code = tmfabort_hdr->opcode; | 394 | tmfabort_wqe->op_code = tmfabort_hdr->opcode; |
396 | tmfabort_wqe->op_attr = 0; | 395 | tmfabort_wqe->op_attr = tmfabort_hdr->flags; |
397 | tmfabort_wqe->op_attr = | ||
398 | ISCSI_TMF_REQUEST_ALWAYS_ONE | ISCSI_TM_FUNC_ABORT_TASK; | ||
399 | 396 | ||
400 | tmfabort_wqe->itt = (mtask->itt | (ISCSI_TASK_TYPE_MPATH << 14)); | 397 | tmfabort_wqe->itt = (mtask->itt | (ISCSI_TASK_TYPE_MPATH << 14)); |
401 | tmfabort_wqe->reserved2 = 0; | 398 | tmfabort_wqe->reserved2 = 0; |
402 | tmfabort_wqe->cmd_sn = be32_to_cpu(tmfabort_hdr->cmdsn); | 399 | tmfabort_wqe->cmd_sn = be32_to_cpu(tmfabort_hdr->cmdsn); |
403 | 400 | ||
404 | ctask = iscsi_itt_to_task(conn, tmfabort_hdr->rtt); | 401 | switch (tmfabort_hdr->flags & ISCSI_FLAG_TM_FUNC_MASK) { |
405 | if (!ctask || !ctask->sc) | 402 | case ISCSI_TM_FUNC_ABORT_TASK: |
406 | /* | 403 | case ISCSI_TM_FUNC_TASK_REASSIGN: |
407 | * the iscsi layer must have completed the cmd while this | 404 | ctask = iscsi_itt_to_task(conn, tmfabort_hdr->rtt); |
408 | * was starting up. | 405 | if (!ctask || !ctask->sc) |
409 | * | 406 | /* |
410 | * Note: In the case of a SCSI cmd timeout, the task's sc | 407 | * the iscsi layer must have completed the cmd while |
411 | * is still active; hence ctask->sc != 0 | 408 | * was starting up. |
412 | * In this case, the task must be aborted | 409 | * |
413 | */ | 410 | * Note: In the case of a SCSI cmd timeout, the task's |
414 | return 0; | 411 | * sc is still active; hence ctask->sc != 0 |
415 | 412 | * In this case, the task must be aborted | |
416 | ref_sc = ctask->sc; | 413 | */ |
417 | 414 | return 0; | |
418 | /* Retrieve LUN directly from the ref_sc */ | 415 | |
419 | int_to_scsilun(ref_sc->device->lun, (struct scsi_lun *) scsi_lun); | 416 | ref_sc = ctask->sc; |
420 | tmfabort_wqe->lun[0] = be32_to_cpu(scsi_lun[0]); | 417 | if (ref_sc->sc_data_direction == DMA_TO_DEVICE) |
421 | tmfabort_wqe->lun[1] = be32_to_cpu(scsi_lun[1]); | 418 | dword = (ISCSI_TASK_TYPE_WRITE << |
422 | 419 | ISCSI_CMD_REQUEST_TYPE_SHIFT); | |
423 | if (ref_sc->sc_data_direction == DMA_TO_DEVICE) | 420 | else |
424 | dword = (ISCSI_TASK_TYPE_WRITE << ISCSI_CMD_REQUEST_TYPE_SHIFT); | 421 | dword = (ISCSI_TASK_TYPE_READ << |
425 | else | 422 | ISCSI_CMD_REQUEST_TYPE_SHIFT); |
426 | dword = (ISCSI_TASK_TYPE_READ << ISCSI_CMD_REQUEST_TYPE_SHIFT); | 423 | tmfabort_wqe->ref_itt = (dword | |
427 | tmfabort_wqe->ref_itt = (dword | (tmfabort_hdr->rtt & ISCSI_ITT_MASK)); | 424 | (tmfabort_hdr->rtt & ISCSI_ITT_MASK)); |
425 | break; | ||
426 | default: | ||
427 | tmfabort_wqe->ref_itt = RESERVED_ITT; | ||
428 | } | ||
429 | memcpy(tmfabort_wqe->lun, tmfabort_hdr->lun, sizeof(struct scsi_lun)); | ||
428 | tmfabort_wqe->ref_cmd_sn = be32_to_cpu(tmfabort_hdr->refcmdsn); | 430 | tmfabort_wqe->ref_cmd_sn = be32_to_cpu(tmfabort_hdr->refcmdsn); |
429 | 431 | ||
430 | tmfabort_wqe->bd_list_addr_lo = (u32) bnx2i_conn->hba->mp_bd_dma; | 432 | tmfabort_wqe->bd_list_addr_lo = (u32) bnx2i_conn->hba->mp_bd_dma; |
@@ -464,7 +466,6 @@ int bnx2i_send_iscsi_scsicmd(struct bnx2i_conn *bnx2i_conn, | |||
464 | * @conn: iscsi connection | 466 | * @conn: iscsi connection |
465 | * @cmd: driver command structure which is requesting | 467 | * @cmd: driver command structure which is requesting |
466 | * a WQE to sent to chip for further processing | 468 | * a WQE to sent to chip for further processing |
467 | * @ttt: TTT to be used when building pdu header | ||
468 | * @datap: payload buffer pointer | 469 | * @datap: payload buffer pointer |
469 | * @data_len: payload data length | 470 | * @data_len: payload data length |
470 | * @unsol: indicated whether nopout pdu is unsolicited pdu or | 471 | * @unsol: indicated whether nopout pdu is unsolicited pdu or |
@@ -473,7 +474,7 @@ int bnx2i_send_iscsi_scsicmd(struct bnx2i_conn *bnx2i_conn, | |||
473 | * prepare and post a nopout request WQE to CNIC firmware | 474 | * prepare and post a nopout request WQE to CNIC firmware |
474 | */ | 475 | */ |
475 | int bnx2i_send_iscsi_nopout(struct bnx2i_conn *bnx2i_conn, | 476 | int bnx2i_send_iscsi_nopout(struct bnx2i_conn *bnx2i_conn, |
476 | struct iscsi_task *task, u32 ttt, | 477 | struct iscsi_task *task, |
477 | char *datap, int data_len, int unsol) | 478 | char *datap, int data_len, int unsol) |
478 | { | 479 | { |
479 | struct bnx2i_endpoint *ep = bnx2i_conn->ep; | 480 | struct bnx2i_endpoint *ep = bnx2i_conn->ep; |
@@ -498,7 +499,7 @@ int bnx2i_send_iscsi_nopout(struct bnx2i_conn *bnx2i_conn, | |||
498 | nopout_wqe->itt = ((u16)task->itt | | 499 | nopout_wqe->itt = ((u16)task->itt | |
499 | (ISCSI_TASK_TYPE_MPATH << | 500 | (ISCSI_TASK_TYPE_MPATH << |
500 | ISCSI_TMF_REQUEST_TYPE_SHIFT)); | 501 | ISCSI_TMF_REQUEST_TYPE_SHIFT)); |
501 | nopout_wqe->ttt = ttt; | 502 | nopout_wqe->ttt = nopout_hdr->ttt; |
502 | nopout_wqe->flags = 0; | 503 | nopout_wqe->flags = 0; |
503 | if (!unsol) | 504 | if (!unsol) |
504 | nopout_wqe->flags = ISCSI_NOP_OUT_REQUEST_LOCAL_COMPLETION; | 505 | nopout_wqe->flags = ISCSI_NOP_OUT_REQUEST_LOCAL_COMPLETION; |
diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c index a796f565f383..50c2aa3b8eb1 100644 --- a/drivers/scsi/bnx2i/bnx2i_init.c +++ b/drivers/scsi/bnx2i/bnx2i_init.c | |||
@@ -17,15 +17,17 @@ static struct list_head adapter_list = LIST_HEAD_INIT(adapter_list); | |||
17 | static u32 adapter_count; | 17 | static u32 adapter_count; |
18 | 18 | ||
19 | #define DRV_MODULE_NAME "bnx2i" | 19 | #define DRV_MODULE_NAME "bnx2i" |
20 | #define DRV_MODULE_VERSION "2.1.2" | 20 | #define DRV_MODULE_VERSION "2.1.3" |
21 | #define DRV_MODULE_RELDATE "Jun 28, 2010" | 21 | #define DRV_MODULE_RELDATE "Aug 10, 2010" |
22 | 22 | ||
23 | static char version[] __devinitdata = | 23 | static char version[] __devinitdata = |
24 | "Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \ | 24 | "Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \ |
25 | " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; | 25 | " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; |
26 | 26 | ||
27 | 27 | ||
28 | MODULE_AUTHOR("Anil Veerabhadrappa <anilgv@broadcom.com>"); | 28 | MODULE_AUTHOR("Anil Veerabhadrappa <anilgv@broadcom.com> and " |
29 | "Eddie Wai <eddie.wai@broadcom.com>"); | ||
30 | |||
29 | MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709/57710/57711" | 31 | MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709/57710/57711" |
30 | " iSCSI Driver"); | 32 | " iSCSI Driver"); |
31 | MODULE_LICENSE("GPL"); | 33 | MODULE_LICENSE("GPL"); |
@@ -167,6 +169,38 @@ void bnx2i_start(void *handle) | |||
167 | 169 | ||
168 | 170 | ||
169 | /** | 171 | /** |
172 | * bnx2i_chip_cleanup - local routine to handle chip cleanup | ||
173 | * @hba: Adapter instance to register | ||
174 | * | ||
175 | * Driver checks if adapter still has any active connections before | ||
176 | * executing the cleanup process | ||
177 | */ | ||
178 | static void bnx2i_chip_cleanup(struct bnx2i_hba *hba) | ||
179 | { | ||
180 | struct bnx2i_endpoint *bnx2i_ep; | ||
181 | struct list_head *pos, *tmp; | ||
182 | |||
183 | if (hba->ofld_conns_active) { | ||
184 | /* Stage to force the disconnection | ||
185 | * This is the case where the daemon is either slow or | ||
186 | * not present | ||
187 | */ | ||
188 | printk(KERN_ALERT "bnx2i: (%s) chip cleanup for %d active " | ||
189 | "connections\n", hba->netdev->name, | ||
190 | hba->ofld_conns_active); | ||
191 | mutex_lock(&hba->net_dev_lock); | ||
192 | list_for_each_safe(pos, tmp, &hba->ep_active_list) { | ||
193 | bnx2i_ep = list_entry(pos, struct bnx2i_endpoint, link); | ||
194 | /* Clean up the chip only */ | ||
195 | bnx2i_hw_ep_disconnect(bnx2i_ep); | ||
196 | bnx2i_ep->cm_sk = NULL; | ||
197 | } | ||
198 | mutex_unlock(&hba->net_dev_lock); | ||
199 | } | ||
200 | } | ||
201 | |||
202 | |||
203 | /** | ||
170 | * bnx2i_stop - cnic callback to shutdown adapter instance | 204 | * bnx2i_stop - cnic callback to shutdown adapter instance |
171 | * @handle: transparent handle pointing to adapter structure | 205 | * @handle: transparent handle pointing to adapter structure |
172 | * | 206 | * |
@@ -176,8 +210,6 @@ void bnx2i_start(void *handle) | |||
176 | void bnx2i_stop(void *handle) | 210 | void bnx2i_stop(void *handle) |
177 | { | 211 | { |
178 | struct bnx2i_hba *hba = handle; | 212 | struct bnx2i_hba *hba = handle; |
179 | struct list_head *pos, *tmp; | ||
180 | struct bnx2i_endpoint *bnx2i_ep; | ||
181 | int conns_active; | 213 | int conns_active; |
182 | 214 | ||
183 | /* check if cleanup happened in GOING_DOWN context */ | 215 | /* check if cleanup happened in GOING_DOWN context */ |
@@ -198,24 +230,7 @@ void bnx2i_stop(void *handle) | |||
198 | if (hba->ofld_conns_active == conns_active) | 230 | if (hba->ofld_conns_active == conns_active) |
199 | break; | 231 | break; |
200 | } | 232 | } |
201 | if (hba->ofld_conns_active) { | 233 | bnx2i_chip_cleanup(hba); |
202 | /* Stage to force the disconnection | ||
203 | * This is the case where the daemon is either slow or | ||
204 | * not present | ||
205 | */ | ||
206 | printk(KERN_ALERT "bnx2i: Wait timeout, force all eps " | ||
207 | "to disconnect (%d)\n", hba->ofld_conns_active); | ||
208 | mutex_lock(&hba->net_dev_lock); | ||
209 | list_for_each_safe(pos, tmp, &hba->ep_active_list) { | ||
210 | bnx2i_ep = list_entry(pos, struct bnx2i_endpoint, link); | ||
211 | /* Clean up the chip only */ | ||
212 | bnx2i_hw_ep_disconnect(bnx2i_ep); | ||
213 | } | ||
214 | mutex_unlock(&hba->net_dev_lock); | ||
215 | if (hba->ofld_conns_active) | ||
216 | printk(KERN_ERR "bnx2i: EP disconnect timeout (%d)!\n", | ||
217 | hba->ofld_conns_active); | ||
218 | } | ||
219 | 234 | ||
220 | /* This flag should be cleared last so that ep_disconnect() gracefully | 235 | /* This flag should be cleared last so that ep_disconnect() gracefully |
221 | * cleans up connection context | 236 | * cleans up connection context |
@@ -457,6 +472,7 @@ static void __exit bnx2i_mod_exit(void) | |||
457 | adapter_count--; | 472 | adapter_count--; |
458 | 473 | ||
459 | if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) { | 474 | if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) { |
475 | bnx2i_chip_cleanup(hba); | ||
460 | hba->cnic->unregister_device(hba->cnic, CNIC_ULP_ISCSI); | 476 | hba->cnic->unregister_device(hba->cnic, CNIC_ULP_ISCSI); |
461 | clear_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic); | 477 | clear_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic); |
462 | } | 478 | } |
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index a46ccc380ab1..fb50efbce087 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c | |||
@@ -1078,11 +1078,9 @@ static int bnx2i_iscsi_send_generic_request(struct iscsi_task *task) | |||
1078 | buf = bnx2i_conn->gen_pdu.req_buf; | 1078 | buf = bnx2i_conn->gen_pdu.req_buf; |
1079 | if (data_len) | 1079 | if (data_len) |
1080 | rc = bnx2i_send_iscsi_nopout(bnx2i_conn, task, | 1080 | rc = bnx2i_send_iscsi_nopout(bnx2i_conn, task, |
1081 | RESERVED_ITT, | ||
1082 | buf, data_len, 1); | 1081 | buf, data_len, 1); |
1083 | else | 1082 | else |
1084 | rc = bnx2i_send_iscsi_nopout(bnx2i_conn, task, | 1083 | rc = bnx2i_send_iscsi_nopout(bnx2i_conn, task, |
1085 | RESERVED_ITT, | ||
1086 | NULL, 0, 1); | 1084 | NULL, 0, 1); |
1087 | break; | 1085 | break; |
1088 | case ISCSI_OP_LOGOUT: | 1086 | case ISCSI_OP_LOGOUT: |
@@ -1955,6 +1953,9 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep) | |||
1955 | if (!cnic) | 1953 | if (!cnic) |
1956 | return 0; | 1954 | return 0; |
1957 | 1955 | ||
1956 | if (bnx2i_ep->state == EP_STATE_IDLE) | ||
1957 | return 0; | ||
1958 | |||
1958 | if (!bnx2i_ep_tcp_conn_active(bnx2i_ep)) | 1959 | if (!bnx2i_ep_tcp_conn_active(bnx2i_ep)) |
1959 | goto destroy_conn; | 1960 | goto destroy_conn; |
1960 | 1961 | ||
@@ -1998,11 +1999,13 @@ int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep) | |||
1998 | else | 1999 | else |
1999 | close_ret = cnic->cm_abort(bnx2i_ep->cm_sk); | 2000 | close_ret = cnic->cm_abort(bnx2i_ep->cm_sk); |
2000 | 2001 | ||
2002 | /* No longer allow CFC delete if cm_close/abort fails the request */ | ||
2001 | if (close_ret) | 2003 | if (close_ret) |
2002 | bnx2i_ep->state = EP_STATE_DISCONN_COMPL; | 2004 | printk(KERN_ALERT "bnx2i: %s close/abort(%d) returned %d\n", |
2003 | 2005 | bnx2i_ep->hba->netdev->name, close, close_ret); | |
2004 | /* wait for option-2 conn teardown */ | 2006 | else |
2005 | wait_event_interruptible(bnx2i_ep->ofld_wait, | 2007 | /* wait for option-2 conn teardown */ |
2008 | wait_event_interruptible(bnx2i_ep->ofld_wait, | ||
2006 | bnx2i_ep->state != EP_STATE_DISCONN_START); | 2009 | bnx2i_ep->state != EP_STATE_DISCONN_START); |
2007 | 2010 | ||
2008 | if (signal_pending(current)) | 2011 | if (signal_pending(current)) |