aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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,