Skip to content

Commit 52e21b1

Browse files
Jan-Bernd Themanndavem330
authored andcommitted
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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent f9ac30f commit 52e21b1

File tree

2 files changed

+31
-27
lines changed

2 files changed

+31
-27
lines changed

drivers/net/ehea/ehea.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
#include <asm/io.h>
4141

4242
#define DRV_NAME "ehea"
43-
#define DRV_VERSION "EHEA_0099"
43+
#define DRV_VERSION "EHEA_0100"
4444

4545
/* eHEA capability flags */
4646
#define DLPAR_PORT_ADD_REM 1

drivers/net/ehea/ehea_main.c

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ static void ehea_update_firmware_handles(void)
155155
int num_fw_handles, k, l;
156156

157157
/* Determine number of handles */
158+
mutex_lock(&ehea_fw_handles.lock);
159+
158160
list_for_each_entry(adapter, &adapter_list, list) {
159161
num_adapters++;
160162

@@ -176,15 +178,19 @@ static void ehea_update_firmware_handles(void)
176178
if (num_fw_handles) {
177179
arr = kzalloc(num_fw_handles * sizeof(*arr), GFP_KERNEL);
178180
if (!arr)
179-
return; /* Keep the existing array */
181+
goto out; /* Keep the existing array */
180182
} else
181183
goto out_update;
182184

183185
list_for_each_entry(adapter, &adapter_list, list) {
186+
if (num_adapters == 0)
187+
break;
188+
184189
for (k = 0; k < EHEA_MAX_PORTS; k++) {
185190
struct ehea_port *port = adapter->port[k];
186191

187-
if (!port || (port->state != EHEA_PORT_UP))
192+
if (!port || (port->state != EHEA_PORT_UP)
193+
|| (num_ports == 0))
188194
continue;
189195

190196
for (l = 0;
@@ -207,6 +213,7 @@ static void ehea_update_firmware_handles(void)
207213
}
208214
arr[i].adh = adapter->handle;
209215
arr[i++].fwh = port->qp_eq->fw_handle;
216+
num_ports--;
210217
}
211218

212219
arr[i].adh = adapter->handle;
@@ -216,23 +223,29 @@ static void ehea_update_firmware_handles(void)
216223
arr[i].adh = adapter->handle;
217224
arr[i++].fwh = adapter->mr.handle;
218225
}
226+
num_adapters--;
219227
}
220228

221229
out_update:
222230
kfree(ehea_fw_handles.arr);
223231
ehea_fw_handles.arr = arr;
224232
ehea_fw_handles.num_entries = i;
233+
out:
234+
mutex_unlock(&ehea_fw_handles.lock);
225235
}
226236

227237
static void ehea_update_bcmc_registrations(void)
228238
{
239+
unsigned long flags;
229240
struct ehea_bcmc_reg_entry *arr = NULL;
230241
struct ehea_adapter *adapter;
231242
struct ehea_mc_list *mc_entry;
232243
int num_registrations = 0;
233244
int i = 0;
234245
int k;
235246

247+
spin_lock_irqsave(&ehea_bcmc_regs.lock, flags);
248+
236249
/* Determine number of registrations */
237250
list_for_each_entry(adapter, &adapter_list, list)
238251
for (k = 0; k < EHEA_MAX_PORTS; k++) {
@@ -250,7 +263,7 @@ static void ehea_update_bcmc_registrations(void)
250263
if (num_registrations) {
251264
arr = kzalloc(num_registrations * sizeof(*arr), GFP_ATOMIC);
252265
if (!arr)
253-
return; /* Keep the existing array */
266+
goto out; /* Keep the existing array */
254267
} else
255268
goto out_update;
256269

@@ -261,6 +274,9 @@ static void ehea_update_bcmc_registrations(void)
261274
if (!port || (port->state != EHEA_PORT_UP))
262275
continue;
263276

277+
if (num_registrations == 0)
278+
goto out_update;
279+
264280
arr[i].adh = adapter->handle;
265281
arr[i].port_id = port->logical_port_id;
266282
arr[i].reg_type = EHEA_BCMC_BROADCAST |
@@ -272,9 +288,13 @@ static void ehea_update_bcmc_registrations(void)
272288
arr[i].reg_type = EHEA_BCMC_BROADCAST |
273289
EHEA_BCMC_VLANID_ALL;
274290
arr[i++].macaddr = port->mac_addr;
291+
num_registrations -= 2;
275292

276293
list_for_each_entry(mc_entry,
277294
&port->mc_list->list, list) {
295+
if (num_registrations == 0)
296+
goto out_update;
297+
278298
arr[i].adh = adapter->handle;
279299
arr[i].port_id = port->logical_port_id;
280300
arr[i].reg_type = EHEA_BCMC_SCOPE_ALL |
@@ -288,6 +308,7 @@ static void ehea_update_bcmc_registrations(void)
288308
EHEA_BCMC_MULTICAST |
289309
EHEA_BCMC_VLANID_ALL;
290310
arr[i++].macaddr = mc_entry->macaddr;
311+
num_registrations -= 2;
291312
}
292313
}
293314
}
@@ -296,6 +317,8 @@ static void ehea_update_bcmc_registrations(void)
296317
kfree(ehea_bcmc_regs.arr);
297318
ehea_bcmc_regs.arr = arr;
298319
ehea_bcmc_regs.num_entries = i;
320+
out:
321+
spin_unlock_irqrestore(&ehea_bcmc_regs.lock, flags);
299322
}
300323

