diff options
Diffstat (limited to 'drivers/scsi/bnx2i/bnx2i_iscsi.c')
-rw-r--r-- | drivers/scsi/bnx2i/bnx2i_iscsi.c | 38 |
1 files changed, 33 insertions, 5 deletions
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 | */ |
28 | static DEFINE_SPINLOCK(bnx2i_resc_lock); /* protects global resources */ | 28 | static DEFINE_SPINLOCK(bnx2i_resc_lock); /* protects global resources */ |
29 | 29 | ||
30 | DECLARE_PER_CPU(struct bnx2i_percpu_s, bnx2i_percpu); | ||
30 | 31 | ||
31 | static int bnx2i_adapter_ready(struct bnx2i_hba *hba) | 32 | static 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, |