Forráskód Böngészése

ehea: only register irq after setting up ports

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>
Thadeu Lima de Souza Cascardo 13 éve
szülő
commit
c2f1244b86
1 módosított fájl, 18 hozzáadás és 12 törlés
  1. 18 12
      drivers/net/ethernet/ibm/ehea/ehea_main.c

+ 18 - 12
drivers/net/ethernet/ibm/ehea/ehea_main.c

@@ -3261,6 +3261,7 @@ static int __devinit ehea_probe_adapter(struct platform_device *dev,
 	struct ehea_adapter *adapter;
 	struct ehea_adapter *adapter;
 	const u64 *adapter_handle;
 	const u64 *adapter_handle;
 	int ret;
 	int ret;
+	int i;
 
 
 	if (!dev || !dev->dev.of_node) {
 	if (!dev || !dev->dev.of_node) {
 		pr_err("Invalid ibmebus device probed\n");
 		pr_err("Invalid ibmebus device probed\n");
@@ -3314,17 +3315,9 @@ static int __devinit ehea_probe_adapter(struct platform_device *dev,
 	tasklet_init(&adapter->neq_tasklet, ehea_neq_tasklet,
 	tasklet_init(&adapter->neq_tasklet, ehea_neq_tasklet,
 		     (unsigned long)adapter);
 		     (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);
 	ret = ehea_create_device_sysfs(dev);
 	if (ret)
 	if (ret)
-		goto out_free_irq;
+		goto out_kill_eq;
 
 
 	ret = ehea_setup_ports(adapter);
 	ret = ehea_setup_ports(adapter);
 	if (ret) {
 	if (ret) {
@@ -3332,15 +3325,28 @@ static int __devinit ehea_probe_adapter(struct platform_device *dev,
 		goto out_rem_dev_sysfs;
 		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;
 	ret = 0;
 	goto out;
 	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:
 out_rem_dev_sysfs:
 	ehea_remove_device_sysfs(dev);
 	ehea_remove_device_sysfs(dev);
 
 
-out_free_irq:
-	ibmebus_free_irq(adapter->neq->attr.ist1, adapter);
-
 out_kill_eq:
 out_kill_eq:
 	ehea_destroy_eq(adapter->neq);
 	ehea_destroy_eq(adapter->neq);