aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan-Bernd Themann <themann@de.ibm.com>2009-03-13 16:50:40 -0400
committerDavid S. Miller <davem@davemloft.net>2009-03-13 16:50:40 -0400
commit52e21b1bd96444c452f6eab7dc438a8a898aa14a (patch)
tree8e25fd2a92457662bbc72d3027b3d419dd6b9b76
parentf9ac30f080d23ef0a2d4a1b7c6806c9a21c0f324 (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>
-rw-r--r--drivers/net/ehea/ehea.h2
-rw-r--r--drivers/net/ehea/ehea_main.c56
2 files changed, 31 insertions, 27 deletions
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 029631c58f0c..6e317caf429c 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -40,7 +40,7 @@
40#include <asm/io.h> 40#include <asm/io.h>
41 41
42#define DRV_NAME "ehea" 42#define DRV_NAME "ehea"
43#define DRV_VERSION "EHEA_0099" 43#define DRV_VERSION "EHEA_0100"
44 44
45/* eHEA capability flags */ 45/* eHEA capability flags */
46#define DLPAR_PORT_ADD_REM 1 46#define DLPAR_PORT_ADD_REM 1
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
221out_update: 229out_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;
233out:
234 mutex_unlock(&ehea_fw_handles.lock);
225} 235}
226 236
227static void ehea_update_bcmc_registrations(void) 237static 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;
320out:
321 spin_unlock_irqrestore(&ehea_bcmc_regs.lock, flags);
299} 322}
300 323
301static struct net_device_stats *ehea_get_stats(struct net_device *dev) 324static 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
1785out_upregs: 1806out_upregs:
1786 ehea_update_bcmc_registrations(); 1807 ehea_update_bcmc_registrations();
1787 spin_unlock(&ehea_bcmc_regs.lock);
1788out_free: 1808out_free:
1789 free_page((unsigned long)cb0); 1809 free_page((unsigned long)cb0);
1790out: 1810out:
@@ -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 }
1978out: 1996out:
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
3454out: 3458out:
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