diff options
Diffstat (limited to 'drivers/scsi/bnx2i/bnx2i_hwi.c')
-rw-r--r-- | drivers/scsi/bnx2i/bnx2i_hwi.c | 96 |
1 files changed, 69 insertions, 27 deletions
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c index 2f9622ebbd84..96505e3ab986 100644 --- a/drivers/scsi/bnx2i/bnx2i_hwi.c +++ b/drivers/scsi/bnx2i/bnx2i_hwi.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* bnx2i_hwi.c: Broadcom NetXtreme II iSCSI driver. | 1 | /* bnx2i_hwi.c: Broadcom NetXtreme II iSCSI driver. |
2 | * | 2 | * |
3 | * Copyright (c) 2006 - 2009 Broadcom Corporation | 3 | * Copyright (c) 2006 - 2010 Broadcom Corporation |
4 | * Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved. | 4 | * Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved. |
5 | * Copyright (c) 2007, 2008 Mike Christie | 5 | * Copyright (c) 2007, 2008 Mike Christie |
6 | * | 6 | * |
@@ -9,6 +9,7 @@ | |||
9 | * the Free Software Foundation. | 9 | * the Free Software Foundation. |
10 | * | 10 | * |
11 | * Written by: Anil Veerabhadrappa (anilgv@broadcom.com) | 11 | * Written by: Anil Veerabhadrappa (anilgv@broadcom.com) |
12 | * Maintained by: Eddie Wai (eddie.wai@broadcom.com) | ||
12 | */ | 13 | */ |
13 | 14 | ||
14 | #include <linux/gfp.h> | 15 | #include <linux/gfp.h> |
@@ -385,6 +386,7 @@ int bnx2i_send_iscsi_tmf(struct bnx2i_conn *bnx2i_conn, | |||
385 | struct bnx2i_cmd *bnx2i_cmd; | 386 | struct bnx2i_cmd *bnx2i_cmd; |
386 | struct bnx2i_tmf_request *tmfabort_wqe; | 387 | struct bnx2i_tmf_request *tmfabort_wqe; |
387 | u32 dword; | 388 | u32 dword; |
389 | u32 scsi_lun[2]; | ||
388 | 390 | ||
389 | bnx2i_cmd = (struct bnx2i_cmd *)mtask->dd_data; | 391 | bnx2i_cmd = (struct bnx2i_cmd *)mtask->dd_data; |
390 | tmfabort_hdr = (struct iscsi_tm *)mtask->hdr; | 392 | tmfabort_hdr = (struct iscsi_tm *)mtask->hdr; |
@@ -426,7 +428,10 @@ int bnx2i_send_iscsi_tmf(struct bnx2i_conn *bnx2i_conn, | |||
426 | default: | 428 | default: |
427 | tmfabort_wqe->ref_itt = RESERVED_ITT; | 429 | tmfabort_wqe->ref_itt = RESERVED_ITT; |
428 | } | 430 | } |
429 | memcpy(tmfabort_wqe->lun, tmfabort_hdr->lun, sizeof(struct scsi_lun)); | 431 | memcpy(scsi_lun, tmfabort_hdr->lun, sizeof(struct scsi_lun)); |
432 | tmfabort_wqe->lun[0] = be32_to_cpu(scsi_lun[0]); | ||
433 | tmfabort_wqe->lun[1] = be32_to_cpu(scsi_lun[1]); | ||
434 | |||
430 | tmfabort_wqe->ref_cmd_sn = be32_to_cpu(tmfabort_hdr->refcmdsn); | 435 | tmfabort_wqe->ref_cmd_sn = be32_to_cpu(tmfabort_hdr->refcmdsn); |
431 | 436 | ||
432 | tmfabort_wqe->bd_list_addr_lo = (u32) bnx2i_conn->hba->mp_bd_dma; | 437 | tmfabort_wqe->bd_list_addr_lo = (u32) bnx2i_conn->hba->mp_bd_dma; |
@@ -697,10 +702,11 @@ void bnx2i_send_cmd_cleanup_req(struct bnx2i_hba *hba, struct bnx2i_cmd *cmd) | |||
697 | * this routine prepares and posts CONN_OFLD_REQ1/2 KWQE to initiate | 702 | * this routine prepares and posts CONN_OFLD_REQ1/2 KWQE to initiate |
698 | * iscsi connection context clean-up process | 703 | * iscsi connection context clean-up process |
699 | */ | 704 | */ |
700 | void bnx2i_send_conn_destroy(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep) | 705 | int bnx2i_send_conn_destroy(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep) |
701 | { | 706 | { |
702 | struct kwqe *kwqe_arr[2]; | 707 | struct kwqe *kwqe_arr[2]; |
703 | struct iscsi_kwqe_conn_destroy conn_cleanup; | 708 | struct iscsi_kwqe_conn_destroy conn_cleanup; |
709 | int rc = -EINVAL; | ||
704 | 710 | ||
705 | memset(&conn_cleanup, 0x00, sizeof(struct iscsi_kwqe_conn_destroy)); | 711 | memset(&conn_cleanup, 0x00, sizeof(struct iscsi_kwqe_conn_destroy)); |
706 | 712 | ||
@@ -717,7 +723,9 @@ void bnx2i_send_conn_destroy(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep) | |||
717 | 723 | ||
718 | kwqe_arr[0] = (struct kwqe *) &conn_cleanup; | 724 | kwqe_arr[0] = (struct kwqe *) &conn_cleanup; |
719 | if (hba->cnic && hba->cnic->submit_kwqes) | 725 | if (hba->cnic && hba->cnic->submit_kwqes) |
720 | hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, 1); | 726 | rc = hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, 1); |
727 | |||
728 | return rc; | ||
721 | } | 729 | } |
722 | 730 | ||
723 | 731 | ||
@@ -728,8 +736,8 @@ void bnx2i_send_conn_destroy(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep) | |||
728 | * | 736 | * |
729 | * 5706/5708/5709 specific - prepares and posts CONN_OFLD_REQ1/2 KWQE | 737 | * 5706/5708/5709 specific - prepares and posts CONN_OFLD_REQ1/2 KWQE |
730 | */ | 738 | */ |
731 | static void bnx2i_570x_send_conn_ofld_req(struct bnx2i_hba *hba, | 739 | static int bnx2i_570x_send_conn_ofld_req(struct bnx2i_hba *hba, |
732 | struct bnx2i_endpoint *ep) | 740 | struct bnx2i_endpoint *ep) |
733 | { | 741 | { |
734 | struct kwqe *kwqe_arr[2]; | 742 | struct kwqe *kwqe_arr[2]; |
735 | struct iscsi_kwqe_conn_offload1 ofld_req1; | 743 | struct iscsi_kwqe_conn_offload1 ofld_req1; |
@@ -737,6 +745,7 @@ static void bnx2i_570x_send_conn_ofld_req(struct bnx2i_hba *hba, | |||
737 | dma_addr_t dma_addr; | 745 | dma_addr_t dma_addr; |
738 | int num_kwqes = 2; | 746 | int num_kwqes = 2; |
739 | u32 *ptbl; | 747 | u32 *ptbl; |
748 | int rc = -EINVAL; | ||
740 | 749 | ||
741 | ofld_req1.hdr.op_code = ISCSI_KWQE_OPCODE_OFFLOAD_CONN1; | 750 | ofld_req1.hdr.op_code = ISCSI_KWQE_OPCODE_OFFLOAD_CONN1; |
742 | ofld_req1.hdr.flags = | 751 | ofld_req1.hdr.flags = |
@@ -774,7 +783,9 @@ static void bnx2i_570x_send_conn_ofld_req(struct bnx2i_hba *hba, | |||
774 | ofld_req2.num_additional_wqes = 0; | 783 | ofld_req2.num_additional_wqes = 0; |
775 | 784 | ||
776 | if (hba->cnic && hba->cnic->submit_kwqes) | 785 | if (hba->cnic && hba->cnic->submit_kwqes) |
777 | hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes); | 786 | rc = hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes); |
787 | |||
788 | return rc; | ||
778 | } | 789 | } |
779 | 790 | ||
780 | 791 | ||
@@ -785,8 +796,8 @@ static void bnx2i_570x_send_conn_ofld_req(struct bnx2i_hba *hba, | |||
785 | * | 796 | * |
786 | * 57710 specific - prepares and posts CONN_OFLD_REQ1/2 KWQE | 797 | * 57710 specific - prepares and posts CONN_OFLD_REQ1/2 KWQE |
787 | */ | 798 | */ |
788 | static void bnx2i_5771x_send_conn_ofld_req(struct bnx2i_hba *hba, | 799 | static int bnx2i_5771x_send_conn_ofld_req(struct bnx2i_hba *hba, |
789 | struct bnx2i_endpoint *ep) | 800 | struct bnx2i_endpoint *ep) |
790 | { | 801 | { |
791 | struct kwqe *kwqe_arr[5]; | 802 | struct kwqe *kwqe_arr[5]; |
792 | struct iscsi_kwqe_conn_offload1 ofld_req1; | 803 | struct iscsi_kwqe_conn_offload1 ofld_req1; |
@@ -795,6 +806,7 @@ static void bnx2i_5771x_send_conn_ofld_req(struct bnx2i_hba *hba, | |||
795 | dma_addr_t dma_addr; | 806 | dma_addr_t dma_addr; |
796 | int num_kwqes = 2; | 807 | int num_kwqes = 2; |
797 | u32 *ptbl; | 808 | u32 *ptbl; |
809 | int rc = -EINVAL; | ||
798 | 810 | ||
799 | ofld_req1.hdr.op_code = ISCSI_KWQE_OPCODE_OFFLOAD_CONN1; | 811 | ofld_req1.hdr.op_code = ISCSI_KWQE_OPCODE_OFFLOAD_CONN1; |
800 | ofld_req1.hdr.flags = | 812 | ofld_req1.hdr.flags = |
@@ -840,7 +852,9 @@ static void bnx2i_5771x_send_conn_ofld_req(struct bnx2i_hba *hba, | |||
840 | num_kwqes += 1; | 852 | num_kwqes += 1; |
841 | 853 | ||
842 | if (hba->cnic && hba->cnic->submit_kwqes) | 854 | if (hba->cnic && hba->cnic->submit_kwqes) |
843 | hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes); | 855 | rc = hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes); |
856 | |||
857 | return rc; | ||
844 | } | 858 | } |
845 | 859 | ||
846 | /** | 860 | /** |
@@ -851,12 +865,16 @@ static void bnx2i_5771x_send_conn_ofld_req(struct bnx2i_hba *hba, | |||
851 | * | 865 | * |
852 | * this routine prepares and posts CONN_OFLD_REQ1/2 KWQE | 866 | * this routine prepares and posts CONN_OFLD_REQ1/2 KWQE |
853 | */ | 867 | */ |
854 | void bnx2i_send_conn_ofld_req(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep) | 868 | int bnx2i_send_conn_ofld_req(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep) |
855 | { | 869 | { |
870 | int rc; | ||
871 | |||
856 | if (test_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type)) | 872 | if (test_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type)) |
857 | bnx2i_5771x_send_conn_ofld_req(hba, ep); | 873 | rc = bnx2i_5771x_send_conn_ofld_req(hba, ep); |
858 | else | 874 | else |
859 | bnx2i_570x_send_conn_ofld_req(hba, ep); | 875 | rc = bnx2i_570x_send_conn_ofld_req(hba, ep); |
876 | |||
877 | return rc; | ||
860 | } | 878 | } |
861 | 879 | ||
862 | 880 | ||
@@ -1513,7 +1531,7 @@ static void bnx2i_process_nopin_local_cmpl(struct iscsi_session *session, | |||
1513 | task = iscsi_itt_to_task(conn, | 1531 | task = iscsi_itt_to_task(conn, |
1514 | nop_in->itt & ISCSI_NOP_IN_MSG_INDEX); | 1532 | nop_in->itt & ISCSI_NOP_IN_MSG_INDEX); |
1515 | if (task) | 1533 | if (task) |
1516 | iscsi_put_task(task); | 1534 | __iscsi_put_task(task); |
1517 | spin_unlock(&session->lock); | 1535 | spin_unlock(&session->lock); |
1518 | } | 1536 | } |
1519 | 1537 | ||
@@ -1549,11 +1567,9 @@ static int bnx2i_process_nopin_mesg(struct iscsi_session *session, | |||
1549 | struct iscsi_task *task; | 1567 | struct iscsi_task *task; |
1550 | struct bnx2i_nop_in_msg *nop_in; | 1568 | struct bnx2i_nop_in_msg *nop_in; |
1551 | struct iscsi_nopin *hdr; | 1569 | struct iscsi_nopin *hdr; |
1552 | u32 itt; | ||
1553 | int tgt_async_nop = 0; | 1570 | int tgt_async_nop = 0; |
1554 | 1571 | ||
1555 | nop_in = (struct bnx2i_nop_in_msg *)cqe; | 1572 | nop_in = (struct bnx2i_nop_in_msg *)cqe; |
1556 | itt = nop_in->itt & ISCSI_NOP_IN_MSG_INDEX; | ||
1557 | 1573 | ||
1558 | spin_lock(&session->lock); | 1574 | spin_lock(&session->lock); |
1559 | hdr = (struct iscsi_nopin *)&bnx2i_conn->gen_pdu.resp_hdr; | 1575 | hdr = (struct iscsi_nopin *)&bnx2i_conn->gen_pdu.resp_hdr; |
@@ -1563,7 +1579,7 @@ static int bnx2i_process_nopin_mesg(struct iscsi_session *session, | |||
1563 | hdr->exp_cmdsn = cpu_to_be32(nop_in->exp_cmd_sn); | 1579 | hdr->exp_cmdsn = cpu_to_be32(nop_in->exp_cmd_sn); |
1564 | hdr->ttt = cpu_to_be32(nop_in->ttt); | 1580 | hdr->ttt = cpu_to_be32(nop_in->ttt); |
1565 | 1581 | ||
1566 | if (itt == (u16) RESERVED_ITT) { | 1582 | if (nop_in->itt == (u16) RESERVED_ITT) { |
1567 | bnx2i_unsol_pdu_adjust_rq(bnx2i_conn); | 1583 | bnx2i_unsol_pdu_adjust_rq(bnx2i_conn); |
1568 | hdr->itt = RESERVED_ITT; | 1584 | hdr->itt = RESERVED_ITT; |
1569 | tgt_async_nop = 1; | 1585 | tgt_async_nop = 1; |
@@ -1571,7 +1587,8 @@ static int bnx2i_process_nopin_mesg(struct iscsi_session *session, | |||
1571 | } | 1587 | } |
1572 | 1588 | ||
1573 | /* this is a response to one of our nop-outs */ | 1589 | /* this is a response to one of our nop-outs */ |
1574 | task = iscsi_itt_to_task(conn, itt); | 1590 | task = iscsi_itt_to_task(conn, |
1591 | (itt_t) (nop_in->itt & ISCSI_NOP_IN_MSG_INDEX)); | ||
1575 | if (task) { | 1592 | if (task) { |
1576 | hdr->flags = ISCSI_FLAG_CMD_FINAL; | 1593 | hdr->flags = ISCSI_FLAG_CMD_FINAL; |
1577 | hdr->itt = task->hdr->itt; | 1594 | hdr->itt = task->hdr->itt; |
@@ -1721,9 +1738,18 @@ static void bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn) | |||
1721 | if (nopin->cq_req_sn != qp->cqe_exp_seq_sn) | 1738 | if (nopin->cq_req_sn != qp->cqe_exp_seq_sn) |
1722 | break; | 1739 | break; |
1723 | 1740 | ||
1724 | if (unlikely(test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx))) | 1741 | if (unlikely(test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx))) { |
1742 | if (nopin->op_code == ISCSI_OP_NOOP_IN && | ||
1743 | nopin->itt == (u16) RESERVED_ITT) { | ||
1744 | printk(KERN_ALERT "bnx2i: Unsolicited " | ||
1745 | "NOP-In detected for suspended " | ||
1746 | "connection dev=%s!\n", | ||
1747 | bnx2i_conn->hba->netdev->name); | ||
1748 | bnx2i_unsol_pdu_adjust_rq(bnx2i_conn); | ||
1749 | goto cqe_out; | ||
1750 | } | ||
1725 | break; | 1751 | break; |
1726 | 1752 | } | |
1727 | tgt_async_msg = 0; | 1753 | tgt_async_msg = 0; |
1728 | 1754 | ||
1729 | switch (nopin->op_code) { | 1755 | switch (nopin->op_code) { |
@@ -1770,10 +1796,9 @@ static void bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn) | |||
1770 | printk(KERN_ALERT "bnx2i: unknown opcode 0x%x\n", | 1796 | printk(KERN_ALERT "bnx2i: unknown opcode 0x%x\n", |
1771 | nopin->op_code); | 1797 | nopin->op_code); |
1772 | } | 1798 | } |
1773 | |||
1774 | if (!tgt_async_msg) | 1799 | if (!tgt_async_msg) |
1775 | bnx2i_conn->ep->num_active_cmds--; | 1800 | bnx2i_conn->ep->num_active_cmds--; |
1776 | 1801 | cqe_out: | |
1777 | /* clear out in production version only, till beta keep opcode | 1802 | /* clear out in production version only, till beta keep opcode |
1778 | * field intact, will be helpful in debugging (context dump) | 1803 | * field intact, will be helpful in debugging (context dump) |
1779 | * nopin->op_code = 0; | 1804 | * nopin->op_code = 0; |
@@ -2154,11 +2179,24 @@ static void bnx2i_process_ofld_cmpl(struct bnx2i_hba *hba, | |||
2154 | } | 2179 | } |
2155 | 2180 | ||
2156 | if (ofld_kcqe->completion_status) { | 2181 | if (ofld_kcqe->completion_status) { |
2182 | ep->state = EP_STATE_OFLD_FAILED; | ||
2157 | if (ofld_kcqe->completion_status == | 2183 | if (ofld_kcqe->completion_status == |
2158 | ISCSI_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAILURE) | 2184 | ISCSI_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAILURE) |
2159 | printk(KERN_ALERT "bnx2i: unable to allocate" | 2185 | printk(KERN_ALERT "bnx2i (%s): ofld1 cmpl - unable " |
2160 | " iSCSI context resources\n"); | 2186 | "to allocate iSCSI context resources\n", |
2161 | ep->state = EP_STATE_OFLD_FAILED; | 2187 | hba->netdev->name); |
2188 | else if (ofld_kcqe->completion_status == | ||
2189 | ISCSI_KCQE_COMPLETION_STATUS_INVALID_OPCODE) | ||
2190 | printk(KERN_ALERT "bnx2i (%s): ofld1 cmpl - invalid " | ||
2191 | "opcode\n", hba->netdev->name); | ||
2192 | else if (ofld_kcqe->completion_status == | ||
2193 | ISCSI_KCQE_COMPLETION_STATUS_CID_BUSY) | ||
2194 | /* error status code valid only for 5771x chipset */ | ||
2195 | ep->state = EP_STATE_OFLD_FAILED_CID_BUSY; | ||
2196 | else | ||
2197 | printk(KERN_ALERT "bnx2i (%s): ofld1 cmpl - invalid " | ||
2198 | "error code %d\n", hba->netdev->name, | ||
2199 | ofld_kcqe->completion_status); | ||
2162 | } else { | 2200 | } else { |
2163 | ep->state = EP_STATE_OFLD_COMPL; | 2201 | ep->state = EP_STATE_OFLD_COMPL; |
2164 | cid_addr = ofld_kcqe->iscsi_conn_context_id; | 2202 | cid_addr = ofld_kcqe->iscsi_conn_context_id; |
@@ -2339,10 +2377,14 @@ static void bnx2i_cm_remote_close(struct cnic_sock *cm_sk) | |||
2339 | static void bnx2i_cm_remote_abort(struct cnic_sock *cm_sk) | 2377 | static void bnx2i_cm_remote_abort(struct cnic_sock *cm_sk) |
2340 | { | 2378 | { |
2341 | struct bnx2i_endpoint *ep = (struct bnx2i_endpoint *) cm_sk->context; | 2379 | struct bnx2i_endpoint *ep = (struct bnx2i_endpoint *) cm_sk->context; |
2380 | u32 old_state = ep->state; | ||
2342 | 2381 | ||
2343 | ep->state = EP_STATE_TCP_RST_RCVD; | 2382 | ep->state = EP_STATE_TCP_RST_RCVD; |
2344 | if (ep->conn) | 2383 | if (old_state == EP_STATE_DISCONN_START) |
2345 | bnx2i_recovery_que_add_conn(ep->hba, ep->conn); | 2384 | wake_up_interruptible(&ep->ofld_wait); |
2385 | else | ||
2386 | if (ep->conn) | ||
2387 | bnx2i_recovery_que_add_conn(ep->hba, ep->conn); | ||
2346 | } | 2388 | } |
2347 | 2389 | ||
2348 | 2390 | ||