diff options
Diffstat (limited to 'drivers/net/cnic.c')
-rw-r--r-- | drivers/net/cnic.c | 166 |
1 files changed, 125 insertions, 41 deletions
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 4d1515f45ba2..74c342959b7b 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c | |||
@@ -138,6 +138,16 @@ static struct cnic_dev *cnic_from_netdev(struct net_device *netdev) | |||
138 | return NULL; | 138 | return NULL; |
139 | } | 139 | } |
140 | 140 | ||
141 | static inline void ulp_get(struct cnic_ulp_ops *ulp_ops) | ||
142 | { | ||
143 | atomic_inc(&ulp_ops->ref_count); | ||
144 | } | ||
145 | |||
146 | static inline void ulp_put(struct cnic_ulp_ops *ulp_ops) | ||
147 | { | ||
148 | atomic_dec(&ulp_ops->ref_count); | ||
149 | } | ||
150 | |||
141 | static void cnic_ctx_wr(struct cnic_dev *dev, u32 cid_addr, u32 off, u32 val) | 151 | static void cnic_ctx_wr(struct cnic_dev *dev, u32 cid_addr, u32 off, u32 val) |
142 | { | 152 | { |
143 | struct cnic_local *cp = dev->cnic_priv; | 153 | struct cnic_local *cp = dev->cnic_priv; |
@@ -227,7 +237,7 @@ static int cnic_send_nlmsg(struct cnic_local *cp, u32 type, | |||
227 | } | 237 | } |
228 | 238 | ||
229 | rcu_read_lock(); | 239 | rcu_read_lock(); |
230 | ulp_ops = rcu_dereference(cp->ulp_ops[CNIC_ULP_ISCSI]); | 240 | ulp_ops = rcu_dereference(cnic_ulp_tbl[CNIC_ULP_ISCSI]); |
231 | if (ulp_ops) | 241 | if (ulp_ops) |
232 | ulp_ops->iscsi_nl_send_msg(cp->dev, msg_type, buf, len); | 242 | ulp_ops->iscsi_nl_send_msg(cp->dev, msg_type, buf, len); |
233 | rcu_read_unlock(); | 243 | rcu_read_unlock(); |
@@ -319,6 +329,20 @@ static int cnic_abort_prep(struct cnic_sock *csk) | |||
319 | return 0; | 329 | return 0; |
320 | } | 330 | } |
321 | 331 | ||
332 | static void cnic_uio_stop(void) | ||
333 | { | ||
334 | struct cnic_dev *dev; | ||
335 | |||
336 | read_lock(&cnic_dev_lock); | ||
337 | list_for_each_entry(dev, &cnic_dev_list, list) { | ||
338 | struct cnic_local *cp = dev->cnic_priv; | ||
339 | |||
340 | if (cp->cnic_uinfo) | ||
341 | cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL); | ||
342 | } | ||
343 | read_unlock(&cnic_dev_lock); | ||
344 | } | ||
345 | |||
322 | int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops) | 346 | int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops) |
323 | { | 347 | { |
324 | struct cnic_dev *dev; | 348 | struct cnic_dev *dev; |
@@ -344,6 +368,7 @@ int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops) | |||
344 | } | 368 | } |
345 | read_unlock(&cnic_dev_lock); | 369 | read_unlock(&cnic_dev_lock); |
346 | 370 | ||
371 | atomic_set(&ulp_ops->ref_count, 0); | ||
347 | rcu_assign_pointer(cnic_ulp_tbl[ulp_type], ulp_ops); | 372 | rcu_assign_pointer(cnic_ulp_tbl[ulp_type], ulp_ops); |
348 | mutex_unlock(&cnic_lock); | 373 | mutex_unlock(&cnic_lock); |
349 | 374 | ||
@@ -365,6 +390,8 @@ int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops) | |||
365 | int cnic_unregister_driver(int ulp_type) | 390 | int cnic_unregister_driver(int ulp_type) |
366 | { | 391 | { |
367 | struct cnic_dev *dev; | 392 | struct cnic_dev *dev; |
393 | struct cnic_ulp_ops *ulp_ops; | ||
394 | int i = 0; | ||
368 | 395 | ||
369 | if (ulp_type >= MAX_CNIC_ULP_TYPE) { | 396 | if (ulp_type >= MAX_CNIC_ULP_TYPE) { |
370 | printk(KERN_ERR PFX "cnic_unregister_driver: Bad type %d\n", | 397 | printk(KERN_ERR PFX "cnic_unregister_driver: Bad type %d\n", |
@@ -372,7 +399,8 @@ int cnic_unregister_driver(int ulp_type) | |||
372 | return -EINVAL; | 399 | return -EINVAL; |
373 | } | 400 | } |
374 | mutex_lock(&cnic_lock); | 401 | mutex_lock(&cnic_lock); |
375 | if (!cnic_ulp_tbl[ulp_type]) { | 402 | ulp_ops = cnic_ulp_tbl[ulp_type]; |
403 | if (!ulp_ops) { | ||
376 | printk(KERN_ERR PFX "cnic_unregister_driver: Type %d has not " | 404 | printk(KERN_ERR PFX "cnic_unregister_driver: Type %d has not " |
377 | "been registered\n", ulp_type); | 405 | "been registered\n", ulp_type); |
378 | goto out_unlock; | 406 | goto out_unlock; |
@@ -390,10 +418,21 @@ int cnic_unregister_driver(int ulp_type) | |||
390 | } | 418 | } |
391 | read_unlock(&cnic_dev_lock); | 419 | read_unlock(&cnic_dev_lock); |
392 | 420 | ||
421 | if (ulp_type == CNIC_ULP_ISCSI) | ||
422 | cnic_uio_stop(); | ||
423 | |||
393 | rcu_assign_pointer(cnic_ulp_tbl[ulp_type], NULL); | 424 | rcu_assign_pointer(cnic_ulp_tbl[ulp_type], NULL); |
394 | 425 | ||
395 | mutex_unlock(&cnic_lock); | 426 | mutex_unlock(&cnic_lock); |
396 | synchronize_rcu(); | 427 | synchronize_rcu(); |
428 | while ((atomic_read(&ulp_ops->ref_count) != 0) && (i < 20)) { | ||
429 | msleep(100); | ||
430 | i++; | ||
431 | } | ||
432 | |||
433 | if (atomic_read(&ulp_ops->ref_count) != 0) | ||
434 | printk(KERN_WARNING PFX "%s: Failed waiting for ref count to go" | ||
435 | " to zero.\n", dev->netdev->name); | ||
397 | return 0; | 436 | return 0; |
398 | 437 | ||
399 | out_unlock: | 438 | out_unlock: |
@@ -449,6 +488,7 @@ EXPORT_SYMBOL(cnic_register_driver); | |||
449 | static int cnic_unregister_device(struct cnic_dev *dev, int ulp_type) | 488 | static int cnic_unregister_device(struct cnic_dev *dev, int ulp_type) |
450 | { | 489 | { |
451 | struct cnic_local *cp = dev->cnic_priv; | 490 | struct cnic_local *cp = dev->cnic_priv; |
491 | int i = 0; | ||
452 | 492 | ||
453 | if (ulp_type >= MAX_CNIC_ULP_TYPE) { | 493 | if (ulp_type >= MAX_CNIC_ULP_TYPE) { |
454 | printk(KERN_ERR PFX "cnic_unregister_device: Bad type %d\n", | 494 | printk(KERN_ERR PFX "cnic_unregister_device: Bad type %d\n", |
@@ -469,6 +509,15 @@ static int cnic_unregister_device(struct cnic_dev *dev, int ulp_type) | |||
469 | 509 | ||
470 | synchronize_rcu(); | 510 | synchronize_rcu(); |
471 | 511 | ||
512 | while (test_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[ulp_type]) && | ||
513 | i < 20) { | ||
514 | msleep(100); | ||
515 | i++; | ||
516 | } | ||
517 | if (test_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[ulp_type])) | ||
518 | printk(KERN_WARNING PFX "%s: Failed waiting for ULP up call" | ||
519 | " to complete.\n", dev->netdev->name); | ||
520 | |||
472 | return 0; | 521 | return 0; |
473 | } | 522 | } |
474 | EXPORT_SYMBOL(cnic_unregister_driver); | 523 | EXPORT_SYMBOL(cnic_unregister_driver); |
@@ -632,7 +681,6 @@ static void cnic_free_resc(struct cnic_dev *dev) | |||
632 | int i = 0; | 681 | int i = 0; |
633 | 682 | ||
634 | if (cp->cnic_uinfo) { | 683 | if (cp->cnic_uinfo) { |
635 | cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL); | ||
636 | while (cp->uio_dev != -1 && i < 15) { | 684 | while (cp->uio_dev != -1 && i < 15) { |
637 | msleep(100); | 685 | msleep(100); |
638 | i++; | 686 | i++; |
@@ -1057,18 +1105,26 @@ static void cnic_ulp_stop(struct cnic_dev *dev) | |||
1057 | struct cnic_local *cp = dev->cnic_priv; | 1105 | struct cnic_local *cp = dev->cnic_priv; |
1058 | int if_type; | 1106 | int if_type; |
1059 | 1107 | ||
1060 | rcu_read_lock(); | 1108 | if (cp->cnic_uinfo) |
1109 | cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL); | ||
1110 | |||
1061 | for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) { | 1111 | for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) { |
1062 | struct cnic_ulp_ops *ulp_ops; | 1112 | struct cnic_ulp_ops *ulp_ops; |
1063 | 1113 | ||
1064 | ulp_ops = rcu_dereference(cp->ulp_ops[if_type]); | 1114 | mutex_lock(&cnic_lock); |
1065 | if (!ulp_ops) | 1115 | ulp_ops = cp->ulp_ops[if_type]; |
1116 | if (!ulp_ops) { | ||
1117 | mutex_unlock(&cnic_lock); | ||
1066 | continue; | 1118 | continue; |
1119 | } | ||
1120 | set_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]); | ||
1121 | mutex_unlock(&cnic_lock); | ||
1067 | 1122 | ||
1068 | if (test_and_clear_bit(ULP_F_START, &cp->ulp_flags[if_type])) | 1123 | if (test_and_clear_bit(ULP_F_START, &cp->ulp_flags[if_type])) |
1069 | ulp_ops->cnic_stop(cp->ulp_handle[if_type]); | 1124 | ulp_ops->cnic_stop(cp->ulp_handle[if_type]); |
1125 | |||
1126 | clear_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]); | ||
1070 | } | 1127 | } |
1071 | rcu_read_unlock(); | ||
1072 | } | 1128 | } |
1073 | 1129 | ||
1074 | static void cnic_ulp_start(struct cnic_dev *dev) | 1130 | static void cnic_ulp_start(struct cnic_dev *dev) |
@@ -1076,18 +1132,23 @@ static void cnic_ulp_start(struct cnic_dev *dev) | |||
1076 | struct cnic_local *cp = dev->cnic_priv; | 1132 | struct cnic_local *cp = dev->cnic_priv; |
1077 | int if_type; | 1133 | int if_type; |
1078 | 1134 | ||
1079 | rcu_read_lock(); | ||
1080 | for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) { | 1135 | for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) { |
1081 | struct cnic_ulp_ops *ulp_ops; | 1136 | struct cnic_ulp_ops *ulp_ops; |
1082 | 1137 | ||
1083 | ulp_ops = rcu_dereference(cp->ulp_ops[if_type]); | 1138 | mutex_lock(&cnic_lock); |
1084 | if (!ulp_ops || !ulp_ops->cnic_start) | 1139 | ulp_ops = cp->ulp_ops[if_type]; |
1140 | if (!ulp_ops || !ulp_ops->cnic_start) { | ||
1141 | mutex_unlock(&cnic_lock); | ||
1085 | continue; | 1142 | continue; |
1143 | } | ||
1144 | set_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]); | ||
1145 | mutex_unlock(&cnic_lock); | ||
1086 | 1146 | ||
1087 | if (!test_and_set_bit(ULP_F_START, &cp->ulp_flags[if_type])) | 1147 | if (!test_and_set_bit(ULP_F_START, &cp->ulp_flags[if_type])) |
1088 | ulp_ops->cnic_start(cp->ulp_handle[if_type]); | 1148 | ulp_ops->cnic_start(cp->ulp_handle[if_type]); |
1149 | |||
1150 | clear_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]); | ||
1089 | } | 1151 | } |
1090 | rcu_read_unlock(); | ||
1091 | } | 1152 | } |
1092 | 1153 | ||
1093 | static int cnic_ctl(void *data, struct cnic_ctl_info *info) | 1154 | static int cnic_ctl(void *data, struct cnic_ctl_info *info) |
@@ -1097,22 +1158,18 @@ static int cnic_ctl(void *data, struct cnic_ctl_info *info) | |||
1097 | switch (info->cmd) { | 1158 | switch (info->cmd) { |
1098 | case CNIC_CTL_STOP_CMD: | 1159 | case CNIC_CTL_STOP_CMD: |
1099 | cnic_hold(dev); | 1160 | cnic_hold(dev); |
1100 | mutex_lock(&cnic_lock); | ||
1101 | 1161 | ||
1102 | cnic_ulp_stop(dev); | 1162 | cnic_ulp_stop(dev); |
1103 | cnic_stop_hw(dev); | 1163 | cnic_stop_hw(dev); |
1104 | 1164 | ||
1105 | mutex_unlock(&cnic_lock); | ||
1106 | cnic_put(dev); | 1165 | cnic_put(dev); |
1107 | break; | 1166 | break; |
1108 | case CNIC_CTL_START_CMD: | 1167 | case CNIC_CTL_START_CMD: |
1109 | cnic_hold(dev); | 1168 | cnic_hold(dev); |
1110 | mutex_lock(&cnic_lock); | ||
1111 | 1169 | ||
1112 | if (!cnic_start_hw(dev)) | 1170 | if (!cnic_start_hw(dev)) |
1113 | cnic_ulp_start(dev); | 1171 | cnic_ulp_start(dev); |
1114 | 1172 | ||
1115 | mutex_unlock(&cnic_lock); | ||
1116 | cnic_put(dev); | 1173 | cnic_put(dev); |
1117 | break; | 1174 | break; |
1118 | default: | 1175 | default: |
@@ -1126,19 +1183,23 @@ static void cnic_ulp_init(struct cnic_dev *dev) | |||
1126 | int i; | 1183 | int i; |
1127 | struct cnic_local *cp = dev->cnic_priv; | 1184 | struct cnic_local *cp = dev->cnic_priv; |
1128 | 1185 | ||
1129 | rcu_read_lock(); | ||
1130 | for (i = 0; i < MAX_CNIC_ULP_TYPE_EXT; i++) { | 1186 | for (i = 0; i < MAX_CNIC_ULP_TYPE_EXT; i++) { |
1131 | struct cnic_ulp_ops *ulp_ops; | 1187 | struct cnic_ulp_ops *ulp_ops; |
1132 | 1188 | ||
1133 | ulp_ops = rcu_dereference(cnic_ulp_tbl[i]); | 1189 | mutex_lock(&cnic_lock); |
1134 | if (!ulp_ops || !ulp_ops->cnic_init) | 1190 | ulp_ops = cnic_ulp_tbl[i]; |
1191 | if (!ulp_ops || !ulp_ops->cnic_init) { | ||
1192 | mutex_unlock(&cnic_lock); | ||
1135 | continue; | 1193 | continue; |
1194 | } | ||
1195 | ulp_get(ulp_ops); | ||
1196 | mutex_unlock(&cnic_lock); | ||
1136 | 1197 | ||
1137 | if (!test_and_set_bit(ULP_F_INIT, &cp->ulp_flags[i])) | 1198 | if (!test_and_set_bit(ULP_F_INIT, &cp->ulp_flags[i])) |
1138 | ulp_ops->cnic_init(dev); | 1199 | ulp_ops->cnic_init(dev); |
1139 | 1200 | ||
1201 | ulp_put(ulp_ops); | ||
1140 | } | 1202 | } |
1141 | rcu_read_unlock(); | ||
1142 | } | 1203 | } |
1143 | 1204 | ||
1144 | static void cnic_ulp_exit(struct cnic_dev *dev) | 1205 | static void cnic_ulp_exit(struct cnic_dev *dev) |
@@ -1146,19 +1207,23 @@ static void cnic_ulp_exit(struct cnic_dev *dev) | |||
1146 | int i; | 1207 | int i; |
1147 | struct cnic_local *cp = dev->cnic_priv; | 1208 | struct cnic_local *cp = dev->cnic_priv; |
1148 | 1209 | ||
1149 | rcu_read_lock(); | ||
1150 | for (i = 0; i < MAX_CNIC_ULP_TYPE_EXT; i++) { | 1210 | for (i = 0; i < MAX_CNIC_ULP_TYPE_EXT; i++) { |
1151 | struct cnic_ulp_ops *ulp_ops; | 1211 | struct cnic_ulp_ops *ulp_ops; |
1152 | 1212 | ||
1153 | ulp_ops = rcu_dereference(cnic_ulp_tbl[i]); | 1213 | mutex_lock(&cnic_lock); |
1154 | if (!ulp_ops || !ulp_ops->cnic_exit) | 1214 | ulp_ops = cnic_ulp_tbl[i]; |
1215 | if (!ulp_ops || !ulp_ops->cnic_exit) { | ||
1216 | mutex_unlock(&cnic_lock); | ||
1155 | continue; | 1217 | continue; |
1218 | } | ||
1219 | ulp_get(ulp_ops); | ||
1220 | mutex_unlock(&cnic_lock); | ||
1156 | 1221 | ||
1157 | if (test_and_clear_bit(ULP_F_INIT, &cp->ulp_flags[i])) | 1222 | if (test_and_clear_bit(ULP_F_INIT, &cp->ulp_flags[i])) |
1158 | ulp_ops->cnic_exit(dev); | 1223 | ulp_ops->cnic_exit(dev); |
1159 | 1224 | ||
1225 | ulp_put(ulp_ops); | ||
1160 | } | 1226 | } |
1161 | rcu_read_unlock(); | ||
1162 | } | 1227 | } |
1163 | 1228 | ||
1164 | static int cnic_cm_offload_pg(struct cnic_sock *csk) | 1229 | static int cnic_cm_offload_pg(struct cnic_sock *csk) |
@@ -2374,21 +2439,45 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev) | |||
2374 | return 0; | 2439 | return 0; |
2375 | } | 2440 | } |
2376 | 2441 | ||
2377 | static int cnic_start_hw(struct cnic_dev *dev) | 2442 | static int cnic_register_netdev(struct cnic_dev *dev) |
2378 | { | 2443 | { |
2379 | struct cnic_local *cp = dev->cnic_priv; | 2444 | struct cnic_local *cp = dev->cnic_priv; |
2380 | struct cnic_eth_dev *ethdev = cp->ethdev; | 2445 | struct cnic_eth_dev *ethdev = cp->ethdev; |
2381 | int err; | 2446 | int err; |
2382 | 2447 | ||
2383 | if (test_bit(CNIC_F_CNIC_UP, &dev->flags)) | 2448 | if (!ethdev) |
2384 | return -EALREADY; | 2449 | return -ENODEV; |
2450 | |||
2451 | if (ethdev->drv_state & CNIC_DRV_STATE_REGD) | ||
2452 | return 0; | ||
2385 | 2453 | ||
2386 | err = ethdev->drv_register_cnic(dev->netdev, cp->cnic_ops, dev); | 2454 | err = ethdev->drv_register_cnic(dev->netdev, cp->cnic_ops, dev); |
2387 | if (err) { | 2455 | if (err) |
2388 | printk(KERN_ERR PFX "%s: register_cnic failed\n", | 2456 | printk(KERN_ERR PFX "%s: register_cnic failed\n", |
2389 | dev->netdev->name); | 2457 | dev->netdev->name); |
2390 | goto err2; | 2458 | |
2391 | } | 2459 | return err; |
2460 | } | ||
2461 | |||
2462 | static void cnic_unregister_netdev(struct cnic_dev *dev) | ||
2463 | { | ||
2464 | struct cnic_local *cp = dev->cnic_priv; | ||
2465 | struct cnic_eth_dev *ethdev = cp->ethdev; | ||
2466 | |||
2467 | if (!ethdev) | ||
2468 | return; | ||
2469 | |||
2470 | ethdev->drv_unregister_cnic(dev->netdev); | ||
2471 | } | ||
2472 | |||
2473 | static int cnic_start_hw(struct cnic_dev *dev) | ||
2474 | { | ||
2475 | struct cnic_local *cp = dev->cnic_priv; | ||
2476 | struct cnic_eth_dev *ethdev = cp->ethdev; | ||
2477 | int err; | ||
2478 | |||
2479 | if (test_bit(CNIC_F_CNIC_UP, &dev->flags)) | ||
2480 | return -EALREADY; | ||
2392 | 2481 | ||
2393 | dev->regview = ethdev->io_base; | 2482 | dev->regview = ethdev->io_base; |
2394 | cp->chip_id = ethdev->chip_id; | 2483 | cp->chip_id = ethdev->chip_id; |
@@ -2419,18 +2508,13 @@ static int cnic_start_hw(struct cnic_dev *dev) | |||
2419 | return 0; | 2508 | return 0; |
2420 | 2509 | ||
2421 | err1: | 2510 | err1: |
2422 | ethdev->drv_unregister_cnic(dev->netdev); | ||
2423 | cp->free_resc(dev); | 2511 | cp->free_resc(dev); |
2424 | pci_dev_put(dev->pcidev); | 2512 | pci_dev_put(dev->pcidev); |
2425 | err2: | ||
2426 | return err; | 2513 | return err; |
2427 | } | 2514 | } |
2428 | 2515 | ||
2429 | static void cnic_stop_bnx2_hw(struct cnic_dev *dev) | 2516 | static void cnic_stop_bnx2_hw(struct cnic_dev *dev) |
2430 | { | 2517 | { |
2431 | struct cnic_local *cp = dev->cnic_priv; | ||
2432 | struct cnic_eth_dev *ethdev = cp->ethdev; | ||
2433 | |||
2434 | cnic_disable_bnx2_int_sync(dev); | 2518 | cnic_disable_bnx2_int_sync(dev); |
2435 | 2519 | ||
2436 | cnic_reg_wr_ind(dev, BNX2_CP_SCRATCH + 0x20, 0); | 2520 | cnic_reg_wr_ind(dev, BNX2_CP_SCRATCH + 0x20, 0); |
@@ -2442,8 +2526,6 @@ static void cnic_stop_bnx2_hw(struct cnic_dev *dev) | |||
2442 | cnic_setup_5709_context(dev, 0); | 2526 | cnic_setup_5709_context(dev, 0); |
2443 | cnic_free_irq(dev); | 2527 | cnic_free_irq(dev); |
2444 | 2528 | ||
2445 | ethdev->drv_unregister_cnic(dev->netdev); | ||
2446 | |||
2447 | cnic_free_resc(dev); | 2529 | cnic_free_resc(dev); |
2448 | } | 2530 | } |
2449 | 2531 | ||
@@ -2524,7 +2606,7 @@ static struct cnic_dev *init_bnx2_cnic(struct net_device *dev) | |||
2524 | probe = symbol_get(bnx2_cnic_probe); | 2606 | probe = symbol_get(bnx2_cnic_probe); |
2525 | if (probe) { | 2607 | if (probe) { |
2526 | ethdev = (*probe)(dev); | 2608 | ethdev = (*probe)(dev); |
2527 | symbol_put_addr(probe); | 2609 | symbol_put(bnx2_cnic_probe); |
2528 | } | 2610 | } |
2529 | if (!ethdev) | 2611 | if (!ethdev) |
2530 | return NULL; | 2612 | return NULL; |
@@ -2627,10 +2709,12 @@ static int cnic_netdev_event(struct notifier_block *this, unsigned long event, | |||
2627 | else if (event == NETDEV_UNREGISTER) | 2709 | else if (event == NETDEV_UNREGISTER) |
2628 | cnic_ulp_exit(dev); | 2710 | cnic_ulp_exit(dev); |
2629 | else if (event == NETDEV_UP) { | 2711 | else if (event == NETDEV_UP) { |
2630 | mutex_lock(&cnic_lock); | 2712 | if (cnic_register_netdev(dev) != 0) { |
2713 | cnic_put(dev); | ||
2714 | goto done; | ||
2715 | } | ||
2631 | if (!cnic_start_hw(dev)) | 2716 | if (!cnic_start_hw(dev)) |
2632 | cnic_ulp_start(dev); | 2717 | cnic_ulp_start(dev); |
2633 | mutex_unlock(&cnic_lock); | ||
2634 | } | 2718 | } |
2635 | 2719 | ||
2636 | rcu_read_lock(); | 2720 | rcu_read_lock(); |
@@ -2649,10 +2733,9 @@ static int cnic_netdev_event(struct notifier_block *this, unsigned long event, | |||
2649 | rcu_read_unlock(); | 2733 | rcu_read_unlock(); |
2650 | 2734 | ||
2651 | if (event == NETDEV_GOING_DOWN) { | 2735 | if (event == NETDEV_GOING_DOWN) { |
2652 | mutex_lock(&cnic_lock); | ||
2653 | cnic_ulp_stop(dev); | 2736 | cnic_ulp_stop(dev); |
2654 | cnic_stop_hw(dev); | 2737 | cnic_stop_hw(dev); |
2655 | mutex_unlock(&cnic_lock); | 2738 | cnic_unregister_netdev(dev); |
2656 | } else if (event == NETDEV_UNREGISTER) { | 2739 | } else if (event == NETDEV_UNREGISTER) { |
2657 | write_lock(&cnic_dev_lock); | 2740 | write_lock(&cnic_dev_lock); |
2658 | list_del_init(&dev->list); | 2741 | list_del_init(&dev->list); |
@@ -2684,6 +2767,7 @@ static void cnic_release(void) | |||
2684 | } | 2767 | } |
2685 | 2768 | ||
2686 | cnic_ulp_exit(dev); | 2769 | cnic_ulp_exit(dev); |
2770 | cnic_unregister_netdev(dev); | ||
2687 | list_del_init(&dev->list); | 2771 | list_del_init(&dev->list); |
2688 | cnic_free_dev(dev); | 2772 | cnic_free_dev(dev); |
2689 | } | 2773 | } |