301324
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)
17621785

17631786
memcpy(dev->dev_addr, mac_addr->sa_data, dev->addr_len);
17641787

1765-
spin_lock(&ehea_bcmc_regs.lock);
1766-
17671788
/* Deregister old MAC in pHYP */
17681789
if (port->state == EHEA_PORT_UP) {
17691790
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)
17841805

17851806
out_upregs:
17861807
ehea_update_bcmc_registrations();
1787-
spin_unlock(&ehea_bcmc_regs.lock);
17881808
out_free:
17891809
free_page((unsigned long)cb0);
17901810
out:
@@ -1946,8 +1966,6 @@ static void ehea_set_multicast_list(struct net_device *dev)
19461966
}
19471967
ehea_promiscuous(dev, 0);
19481968

1949-
spin_lock(&ehea_bcmc_regs.lock);
1950-
19511969
if (dev->flags & IFF_ALLMULTI) {
19521970
ehea_allmulti(dev, 1);
19531971
goto out;
@@ -1977,7 +1995,6 @@ static void ehea_set_multicast_list(struct net_device *dev)
19771995
}
19781996
out:
19791997
ehea_update_bcmc_registrations();
1980-
spin_unlock(&ehea_bcmc_regs.lock);
19811998
return;
19821999
}
19832000

@@ -2458,8 +2475,6 @@ static int ehea_up(struct net_device *dev)
24582475
if (port->state == EHEA_PORT_UP)
24592476
return 0;
24602477

2461-
mutex_lock(&ehea_fw_handles.lock);
2462-
24632478
ret = ehea_port_res_setup(port, port->num_def_qps,
24642479
port->num_add_tx_qps);
24652480
if (ret) {
@@ -2496,8 +2511,6 @@ static int ehea_up(struct net_device *dev)
24962511
}
24972512
}
24982513

2499-
spin_lock(&ehea_bcmc_regs.lock);
2500-
25012514
ret = ehea_broadcast_reg_helper(port, H_REG_BCMC);
25022515
if (ret) {
25032516
ret = -EIO;
@@ -2519,10 +2532,7 @@ static int ehea_up(struct net_device *dev)
25192532
ehea_info("Failed starting %s. ret=%i", dev->name, ret);
25202533

25212534
ehea_update_bcmc_registrations();
2522-
spin_unlock(&ehea_bcmc_regs.lock);
2523-
25242535
ehea_update_firmware_handles();
2525-
mutex_unlock(&ehea_fw_handles.lock);
25262536

25272537
return ret;
25282538
}
@@ -2572,9 +2582,6 @@ static int ehea_down(struct net_device *dev)
25722582
if (port->state == EHEA_PORT_DOWN)
25732583
return 0;
25742584

2575-
mutex_lock(&ehea_fw_handles.lock);
2576-
2577-
spin_lock(&ehea_bcmc_regs.lock);
25782585
ehea_drop_multicast_list(dev);
25792586
ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
25802587

@@ -2583,15 +2590,13 @@ static int ehea_down(struct net_device *dev)
25832590
port->state = EHEA_PORT_DOWN;
25842591

25852592
ehea_update_bcmc_registrations();
2586-
spin_unlock(&ehea_bcmc_regs.lock);
25872593

25882594
ret = ehea_clean_all_portres(port);
25892595
if (ret)
25902596
ehea_info("Failed freeing resources for %s. ret=%i",
25912597
dev->name, ret);
25922598

25932599
ehea_update_firmware_handles();
2594-
mutex_unlock(&ehea_fw_handles.lock);
25952600

25962601
return ret;
25972602
}
@@ -3368,7 +3373,6 @@ static int __devinit ehea_probe_adapter(struct of_device *dev,
33683373
ehea_error("Invalid ibmebus device probed");
33693374
return -EINVAL;
33703375
}
3371-
mutex_lock(&ehea_fw_handles.lock);
33723376

33733377
adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
33743378
if (!adapter) {
@@ -3453,7 +3457,7 @@ static int __devinit ehea_probe_adapter(struct of_device *dev,
34533457

34543458
out:
34553459
ehea_update_firmware_handles();
3456-
mutex_unlock(&ehea_fw_handles.lock);
3460+
34573461
return ret;
34583462
}
34593463

@@ -3472,8 +3476,6 @@ static int __devexit ehea_remove(struct of_device *dev)
34723476

34733477
flush_scheduled_work();
34743478

3475-
mutex_lock(&ehea_fw_handles.lock);
3476-
34773479
ibmebus_free_irq(adapter->neq->attr.ist1, adapter);
34783480
tasklet_kill(&adapter->neq_tasklet);
34793481

@@ -3483,7 +3485,6 @@ static int __devexit ehea_remove(struct of_device *dev)
34833485
kfree(adapter);
34843486

34853487
ehea_update_firmware_handles();
3486-
mutex_unlock(&ehea_fw_handles.lock);
34873488

34883489
return 0;
34893490
}
@@ -3532,6 +3533,9 @@ static int ehea_mem_notifier(struct notifier_block *nb,
35323533
default:
35333534
break;
35343535
}
3536+
3537+
ehea_update_firmware_handles();
3538+
35353539
return NOTIFY_OK;
35363540
}
35373541

0 commit comments

Comments
 (0)