aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorEddie Wai <eddie.wai@broadcom.com>2011-06-23 18:51:34 -0400
committerJames Bottomley <JBottomley@Parallels.com>2011-06-29 17:48:23 -0400
commitb5cf6b63f73abdc051035f0050b367beeb2ef94c (patch)
treee627d05b8cca847e3364e198b49b985efbaf14b2 /drivers/scsi
parent74dcd0ec735ba9c5bef254b2f6e53068cf3f9ff0 (diff)
[SCSI] bnx2i: Added the use of kthreads to handle SCSI cmd completion
This patch breaks the SCSI cmd completion into two parts: 1. The bh will allocate and queued work to the cmd specific CPU IO completion kthread. The CPU for the cmd is from the sc->request->cpu. 2. The CPU specific IO completion kthread will call the scsi_cmd_resp routine to do the actual cmd completion. In the normal case, these IO completion kthreads should complete before the blk IO times out at 60s. However, in the case when these kthreads are blocked for whatever reason and exceeded the timeout, the call to conn_destroy will have to iterate and exhaust all related work in the percpu work list for all online CPUs. This will guarantee the protection of the work->session and conn pointers before they get freed. Also modified the event coalescing formula to have at least the event_coal_min outstanding cmds in the pipeline so the SCSI producer would not get underrun. Also changed the following SCSI parameters: - can_queue from 1024 to 2048 - cmds_per_lun from 24 to 128 Signed-off-by: Eddie Wai <eddie.wai@broadcom.com> Acked-by: Benjamin Li <benli@broadcom.com> Acked-by: Michael Chan <mchan@broadcom.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/bnx2i/bnx2i.h31
-rw-r--r--drivers/scsi/bnx2i/bnx2i_hwi.c183
-rw-r--r--drivers/scsi/bnx2i/bnx2i_init.c118
-rw-r--r--drivers/scsi/bnx2i/bnx2i_iscsi.c36
4 files changed, 333 insertions, 35 deletions
diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h
index 6bdd25a93db9..239bc4e395b2 100644
--- a/drivers/scsi/bnx2i/bnx2i.h
+++ b/drivers/scsi/bnx2i/bnx2i.h
@@ -22,11 +22,14 @@
22#include <linux/pci.h> 22#include <linux/pci.h>
23#include <linux/spinlock.h> 23#include <linux/spinlock.h>
24#include <linux/interrupt.h> 24#include <linux/interrupt.h>
25#include <linux/delay.h>
25#include <linux/sched.h> 26#include <linux/sched.h>
26#include <linux/in.h> 27#include <linux/in.h>
27#include <linux/kfifo.h> 28#include <linux/kfifo.h>
28#include <linux/netdevice.h> 29#include <linux/netdevice.h>
29#include <linux/completion.h> 30#include <linux/completion.h>
31#include <linux/kthread.h>
32#include <linux/cpu.h>
30 33
31#include <scsi/scsi_cmnd.h> 34#include <scsi/scsi_cmnd.h>
32#include <scsi/scsi_device.h> 35#include <scsi/scsi_device.h>
@@ -202,10 +205,13 @@ struct io_bdt {
202/** 205/**
203 * bnx2i_cmd - iscsi command structure 206 * bnx2i_cmd - iscsi command structure
204 * 207 *
208 * @hdr: iSCSI header
209 * @conn: iscsi_conn pointer
205 * @scsi_cmd: SCSI-ML task pointer corresponding to this iscsi cmd 210 * @scsi_cmd: SCSI-ML task pointer corresponding to this iscsi cmd
206 * @sg: SG list 211 * @sg: SG list
207 * @io_tbl: buffer descriptor (BD) table 212 * @io_tbl: buffer descriptor (BD) table
208 * @bd_tbl_dma: buffer descriptor (BD) table's dma address 213 * @bd_tbl_dma: buffer descriptor (BD) table's dma address
214 * @req: bnx2i specific command request struct
209 */ 215 */
210struct bnx2i_cmd { 216struct bnx2i_cmd {
211 struct iscsi_hdr hdr; 217 struct iscsi_hdr hdr;
@@ -229,6 +235,7 @@ struct bnx2i_cmd {
229 * @gen_pdu: login/nopout/logout pdu resources 235 * @gen_pdu: login/nopout/logout pdu resources
230 * @violation_notified: bit mask used to track iscsi error/warning messages 236 * @violation_notified: bit mask used to track iscsi error/warning messages
231 * already printed out 237 * already printed out
238 * @work_cnt: keeps track of the number of outstanding work
232 * 239 *
233 * iSCSI connection structure 240 * iSCSI connection structure
234 */ 241 */
@@ -252,6 +259,8 @@ struct bnx2i_conn {
252 */ 259 */
253 struct generic_pdu_resc gen_pdu; 260 struct generic_pdu_resc gen_pdu;
254 u64 violation_notified; 261 u64 violation_notified;
262
263 atomic_t work_cnt;
255}; 264};
256 265
257 266
@@ -661,7 +670,6 @@ enum {
661 * @hba: adapter to which this connection belongs 670 * @hba: adapter to which this connection belongs
662 * @conn: iscsi connection this EP is linked to 671 * @conn: iscsi connection this EP is linked to
663 * @cls_ep: associated iSCSI endpoint pointer 672 * @cls_ep: associated iSCSI endpoint pointer
664 * @sess: iscsi session this EP is linked to
665 * @cm_sk: cnic sock struct 673 * @cm_sk: cnic sock struct
666 * @hba_age: age to detect if 'iscsid' issues ep_disconnect() 674 * @hba_age: age to detect if 'iscsid' issues ep_disconnect()
667 * after HBA reset is completed by bnx2i/cnic/bnx2 675 * after HBA reset is completed by bnx2i/cnic/bnx2
@@ -687,7 +695,7 @@ struct bnx2i_endpoint {
687 u32 hba_age; 695 u32 hba_age;
688 u32 state; 696 u32 state;
689 unsigned long timestamp; 697 unsigned long timestamp;
690 int num_active_cmds; 698 atomic_t num_active_cmds;
691 u32 ec_shift; 699 u32 ec_shift;
692 700
693 struct qp_info qp; 701 struct qp_info qp;
@@ -700,6 +708,19 @@ struct bnx2i_endpoint {
700}; 708};
701 709
702 710
711struct bnx2i_work {
712 struct list_head list;
713 struct iscsi_session *session;
714 struct bnx2i_conn *bnx2i_conn;
715 struct cqe cqe;
716};
717
718struct bnx2i_percpu_s {
719 struct task_struct *iothread;
720 struct list_head work_list;
721 spinlock_t p_work_lock;
722};
723
703 724
704/* Global variables */ 725/* Global variables */
705extern unsigned int error_mask1, error_mask2; 726extern unsigned int error_mask1, error_mask2;
@@ -783,7 +804,7 @@ extern struct bnx2i_endpoint *bnx2i_find_ep_in_destroy_list(
783 struct bnx2i_hba *hba, u32 iscsi_cid); 804 struct bnx2i_hba *hba, u32 iscsi_cid);
784 805
785extern int bnx2i_map_ep_dbell_regs(struct bnx2i_endpoint *ep); 806extern int bnx2i_map_ep_dbell_regs(struct bnx2i_endpoint *ep);
786extern void bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action); 807extern int bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action);
787 808
788extern int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep); 809extern int bnx2i_hw_ep_disconnect(struct bnx2i_endpoint *bnx2i_ep);
789 810
@@ -793,4 +814,8 @@ extern void bnx2i_print_active_cmd_queue(struct bnx2i_conn *conn);
793extern void bnx2i_print_xmit_pdu_queue(struct bnx2i_conn *conn); 814extern void bnx2i_print_xmit_pdu_queue(struct bnx2i_conn *conn);
794extern void bnx2i_print_recv_state(struct bnx2i_conn *conn); 815extern void bnx2i_print_recv_state(struct bnx2i_conn *conn);
795 816
817extern int bnx2i_percpu_io_thread(void *arg);
818extern int bnx2i_process_scsi_cmd_resp(struct iscsi_session *session,
819 struct bnx2i_conn *bnx2i_conn,
820 struct cqe *cqe);
796#endif 821#endif
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c
index 550e6c4ea8b4..a501a72a243d 100644
--- a/drivers/scsi/bnx2i/bnx2i_hwi.c
+++ b/drivers/scsi/bnx2i/bnx2i_hwi.c
@@ -17,6 +17,8 @@
17#include <scsi/libiscsi.h> 17#include <scsi/libiscsi.h>
18#include "bnx2i.h" 18#include "bnx2i.h"
19 19
20DECLARE_PER_CPU(struct bnx2i_percpu_s, bnx2i_percpu);
21
20/** 22/**
21 * bnx2i_get_cid_num - get cid from ep 23 * bnx2i_get_cid_num - get cid from ep
22 * @ep: endpoint pointer 24 * @ep: endpoint pointer
@@ -131,16 +133,16 @@ static void bnx2i_iscsi_license_error(struct bnx2i_hba *hba, u32 error_code)
131 * the driver. EQ event is generated CQ index is hit or at least 1 CQ is 133 * the driver. EQ event is generated CQ index is hit or at least 1 CQ is
132 * outstanding and on chip timer expires 134 * outstanding and on chip timer expires
133 */ 135 */
134void bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action) 136int bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action)
135{ 137{
136 struct bnx2i_5771x_cq_db *cq_db; 138 struct bnx2i_5771x_cq_db *cq_db;
137 u16 cq_index; 139 u16 cq_index;
138 u16 next_index; 140 u16 next_index = 0;
139 u32 num_active_cmds; 141 u32 num_active_cmds;
140 142
141 /* Coalesce CQ entries only on 10G devices */ 143 /* Coalesce CQ entries only on 10G devices */
142 if (!test_bit(BNX2I_NX2_DEV_57710, &ep->hba->cnic_dev_type)) 144 if (!test_bit(BNX2I_NX2_DEV_57710, &ep->hba->cnic_dev_type))
143 return; 145 return 0;
144 146
145 /* Do not update CQ DB multiple times before firmware writes 147 /* Do not update CQ DB multiple times before firmware writes
146 * '0xFFFF' to CQDB->SQN field. Deviation may cause spurious 148 * '0xFFFF' to CQDB->SQN field. Deviation may cause spurious
@@ -150,16 +152,17 @@ void bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action)
150 152
151 if (action != CNIC_ARM_CQE_FP) 153 if (action != CNIC_ARM_CQE_FP)
152 if (cq_db->sqn[0] && cq_db->sqn[0] != 0xFFFF) 154 if (cq_db->sqn[0] && cq_db->sqn[0] != 0xFFFF)
153 return; 155 return 0;
154 156
155 if (action == CNIC_ARM_CQE || action == CNIC_ARM_CQE_FP) { 157 if (action == CNIC_ARM_CQE || action == CNIC_ARM_CQE_FP) {
156 num_active_cmds = ep->num_active_cmds; 158 num_active_cmds = atomic_read(&ep->num_active_cmds);
157 if (num_active_cmds <= event_coal_min) 159 if (num_active_cmds <= event_coal_min)
158 next_index = 1; 160 next_index = 1;
159 else 161 else {
160 next_index = event_coal_min + 162 next_index = num_active_cmds >> ep->ec_shift;
161 ((num_active_cmds - event_coal_min) >> 163 if (next_index > num_active_cmds - event_coal_min)
162 ep->ec_shift); 164 next_index = num_active_cmds - event_coal_min;
165 }
163 if (!next_index) 166 if (!next_index)
164 next_index = 1; 167 next_index = 1;
165 cq_index = ep->qp.cqe_exp_seq_sn + next_index - 1; 168 cq_index = ep->qp.cqe_exp_seq_sn + next_index - 1;
@@ -170,6 +173,7 @@ void bnx2i_arm_cq_event_coalescing(struct bnx2i_endpoint *ep, u8 action)
170 173
171 cq_db->sqn[0] = cq_index; 174 cq_db->sqn[0] = cq_index;
172 } 175 }
176 return next_index;
173} 177}
174 178
175 179
@@ -265,7 +269,7 @@ static void bnx2i_ring_sq_dbell(struct bnx2i_conn *bnx2i_conn, int count)
265 struct bnx2i_5771x_sq_rq_db *sq_db; 269 struct bnx2i_5771x_sq_rq_db *sq_db;
266 struct bnx2i_endpoint *ep = bnx2i_conn->ep; 270 struct bnx2i_endpoint *ep = bnx2i_conn->ep;
267 271
268 ep->num_active_cmds++; 272 atomic_inc(&ep->num_active_cmds);
269 wmb(); /* flush SQ WQE memory before the doorbell is rung */ 273 wmb(); /* flush SQ WQE memory before the doorbell is rung */
270 if (test_bit(BNX2I_NX2_DEV_57710, &ep->hba->cnic_dev_type)) { 274 if (test_bit(BNX2I_NX2_DEV_57710, &ep->hba->cnic_dev_type)) {
271 sq_db = (struct bnx2i_5771x_sq_rq_db *) ep->qp.sq_pgtbl_virt; 275 sq_db = (struct bnx2i_5771x_sq_rq_db *) ep->qp.sq_pgtbl_virt;
@@ -1331,14 +1335,15 @@ int bnx2i_send_fw_iscsi_init_msg(struct bnx2i_hba *hba)
1331 1335
1332/** 1336/**
1333 * bnx2i_process_scsi_cmd_resp - this function handles scsi cmd completion. 1337 * bnx2i_process_scsi_cmd_resp - this function handles scsi cmd completion.
1334 * @conn: iscsi connection 1338 * @session: iscsi session
1339 * @bnx2i_conn: bnx2i connection
1335 * @cqe: pointer to newly DMA'ed CQE entry for processing 1340 * @cqe: pointer to newly DMA'ed CQE entry for processing
1336 * 1341 *
1337 * process SCSI CMD Response CQE & complete the request to SCSI-ML 1342 * process SCSI CMD Response CQE & complete the request to SCSI-ML
1338 */ 1343 */
1339static int bnx2i_process_scsi_cmd_resp(struct iscsi_session *session, 1344int bnx2i_process_scsi_cmd_resp(struct iscsi_session *session,
1340 struct bnx2i_conn *bnx2i_conn, 1345 struct bnx2i_conn *bnx2i_conn,
1341 struct cqe *cqe) 1346 struct cqe *cqe)
1342{ 1347{
1343 struct iscsi_conn *conn = bnx2i_conn->cls_conn->dd_data; 1348 struct iscsi_conn *conn = bnx2i_conn->cls_conn->dd_data;
1344 struct bnx2i_cmd_response *resp_cqe; 1349 struct bnx2i_cmd_response *resp_cqe;
@@ -1348,7 +1353,7 @@ static int bnx2i_process_scsi_cmd_resp(struct iscsi_session *session,
1348 u32 datalen = 0; 1353 u32 datalen = 0;
1349 1354
1350 resp_cqe = (struct bnx2i_cmd_response *)cqe; 1355 resp_cqe = (struct bnx2i_cmd_response *)cqe;
1351 spin_lock(&session->lock); 1356 spin_lock_bh(&session->lock);
1352 task = iscsi_itt_to_task(conn, 1357 task = iscsi_itt_to_task(conn,
1353 resp_cqe->itt & ISCSI_CMD_RESPONSE_INDEX); 1358 resp_cqe->itt & ISCSI_CMD_RESPONSE_INDEX);
1354 if (!task) 1359 if (!task)
@@ -1409,7 +1414,7 @@ done:
1409 __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, 1414 __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr,
1410 conn->data, datalen); 1415 conn->data, datalen);
1411fail: 1416fail:
1412 spin_unlock(&session->lock); 1417 spin_unlock_bh(&session->lock);
1413 return 0; 1418 return 0;
1414} 1419}
1415 1420
@@ -1836,21 +1841,130 @@ static void bnx2i_process_cmd_cleanup_resp(struct iscsi_session *session,
1836} 1841}
1837 1842
1838 1843
1844/**
1845 * bnx2i_percpu_io_thread - thread per cpu for ios
1846 *
1847 * @arg: ptr to bnx2i_percpu_info structure
1848 */
1849int bnx2i_percpu_io_thread(void *arg)
1850{
1851 struct bnx2i_percpu_s *p = arg;
1852 struct bnx2i_work *work, *tmp;
1853 LIST_HEAD(work_list);
1854
1855 set_user_nice(current, -20);
1856
1857 while (!kthread_should_stop()) {
1858 spin_lock_bh(&p->p_work_lock);
1859 while (!list_empty(&p->work_list)) {
1860 list_splice_init(&p->work_list, &work_list);
1861 spin_unlock_bh(&p->p_work_lock);
1862
1863 list_for_each_entry_safe(work, tmp, &work_list, list) {
1864 list_del_init(&work->list);
1865 /* work allocated in the bh, freed here */
1866 bnx2i_process_scsi_cmd_resp(work->session,
1867 work->bnx2i_conn,
1868 &work->cqe);
1869 atomic_dec(&work->bnx2i_conn->work_cnt);
1870 kfree(work);
1871 }
1872 spin_lock_bh(&p->p_work_lock);
1873 }
1874 set_current_state(TASK_INTERRUPTIBLE);
1875 spin_unlock_bh(&p->p_work_lock);
1876 schedule();
1877 }
1878 __set_current_state(TASK_RUNNING);
1879
1880 return 0;
1881}
1882
1883
1884/**
1885 * bnx2i_queue_scsi_cmd_resp - queue cmd completion to the percpu thread
1886 * @bnx2i_conn: bnx2i connection
1887 *
1888 * this function is called by generic KCQ handler to queue all pending cmd
1889 * completion CQEs
1890 *
1891 * The implementation is to queue the cmd response based on the
1892 * last recorded command for the given connection. The
1893 * cpu_id gets recorded upon task_xmit. No out-of-order completion!
1894 */
1895static int bnx2i_queue_scsi_cmd_resp(struct iscsi_session *session,
1896 struct bnx2i_conn *bnx2i_conn,
1897 struct bnx2i_nop_in_msg *cqe)
1898{
1899 struct bnx2i_work *bnx2i_work = NULL;
1900 struct bnx2i_percpu_s *p = NULL;
1901 struct iscsi_task *task;
1902 struct scsi_cmnd *sc;
1903 int rc = 0;
1904
1905 spin_lock(&session->lock);
1906 task = iscsi_itt_to_task(bnx2i_conn->cls_conn->dd_data,
1907 cqe->itt & ISCSI_CMD_RESPONSE_INDEX);
1908 if (!task) {
1909 spin_unlock(&session->lock);
1910 return -EINVAL;
1911 }
1912 sc = task->sc;
1913 spin_unlock(&session->lock);
1914
1915 p = &per_cpu(bnx2i_percpu, sc->request->cpu);
1916 spin_lock(&p->p_work_lock);
1917 if (unlikely(!p->iothread)) {
1918 rc = -EINVAL;
1919 goto err;
1920 }
1921 /* Alloc and copy to the cqe */
1922 bnx2i_work = kzalloc(sizeof(struct bnx2i_work), GFP_ATOMIC);
1923 if (bnx2i_work) {
1924 INIT_LIST_HEAD(&bnx2i_work->list);
1925 bnx2i_work->session = session;
1926 bnx2i_work->bnx2i_conn = bnx2i_conn;
1927 memcpy(&bnx2i_work->cqe, cqe, sizeof(struct cqe));
1928 list_add_tail(&bnx2i_work->list, &p->work_list);
1929 atomic_inc(&bnx2i_conn->work_cnt);
1930 wake_up_process(p->iothread);
1931 spin_unlock(&p->p_work_lock);
1932 goto done;
1933 } else
1934 rc = -ENOMEM;
1935err:
1936 spin_unlock(&p->p_work_lock);
1937 bnx2i_process_scsi_cmd_resp(session, bnx2i_conn, (struct cqe *)cqe);
1938done:
1939 return rc;
1940}
1941
1839 1942
1840/** 1943/**
1841 * bnx2i_process_new_cqes - process newly DMA'ed CQE's 1944 * bnx2i_process_new_cqes - process newly DMA'ed CQE's
1842 * @bnx2i_conn: iscsi connection 1945 * @bnx2i_conn: bnx2i connection
1843 * 1946 *
1844 * this function is called by generic KCQ handler to process all pending CQE's 1947 * this function is called by generic KCQ handler to process all pending CQE's
1845 */ 1948 */
1846static void bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn) 1949static int bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn)
1847{ 1950{
1848 struct iscsi_conn *conn = bnx2i_conn->cls_conn->dd_data; 1951 struct iscsi_conn *conn = bnx2i_conn->cls_conn->dd_data;
1849 struct iscsi_session *session = conn->session; 1952 struct iscsi_session *session = conn->session;
1850 struct qp_info *qp = &bnx2i_conn->ep->qp; 1953 struct qp_info *qp;
1851 struct bnx2i_nop_in_msg *nopin; 1954 struct bnx2i_nop_in_msg *nopin;
1852 int tgt_async_msg; 1955 int tgt_async_msg;
1956 int cqe_cnt = 0;
1853 1957
1958 if (bnx2i_conn->ep == NULL)
1959 return 0;
1960
1961 qp = &bnx2i_conn->ep->qp;
1962
1963 if (!qp->cq_virt) {
1964 printk(KERN_ALERT "bnx2i (%s): cq resr freed in bh execution!",
1965 bnx2i_conn->hba->netdev->name);
1966 goto out;
1967 }
1854 while (1) { 1968 while (1) {
1855 nopin = (struct bnx2i_nop_in_msg *) qp->cq_cons_qe; 1969 nopin = (struct bnx2i_nop_in_msg *) qp->cq_cons_qe;
1856 if (nopin->cq_req_sn != qp->cqe_exp_seq_sn) 1970 if (nopin->cq_req_sn != qp->cqe_exp_seq_sn)
@@ -1873,8 +1987,9 @@ static void bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn)
1873 switch (nopin->op_code) { 1987 switch (nopin->op_code) {
1874 case ISCSI_OP_SCSI_CMD_RSP: 1988 case ISCSI_OP_SCSI_CMD_RSP:
1875 case ISCSI_OP_SCSI_DATA_IN: 1989 case ISCSI_OP_SCSI_DATA_IN:
1876 bnx2i_process_scsi_cmd_resp(session, bnx2i_conn, 1990 /* Run the kthread engine only for data cmds
1877 qp->cq_cons_qe); 1991 All other cmds will be completed in this bh! */
1992 bnx2i_queue_scsi_cmd_resp(session, bnx2i_conn, nopin);
1878 break; 1993 break;
1879 case ISCSI_OP_LOGIN_RSP: 1994 case ISCSI_OP_LOGIN_RSP:
1880 bnx2i_process_login_resp(session, bnx2i_conn, 1995 bnx2i_process_login_resp(session, bnx2i_conn,
@@ -1918,13 +2033,21 @@ static void bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn)
1918 printk(KERN_ALERT "bnx2i: unknown opcode 0x%x\n", 2033 printk(KERN_ALERT "bnx2i: unknown opcode 0x%x\n",
1919 nopin->op_code); 2034 nopin->op_code);
1920 } 2035 }
1921 if (!tgt_async_msg) 2036 if (!tgt_async_msg) {
1922 bnx2i_conn->ep->num_active_cmds--; 2037 if (!atomic_read(&bnx2i_conn->ep->num_active_cmds))
2038 printk(KERN_ALERT "bnx2i (%s): no active cmd! "
2039 "op 0x%x\n",
2040 bnx2i_conn->hba->netdev->name,
2041 nopin->op_code);
2042 else
2043 atomic_dec(&bnx2i_conn->ep->num_active_cmds);
2044 }
1923cqe_out: 2045cqe_out:
1924 /* clear out in production version only, till beta keep opcode 2046 /* clear out in production version only, till beta keep opcode
1925 * field intact, will be helpful in debugging (context dump) 2047 * field intact, will be helpful in debugging (context dump)
1926 * nopin->op_code = 0; 2048 * nopin->op_code = 0;
1927 */ 2049 */
2050 cqe_cnt++;
1928 qp->cqe_exp_seq_sn++; 2051 qp->cqe_exp_seq_sn++;
1929 if (qp->cqe_exp_seq_sn == (qp->cqe_size * 2 + 1)) 2052 if (qp->cqe_exp_seq_sn == (qp->cqe_size * 2 + 1))
1930 qp->cqe_exp_seq_sn = ISCSI_INITIAL_SN; 2053 qp->cqe_exp_seq_sn = ISCSI_INITIAL_SN;
@@ -1937,6 +2060,8 @@ cqe_out:
1937 qp->cq_cons_idx++; 2060 qp->cq_cons_idx++;
1938 } 2061 }
1939 } 2062 }
2063out:
2064 return cqe_cnt;
1940} 2065}
1941 2066
1942/** 2067/**
@@ -1952,6 +2077,7 @@ static void bnx2i_fastpath_notification(struct bnx2i_hba *hba,
1952{ 2077{
1953 struct bnx2i_conn *bnx2i_conn; 2078 struct bnx2i_conn *bnx2i_conn;
1954 u32 iscsi_cid; 2079 u32 iscsi_cid;
2080 int nxt_idx;
1955 2081
1956 iscsi_cid = new_cqe_kcqe->iscsi_conn_id; 2082 iscsi_cid = new_cqe_kcqe->iscsi_conn_id;
1957 bnx2i_conn = bnx2i_get_conn_from_id(hba, iscsi_cid); 2083 bnx2i_conn = bnx2i_get_conn_from_id(hba, iscsi_cid);
@@ -1964,9 +2090,12 @@ static void bnx2i_fastpath_notification(struct bnx2i_hba *hba,
1964 printk(KERN_ALERT "cid #%x - ep not bound\n", iscsi_cid); 2090 printk(KERN_ALERT "cid #%x - ep not bound\n", iscsi_cid);
1965 return; 2091 return;
1966 } 2092 }
2093
1967 bnx2i_process_new_cqes(bnx2i_conn); 2094 bnx2i_process_new_cqes(bnx2i_conn);
1968 bnx2i_arm_cq_event_coalescing(bnx2i_conn->ep, CNIC_ARM_CQE_FP); 2095 nxt_idx = bnx2i_arm_cq_event_coalescing(bnx2i_conn->ep,
1969 bnx2i_process_new_cqes(bnx2i_conn); 2096 CNIC_ARM_CQE_FP);
2097 if (nxt_idx && nxt_idx == bnx2i_process_new_cqes(bnx2i_conn))
2098 bnx2i_arm_cq_event_coalescing(bnx2i_conn->ep, CNIC_ARM_CQE_FP);
1970} 2099}
1971 2100
1972 2101
@@ -2312,7 +2441,7 @@ static void bnx2i_process_ofld_cmpl(struct bnx2i_hba *hba,
2312 printk(KERN_ALERT "bnx2i (%s): ofld1 cmpl - invalid " 2441 printk(KERN_ALERT "bnx2i (%s): ofld1 cmpl - invalid "
2313 "opcode\n", hba->netdev->name); 2442 "opcode\n", hba->netdev->name);
2314 else if (ofld_kcqe->completion_status == 2443 else if (ofld_kcqe->completion_status ==
2315 ISCSI_KCQE_COMPLETION_STATUS_CID_BUSY) 2444 ISCSI_KCQE_COMPLETION_STATUS_CID_BUSY)
2316 /* error status code valid only for 5771x chipset */ 2445 /* error status code valid only for 5771x chipset */
2317 ep->state = EP_STATE_OFLD_FAILED_CID_BUSY; 2446 ep->state = EP_STATE_OFLD_FAILED_CID_BUSY;
2318 else 2447 else
@@ -2511,7 +2640,7 @@ static void bnx2i_cm_remote_abort(struct cnic_sock *cm_sk)
2511 2640
2512 2641
2513static int bnx2i_send_nl_mesg(void *context, u32 msg_type, 2642static int bnx2i_send_nl_mesg(void *context, u32 msg_type,
2514 char *buf, u16 buflen) 2643 char *buf, u16 buflen)
2515{ 2644{
2516 struct bnx2i_hba *hba = context; 2645 struct bnx2i_hba *hba = context;
2517 int rc; 2646 int rc;
diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c
index 6adbdc34a9a5..0f7fb14c78ab 100644
--- a/drivers/scsi/bnx2i/bnx2i_init.c
+++ b/drivers/scsi/bnx2i/bnx2i_init.c
@@ -40,7 +40,7 @@ unsigned int event_coal_min = 24;
40module_param(event_coal_min, int, 0664); 40module_param(event_coal_min, int, 0664);
41MODULE_PARM_DESC(event_coal_min, "Event Coalescing Minimum Commands"); 41MODULE_PARM_DESC(event_coal_min, "Event Coalescing Minimum Commands");
42 42
43unsigned int event_coal_div = 1; 43unsigned int event_coal_div = 2;
44module_param(event_coal_div, int, 0664); 44module_param(event_coal_div, int, 0664);
45MODULE_PARM_DESC(event_coal_div, "Event Coalescing Divide Factor"); 45MODULE_PARM_DESC(event_coal_div, "Event Coalescing Divide Factor");
46 46
@@ -66,6 +66,15 @@ MODULE_PARM_DESC(rq_size, "Configure RQ size");
66 66
67u64 iscsi_error_mask = 0x00; 67u64 iscsi_error_mask = 0x00;
68 68
69DEFINE_PER_CPU(struct bnx2i_percpu_s, bnx2i_percpu);
70
71static int bnx2i_cpu_callback(struct notifier_block *nfb,
72 unsigned long action, void *hcpu);
73/* notification function for CPU hotplug events */
74static struct notifier_block bnx2i_cpu_notifier = {
75 .notifier_call = bnx2i_cpu_callback,
76};
77
69 78
70/** 79/**
71 * bnx2i_identify_device - identifies NetXtreme II device type 80 * bnx2i_identify_device - identifies NetXtreme II device type
@@ -362,6 +371,91 @@ void bnx2i_ulp_exit(struct cnic_dev *dev)
362 371
363 372
364/** 373/**
374 * bnx2i_percpu_thread_create - Create a receive thread for an
375 * online CPU
376 *
377 * @cpu: cpu index for the online cpu
378 */
379static void bnx2i_percpu_thread_create(unsigned int cpu)
380{
381 struct bnx2i_percpu_s *p;
382 struct task_struct *thread;
383
384 p = &per_cpu(bnx2i_percpu, cpu);
385
386 thread = kthread_create(bnx2i_percpu_io_thread, (void *)p,
387 "bnx2i_thread/%d", cpu);
388 /* bind thread to the cpu */
389 if (likely(!IS_ERR(thread))) {
390 kthread_bind(thread, cpu);
391 p->iothread = thread;
392 wake_up_process(thread);
393 }
394}
395
396
397static void bnx2i_percpu_thread_destroy(unsigned int cpu)
398{
399 struct bnx2i_percpu_s *p;
400 struct task_struct *thread;
401 struct bnx2i_work *work, *tmp;
402
403 /* Prevent any new work from being queued for this CPU */
404 p = &per_cpu(bnx2i_percpu, cpu);
405 spin_lock_bh(&p->p_work_lock);
406 thread = p->iothread;
407 p->iothread = NULL;
408
409 /* Free all work in the list */
410 list_for_each_entry_safe(work, tmp, &p->work_list, list) {
411 list_del_init(&work->list);
412 bnx2i_process_scsi_cmd_resp(work->session,
413 work->bnx2i_conn, &work->cqe);
414 kfree(work);
415 }
416
417 spin_unlock_bh(&p->p_work_lock);
418 if (thread)
419 kthread_stop(thread);
420}
421
422
423/**
424 * bnx2i_cpu_callback - Handler for CPU hotplug events
425 *
426 * @nfb: The callback data block
427 * @action: The event triggering the callback
428 * @hcpu: The index of the CPU that the event is for
429 *
430 * This creates or destroys per-CPU data for iSCSI
431 *
432 * Returns NOTIFY_OK always.
433 */
434static int bnx2i_cpu_callback(struct notifier_block *nfb,
435 unsigned long action, void *hcpu)
436{
437 unsigned cpu = (unsigned long)hcpu;
438
439 switch (action) {
440 case CPU_ONLINE:
441 case CPU_ONLINE_FROZEN:
442 printk(KERN_INFO "bnx2i: CPU %x online: Create Rx thread\n",
443 cpu);
444 bnx2i_percpu_thread_create(cpu);
445 break;
446 case CPU_DEAD:
447 case CPU_DEAD_FROZEN:
448 printk(KERN_INFO "CPU %x offline: Remove Rx thread\n", cpu);
449 bnx2i_percpu_thread_destroy(cpu);
450 break;
451 default:
452 break;
453 }
454 return NOTIFY_OK;
455}
456
457
458/**
365 * bnx2i_mod_init - module init entry point 459 * bnx2i_mod_init - module init entry point
366 * 460 *
367 * initialize any driver wide global data structures such as endpoint pool, 461 * initialize any driver wide global data structures such as endpoint pool,
@@ -371,6 +465,8 @@ void bnx2i_ulp_exit(struct cnic_dev *dev)
371static int __init bnx2i_mod_init(void) 465static int __init bnx2i_mod_init(void)
372{ 466{
373 int err; 467 int err;
468 unsigned cpu = 0;
469 struct bnx2i_percpu_s *p;
374 470
375 printk(KERN_INFO "%s", version); 471 printk(KERN_INFO "%s", version);
376 472
@@ -393,6 +489,20 @@ static int __init bnx2i_mod_init(void)
393 goto unreg_xport; 489 goto unreg_xport;
394 } 490 }
395 491
492 /* Create percpu kernel threads to handle iSCSI I/O completions */
493 for_each_possible_cpu(cpu) {
494 p = &per_cpu(bnx2i_percpu, cpu);
495 INIT_LIST_HEAD(&p->work_list);
496 spin_lock_init(&p->p_work_lock);
497 p->iothread = NULL;
498 }
499
500 for_each_online_cpu(cpu)
501 bnx2i_percpu_thread_create(cpu);
502
503 /* Initialize per CPU interrupt thread */
504 register_hotcpu_notifier(&bnx2i_cpu_notifier);
505
396 return 0; 506 return 0;
397 507
398unreg_xport: 508unreg_xport:
@@ -413,6 +523,7 @@ out:
413static void __exit bnx2i_mod_exit(void) 523static void __exit bnx2i_mod_exit(void)
414{ 524{
415 struct bnx2i_hba *hba; 525 struct bnx2i_hba *hba;
526 unsigned cpu = 0;
416 527
417 mutex_lock(&bnx2i_dev_lock); 528 mutex_lock(&bnx2i_dev_lock);
418 while (!list_empty(&adapter_list)) { 529 while (!list_empty(&adapter_list)) {
@@ -430,6 +541,11 @@ static void __exit bnx2i_mod_exit(void)
430 } 541 }
431 mutex_unlock(&bnx2i_dev_lock); 542 mutex_unlock(&bnx2i_dev_lock);
432 543
544 unregister_hotcpu_notifier(&bnx2i_cpu_notifier);
545
546 for_each_online_cpu(cpu)
547 bnx2i_percpu_thread_destroy(cpu);
548
433 iscsi_unregister_transport(&bnx2i_iscsi_transport); 549 iscsi_unregister_transport(&bnx2i_iscsi_transport);
434 cnic_unregister_driver(CNIC_ULP_ISCSI); 550 cnic_unregister_driver(CNIC_ULP_ISCSI);
435} 551}
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
index 041928b23cb0..9d40f3279634 100644
--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
+++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
@@ -27,6 +27,7 @@ static struct scsi_host_template bnx2i_host_template;
27 */ 27 */
28static DEFINE_SPINLOCK(bnx2i_resc_lock); /* protects global resources */ 28static DEFINE_SPINLOCK(bnx2i_resc_lock); /* protects global resources */
29 29
30DECLARE_PER_CPU(struct bnx2i_percpu_s, bnx2i_percpu);
30 31
31static int bnx2i_adapter_ready(struct bnx2i_hba *hba) 32static int bnx2i_adapter_ready(struct bnx2i_hba *hba)
32{ 33{
@@ -1214,7 +1215,8 @@ static int bnx2i_task_xmit(struct iscsi_task *task)
1214 struct bnx2i_cmd *cmd = task->dd_data; 1215 struct bnx2i_cmd *cmd = task->dd_data;
1215 struct iscsi_cmd *hdr = (struct iscsi_cmd *) task->hdr; 1216 struct iscsi_cmd *hdr = (struct iscsi_cmd *) task->hdr;
1216 1217
1217 if (bnx2i_conn->ep->num_active_cmds + 1 > hba->max_sqes) 1218 if (atomic_read(&bnx2i_conn->ep->num_active_cmds) + 1 >
1219 hba->max_sqes)
1218 return -ENOMEM; 1220 return -ENOMEM;
1219 1221
1220 /* 1222 /*
@@ -1354,6 +1356,9 @@ bnx2i_conn_create(struct iscsi_cls_session *cls_session, uint32_t cid)
1354 bnx2i_conn = conn->dd_data; 1356 bnx2i_conn = conn->dd_data;
1355 bnx2i_conn->cls_conn = cls_conn; 1357 bnx2i_conn->cls_conn = cls_conn;
1356 bnx2i_conn->hba = hba; 1358 bnx2i_conn->hba = hba;
1359
1360 atomic_set(&bnx2i_conn->work_cnt, 0);
1361
1357 /* 'ep' ptr will be assigned in bind() call */ 1362 /* 'ep' ptr will be assigned in bind() call */
1358 bnx2i_conn->ep = NULL; 1363 bnx2i_conn->ep = NULL;
1359 init_completion(&bnx2i_conn->cmd_cleanup_cmpl); 1364 init_completion(&bnx2i_conn->cmd_cleanup_cmpl);
@@ -1457,11 +1462,34 @@ static void bnx2i_conn_destroy(struct iscsi_cls_conn *cls_conn)
1457 struct bnx2i_conn *bnx2i_conn = conn->dd_data; 1462 struct bnx2i_conn *bnx2i_conn = conn->dd_data;
1458 struct Scsi_Host *shost; 1463 struct Scsi_Host *shost;
1459 struct bnx2i_hba *hba; 1464 struct bnx2i_hba *hba;
1465 struct bnx2i_work *work, *tmp;
1466 unsigned cpu = 0;
1467 struct bnx2i_percpu_s *p;
1460 1468
1461 shost = iscsi_session_to_shost(iscsi_conn_to_session(cls_conn)); 1469 shost = iscsi_session_to_shost(iscsi_conn_to_session(cls_conn));
1462 hba = iscsi_host_priv(shost); 1470 hba = iscsi_host_priv(shost);
1463 1471
1464 bnx2i_conn_free_login_resources(hba, bnx2i_conn); 1472 bnx2i_conn_free_login_resources(hba, bnx2i_conn);
1473
1474 if (atomic_read(&bnx2i_conn->work_cnt)) {
1475 for_each_online_cpu(cpu) {
1476 p = &per_cpu(bnx2i_percpu, cpu);
1477 spin_lock_bh(&p->p_work_lock);
1478 list_for_each_entry_safe(work, tmp,
1479 &p->work_list, list) {
1480 if (work->session == conn->session &&
1481 work->bnx2i_conn == bnx2i_conn) {
1482 list_del_init(&work->list);
1483 kfree(work);
1484 if (!atomic_dec_and_test(
1485 &bnx2i_conn->work_cnt))
1486 break;
1487 }
1488 }
1489 spin_unlock_bh(&p->p_work_lock);
1490 }
1491 }
1492
1465 iscsi_conn_teardown(cls_conn); 1493 iscsi_conn_teardown(cls_conn);
1466} 1494}
1467 1495
@@ -1769,7 +1797,7 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost,
1769 } 1797 }
1770 bnx2i_ep = ep->dd_data; 1798 bnx2i_ep = ep->dd_data;
1771 1799
1772 bnx2i_ep->num_active_cmds = 0; 1800 atomic_set(&bnx2i_ep->num_active_cmds, 0);
1773 iscsi_cid = bnx2i_alloc_iscsi_cid(hba); 1801 iscsi_cid = bnx2i_alloc_iscsi_cid(hba);
1774 if (iscsi_cid == -1) { 1802 if (iscsi_cid == -1) {
1775 printk(KERN_ALERT "bnx2i (%s): alloc_ep - unable to allocate " 1803 printk(KERN_ALERT "bnx2i (%s): alloc_ep - unable to allocate "
@@ -2163,9 +2191,9 @@ static struct scsi_host_template bnx2i_host_template = {
2163 .eh_device_reset_handler = iscsi_eh_device_reset, 2191 .eh_device_reset_handler = iscsi_eh_device_reset,
2164 .eh_target_reset_handler = iscsi_eh_recover_target, 2192 .eh_target_reset_handler = iscsi_eh_recover_target,
2165 .change_queue_depth = iscsi_change_queue_depth, 2193 .change_queue_depth = iscsi_change_queue_depth,
2166 .can_queue = 1024, 2194 .can_queue = 2048,
2167 .max_sectors = 127, 2195 .max_sectors = 127,
2168 .cmd_per_lun = 24, 2196 .cmd_per_lun = 128,
2169 .this_id = -1, 2197 .this_id = -1,
2170 .use_clustering = ENABLE_CLUSTERING, 2198 .use_clustering = ENABLE_CLUSTERING,
2171 .sg_tablesize = ISCSI_MAX_BDS_PER_CMD, 2199 .sg_tablesize = ISCSI_MAX_BDS_PER_CMD,