aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
diff options
context:
space:
mode:
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);
53static DEFINE_RWLOCK(cxgb3i_snic_rwlock); 53static DEFINE_RWLOCK(cxgb3i_snic_rwlock);
54 54
55/** 55/**
56 * cxgb3i_adapter_add - init a s3 adapter structure and any h/w settings 56 * cxgb3i_adpater_find_by_tdev - find the cxgb3i_adapter structure via t3cdev
57 * @t3dev: t3cdev adapter 57 * @tdev: t3cdev pointer
58 * return the resulting cxgb3i_adapter struct
59 */ 58 */
60struct cxgb3i_adapter *cxgb3i_adapter_add(struct t3cdev *t3dev) 59struct cxgb3i_adapter *cxgb3i_adapter_find_by_tdev(struct t3cdev *tdev)
61{ 60{
62 struct cxgb3i_adapter *snic; 61 struct cxgb3i_adapter *snic;
63 struct adapter *adapter = tdev2adap(t3dev);
64 int i;
65 62
66 snic = kzalloc(sizeof(*snic), GFP_KERNEL); 63 read_lock(&cxgb3i_snic_rwlock);
67 if (!snic) { 64 list_for_each_entry(snic, &cxgb3i_snic_list, list_head) {
68 cxgb3i_api_debug("cxgb3 %s, OOM.\n", t3dev->name); 65 if (snic->tdev == tdev) {
69 return NULL; 66 read_unlock(&cxgb3i_snic_rwlock);
67 return snic;
68 }
70 } 69 }
71 spin_lock_init(&snic->lock); 70 read_unlock(&cxgb3i_snic_rwlock);
71 return NULL;
72}
73
74static inline int adapter_update(struct cxgb3i_adapter *snic)
75{
76 cxgb3i_log_info("snic 0x%p, t3dev 0x%p, updating.\n",
77 snic, snic->tdev);
78 return cxgb3i_adapter_ddp_info(snic->tdev, &snic->tag_format,
79 &snic->tx_max_size,
80 &snic->rx_max_size);
81}
82
83static int adapter_add(struct cxgb3i_adapter *snic)
84{
85 struct t3cdev *t3dev = snic->tdev;
86 struct adapter *adapter = tdev2adap(t3dev);
87 int i, err;
72 88
73 snic->tdev = t3dev;
74 snic->pdev = adapter->pdev; 89 snic->pdev = adapter->pdev;
75 snic->tag_format.sw_bits = sw_tag_idx_bits + sw_tag_age_bits; 90 snic->tag_format.sw_bits = sw_tag_idx_bits + sw_tag_age_bits;
76 91
77 if (cxgb3i_adapter_ddp_init(t3dev, &snic->tag_format, 92 err = cxgb3i_adapter_ddp_info(t3dev, &snic->tag_format,
78 &snic->tx_max_size, 93 &snic->tx_max_size,
79 &snic->rx_max_size) < 0) 94 &snic->rx_max_size);
80 goto free_snic; 95 if (err < 0)
96 return err;
81 97
82 for_each_port(adapter, i) { 98 for_each_port(adapter, i) {
83 snic->hba[i] = cxgb3i_hba_host_add(snic, adapter->port[i]); 99 snic->hba[i] = cxgb3i_hba_host_add(snic, adapter->port[i]);
84 if (!snic->hba[i]) 100 if (!snic->hba[i])
85 goto ulp_cleanup; 101 return -EINVAL;
86 } 102 }
87 snic->hba_cnt = adapter->params.nports; 103 snic->hba_cnt = adapter->params.nports;
88 104
@@ -91,46 +107,71 @@ struct cxgb3i_adapter *cxgb3i_adapter_add(struct t3cdev *t3dev)
91 list_add_tail(&snic->list_head, &cxgb3i_snic_list); 107 list_add_tail(&snic->list_head, &cxgb3i_snic_list);
92 write_unlock(&cxgb3i_snic_rwlock); 108 write_unlock(&cxgb3i_snic_rwlock);
93 109
94 return snic; 110 cxgb3i_log_info("t3dev 0x%p open, snic 0x%p, %u scsi hosts added.\n",
111 t3dev, snic, snic->hba_cnt);
112 return 0;
113}
95 114
96ulp_cleanup: 115/**
97 cxgb3i_adapter_ddp_cleanup(t3dev); 116 * cxgb3i_adapter_open - init a s3 adapter structure and any h/w settings
98free_snic: 117 * @t3dev: t3cdev adapter
99 kfree(snic); 118 */
100 return NULL; 119void cxgb3i_adapter_open(struct t3cdev *t3dev)
120{
121 struct cxgb3i_adapter *snic = cxgb3i_adapter_find_by_tdev(t3dev);
122 int err;
123
124 if (snic)
125 err = adapter_update(snic);
126 else {
127 snic = kzalloc(sizeof(*snic), GFP_KERNEL);
128 if (snic) {
129 spin_lock_init(&snic->lock);
130 snic->tdev = t3dev;
131 err = adapter_add(snic);
132 } else
133 err = -ENOMEM;
134 }
135
136 if (err < 0) {
137 cxgb3i_log_info("snic 0x%p, f 0x%x, t3dev 0x%p open, err %d.\n",
138 snic, snic ? snic->flags : 0, t3dev, err);
139 if (snic) {
140 snic->flags &= ~CXGB3I_ADAPTER_FLAG_RESET;
141 cxgb3i_adapter_close(t3dev);
142 }
143 }
101} 144}
102 145
103/** 146/**
104 * cxgb3i_adapter_remove - release the resources held and cleanup h/w settings 147 * cxgb3i_adapter_close - release the resources held and cleanup h/w settings
105 * @t3dev: t3cdev adapter 148 * @t3dev: t3cdev adapter
106 */ 149 */
107void cxgb3i_adapter_remove(struct t3cdev *t3dev) 150void cxgb3i_adapter_close(struct t3cdev *t3dev)
108{ 151{
152 struct cxgb3i_adapter *snic = cxgb3i_adapter_find_by_tdev(t3dev);
109 int i; 153 int i;
110 struct cxgb3i_adapter *snic; 154
155 if (!snic || snic->flags & CXGB3I_ADAPTER_FLAG_RESET) {
156 cxgb3i_log_info("t3dev 0x%p close, snic 0x%p, f 0x%x.\n",
157 t3dev, snic, snic ? snic->flags : 0);
158 return;
159 }
111 160
112 /* remove from the list */ 161 /* remove from the list */
113 write_lock(&cxgb3i_snic_rwlock); 162 write_lock(&cxgb3i_snic_rwlock);
114 list_for_each_entry(snic, &cxgb3i_snic_list, list_head) { 163 list_del(&snic->list_head);
115 if (snic->tdev == t3dev) {
116 list_del(&snic->list_head);
117 break;
118 }
119 }
120 write_unlock(&cxgb3i_snic_rwlock); 164 write_unlock(&cxgb3i_snic_rwlock);
121 165
122 if (snic) { 166 for (i = 0; i < snic->hba_cnt; i++) {
123 for (i = 0; i < snic->hba_cnt; i++) { 167 if (snic->hba[i]) {
124 if (snic->hba[i]) { 168 cxgb3i_hba_host_remove(snic->hba[i]);
125 cxgb3i_hba_host_remove(snic->hba[i]); 169 snic->hba[i] = NULL;
126 snic->hba[i] = NULL;
127 }
128 } 170 }
129
130 /* release ddp resources */
131 cxgb3i_adapter_ddp_cleanup(snic->tdev);
132 kfree(snic);
133 } 171 }
172 cxgb3i_log_info("t3dev 0x%p close, snic 0x%p, %u scsi hosts removed.\n",
173 t3dev, snic, snic->hba_cnt);
174 kfree(snic);
134} 175}
135 176
136/** 177/**
@@ -170,7 +211,8 @@ struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *snic,
170 shost = iscsi_host_alloc(&cxgb3i_host_template, 211 shost = iscsi_host_alloc(&cxgb3i_host_template,
171 sizeof(struct cxgb3i_hba), 1); 212 sizeof(struct cxgb3i_hba), 1);
172 if (!shost) { 213 if (!shost) {
173 cxgb3i_log_info("iscsi_host_alloc failed.\n"); 214 cxgb3i_log_info("snic 0x%p, ndev 0x%p, host_alloc failed.\n",
215 snic, ndev);
174 return NULL; 216 return NULL;
175 } 217 }
176 218
@@ -188,7 +230,8 @@ struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *snic,
188 pci_dev_get(snic->pdev); 230 pci_dev_get(snic->pdev);
189 err = iscsi_host_add(shost, &snic->pdev->dev); 231 err = iscsi_host_add(shost, &snic->pdev->dev);
190 if (err) { 232 if (err) {
191 cxgb3i_log_info("iscsi_host_add failed.\n"); 233 cxgb3i_log_info("snic 0x%p, ndev 0x%p, host_add failed.\n",
234 snic, ndev);
192 goto pci_dev_put; 235 goto pci_dev_put;
193 } 236 }
194 237