Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target...
[pandora-kernel.git] / drivers / scsi / bnx2i / bnx2i_iscsi.c
index 97ff47c..cffd4d7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * bnx2i_iscsi.c: Broadcom NetXtreme II iSCSI driver.
  *
- * Copyright (c) 2006 - 2010 Broadcom Corporation
+ * Copyright (c) 2006 - 2011 Broadcom Corporation
  * Copyright (c) 2007, 2008 Red Hat, Inc.  All rights reserved.
  * Copyright (c) 2007, 2008 Mike Christie
  *
@@ -27,6 +27,7 @@ static struct scsi_host_template bnx2i_host_template;
  */
 static DEFINE_SPINLOCK(bnx2i_resc_lock); /* protects global resources */
 
+DECLARE_PER_CPU(struct bnx2i_percpu_s, bnx2i_percpu);
 
 static int bnx2i_adapter_ready(struct bnx2i_hba *hba)
 {
@@ -1214,7 +1215,8 @@ static int bnx2i_task_xmit(struct iscsi_task *task)
        struct bnx2i_cmd *cmd = task->dd_data;
        struct iscsi_scsi_req *hdr = (struct iscsi_scsi_req *)task->hdr;
 
-       if (bnx2i_conn->ep->num_active_cmds + 1 > hba->max_sqes)
+       if (atomic_read(&bnx2i_conn->ep->num_active_cmds) + 1  >
+           hba->max_sqes)
                return -ENOMEM;
 
        /*
@@ -1354,6 +1356,9 @@ bnx2i_conn_create(struct iscsi_cls_session *cls_session, uint32_t cid)
        bnx2i_conn = conn->dd_data;
        bnx2i_conn->cls_conn = cls_conn;
        bnx2i_conn->hba = hba;
+
+       atomic_set(&bnx2i_conn->work_cnt, 0);
+
        /* 'ep' ptr will be assigned in bind() call */
        bnx2i_conn->ep = NULL;
        init_completion(&bnx2i_conn->cmd_cleanup_cmpl);
@@ -1457,11 +1462,34 @@ static void bnx2i_conn_destroy(struct iscsi_cls_conn *cls_conn)
        struct bnx2i_conn *bnx2i_conn = conn->dd_data;
        struct Scsi_Host *shost;
        struct bnx2i_hba *hba;
+       struct bnx2i_work *work, *tmp;
+       unsigned cpu = 0;
+       struct bnx2i_percpu_s *p;
 
        shost = iscsi_session_to_shost(iscsi_conn_to_session(cls_conn));
        hba = iscsi_host_priv(shost);
 
        bnx2i_conn_free_login_resources(hba, bnx2i_conn);
+
+       if (atomic_read(&bnx2i_conn->work_cnt)) {
+               for_each_online_cpu(cpu) {
+                       p = &per_cpu(bnx2i_percpu, cpu);
+                       spin_lock_bh(&p->p_work_lock);
+                       list_for_each_entry_safe(work, tmp,
+                                                &p->work_list, list) {
+                               if (work->session == conn->session &&
+                                   work->bnx2i_conn == bnx2i_conn) {
+                                       list_del_init(&work->list);
+                                       kfree(work);
+                                       if (!atomic_dec_and_test(
+                                                       &bnx2i_conn->work_cnt))
+                                               break;
+                               }
+                       }
+                       spin_unlock_bh(&p->p_work_lock);
+               }
+       }
+
        iscsi_conn_teardown(cls_conn);
 }
 
@@ -1769,7 +1797,7 @@ static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost,
        }
        bnx2i_ep = ep->dd_data;
 
-       bnx2i_ep->num_active_cmds = 0;
+       atomic_set(&bnx2i_ep->num_active_cmds, 0);
        iscsi_cid = bnx2i_alloc_iscsi_cid(hba);
        if (iscsi_cid == -1) {
                printk(KERN_ALERT "bnx2i (%s): alloc_ep - unable to allocate "
@@ -2163,9 +2191,9 @@ static struct scsi_host_template bnx2i_host_template = {
        .eh_device_reset_handler = iscsi_eh_device_reset,
        .eh_target_reset_handler = iscsi_eh_recover_target,
        .change_queue_depth     = iscsi_change_queue_depth,
-       .can_queue              = 1024,
+       .can_queue              = 2048,
        .max_sectors            = 127,
-       .cmd_per_lun            = 24,
+       .cmd_per_lun            = 128,
        .this_id                = -1,
        .use_clustering         = ENABLE_CLUSTERING,
        .sg_tablesize           = ISCSI_MAX_BDS_PER_CMD,