diff options
author | Jan-Bernd Themann <themann@de.ibm.com> | 2009-03-13 16:50:40 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-03-13 16:50:40 -0400 |
commit | 52e21b1bd96444c452f6eab7dc438a8a898aa14a (patch) | |
tree | 8e25fd2a92457662bbc72d3027b3d419dd6b9b76 /drivers/net/ehea/ehea_main.c | |
parent | f9ac30f080d23ef0a2d4a1b7c6806c9a21c0f324 (diff) |
ehea: fix circular locking problem
This patch fixes the circular locking problem by changing the locking strategy
concerning the logging of firmware handles.
Signed-off-by: Jan-Bernd Themann <themann@de.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ehea/ehea_main.c')
-rw-r--r-- | drivers/net/ehea/ehea_main.c | 56 |
1 files changed, 30 insertions, 26 deletions
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 40c34bfe2cfa..ac0c5b438e0a 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c | |||
@@ -155,6 +155,8 @@ static void ehea_update_firmware_handles(void) | |||
155 | int num_fw_handles, k, l; | 155 | int num_fw_handles, k, l; |
156 | 156 | ||
157 | /* Determine number of handles */ | 157 | /* Determine number of handles */ |
158 | mutex_lock(&ehea_fw_handles.lock); | ||
159 | |||
158 | list_for_each_entry(adapter, &adapter_list, list) { | 160 | list_for_each_entry(adapter, &adapter_list, list) { |
159 | num_adapters++; | 161 | num_adapters++; |
160 | 162 | ||
@@ -176,15 +178,19 @@ static void ehea_update_firmware_handles(void) | |||
176 | if (num_fw_handles) { | 178 | if (num_fw_handles) { |
177 | arr = kzalloc(num_fw_handles * sizeof(*arr), GFP_KERNEL); | 179 | arr = kzalloc(num_fw_handles * sizeof(*arr), GFP_KERNEL); |
178 | if (!arr) | 180 | if (!arr) |
179 | return; /* Keep the existing array */ | 181 | goto out; /* Keep the existing array */ |
180 | } else | 182 | } else |
181 | goto out_update; | 183 | goto out_update; |
182 | 184 | ||
183 | list_for_each_entry(adapter, &adapter_list, list) { | 185 | list_for_each_entry(adapter, &adapter_list, list) { |
186 | if (num_adapters == 0) | ||
187 | break; | ||
188 | |||
184 | for (k = 0; k < EHEA_MAX_PORTS; k++) { | 189 | for (k = 0; k < EHEA_MAX_PORTS; k++) { |
185 | struct ehea_port *port = adapter->port[k]; | 190 | struct ehea_port *port = adapter->port[k]; |
186 | 191 | ||
187 | if (!port || (port->state != EHEA_PORT_UP)) | 192 | if (!port || (port->state != EHEA_PORT_UP) |
193 | || (num_ports == 0)) | ||
188 | continue; | 194 | continue; |
189 | 195 | ||
190 | for (l = 0; | 196 | for (l = 0; |
@@ -207,6 +213,7 @@ static void ehea_update_firmware_handles(void) | |||
207 | } | 213 | } |
208 | arr[i].adh = adapter->handle; | 214 | arr[i].adh = adapter->handle; |
209 | arr[i++].fwh = port->qp_eq->fw_handle; | 215 | arr[i++].fwh = port->qp_eq->fw_handle; |
216 | num_ports--; | ||
210 | } | 217 | } |
211 | 218 | ||
212 | arr[i].adh = adapter->handle; | 219 | arr[i].adh = adapter->handle; |
@@ -216,16 +223,20 @@ static void ehea_update_firmware_handles(void) | |||
216 | arr[i].adh = adapter->handle; | 223 | arr[i].adh = adapter->handle; |
217 | arr[i++].fwh = adapter->mr.handle; | 224 | arr[i++].fwh = adapter->mr.handle; |
218 | } | 225 | } |
226 | num_adapters--; | ||
219 | } | 227 | } |
220 | 228 | ||
221 | out_update: | 229 | out_update: |
222 | kfree(ehea_fw_handles.arr); | 230 | kfree(ehea_fw_handles.arr); |
223 | ehea_fw_handles.arr = arr; | 231 | ehea_fw_handles.arr = arr; |
224 | ehea_fw_handles.num_entries = i; | 232 | ehea_fw_handles.num_entries = i; |
233 | out: | ||
234 | mutex_unlock(&ehea_fw_handles.lock); | ||
225 | } | 235 | } |
226 | 236 | ||
227 | static void ehea_update_bcmc_registrations(void) | 237 | static void ehea_update_bcmc_registrations(void) |
228 | { | 238 | { |
239 | unsigned long flags; | ||
229 | struct ehea_bcmc_reg_entry *arr = NULL; | 240 | struct ehea_bcmc_reg_entry *arr = NULL; |
230 | struct ehea_adapter *adapter; | 241 | struct ehea_adapter *adapter; |
231 | struct ehea_mc_list *mc_entry; | 242 | struct ehea_mc_list *mc_entry; |
@@ -233,6 +244,8 @@ static void ehea_update_bcmc_registrations(void) | |||
233 | int i = 0; | 244 | int i = 0; |
234 | int k; | 245 | int k; |
235 | 246 | ||
247 | spin_lock_irqsave(&ehea_bcmc_regs.lock, flags); | ||
248 | |||
236 | /* Determine number of registrations */ | 249 | /* Determine number of registrations */ |
237 | list_for_each_entry(adapter, &adapter_list, list) | 250 | list_for_each_entry(adapter, &adapter_list, list) |
238 | for (k = 0; k < EHEA_MAX_PORTS; k++) { | 251 | for (k = 0; k < EHEA_MAX_PORTS; k++) { |
@@ -250,7 +263,7 @@ static void ehea_update_bcmc_registrations(void) | |||
250 | if (num_registrations) { | 263 | if (num_registrations) { |
251 | arr = kzalloc(num_registrations * sizeof(*arr), GFP_ATOMIC); | 264 | arr = kzalloc(num_registrations * sizeof(*arr), GFP_ATOMIC); |
252 | if (!arr) | 265 | if (!arr) |
253 | return; /* Keep the existing array */ | 266 | goto out; /* Keep the existing array */ |
254 | } else | 267 | } else |
255 | goto out_update; | 268 | goto out_update; |
256 | 269 | ||
@@ -261,6 +274,9 @@ static void ehea_update_bcmc_registrations(void) | |||
261 | if (!port || (port->state != EHEA_PORT_UP)) | 274 | if (!port || (port->state != EHEA_PORT_UP)) |
262 | continue; | 275 | continue; |
263 | 276 | ||
277 | if (num_registrations == 0) | ||
278 | goto out_update; | ||
279 | |||
264 | arr[i].adh = adapter->handle; | 280 | arr[i].adh = adapter->handle; |
265 | arr[i].port_id = port->logical_port_id; | 281 | arr[i].port_id = port->logical_port_id; |
266 | arr[i].reg_type = EHEA_BCMC_BROADCAST | | 282 | arr[i].reg_type = EHEA_BCMC_BROADCAST | |
@@ -272,9 +288,13 @@ static void ehea_update_bcmc_registrations(void) | |||
272 | arr[i].reg_type = EHEA_BCMC_BROADCAST | | 288 | arr[i].reg_type = EHEA_BCMC_BROADCAST | |
273 | EHEA_BCMC_VLANID_ALL; | 289 | EHEA_BCMC_VLANID_ALL; |
274 | arr[i++].macaddr = port->mac_addr; | 290 | arr[i++].macaddr = port->mac_addr; |
291 | num_registrations -= 2; | ||
275 | 292 | ||
276 | list_for_each_entry(mc_entry, | 293 | list_for_each_entry(mc_entry, |
277 | &port->mc_list->list, list) { | 294 | &port->mc_list->list, list) { |
295 | if (num_registrations == 0) | ||
296 | goto out_update; | ||
297 | |||
278 | arr[i].adh = adapter->handle; | 298 | arr[i].adh = adapter->handle; |
279 | arr[i].port_id = port->logical_port_id; | 299 | arr[i].port_id = port->logical_port_id; |
280 | arr[i].reg_type = EHEA_BCMC_SCOPE_ALL | | 300 | arr[i].reg_type = EHEA_BCMC_SCOPE_ALL | |
@@ -288,6 +308,7 @@ static void ehea_update_bcmc_registrations(void) | |||
288 | EHEA_BCMC_MULTICAST | | 308 | EHEA_BCMC_MULTICAST | |
289 | EHEA_BCMC_VLANID_ALL; | 309 | EHEA_BCMC_VLANID_ALL; |
290 | arr[i++].macaddr = mc_entry->macaddr; | 310 | arr[i++].macaddr = mc_entry->macaddr; |
311 | num_registrations -= 2; | ||
291 | } | 312 | } |
292 | } | 313 | } |
293 | } | 314 | } |
@@ -296,6 +317,8 @@ out_update: | |||
296 | kfree(ehea_bcmc_regs.arr); | 317 | kfree(ehea_bcmc_regs.arr); |
297 | ehea_bcmc_regs.arr = arr; | 318 | ehea_bcmc_regs.arr = arr; |
298 | ehea_bcmc_regs.num_entries = i; | 319 | ehea_bcmc_regs.num_entries = i; |
320 | out: | ||
321 | spin_unlock_irqrestore(&ehea_bcmc_regs.lock, flags); | ||
299 | } | 322 | } |
300 | 323 | ||
301 | static struct net_device_stats *ehea_get_stats(struct net_device *dev) | 324 | static struct net_device_stats *ehea_get_stats(struct net_device *dev) |
@@ -1762,8 +1785,6 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa) | |||
1762 | 1785 | ||
1763 | memcpy(dev->dev_addr, mac_addr->sa_data, dev->addr_len); | 1786 | memcpy(dev->dev_addr, mac_addr->sa_data, dev->addr_len); |
1764 | 1787 | ||
1765 | spin_lock(&ehea_bcmc_regs.lock); | ||
1766 | |||
1767 | /* Deregister old MAC in pHYP */ | 1788 | /* Deregister old MAC in pHYP */ |
1768 | if (port->state == EHEA_PORT_UP) { | 1789 | if (port->state == EHEA_PORT_UP) { |
1769 | ret = ehea_broadcast_reg_helper(port, H_DEREG_BCMC); | 1790 | ret = ehea_broadcast_reg_helper(port, H_DEREG_BCMC); |
@@ -1784,7 +1805,6 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa) | |||
1784 | 1805 | ||
1785 | out_upregs: | 1806 | out_upregs: |
1786 | ehea_update_bcmc_registrations(); | 1807 | ehea_update_bcmc_registrations(); |
1787 | spin_unlock(&ehea_bcmc_regs.lock); | ||
1788 | out_free: | 1808 | out_free: |
1789 | free_page((unsigned long)cb0); | 1809 | free_page((unsigned long)cb0); |
1790 | out: | 1810 | out: |
@@ -1946,8 +1966,6 @@ static void ehea_set_multicast_list(struct net_device *dev) | |||
1946 | } | 1966 | } |
1947 | ehea_promiscuous(dev, 0); | 1967 | ehea_promiscuous(dev, 0); |
1948 | 1968 | ||
1949 | spin_lock(&ehea_bcmc_regs.lock); | ||
1950 | |||
1951 | if (dev->flags & IFF_ALLMULTI) { | 1969 | if (dev->flags & IFF_ALLMULTI) { |
1952 | ehea_allmulti(dev, 1); | 1970 | ehea_allmulti(dev, 1); |
1953 | goto out; | 1971 | goto out; |
@@ -1977,7 +1995,6 @@ static void ehea_set_multicast_list(struct net_device *dev) | |||
1977 | } | 1995 | } |
1978 | out: | 1996 | out: |
1979 | ehea_update_bcmc_registrations(); | 1997 | ehea_update_bcmc_registrations(); |
1980 | spin_unlock(&ehea_bcmc_regs.lock); | ||
1981 | return; | 1998 | return; |
1982 | } | 1999 | } |
1983 | 2000 | ||
@@ -2458,8 +2475,6 @@ static int ehea_up(struct net_device *dev) | |||
2458 | if (port->state == EHEA_PORT_UP) | 2475 | if (port->state == EHEA_PORT_UP) |
2459 | return 0; | 2476 | return 0; |
2460 | 2477 | ||
2461 | mutex_lock(&ehea_fw_handles.lock); | ||
2462 | |||
2463 | ret = ehea_port_res_setup(port, port->num_def_qps, | 2478 | ret = ehea_port_res_setup(port, port->num_def_qps, |
2464 | port->num_add_tx_qps); | 2479 | port->num_add_tx_qps); |
2465 | if (ret) { | 2480 | if (ret) { |
@@ -2496,8 +2511,6 @@ static int ehea_up(struct net_device *dev) | |||
2496 | } | 2511 | } |
2497 | } | 2512 | } |
2498 | 2513 | ||
2499 | spin_lock(&ehea_bcmc_regs.lock); | ||
2500 | |||
2501 | ret = ehea_broadcast_reg_helper(port, H_REG_BCMC); | 2514 | ret = ehea_broadcast_reg_helper(port, H_REG_BCMC); |
2502 | if (ret) { | 2515 | if (ret) { |
2503 | ret = -EIO; | 2516 | ret = -EIO; |
@@ -2519,10 +2532,7 @@ out: | |||
2519 | ehea_info("Failed starting %s. ret=%i", dev->name, ret); | 2532 | ehea_info("Failed starting %s. ret=%i", dev->name, ret); |
2520 | 2533 | ||
2521 | ehea_update_bcmc_registrations(); | 2534 | ehea_update_bcmc_registrations(); |
2522 | spin_unlock(&ehea_bcmc_regs.lock); | ||
2523 | |||
2524 | ehea_update_firmware_handles(); | 2535 | ehea_update_firmware_handles(); |
2525 | mutex_unlock(&ehea_fw_handles.lock); | ||
2526 | 2536 | ||
2527 | return ret; | 2537 | return ret; |
2528 | } | 2538 | } |
@@ -2572,9 +2582,6 @@ static int ehea_down(struct net_device *dev) | |||
2572 | if (port->state == EHEA_PORT_DOWN) | 2582 | if (port->state == EHEA_PORT_DOWN) |
2573 | return 0; | 2583 | return 0; |
2574 | 2584 | ||
2575 | mutex_lock(&ehea_fw_handles.lock); | ||
2576 | |||
2577 | spin_lock(&ehea_bcmc_regs.lock); | ||
2578 | ehea_drop_multicast_list(dev); | 2585 | ehea_drop_multicast_list(dev); |
2579 | ehea_broadcast_reg_helper(port, H_DEREG_BCMC); | 2586 | ehea_broadcast_reg_helper(port, H_DEREG_BCMC); |
2580 | 2587 | ||
@@ -2583,7 +2590,6 @@ static int ehea_down(struct net_device *dev) | |||
2583 | port->state = EHEA_PORT_DOWN; | 2590 | port->state = EHEA_PORT_DOWN; |
2584 | 2591 | ||
2585 | ehea_update_bcmc_registrations(); | 2592 | ehea_update_bcmc_registrations(); |
2586 | spin_unlock(&ehea_bcmc_regs.lock); | ||
2587 | 2593 | ||
2588 | ret = ehea_clean_all_portres(port); | 2594 | ret = ehea_clean_all_portres(port); |
2589 | if (ret) | 2595 | if (ret) |
@@ -2591,7 +2597,6 @@ static int ehea_down(struct net_device *dev) | |||
2591 | dev->name, ret); | 2597 | dev->name, ret); |
2592 | 2598 | ||
2593 | ehea_update_firmware_handles(); | 2599 | ehea_update_firmware_handles(); |
2594 | mutex_unlock(&ehea_fw_handles.lock); | ||
2595 | 2600 | ||
2596 | return ret; | 2601 | return ret; |
2597 | } | 2602 | } |
@@ -3368,7 +3373,6 @@ static int __devinit ehea_probe_adapter(struct of_device *dev, | |||
3368 | ehea_error("Invalid ibmebus device probed"); | 3373 | ehea_error("Invalid ibmebus device probed"); |
3369 | return -EINVAL; | 3374 | return -EINVAL; |
3370 | } | 3375 | } |
3371 | mutex_lock(&ehea_fw_handles.lock); | ||
3372 | 3376 | ||
3373 | adapter = kzalloc(sizeof(*adapter), GFP_KERNEL); | 3377 | adapter = kzalloc(sizeof(*adapter), GFP_KERNEL); |
3374 | if (!adapter) { | 3378 | if (!adapter) { |
@@ -3453,7 +3457,7 @@ out_free_ad: | |||
3453 | 3457 | ||
3454 | out: | 3458 | out: |
3455 | ehea_update_firmware_handles(); | 3459 | ehea_update_firmware_handles(); |
3456 | mutex_unlock(&ehea_fw_handles.lock); | 3460 | |
3457 | return ret; | 3461 | return ret; |
3458 | } | 3462 | } |
3459 | 3463 | ||
@@ -3472,8 +3476,6 @@ static int __devexit ehea_remove(struct of_device *dev) | |||
3472 | 3476 | ||
3473 | flush_scheduled_work(); | 3477 | flush_scheduled_work(); |
3474 | 3478 | ||
3475 | mutex_lock(&ehea_fw_handles.lock); | ||
3476 | |||
3477 | ibmebus_free_irq(adapter->neq->attr.ist1, adapter); | 3479 | ibmebus_free_irq(adapter->neq->attr.ist1, adapter); |
3478 | tasklet_kill(&adapter->neq_tasklet); | 3480 | tasklet_kill(&adapter->neq_tasklet); |
3479 | 3481 | ||
@@ -3483,7 +3485,6 @@ static int __devexit ehea_remove(struct of_device *dev) | |||
3483 | kfree(adapter); | 3485 | kfree(adapter); |
3484 | 3486 | ||
3485 | ehea_update_firmware_handles(); | 3487 | ehea_update_firmware_handles(); |
3486 | mutex_unlock(&ehea_fw_handles.lock); | ||
3487 | 3488 | ||
3488 | return 0; | 3489 | return 0; |
3489 | } | 3490 | } |
@@ -3532,6 +3533,9 @@ static int ehea_mem_notifier(struct notifier_block *nb, | |||
3532 | default: | 3533 | default: |
3533 | break; | 3534 | break; |
3534 | } | 3535 | } |
3536 | |||
3537 | ehea_update_firmware_handles(); | ||
3538 | |||
3535 | return NOTIFY_OK; | 3539 | return NOTIFY_OK; |
3536 | } | 3540 | } |
3537 | 3541 | ||