summaryrefslogtreecommitdiff
path: root/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-04-07 00:24:49 +0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-07 00:24:49 +0400
commit22eb5aa6c7940861f9603581665b9d9a1c60be30 (patch)
tree22890bcebae5647bcc1a29e7b544a1c5de2b1f8b /drivers/scsi/cxgb3i/cxgb3i_iscsi.c
parentd7ca6f8cdffa5765e486edb3dada9121fba8e6aa (diff)
parent015640edb1f346e0b2eda703587c4cd1c310ec1d (diff)
downloadlinux-22eb5aa6c7940861f9603581665b9d9a1c60be30.tar.xz
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: (74 commits) [SCSI] sg: fix q->queue_lock on scsi_error_handler path [SCSI] replace __inline with inline [SCSI] a2091: make 2 functions static [SCSI] a3000: make 2 functions static [SCSI] ses: #if 0 the unused ses_match_host() [SCSI] use kmem_cache_zalloc instead of kmem_cache_alloc/memset [SCSI] sg: fix iovec bugs introduced by the block layer conversion [SCSI] qlogicpti: use request_firmware [SCSI] advansys: use request_firmware [SCSI] qla1280: use request_firmware [SCSI] libiscsi: fix iscsi pool error path [SCSI] cxgb3i: call ddp release function directly [SCSI] cxgb3i: merge cxgb3i_ddp into cxgb3i module [SCSI] cxgb3i: close all tcp connections upon chip reset [SCSI] cxgb3i: re-read ddp settings information after chip reset [SCSI] cxgb3i: re-initialize ddp settings after chip reset [SCSI] cxgb3i: subscribe to error notification from cxgb3 driver [SCSI] aacraid driver update [SCSI] mptsas: remove unneeded check [SCSI] config: Make need for SCSI_CDROM clearer ...
Diffstat (limited to 'drivers/scsi/cxgb3i/cxgb3i_iscsi.c')
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_iscsi.c129
1 files changed, 86 insertions, 43 deletions
diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
index e185dedc4c1f..fff8e4327644 100644
--- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
+++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
@@ -53,36 +53,52 @@ static LIST_HEAD(cxgb3i_snic_list);
static DEFINE_RWLOCK(cxgb3i_snic_rwlock);
/**
- * cxgb3i_adapter_add - init a s3 adapter structure and any h/w settings
- * @t3dev: t3cdev adapter
- * return the resulting cxgb3i_adapter struct
+ * cxgb3i_adpater_find_by_tdev - find the cxgb3i_adapter structure via t3cdev
+ * @tdev: t3cdev pointer
*/
-struct cxgb3i_adapter *cxgb3i_adapter_add(struct t3cdev *t3dev)
+struct cxgb3i_adapter *cxgb3i_adapter_find_by_tdev(struct t3cdev *tdev)
{
struct cxgb3i_adapter *snic;
- struct adapter *adapter = tdev2adap(t3dev);
- int i;
- snic = kzalloc(sizeof(*snic), GFP_KERNEL);
- if (!snic) {
- cxgb3i_api_debug("cxgb3 %s, OOM.\n", t3dev->name);
- return NULL;
+ read_lock(&cxgb3i_snic_rwlock);
+ list_for_each_entry(snic, &cxgb3i_snic_list, list_head) {
+ if (snic->tdev == tdev) {
+ read_unlock(&cxgb3i_snic_rwlock);
+ return snic;
+ }
}
- spin_lock_init(&snic->lock);
+ read_unlock(&cxgb3i_snic_rwlock);
+ return NULL;
+}
+
+static inline int adapter_update(struct cxgb3i_adapter *snic)
+{
+ cxgb3i_log_info("snic 0x%p, t3dev 0x%p, updating.\n",
+ snic, snic->tdev);
+ return cxgb3i_adapter_ddp_info(snic->tdev, &snic->tag_format,
+ &snic->tx_max_size,
+ &snic->rx_max_size);
+}
+
+static int adapter_add(struct cxgb3i_adapter *snic)
+{
+ struct t3cdev *t3dev = snic->tdev;
+ struct adapter *adapter = tdev2adap(t3dev);
+ int i, err;
- snic->tdev = t3dev;
snic->pdev = adapter->pdev;
snic->tag_format.sw_bits = sw_tag_idx_bits + sw_tag_age_bits;
- if (cxgb3i_adapter_ddp_init(t3dev, &snic->tag_format,
+ err = cxgb3i_adapter_ddp_info(t3dev, &snic->tag_format,
&snic->tx_max_size,
- &snic->rx_max_size) < 0)
- goto free_snic;
+ &snic->rx_max_size);
+ if (err < 0)
+ return err;
for_each_port(adapter, i) {
snic->hba[i] = cxgb3i_hba_host_add(snic, adapter->port[i]);
if (!snic->hba[i])
- goto ulp_cleanup;
+ return -EINVAL;
}
snic->hba_cnt = adapter->params.nports;
@@ -91,46 +107,71 @@ struct cxgb3i_adapter *cxgb3i_adapter_add(struct t3cdev *t3dev)
list_add_tail(&snic->list_head, &cxgb3i_snic_list);
write_unlock(&cxgb3i_snic_rwlock);
- return snic;
+ cxgb3i_log_info("t3dev 0x%p open, snic 0x%p, %u scsi hosts added.\n",
+ t3dev, snic, snic->hba_cnt);
+ return 0;
+}
-ulp_cleanup:
- cxgb3i_adapter_ddp_cleanup(t3dev);
-free_snic:
- kfree(snic);
- return NULL;
+/**
+ * cxgb3i_adapter_open - init a s3 adapter structure and any h/w settings
+ * @t3dev: t3cdev adapter
+ */
+void cxgb3i_adapter_open(struct t3cdev *t3dev)
+{
+ struct cxgb3i_adapter *snic = cxgb3i_adapter_find_by_tdev(t3dev);
+ int err;
+
+ if (snic)
+ err = adapter_update(snic);
+ else {
+ snic = kzalloc(sizeof(*snic), GFP_KERNEL);
+ if (snic) {
+ spin_lock_init(&snic->lock);
+ snic->tdev = t3dev;
+ err = adapter_add(snic);
+ } else
+ err = -ENOMEM;
+ }
+
+ if (err < 0) {
+ cxgb3i_log_info("snic 0x%p, f 0x%x, t3dev 0x%p open, err %d.\n",
+ snic, snic ? snic->flags : 0, t3dev, err);
+ if (snic) {
+ snic->flags &= ~CXGB3I_ADAPTER_FLAG_RESET;
+ cxgb3i_adapter_close(t3dev);
+ }
+ }
}
/**
- * cxgb3i_adapter_remove - release the resources held and cleanup h/w settings
+ * cxgb3i_adapter_close - release the resources held and cleanup h/w settings
* @t3dev: t3cdev adapter
*/
-void cxgb3i_adapter_remove(struct t3cdev *t3dev)
+void cxgb3i_adapter_close(struct t3cdev *t3dev)
{
+ struct cxgb3i_adapter *snic = cxgb3i_adapter_find_by_tdev(t3dev);
int i;
- struct cxgb3i_adapter *snic;
+
+ if (!snic || snic->flags & CXGB3I_ADAPTER_FLAG_RESET) {
+ cxgb3i_log_info("t3dev 0x%p close, snic 0x%p, f 0x%x.\n",
+ t3dev, snic, snic ? snic->flags : 0);
+ return;
+ }
/* remove from the list */
write_lock(&cxgb3i_snic_rwlock);
- list_for_each_entry(snic, &cxgb3i_snic_list, list_head) {
- if (snic->tdev == t3dev) {
- list_del(&snic->list_head);
- break;
- }
- }
+ list_del(&snic->list_head);
write_unlock(&cxgb3i_snic_rwlock);
- if (snic) {
- for (i = 0; i < snic->hba_cnt; i++) {
- if (snic->hba[i]) {
- cxgb3i_hba_host_remove(snic->hba[i]);
- snic->hba[i] = NULL;
- }
+ for (i = 0; i < snic->hba_cnt; i++) {
+ if (snic->hba[i]) {
+ cxgb3i_hba_host_remove(snic->hba[i]);
+ snic->hba[i] = NULL;
}
-
- /* release ddp resources */
- cxgb3i_adapter_ddp_cleanup(snic->tdev);
- kfree(snic);
}
+ cxgb3i_log_info("t3dev 0x%p close, snic 0x%p, %u scsi hosts removed.\n",
+ t3dev, snic, snic->hba_cnt);
+ kfree(snic);
}
/**
@@ -170,7 +211,8 @@ struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *snic,
shost = iscsi_host_alloc(&cxgb3i_host_template,
sizeof(struct cxgb3i_hba), 1);
if (!shost) {
- cxgb3i_log_info("iscsi_host_alloc failed.\n");
+ cxgb3i_log_info("snic 0x%p, ndev 0x%p, host_alloc failed.\n",
+ snic, ndev);
return NULL;
}
@@ -188,7 +230,8 @@ struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *snic,
pci_dev_get(snic->pdev);
err = iscsi_host_add(shost, &snic->pdev->dev);
if (err) {
- cxgb3i_log_info("iscsi_host_add failed.\n");
+ cxgb3i_log_info("snic 0x%p, ndev 0x%p, host_add failed.\n",
+ snic, ndev);
goto pci_dev_put;
}