summary refs log tree commit diff
path: root/drivers/net/sunhme.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/sunhme.c')
-rw-r--r--drivers/net/sunhme.c46
1 files changed, 36 insertions, 10 deletions
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index 7a72a3112f0a..d4fb4acdbebd 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -2543,25 +2543,36 @@ static struct quattro * __devinit quattro_sbus_find(struct of_device *child)
 }
 
 /* After all quattro cards have been probed, we call these functions
- * to register the IRQ handlers.
+ * to register the IRQ handlers for the cards that have been
+ * successfully probed and skip the cards that failed to initialize
  */
-static void __init quattro_sbus_register_irqs(void)
+static int __init quattro_sbus_register_irqs(void)
 {
 	struct quattro *qp;
 
 	for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) {
 		struct of_device *op = qp->quattro_dev;
-		int err;
+		int err, qfe_slot, skip = 0;
+
+		for (qfe_slot = 0; qfe_slot < 4; qfe_slot++) {
+			if (!qp->happy_meals[qfe_slot])
+				skip = 1;
+		}
+		if (skip)
+			continue;
 
 		err = request_irq(op->irqs[0],
 				  quattro_sbus_interrupt,
 				  IRQF_SHARED, "Quattro",
 				  qp);
 		if (err != 0) {
-			printk(KERN_ERR "Quattro: Fatal IRQ registery error %d.\n", err);
-			panic("QFE request irq");
+			printk(KERN_ERR "Quattro HME: IRQ registration "
+			       "error %d.\n", err);
+			return err;
 		}
 	}
+
+	return 0;
 }
 
 static void quattro_sbus_free_irqs(void)
@@ -2570,6 +2581,14 @@ static void quattro_sbus_free_irqs(void)
 
 	for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) {
 		struct of_device *op = qp->quattro_dev;
+		int qfe_slot, skip = 0;
+
+		for (qfe_slot = 0; qfe_slot < 4; qfe_slot++) {
+			if (!qp->happy_meals[qfe_slot])
+				skip = 1;
+		}
+		if (skip)
+			continue;
 
 		free_irq(op->irqs[0], qp);
 	}
@@ -2629,6 +2648,14 @@ static int __devinit happy_meal_sbus_probe_one(struct of_device *op, int is_qfe)
 	int i, qfe_slot = -1;
 	int err = -ENODEV;
 
+	sbus_dp = to_of_device(op->dev.parent)->node;
+	if (is_qfe)
+		sbus_dp = to_of_device(op->dev.parent->parent)->node;
+
+	/* We can match PCI devices too, do not accept those here. */
+	if (strcmp(sbus_dp->name, "sbus"))
+		return err;
+
 	if (is_qfe) {
 		qp = quattro_sbus_find(op);
 		if (qp == NULL)
@@ -2734,10 +2761,6 @@ static int __devinit happy_meal_sbus_probe_one(struct of_device *op, int is_qfe)
 	if (qp != NULL)
 		hp->happy_flags |= HFLAG_QUATTRO;
 
-	sbus_dp = to_of_device(op->dev.parent)->node;
-	if (is_qfe)
-		sbus_dp = to_of_device(op->dev.parent->parent)->node;
-
 	/* Get the supported DVMA burst sizes from our Happy SBUS. */
 	hp->happy_bursts = of_getintprop_default(sbus_dp,
 						 "burst-sizes", 0x00);
@@ -2824,6 +2847,9 @@ err_out_iounmap:
 	if (hp->tcvregs)
 		of_iounmap(&op->resource[4], hp->tcvregs, TCVR_REG_SIZE);
 
+	if (qp)
+		qp->happy_meals[qfe_slot] = NULL;
+
 err_out_free_netdev:
 	free_netdev(dev);
 
@@ -3281,7 +3307,7 @@ static int __init happy_meal_sbus_init(void)
 
 	err = of_register_driver(&hme_sbus_driver, &of_bus_type);
 	if (!err)
-		quattro_sbus_register_irqs();
+		err = quattro_sbus_register_irqs();
 
 	return err;
 }