Skip to content

Commit

Permalink
ehea: only register irq after setting up ports
Browse files Browse the repository at this point in the history
If we receive an interrupt too early before we set up ports in the probe
function, there won't be any port ready to handle it.

Only registering the irq after the ports are setup fixes the problem,
and works fine without losing any interrupts.

This causes crashes in some situations:

[c000000f7ff7fd60] d000000008e223f0 .ehea_neq_tasklet+0x78/0x148 [ehea]
[c000000f7ff7fe00] c0000000000b6cac .tasklet_hi_action+0xdc/0x210
[c000000f7ff7fea0] c0000000000b7cc8 .__do_softirq+0x178/0x300
[c000000f7ff7ff90] c000000000022694 .call_do_softirq+0x14/0x24
[c000000f68ee7900] c000000000010e04 .do_softirq+0xec/0x110
[c000000f68ee79a0] c0000000000b789c .irq_exit+0xac/0xe0
[c000000f68ee7a20] c0000000000110bc .do_IRQ+0x114/0x2a8
[c000000f68ee7ae0] c00000000000553c hardware_interrupt_entry+0x18/0x1c

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Thadeu Lima de Souza Cascardo authored and David S. Miller committed Apr 24, 2012
1 parent e6e056b commit c2f1244
Showing 1 changed file with 18 additions and 12 deletions.
30 changes: 18 additions & 12 deletions drivers/net/ethernet/ibm/ehea/ehea_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -3261,6 +3261,7 @@ static int __devinit ehea_probe_adapter(struct platform_device *dev,
struct ehea_adapter *adapter;
const u64 *adapter_handle;
int ret;
int i;

if (!dev || !dev->dev.of_node) {
pr_err("Invalid ibmebus device probed\n");
Expand Down Expand Up @@ -3314,33 +3315,38 @@ static int __devinit ehea_probe_adapter(struct platform_device *dev,
tasklet_init(&adapter->neq_tasklet, ehea_neq_tasklet,
(unsigned long)adapter);

ret = ibmebus_request_irq(adapter->neq->attr.ist1,
ehea_interrupt_neq, IRQF_DISABLED,
"ehea_neq", adapter);
if (ret) {
dev_err(&dev->dev, "requesting NEQ IRQ failed\n");
goto out_kill_eq;
}

ret = ehea_create_device_sysfs(dev);
if (ret)
goto out_free_irq;
goto out_kill_eq;

ret = ehea_setup_ports(adapter);
if (ret) {
dev_err(&dev->dev, "setup_ports failed\n");
goto out_rem_dev_sysfs;
}

ret = ibmebus_request_irq(adapter->neq->attr.ist1,
ehea_interrupt_neq, IRQF_DISABLED,
"ehea_neq", adapter);
if (ret) {
dev_err(&dev->dev, "requesting NEQ IRQ failed\n");
goto out_shutdown_ports;
}


ret = 0;
goto out;

out_shutdown_ports:
for (i = 0; i < EHEA_MAX_PORTS; i++)
if (adapter->port[i]) {
ehea_shutdown_single_port(adapter->port[i]);
adapter->port[i] = NULL;
}

out_rem_dev_sysfs:
ehea_remove_device_sysfs(dev);

out_free_irq:
ibmebus_free_irq(adapter->neq->attr.ist1, adapter);

out_kill_eq:
ehea_destroy_eq(adapter->neq);

Expand Down

0 comments on commit c2f1244

Please sign in to comment.