diff options
Diffstat (limited to 'drivers/scsi/bnx2i/bnx2i_init.c')
-rw-r--r-- | drivers/scsi/bnx2i/bnx2i_init.c | 100 |
1 files changed, 44 insertions, 56 deletions
diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c index ae4b2d588fd3..0c4210d48ee8 100644 --- a/drivers/scsi/bnx2i/bnx2i_init.c +++ b/drivers/scsi/bnx2i/bnx2i_init.c | |||
@@ -15,11 +15,10 @@ | |||
15 | 15 | ||
16 | static struct list_head adapter_list = LIST_HEAD_INIT(adapter_list); | 16 | static struct list_head adapter_list = LIST_HEAD_INIT(adapter_list); |
17 | static u32 adapter_count; | 17 | static u32 adapter_count; |
18 | static int bnx2i_reg_device; | ||
19 | 18 | ||
20 | #define DRV_MODULE_NAME "bnx2i" | 19 | #define DRV_MODULE_NAME "bnx2i" |
21 | #define DRV_MODULE_VERSION "2.0.1d" | 20 | #define DRV_MODULE_VERSION "2.0.1e" |
22 | #define DRV_MODULE_RELDATE "Mar 25, 2009" | 21 | #define DRV_MODULE_RELDATE "June 22, 2009" |
23 | 22 | ||
24 | static char version[] __devinitdata = | 23 | static char version[] __devinitdata = |
25 | "Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \ | 24 | "Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \ |
@@ -31,7 +30,7 @@ MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709 iSCSI Driver"); | |||
31 | MODULE_LICENSE("GPL"); | 30 | MODULE_LICENSE("GPL"); |
32 | MODULE_VERSION(DRV_MODULE_VERSION); | 31 | MODULE_VERSION(DRV_MODULE_VERSION); |
33 | 32 | ||
34 | static DEFINE_RWLOCK(bnx2i_dev_lock); | 33 | static DEFINE_MUTEX(bnx2i_dev_lock); |
35 | 34 | ||
36 | unsigned int event_coal_div = 1; | 35 | unsigned int event_coal_div = 1; |
37 | module_param(event_coal_div, int, 0664); | 36 | module_param(event_coal_div, int, 0664); |
@@ -100,14 +99,14 @@ struct bnx2i_hba *get_adapter_list_head(void) | |||
100 | if (!adapter_count) | 99 | if (!adapter_count) |
101 | goto hba_not_found; | 100 | goto hba_not_found; |
102 | 101 | ||
103 | read_lock(&bnx2i_dev_lock); | 102 | mutex_lock(&bnx2i_dev_lock); |
104 | list_for_each_entry(tmp_hba, &adapter_list, link) { | 103 | list_for_each_entry(tmp_hba, &adapter_list, link) { |
105 | if (tmp_hba->cnic && tmp_hba->cnic->cm_select_dev) { | 104 | if (tmp_hba->cnic && tmp_hba->cnic->cm_select_dev) { |
106 | hba = tmp_hba; | 105 | hba = tmp_hba; |
107 | break; | 106 | break; |
108 | } | 107 | } |
109 | } | 108 | } |
110 | read_unlock(&bnx2i_dev_lock); | 109 | mutex_unlock(&bnx2i_dev_lock); |
111 | hba_not_found: | 110 | hba_not_found: |
112 | return hba; | 111 | return hba; |
113 | } | 112 | } |
@@ -122,14 +121,14 @@ struct bnx2i_hba *bnx2i_find_hba_for_cnic(struct cnic_dev *cnic) | |||
122 | { | 121 | { |
123 | struct bnx2i_hba *hba, *temp; | 122 | struct bnx2i_hba *hba, *temp; |
124 | 123 | ||
125 | read_lock(&bnx2i_dev_lock); | 124 | mutex_lock(&bnx2i_dev_lock); |
126 | list_for_each_entry_safe(hba, temp, &adapter_list, link) { | 125 | list_for_each_entry_safe(hba, temp, &adapter_list, link) { |
127 | if (hba->cnic == cnic) { | 126 | if (hba->cnic == cnic) { |
128 | read_unlock(&bnx2i_dev_lock); | 127 | mutex_unlock(&bnx2i_dev_lock); |
129 | return hba; | 128 | return hba; |
130 | } | 129 | } |
131 | } | 130 | } |
132 | read_unlock(&bnx2i_dev_lock); | 131 | mutex_unlock(&bnx2i_dev_lock); |
133 | return NULL; | 132 | return NULL; |
134 | } | 133 | } |
135 | 134 | ||
@@ -186,18 +185,17 @@ void bnx2i_stop(void *handle) | |||
186 | */ | 185 | */ |
187 | void bnx2i_register_device(struct bnx2i_hba *hba) | 186 | void bnx2i_register_device(struct bnx2i_hba *hba) |
188 | { | 187 | { |
188 | int rc; | ||
189 | |||
189 | if (test_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state) || | 190 | if (test_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state) || |
190 | test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) { | 191 | test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) { |
191 | return; | 192 | return; |
192 | } | 193 | } |
193 | 194 | ||
194 | hba->cnic->register_device(hba->cnic, CNIC_ULP_ISCSI, hba); | 195 | rc = hba->cnic->register_device(hba->cnic, CNIC_ULP_ISCSI, hba); |
195 | 196 | ||
196 | spin_lock(&hba->lock); | 197 | if (!rc) |
197 | bnx2i_reg_device++; | 198 | set_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic); |
198 | spin_unlock(&hba->lock); | ||
199 | |||
200 | set_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic); | ||
201 | } | 199 | } |
202 | 200 | ||
203 | 201 | ||
@@ -211,10 +209,10 @@ void bnx2i_reg_dev_all(void) | |||
211 | { | 209 | { |
212 | struct bnx2i_hba *hba, *temp; | 210 | struct bnx2i_hba *hba, *temp; |
213 | 211 | ||
214 | read_lock(&bnx2i_dev_lock); | 212 | mutex_lock(&bnx2i_dev_lock); |
215 | list_for_each_entry_safe(hba, temp, &adapter_list, link) | 213 | list_for_each_entry_safe(hba, temp, &adapter_list, link) |
216 | bnx2i_register_device(hba); | 214 | bnx2i_register_device(hba); |
217 | read_unlock(&bnx2i_dev_lock); | 215 | mutex_unlock(&bnx2i_dev_lock); |
218 | } | 216 | } |
219 | 217 | ||
220 | 218 | ||
@@ -234,10 +232,6 @@ static void bnx2i_unreg_one_device(struct bnx2i_hba *hba) | |||
234 | 232 | ||
235 | hba->cnic->unregister_device(hba->cnic, CNIC_ULP_ISCSI); | 233 | hba->cnic->unregister_device(hba->cnic, CNIC_ULP_ISCSI); |
236 | 234 | ||
237 | spin_lock(&hba->lock); | ||
238 | bnx2i_reg_device--; | ||
239 | spin_unlock(&hba->lock); | ||
240 | |||
241 | /* ep_disconnect could come before NETDEV_DOWN, driver won't | 235 | /* ep_disconnect could come before NETDEV_DOWN, driver won't |
242 | * see NETDEV_DOWN as it already unregistered itself. | 236 | * see NETDEV_DOWN as it already unregistered itself. |
243 | */ | 237 | */ |
@@ -255,10 +249,10 @@ void bnx2i_unreg_dev_all(void) | |||
255 | { | 249 | { |
256 | struct bnx2i_hba *hba, *temp; | 250 | struct bnx2i_hba *hba, *temp; |
257 | 251 | ||
258 | read_lock(&bnx2i_dev_lock); | 252 | mutex_lock(&bnx2i_dev_lock); |
259 | list_for_each_entry_safe(hba, temp, &adapter_list, link) | 253 | list_for_each_entry_safe(hba, temp, &adapter_list, link) |
260 | bnx2i_unreg_one_device(hba); | 254 | bnx2i_unreg_one_device(hba); |
261 | read_unlock(&bnx2i_dev_lock); | 255 | mutex_unlock(&bnx2i_dev_lock); |
262 | } | 256 | } |
263 | 257 | ||
264 | 258 | ||
@@ -267,35 +261,34 @@ void bnx2i_unreg_dev_all(void) | |||
267 | * @hba: bnx2i adapter instance | 261 | * @hba: bnx2i adapter instance |
268 | * @cnic: cnic device handle | 262 | * @cnic: cnic device handle |
269 | * | 263 | * |
270 | * Global resource lock and host adapter lock is held during critical sections | 264 | * Global resource lock is held during critical sections below. This routine is |
271 | * below. This routine is called from cnic_register_driver() context and | 265 | * called from either cnic_register_driver() or device hot plug context and |
272 | * work horse thread which does majority of device specific initialization | 266 | * and does majority of device specific initialization |
273 | */ | 267 | */ |
274 | static int bnx2i_init_one(struct bnx2i_hba *hba, struct cnic_dev *cnic) | 268 | static int bnx2i_init_one(struct bnx2i_hba *hba, struct cnic_dev *cnic) |
275 | { | 269 | { |
276 | int rc; | 270 | int rc; |
277 | 271 | ||
278 | read_lock(&bnx2i_dev_lock); | 272 | mutex_lock(&bnx2i_dev_lock); |
279 | if (bnx2i_reg_device && | 273 | rc = cnic->register_device(cnic, CNIC_ULP_ISCSI, hba); |
280 | !test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) { | 274 | if (!rc) { |
281 | rc = cnic->register_device(cnic, CNIC_ULP_ISCSI, hba); | ||
282 | if (rc) /* duplicate registration */ | ||
283 | printk(KERN_ERR "bnx2i- dev reg failed\n"); | ||
284 | |||
285 | spin_lock(&hba->lock); | ||
286 | bnx2i_reg_device++; | ||
287 | hba->age++; | 275 | hba->age++; |
288 | spin_unlock(&hba->lock); | ||
289 | |||
290 | set_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic); | 276 | set_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic); |
291 | } | 277 | list_add_tail(&hba->link, &adapter_list); |
292 | read_unlock(&bnx2i_dev_lock); | 278 | adapter_count++; |
293 | 279 | } else if (rc == -EBUSY) /* duplicate registration */ | |
294 | write_lock(&bnx2i_dev_lock); | 280 | printk(KERN_ALERT "bnx2i, duplicate registration" |
295 | list_add_tail(&hba->link, &adapter_list); | 281 | "hba=%p, cnic=%p\n", hba, cnic); |
296 | adapter_count++; | 282 | else if (rc == -EAGAIN) |
297 | write_unlock(&bnx2i_dev_lock); | 283 | printk(KERN_ERR "bnx2i, driver not registered\n"); |
298 | return 0; | 284 | else if (rc == -EINVAL) |
285 | printk(KERN_ERR "bnx2i, invalid type %d\n", CNIC_ULP_ISCSI); | ||
286 | else | ||
287 | printk(KERN_ERR "bnx2i dev reg, unknown error, %d\n", rc); | ||
288 | |||
289 | mutex_unlock(&bnx2i_dev_lock); | ||
290 | |||
291 | return rc; | ||
299 | } | 292 | } |
300 | 293 | ||
301 | 294 | ||
@@ -343,19 +336,15 @@ void bnx2i_ulp_exit(struct cnic_dev *dev) | |||
343 | "found, dev 0x%p\n", dev); | 336 | "found, dev 0x%p\n", dev); |
344 | return; | 337 | return; |
345 | } | 338 | } |
346 | write_lock(&bnx2i_dev_lock); | 339 | mutex_lock(&bnx2i_dev_lock); |
347 | list_del_init(&hba->link); | 340 | list_del_init(&hba->link); |
348 | adapter_count--; | 341 | adapter_count--; |
349 | 342 | ||
350 | if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) { | 343 | if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) { |
351 | hba->cnic->unregister_device(hba->cnic, CNIC_ULP_ISCSI); | 344 | hba->cnic->unregister_device(hba->cnic, CNIC_ULP_ISCSI); |
352 | clear_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic); | 345 | clear_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic); |
353 | |||
354 | spin_lock(&hba->lock); | ||
355 | bnx2i_reg_device--; | ||
356 | spin_unlock(&hba->lock); | ||
357 | } | 346 | } |
358 | write_unlock(&bnx2i_dev_lock); | 347 | mutex_unlock(&bnx2i_dev_lock); |
359 | 348 | ||
360 | bnx2i_free_hba(hba); | 349 | bnx2i_free_hba(hba); |
361 | } | 350 | } |
@@ -377,6 +366,8 @@ static int __init bnx2i_mod_init(void) | |||
377 | if (!is_power_of_2(sq_size)) | 366 | if (!is_power_of_2(sq_size)) |
378 | sq_size = roundup_pow_of_two(sq_size); | 367 | sq_size = roundup_pow_of_two(sq_size); |
379 | 368 | ||
369 | mutex_init(&bnx2i_dev_lock); | ||
370 | |||
380 | bnx2i_scsi_xport_template = | 371 | bnx2i_scsi_xport_template = |
381 | iscsi_register_transport(&bnx2i_iscsi_transport); | 372 | iscsi_register_transport(&bnx2i_iscsi_transport); |
382 | if (!bnx2i_scsi_xport_template) { | 373 | if (!bnx2i_scsi_xport_template) { |
@@ -412,7 +403,7 @@ static void __exit bnx2i_mod_exit(void) | |||
412 | { | 403 | { |
413 | struct bnx2i_hba *hba; | 404 | struct bnx2i_hba *hba; |
414 | 405 | ||
415 | write_lock(&bnx2i_dev_lock); | 406 | mutex_lock(&bnx2i_dev_lock); |
416 | while (!list_empty(&adapter_list)) { | 407 | while (!list_empty(&adapter_list)) { |
417 | hba = list_entry(adapter_list.next, struct bnx2i_hba, link); | 408 | hba = list_entry(adapter_list.next, struct bnx2i_hba, link); |
418 | list_del(&hba->link); | 409 | list_del(&hba->link); |
@@ -421,14 +412,11 @@ static void __exit bnx2i_mod_exit(void) | |||
421 | if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) { | 412 | if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) { |
422 | hba->cnic->unregister_device(hba->cnic, CNIC_ULP_ISCSI); | 413 | hba->cnic->unregister_device(hba->cnic, CNIC_ULP_ISCSI); |
423 | clear_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic); | 414 | clear_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic); |
424 | bnx2i_reg_device--; | ||
425 | } | 415 | } |
426 | 416 | ||
427 | write_unlock(&bnx2i_dev_lock); | ||
428 | bnx2i_free_hba(hba); | 417 | bnx2i_free_hba(hba); |
429 | write_lock(&bnx2i_dev_lock); | ||
430 | } | 418 | } |
431 | write_unlock(&bnx2i_dev_lock); | 419 | mutex_unlock(&bnx2i_dev_lock); |
432 | 420 | ||
433 | iscsi_unregister_transport(&bnx2i_iscsi_transport); | 421 | iscsi_unregister_transport(&bnx2i_iscsi_transport); |
434 | cnic_unregister_driver(CNIC_ULP_ISCSI); | 422 | cnic_unregister_driver(CNIC_ULP_ISCSI); |