aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/bnx2i
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-07-23 14:13:11 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-07-23 14:13:11 -0400
commitd4e06701b89286a306b31e20ec69a904fae374a1 (patch)
treef6adefd65b021ccddb7655109ea8b9ab4e714292 /drivers/scsi/bnx2i
parente4980371059ca4a81ccdcb4381c41af8869ca711 (diff)
parent87045b033a62777337ae4aa62834876da09b5fb5 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (77 commits) [SCSI] fix crash in scsi_dispatch_cmd() [SCSI] sr: check_events() ignore GET_EVENT when TUR says otherwise [SCSI] bnx2i: Fixed kernel panic due to illegal usage of sc->request->cpu [SCSI] bfa: Update the driver version to 3.0.2.1 [SCSI] bfa: Driver and BSG enhancements. [SCSI] bfa: Added support to query PHY. [SCSI] bfa: Added HBA diagnostics support. [SCSI] bfa: Added support for flash configuration [SCSI] bfa: Added support to obtain SFP info. [SCSI] bfa: Added support for CEE info and stats query. [SCSI] bfa: Extend BSG interface. [SCSI] bfa: FCS bug fixes. [SCSI] bfa: DMA memory allocation enhancement. [SCSI] bfa: Brocade-1860 Fabric Adapter vHBA support. [SCSI] bfa: Brocade-1860 Fabric Adapter PLL init fixes. [SCSI] bfa: Added Fabric Assigned Address(FAA) support [SCSI] bfa: IOC bug fixes. [SCSI] bfa: Enable ASIC block configuration and query. [SCSI] bnx2i: Updated copyright and bump version [SCSI] bnx2i: Modified to skip CNIC registration if iSCSI is not supported ... Fix up some trivial conflicts in: - drivers/scsi/bnx2fc/{bnx2fc.h,bnx2fc_fcoe.c}: Crazy broadcom version number conflicts - drivers/target/tcm_fc/tfc_cmd.c Just trivial cleanups done on adjacent lines
Diffstat (limited to 'drivers/scsi/bnx2i')
-rw-r--r--drivers/scsi/bnx2i/57xx_iscsi_constants.h2
-rw-r--r--drivers/scsi/bnx2i/57xx_iscsi_hsi.h2
-rw-r--r--drivers/scsi/bnx2i/bnx2i.h33
-rw-r--r--drivers/scsi/bnx2i/bnx2i_hwi.c199
-rw-r--r--drivers/scsi/bnx2i/bnx2i_init.c153
-rw-r--r--drivers/scsi/bnx2i/bnx2i_iscsi.c38
-rw-r--r--drivers/scsi/bnx2i/bnx2i_sysfs.c2
7 files changed, 367 insertions, 62 deletions
diff --git a/drivers/scsi/bnx2i/57xx_iscsi_constants.h b/drivers/scsi/bnx2i/57xx_iscsi_constants.h
index 15673cc786ff..57515f1f1690 100644
--- a/drivers/scsi/bnx2i/57xx_iscsi_constants.h
+++ b/drivers/scsi/bnx2i/57xx_iscsi_constants.h
@@ -1,6 +1,6 @@
1/* 57xx_iscsi_constants.h: Broadcom NetXtreme II iSCSI HSI 1/* 57xx_iscsi_constants.h: Broadcom NetXtreme II iSCSI HSI
2 * 2 *
3 * Copyright (c) 2006 - 2010 Broadcom Corporation 3 * Copyright (c) 2006 - 2011 Broadcom Corporation
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 6 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/scsi/bnx2i/57xx_iscsi_hsi.h b/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
index 71890a063cd3..72118db89a20 100644
--- a/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
+++ b/drivers/scsi/bnx2i/57xx_iscsi_hsi.h
@@ -1,6 +1,6 @@
1/* 57xx_iscsi_hsi.h: Broadcom NetXtreme II iSCSI HSI. 1/* 57xx_iscsi_hsi.h: Broadcom NetXtreme II iSCSI HSI.
2 * 2 *
3 * Copyright (c) 2006 - 2010 Broadcom Corporation 3 * Copyright (c) 2006 - 2011 Broadcom Corporation
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 6 * it under the terms of the GNU General Public License as published by
diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h
index e7cb7ecf6847..dc5700765db4 100644
--- a/drivers/scsi/bnx2i/bnx2i.h
+++ b/drivers/scsi/bnx2i/bnx2i.h
@@ -1,6 +1,6 @@
1/* bnx2i.h: Broadcom NetXtreme II iSCSI driver. 1/* bnx2i.h: Broadcom NetXtreme II iSCSI driver.
2 * 2 *
3 * Copyright (c) 2006 - 2010 Broadcom Corporation 3 * Copyright (c) 2006 - 2011 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 *
@@ -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 372d30c099cc..030a96c646c3 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 - 2010 Broadcom Corporation 3 * Copyright (c) 2006 - 2011 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 *
@@ -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;
@@ -430,7 +434,7 @@ int bnx2i_send_iscsi_tmf(struct bnx2i_conn *bnx2i_conn,
430 default: 434 default:
431 tmfabort_wqe->ref_itt = RESERVED_ITT; 435 tmfabort_wqe->ref_itt = RESERVED_ITT;
432 } 436 }
433 memcpy(scsi_lun, tmfabort_hdr->lun, sizeof(struct scsi_lun)); 437 memcpy(scsi_lun, &tmfabort_hdr->lun, sizeof(struct scsi_lun));
434 tmfabort_wqe->lun[0] = be32_to_cpu(scsi_lun[0]); 438 tmfabort_wqe->lun[0] = be32_to_cpu(scsi_lun[0]);
435 tmfabort_wqe->lun[1] = be32_to_cpu(scsi_lun[1]); 439 tmfabort_wqe->lun[1] = be32_to_cpu(scsi_lun[1]);
436 440
@@ -547,7 +551,7 @@ int bnx2i_send_iscsi_nopout(struct bnx2i_conn *bnx2i_conn,
547 551
548 nopout_wqe->op_code = nopout_hdr->opcode; 552 nopout_wqe->op_code = nopout_hdr->opcode;
549 nopout_wqe->op_attr = ISCSI_FLAG_CMD_FINAL; 553 nopout_wqe->op_attr = ISCSI_FLAG_CMD_FINAL;
550 memcpy(nopout_wqe->lun, nopout_hdr->lun, 8); 554 memcpy(nopout_wqe->lun, &nopout_hdr->lun, 8);
551 555
552 if (test_bit(BNX2I_NX2_DEV_57710, &ep->hba->cnic_dev_type)) { 556 if (test_bit(BNX2I_NX2_DEV_57710, &ep->hba->cnic_dev_type)) {
553 u32 tmp = nopout_wqe->lun[0]; 557 u32 tmp = nopout_wqe->lun[0];
@@ -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
@@ -1711,7 +1716,7 @@ static int bnx2i_process_nopin_mesg(struct iscsi_session *session,
1711 hdr->flags = ISCSI_FLAG_CMD_FINAL; 1716 hdr->flags = ISCSI_FLAG_CMD_FINAL;
1712 hdr->itt = task->hdr->itt; 1717 hdr->itt = task->hdr->itt;
1713 hdr->ttt = cpu_to_be32(nop_in->ttt); 1718 hdr->ttt = cpu_to_be32(nop_in->ttt);
1714 memcpy(hdr->lun, nop_in->lun, 8); 1719 memcpy(&hdr->lun, nop_in->lun, 8);
1715 } 1720 }
1716done: 1721done:
1717 __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0); 1722 __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0);
@@ -1754,7 +1759,7 @@ static void bnx2i_process_async_mesg(struct iscsi_session *session,
1754 resp_hdr->opcode = async_cqe->op_code; 1759 resp_hdr->opcode = async_cqe->op_code;
1755 resp_hdr->flags = 0x80; 1760 resp_hdr->flags = 0x80;
1756 1761
1757 memcpy(resp_hdr->lun, async_cqe->lun, 8); 1762 memcpy(&resp_hdr->lun, async_cqe->lun, 8);
1758 resp_hdr->exp_cmdsn = cpu_to_be32(async_cqe->exp_cmd_sn); 1763 resp_hdr->exp_cmdsn = cpu_to_be32(async_cqe->exp_cmd_sn);
1759 resp_hdr->max_cmdsn = cpu_to_be32(async_cqe->max_cmd_sn); 1764 resp_hdr->max_cmdsn = cpu_to_be32(async_cqe->max_cmd_sn);
1760 1765
@@ -1836,21 +1841,136 @@ 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 int cpu;
1905
1906 spin_lock(&session->lock);
1907 task = iscsi_itt_to_task(bnx2i_conn->cls_conn->dd_data,
1908 cqe->itt & ISCSI_CMD_RESPONSE_INDEX);
1909 if (!task) {
1910 spin_unlock(&session->lock);
1911 return -EINVAL;
1912 }
1913 sc = task->sc;
1914 spin_unlock(&session->lock);
1915
1916 if (!blk_rq_cpu_valid(sc->request))
1917 cpu = smp_processor_id();
1918 else
1919 cpu = sc->request->cpu;
1920
1921 p = &per_cpu(bnx2i_percpu, cpu);
1922 spin_lock(&p->p_work_lock);
1923 if (unlikely(!p->iothread)) {
1924 rc = -EINVAL;
1925 goto err;
1926 }
1927 /* Alloc and copy to the cqe */
1928 bnx2i_work = kzalloc(sizeof(struct bnx2i_work), GFP_ATOMIC);
1929 if (bnx2i_work) {
1930 INIT_LIST_HEAD(&bnx2i_work->list);
1931 bnx2i_work->session = session;
1932 bnx2i_work->bnx2i_conn = bnx2i_conn;
1933 memcpy(&bnx2i_work->cqe, cqe, sizeof(struct cqe));
1934 list_add_tail(&bnx2i_work->list, &p->work_list);
1935 atomic_inc(&bnx2i_conn->work_cnt);
1936 wake_up_process(p->iothread);
1937 spin_unlock(&p->p_work_lock);
1938 goto done;
1939 } else
1940 rc = -ENOMEM;
1941err:
1942 spin_unlock(&p->p_work_lock);
1943 bnx2i_process_scsi_cmd_resp(session, bnx2i_conn, (struct cqe *)cqe);
1944done:
1945 return rc;
1946}
1947
1839 1948
1840/** 1949/**
1841 * bnx2i_process_new_cqes - process newly DMA'ed CQE's 1950 * bnx2i_process_new_cqes - process newly DMA'ed CQE's
1842 * @bnx2i_conn: iscsi connection 1951 * @bnx2i_conn: bnx2i connection
1843 * 1952 *
1844 * this function is called by generic KCQ handler to process all pending CQE's 1953 * this function is called by generic KCQ handler to process all pending CQE's
1845 */ 1954 */
1846static void bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn) 1955static int bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn)
1847{ 1956{
1848 struct iscsi_conn *conn = bnx2i_conn->cls_conn->dd_data; 1957 struct iscsi_conn *conn = bnx2i_conn->cls_conn->dd_data;
1849 struct iscsi_session *session = conn->session; 1958 struct iscsi_session *session = conn->session;
1850 struct qp_info *qp = &bnx2i_conn->ep->qp; 1959 struct qp_info *qp;
1851 struct bnx2i_nop_in_msg *nopin; 1960 struct bnx2i_nop_in_msg *nopin;
1852 int tgt_async_msg; 1961 int tgt_async_msg;
1962 int cqe_cnt = 0;
1853 1963
1964 if (bnx2i_conn->ep == NULL)
1965 return 0;
1966
1967 qp = &bnx2i_conn->ep->qp;
1968
1969 if (!qp->cq_virt) {
1970 printk(KERN_ALERT "bnx2i (%s): cq resr freed in bh execution!",
1971 bnx2i_conn->hba->netdev->name);
1972 goto out;
1973 }
1854 while (1) { 1974 while (1) {
1855 nopin = (struct bnx2i_nop_in_msg *) qp->cq_cons_qe; 1975 nopin = (struct bnx2i_nop_in_msg *) qp->cq_cons_qe;
1856 if (nopin->cq_req_sn != qp->cqe_exp_seq_sn) 1976 if (nopin->cq_req_sn != qp->cqe_exp_seq_sn)
@@ -1873,8 +1993,9 @@ static void bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn)
1873 switch (nopin->op_code) { 1993 switch (nopin->op_code) {
1874 case ISCSI_OP_SCSI_CMD_RSP: 1994 case ISCSI_OP_SCSI_CMD_RSP:
1875 case ISCSI_OP_SCSI_DATA_IN: 1995 case ISCSI_OP_SCSI_DATA_IN:
1876 bnx2i_process_scsi_cmd_resp(session, bnx2i_conn, 1996 /* Run the kthread engine only for data cmds
1877 qp->cq_cons_qe); 1997 All other cmds will be completed in this bh! */
1998 bnx2i_queue_scsi_cmd_resp(session, bnx2i_conn, nopin);
1878 break; 1999 break;
1879 case ISCSI_OP_LOGIN_RSP: 2000 case ISCSI_OP_LOGIN_RSP:
1880 bnx2i_process_login_resp(session, bnx2i_conn, 2001 bnx2i_process_login_resp(session, bnx2i_conn,
@@ -1918,13 +2039,21 @@ static void bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn)
1918 printk(KERN_ALERT "bnx2i: unknown opcode 0x%x\n", 2039 printk(KERN_ALERT "bnx2i: unknown opcode 0x%x\n",
1919 nopin->op_code); 2040 nopin->op_code);
1920 } 2041 }
1921 if (!tgt_async_msg) 2042 if (!tgt_async_msg) {
1922 bnx2i_conn->ep->num_active_cmds--; 2043 if (!atomic_read(&bnx2i_conn->ep->num_active_cmds))
2044 printk(KERN_ALERT "bnx2i (%s): no active cmd! "
2045 "op 0x%x\n",
2046 bnx2i_conn->hba->netdev->name,
2047 nopin->op_code);
2048 else
2049 atomic_dec(&bnx2i_conn->ep->num_active_cmds);
2050 }
1923cqe_out: 2051cqe_out:
1924 /* clear out in production version only, till beta keep opcode 2052 /* clear out in production version only, till beta keep opcode
1925 * field intact, will be helpful in debugging (context dump) 2053 * field intact, will be helpful in debugging (context dump)
1926 * nopin->op_code = 0; 2054 * nopin->op_code = 0;
1927 */ 2055 */
2056 cqe_cnt++;
1928 qp->cqe_exp_seq_sn++; 2057 qp->cqe_exp_seq_sn++;
1929 if (qp->cqe_exp_seq_sn == (qp->cqe_size * 2 + 1)) 2058 if (qp->cqe_exp_seq_sn == (qp->cqe_size * 2 + 1))
1930 qp->cqe_exp_seq_sn = ISCSI_INITIAL_SN; 2059 qp->cqe_exp_seq_sn = ISCSI_INITIAL_SN;
@@ -1937,6 +2066,8 @@ cqe_out:
1937 qp->cq_cons_idx++; 2066 qp->cq_cons_idx++;
1938 } 2067 }
1939 } 2068 }
2069out:
2070 return cqe_cnt;
1940} 2071}
1941 2072
1942/** 2073/**
@@ -1952,6 +2083,7 @@ static void bnx2i_fastpath_notification(struct bnx2i_hba *hba,
1952{ 2083{
1953 struct bnx2i_conn *bnx2i_conn; 2084 struct bnx2i_conn *bnx2i_conn;
1954 u32 iscsi_cid; 2085 u32 iscsi_cid;
2086 int nxt_idx;
1955 2087
1956 iscsi_cid = new_cqe_kcqe->iscsi_conn_id; 2088 iscsi_cid = new_cqe_kcqe->iscsi_conn_id;
1957 bnx2i_conn = bnx2i_get_conn_from_id(hba, iscsi_cid); 2089 bnx2i_conn = bnx2i_get_conn_from_id(hba, iscsi_cid);
@@ -1964,9 +2096,12 @@ static void bnx2i_fastpath_notification(struct bnx2i_hba *hba,
1964 printk(KERN_ALERT "cid #%x - ep not bound\n", iscsi_cid); 2096 printk(KERN_ALERT "cid #%x - ep not bound\n", iscsi_cid);
1965 return; 2097 return;
1966 } 2098 }
2099
1967 bnx2i_process_new_cqes(bnx2i_conn); 2100 bnx2i_process_new_cqes(bnx2i_conn);
1968 bnx2i_arm_cq_event_coalescing(bnx2i_conn->ep, CNIC_ARM_CQE_FP); 2101 nxt_idx = bnx2i_arm_cq_event_coalescing(bnx2i_conn->ep,
1969 bnx2i_process_new_cqes(bnx2i_conn); 2102 CNIC_ARM_CQE_FP);
2103 if (nxt_idx && nxt_idx == bnx2i_process_new_cqes(bnx2i_conn))
2104 bnx2i_arm_cq_event_coalescing(bnx2i_conn->ep, CNIC_ARM_CQE_FP);
1970} 2105}
1971 2106
1972 2107
@@ -2312,7 +2447,7 @@ static void bnx2i_process_ofld_cmpl(struct bnx2i_hba *hba,
2312 printk(KERN_ALERT "bnx2i (%s): ofld1 cmpl - invalid " 2447 printk(KERN_ALERT "bnx2i (%s): ofld1 cmpl - invalid "
2313 "opcode\n", hba->netdev->name); 2448 "opcode\n", hba->netdev->name);
2314 else if (ofld_kcqe->completion_status == 2449 else if (ofld_kcqe->completion_status ==
2315 ISCSI_KCQE_COMPLETION_STATUS_CID_BUSY) 2450 ISCSI_KCQE_COMPLETION_STATUS_CID_BUSY)
2316 /* error status code valid only for 5771x chipset */ 2451 /* error status code valid only for 5771x chipset */
2317 ep->state = EP_STATE_OFLD_FAILED_CID_BUSY; 2452 ep->state = EP_STATE_OFLD_FAILED_CID_BUSY;
2318 else 2453 else
@@ -2517,7 +2652,7 @@ static void bnx2i_cm_remote_abort(struct cnic_sock *cm_sk)
2517 2652
2518 2653
2519static int bnx2i_send_nl_mesg(void *context, u32 msg_type, 2654static int bnx2i_send_nl_mesg(void *context, u32 msg_type,
2520 char *buf, u16 buflen) 2655 char *buf, u16 buflen)
2521{ 2656{
2522 struct bnx2i_hba *hba = context; 2657 struct bnx2i_hba *hba = context;
2523 int rc; 2658 int rc;
diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c
index 6973413e91ec..1a947f1b9729 100644
--- a/drivers/scsi/bnx2i/bnx2i_init.c
+++ b/drivers/scsi/bnx2i/bnx2i_init.c
@@ -1,6 +1,6 @@
1/* bnx2i.c: Broadcom NetXtreme II iSCSI driver. 1/* bnx2i.c: Broadcom NetXtreme II iSCSI driver.
2 * 2 *
3 * Copyright (c) 2006 - 2010 Broadcom Corporation 3 * Copyright (c) 2006 - 2011 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 *
@@ -18,8 +18,8 @@ static struct list_head adapter_list = LIST_HEAD_INIT(adapter_list);
18static u32 adapter_count; 18static u32 adapter_count;
19 19
20#define DRV_MODULE_NAME "bnx2i" 20#define DRV_MODULE_NAME "bnx2i"
21#define DRV_MODULE_VERSION "2.6.2.3" 21#define DRV_MODULE_VERSION "2.7.0.3"
22#define DRV_MODULE_RELDATE "Dec 31, 2010" 22#define DRV_MODULE_RELDATE "Jun 15, 2011"
23 23
24static char version[] __devinitdata = 24static char version[] __devinitdata =
25 "Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \ 25 "Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \
@@ -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
@@ -172,21 +181,14 @@ void bnx2i_start(void *handle)
172 struct bnx2i_hba *hba = handle; 181 struct bnx2i_hba *hba = handle;
173 int i = HZ; 182 int i = HZ;
174 183
175 if (!hba->cnic->max_iscsi_conn) { 184 /*
176 printk(KERN_ALERT "bnx2i: dev %s does not support " 185 * We should never register devices that don't support iSCSI
177 "iSCSI\n", hba->netdev->name); 186 * (see bnx2i_init_one), so something is wrong if we try to
187 * start a iSCSI adapter on hardware with 0 supported iSCSI
188 * connections
189 */
190 BUG_ON(!hba->cnic->max_iscsi_conn);
178 191
179 if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) {
180 mutex_lock(&bnx2i_dev_lock);
181 list_del_init(&hba->link);
182 adapter_count--;
183 hba->cnic->unregister_device(hba->cnic, CNIC_ULP_ISCSI);
184 clear_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic);
185 mutex_unlock(&bnx2i_dev_lock);
186 bnx2i_free_hba(hba);
187 }
188 return;
189 }
190 bnx2i_send_fw_iscsi_init_msg(hba); 192 bnx2i_send_fw_iscsi_init_msg(hba);
191 while (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state) && i--) 193 while (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state) && i--)
192 msleep(BNX2I_INIT_POLL_TIME); 194 msleep(BNX2I_INIT_POLL_TIME);
@@ -290,6 +292,13 @@ static int bnx2i_init_one(struct bnx2i_hba *hba, struct cnic_dev *cnic)
290 int rc; 292 int rc;
291 293
292 mutex_lock(&bnx2i_dev_lock); 294 mutex_lock(&bnx2i_dev_lock);
295 if (!cnic->max_iscsi_conn) {
296 printk(KERN_ALERT "bnx2i: dev %s does not support "
297 "iSCSI\n", hba->netdev->name);
298 rc = -EOPNOTSUPP;
299 goto out;
300 }
301
293 hba->cnic = cnic; 302 hba->cnic = cnic;
294 rc = cnic->register_device(cnic, CNIC_ULP_ISCSI, hba); 303 rc = cnic->register_device(cnic, CNIC_ULP_ISCSI, hba);
295 if (!rc) { 304 if (!rc) {
@@ -307,6 +316,7 @@ static int bnx2i_init_one(struct bnx2i_hba *hba, struct cnic_dev *cnic)
307 else 316 else
308 printk(KERN_ERR "bnx2i dev reg, unknown error, %d\n", rc); 317 printk(KERN_ERR "bnx2i dev reg, unknown error, %d\n", rc);
309 318
319out:
310 mutex_unlock(&bnx2i_dev_lock); 320 mutex_unlock(&bnx2i_dev_lock);
311 321
312 return rc; 322 return rc;
@@ -371,6 +381,91 @@ void bnx2i_ulp_exit(struct cnic_dev *dev)
371 381
372 382
373/** 383/**
384 * bnx2i_percpu_thread_create - Create a receive thread for an
385 * online CPU
386 *
387 * @cpu: cpu index for the online cpu
388 */
389static void bnx2i_percpu_thread_create(unsigned int cpu)
390{
391 struct bnx2i_percpu_s *p;
392 struct task_struct *thread;
393
394 p = &per_cpu(bnx2i_percpu, cpu);
395
396 thread = kthread_create(bnx2i_percpu_io_thread, (void *)p,
397 "bnx2i_thread/%d", cpu);
398 /* bind thread to the cpu */
399 if (likely(!IS_ERR(thread))) {
400 kthread_bind(thread, cpu);
401 p->iothread = thread;
402 wake_up_process(thread);
403 }
404}
405
406
407static void bnx2i_percpu_thread_destroy(unsigned int cpu)
408{
409 struct bnx2i_percpu_s *p;
410 struct task_struct *thread;
411 struct bnx2i_work *work, *tmp;
412
413 /* Prevent any new work from being queued for this CPU */
414 p = &per_cpu(bnx2i_percpu, cpu);
415 spin_lock_bh(&p->p_work_lock);
416 thread = p->iothread;
417 p->iothread = NULL;
418
419 /* Free all work in the list */
420 list_for_each_entry_safe(work, tmp, &p->work_list, list) {
421 list_del_init(&work->list);
422 bnx2i_process_scsi_cmd_resp(work->session,
423 work->bnx2i_conn, &work->cqe);
424 kfree(work);
425 }
426
427 spin_unlock_bh(&p->p_work_lock);
428 if (thread)
429 kthread_stop(thread);
430}
431
432
433/**
434 * bnx2i_cpu_callback - Handler for CPU hotplug events
435 *
436 * @nfb: The callback data block
437 * @action: The event triggering the callback
438 * @hcpu: The index of the CPU that the event is for
439 *
440 * This creates or destroys per-CPU data for iSCSI
441 *
442 * Returns NOTIFY_OK always.
443 */
444static int bnx2i_cpu_callback(struct notifier_block *nfb,
445 unsigned long action, void *hcpu)
446{
447 unsigned cpu = (unsigned long)hcpu;
448
449 switch (action) {
450 case CPU_ONLINE:
451 case CPU_ONLINE_FROZEN:
452 printk(KERN_INFO "bnx2i: CPU %x online: Create Rx thread\n",
453 cpu);
454 bnx2i_percpu_thread_create(cpu);
455 break;
456 case CPU_DEAD:
457 case CPU_DEAD_FROZEN:
458 printk(KERN_INFO "CPU %x offline: Remove Rx thread\n", cpu);
459 bnx2i_percpu_thread_destroy(cpu);
460 break;
461 default:
462 break;
463 }
464 return NOTIFY_OK;
465}
466
467
468/**
374 * bnx2i_mod_init - module init entry point 469 * bnx2i_mod_init - module init entry point
375 * 470 *
376 * initialize any driver wide global data structures such as endpoint pool, 471 * initialize any driver wide global data structures such as endpoint pool,
@@ -380,6 +475,8 @@ void bnx2i_ulp_exit(struct cnic_dev *dev)
380static int __init bnx2i_mod_init(void) 475static int __init bnx2i_mod_init(void)
381{ 476{
382 int err; 477 int err;
478 unsigned cpu = 0;
479 struct bnx2i_percpu_s *p;
383 480
384 printk(KERN_INFO "%s", version); 481 printk(KERN_INFO "%s", version);
385 482
@@ -402,6 +499,20 @@ static int __init bnx2i_mod_init(void)
402 goto unreg_xport; 499 goto unreg_xport;
403 } 500 }
404 501
502 /* Create percpu kernel threads to handle iSCSI I/O completions */
503 for_each_possible_cpu(cpu) {
504 p = &per_cpu(bnx2i_percpu, cpu);
505 INIT_LIST_HEAD(&p->work_list);
506 spin_lock_init(&p->p_work_lock);
507 p->iothread = NULL;
508 }
509
510 for_each_online_cpu(cpu)
511 bnx2i_percpu_thread_create(cpu);
512
513 /* Initialize per CPU interrupt thread */
514 register_hotcpu_notifier(&bnx2i_cpu_notifier);
515
405 return 0; 516 return 0;
406 517
407unreg_xport: 518unreg_xport:
@@ -422,6 +533,7 @@ out:
422static void __exit bnx2i_mod_exit(void) 533static void __exit bnx2i_mod_exit(void)
423{ 534{
424 struct bnx2i_hba *hba; 535 struct bnx2i_hba *hba;
536 unsigned cpu = 0;
425 537
426 mutex_lock(&bnx2i_dev_lock); 538 mutex_lock(&bnx2i_dev_lock);
427 while (!list_empty(&adapter_list)) { 539 while (!list_empty(&adapter_list)) {
@@ -439,6 +551,11 @@ static void __exit bnx2i_mod_exit(void)
439 } 551 }
440 mutex_unlock(&bnx2i_dev_lock); 552 mutex_unlock(&bnx2i_dev_lock);
441 553
554 unregister_hotcpu_notifier(&bnx2i_cpu_notifier);
555
556 for_each_online_cpu(cpu)
557 bnx2i_percpu_thread_destroy(cpu);
558
442 iscsi_unregister_transport(&bnx2i_iscsi_transport); 559 iscsi_unregister_transport(&bnx2i_iscsi_transport);
443 cnic_unregister_driver(CNIC_ULP_ISCSI); 560 cnic_unregister_driver(CNIC_ULP_ISCSI);
444} 561}
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
index 041928b23cb0..5c55a75ae597 100644
--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
+++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * bnx2i_iscsi.c: Broadcom NetXtreme II iSCSI driver. 2 * bnx2i_iscsi.c: Broadcom NetXtreme II iSCSI driver.
3 * 3 *
4 * Copyright (c) 2006 - 2010 Broadcom Corporation 4 * Copyright (c) 2006 - 2011 Broadcom Corporation
5 * Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved. 5 * Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved.
6 * Copyright (c) 2007, 2008 Mike Christie 6 * Copyright (c) 2007, 2008 Mike Christie
7 * 7 *
@@ -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,
diff --git a/drivers/scsi/bnx2i/bnx2i_sysfs.c b/drivers/scsi/bnx2i/bnx2i_sysfs.c
index 9174196d9033..83a77f7244d2 100644
--- a/drivers/scsi/bnx2i/bnx2i_sysfs.c
+++ b/drivers/scsi/bnx2i/bnx2i_sysfs.c
@@ -1,6 +1,6 @@
1/* bnx2i_sysfs.c: Broadcom NetXtreme II iSCSI driver. 1/* bnx2i_sysfs.c: Broadcom NetXtreme II iSCSI driver.
2 * 2 *
3 * Copyright (c) 2004 - 2010 Broadcom Corporation 3 * Copyright (c) 2004 - 2011 Broadcom Corporation
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 6 * it under the terms of the GNU General Public License as published by