[PATCH] arch/mips/pci/ioc3.c

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi

I tried to use the mainline ioc3 meta driver with my Octane 
and got it working. But i needed to change a dual_irq test,
which i think would not work with ia64.

Maybe this is a solution.

This is a Patch against the MIPS version.

It does the job on my Octane

Signed-off-by: Johannes Dickgreber tanzy@xxxxxx
---

Changed:

Ethernet submodule is always submodule NR 0

expected in subdrivers if idd->active[id] is 1
  ioc3_submodules[id] is a valid ioc3_submodule
  In the ethernet submodule
      ioc3_submodules[0]->intr is a valid interrupt routine
  In other submodules, if ioc3_submodules[id]->irq_mask is set
      ioc3_submodules[id]->intr is a valid interrupt routine

kmalloc to kzalloc

all IRQ are cleared in the probe routine

--- linux-2.6.22.6-mips20070902-ip30/arch/mips/pci/ioc3.c	2007-09-12 21:54:59 +0200
+++ linux-octane-2/arch/mips/pci/ioc3.c	2007-10-07 20:34:37 +0200
@@ -26,8 +26,9 @@ static LIST_HEAD(ioc3_devices);
 static int ioc3_counter;
 static DECLARE_RWSEM(ioc3_devices_rwsem);
 
+/* ethernet submodule is always 0 */
+#define ETH_ID 0
 static struct ioc3_submodule *ioc3_submodules[IOC3_MAX_SUBMODULES];
-static struct ioc3_submodule *ioc3_ethernet;
 static DEFINE_RWLOCK(ioc3_submodules_lock);
 
 
@@ -426,30 +427,29 @@ static irqreturn_t ioc3_intr_io(int irq,
 {
 	unsigned long flags;
 	struct ioc3_driver_data *idd = (struct ioc3_driver_data *)arg;
-	int handled = 1, id;
+	int handled = 0, id;
 	unsigned int pending;
 
 	read_lock_irqsave(&ioc3_submodules_lock, flags);
-
-	if (!idd->dual_irq && readb(idd->vma->eisr))	/* send Ethernet IRQ to the driver */
-		if (ioc3_ethernet && idd->active[ioc3_ethernet->id] &&
-						 ioc3_ethernet->intr)
-			handled = handled && !ioc3_ethernet->intr(ioc3_ethernet,
-								  idd, 0);
-
-	pending = get_pending_intrs(idd);	/* look at the IO IRQs */
-	for (id = 0; id < IOC3_MAX_SUBMODULES; id++)
-		if (idd->active[id] && ioc3_submodules[id] &&
-		    (pending & ioc3_submodules[id]->irq_mask) &&
-		     ioc3_submodules[id]->intr)
-		{
-			write_ireg(idd, ioc3_submodules[id]->irq_mask, IOC3_W_IEC);
-			if (!ioc3_submodules[id]->intr(ioc3_submodules[id], idd,
-						       (pending &
-							ioc3_submodules[id]->irq_mask)))
-				pending &=~ ioc3_submodules[id]->irq_mask;
-			write_ireg(idd, ioc3_submodules[id]->irq_mask, IOC3_W_IES);
-		}
+	/* send Ethernet IRQ to the driver */
+	if (idd->active[ETH_ID] && !idd->dual_irq)
+		if (readl(&idd->vma->eisr))
+			handled = !ioc3_submodules[ETH_ID]->intr(ioc3_submodules[ETH_ID], idd, 0);
+
+	/* look at the IO IRQs */
+	pending = get_pending_intrs(idd);
+	for (id = 1; id < IOC3_MAX_SUBMODULES; id++)
+		if (idd->active[id])
+			if (pending & ioc3_submodules[id]->irq_mask) {
+				write_ireg(idd, ioc3_submodules[id]->irq_mask, IOC3_W_IEC);
+				if (!ioc3_submodules[id]->intr(ioc3_submodules[id], idd,
+								(pending &
+								ioc3_submodules[id]->irq_mask))) {
+					pending &= ~ioc3_submodules[id]->irq_mask;
+					handled = 1;
+				}	
+				write_ireg(idd, ioc3_submodules[id]->irq_mask, IOC3_W_IES);
+			}
 	read_unlock_irqrestore(&ioc3_submodules_lock, flags);
 
 	if (pending) {
@@ -459,6 +459,7 @@ static irqreturn_t ioc3_intr_io(int irq,
 		write_ireg(idd, pending, IOC3_W_IEC);
 		handled = 1;
 	}
+
 	return handled ? IRQ_HANDLED : IRQ_NONE;
 }
 
@@ -466,15 +467,13 @@ static irqreturn_t ioc3_intr_eth(int irq
 {
 	unsigned long flags;
 	struct ioc3_driver_data *idd = (struct ioc3_driver_data *)arg;
-	int handled = 1;
-
-	if (!idd->dual_irq)
-		return IRQ_NONE;
+	int handled = 0;
 
 	read_lock_irqsave(&ioc3_submodules_lock, flags);
-	if (ioc3_ethernet && idd->active[ioc3_ethernet->id] && ioc3_ethernet->intr)
-		handled = handled && !ioc3_ethernet->intr(ioc3_ethernet, idd, 0);
+	if (idd->active[ETH_ID] && idd->dual_irq)
+		handled = !ioc3_submodules[ETH_ID]->intr(ioc3_submodules[ETH_ID], idd, 0);
 	read_unlock_irqrestore(&ioc3_submodules_lock, flags);
+
 	return handled ? IRQ_HANDLED : IRQ_NONE;
 }
 
@@ -524,7 +523,7 @@ void ioc3_gpio(struct ioc3_driver_data *
 static int find_slot(void **tab, int max)
 {
 	int i;
-	for (i = 0; i < max; i++)
+	for (i = 1; i < max; i++)
 		if (!(tab[i]))
 			return i;
 	return -1;
@@ -538,23 +537,26 @@ int ioc3_register_submodule(struct ioc3_
 	unsigned long flags;
 
 	write_lock_irqsave(&ioc3_submodules_lock, flags);
-	alloc_id = find_slot((void **)ioc3_submodules, IOC3_MAX_SUBMODULES);
-	if (alloc_id != -1) {
-		ioc3_submodules[alloc_id] = is;
-		if (is->ethernet) {
-			if (ioc3_ethernet == NULL)
-				ioc3_ethernet = is;
-			else
-				printk(KERN_WARNING
-				       "IOC3 Ethernet module already registered!\n");
-		}
-	}
+	if (is->ethernet)
+		if (ioc3_submodules[ETH_ID] == NULL)
+			alloc_id = ETH_ID;
+		else
+			alloc_id = -2;
+	else
+		alloc_id = find_slot((void **)ioc3_submodules, IOC3_MAX_SUBMODULES);
+		
+	if (alloc_id >= 0)
+		ioc3_submodules[alloc_id] = is;		
 	write_unlock_irqrestore(&ioc3_submodules_lock, flags);
 
 	if (alloc_id == -1) {
 		printk(KERN_WARNING "Increase IOC3_MAX_SUBMODULES!\n");
 		return -ENOMEM;
 	}
+	if (alloc_id == -2) { 
+		printk(KERN_WARNING "IOC3 Ethernet module already registered!\n");
+		return -ENODEV;
+	}
 
 	is->id=alloc_id;
 
@@ -585,8 +587,6 @@ void ioc3_unregister_submodule(struct io
 	else
 		printk(KERN_WARNING "IOC3 submodule %s has wrong ID.\n",
 				    is->name);
-	if (ioc3_ethernet == is)
-		ioc3_ethernet = NULL;
 	write_unlock_irqrestore(&ioc3_submodules_lock, flags);
 
 	/* Remove submodule for each IOC3 */
@@ -670,7 +670,7 @@ static int ioc3_probe(struct pci_dev *pd
 	}
 
 	/* Set up per-IOC3 data */
-	idd = kmalloc(sizeof(struct ioc3_driver_data), GFP_KERNEL);
+	idd = kzalloc(sizeof(struct ioc3_driver_data), GFP_KERNEL);
 	if (!idd) {
 		printk(KERN_WARNING
 		       "%s: Failed to allocate IOC3 data for pci_dev %s.\n",
@@ -678,7 +678,7 @@ static int ioc3_probe(struct pci_dev *pd
 		ret = -ENODEV;
 		goto out_idd;
 	}
-	memset(idd, 0, sizeof(struct ioc3_driver_data));
+
 	spin_lock_init(&idd->ir_lock);
 	spin_lock_init(&idd->gpio_lock);
 	idd->pdev = pdev;
@@ -733,16 +733,18 @@ static int ioc3_probe(struct pci_dev *pd
 	pci_write_config_dword(pdev, PCI_COMMAND,
 			       pcmd | PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
 
+	/* Clear IRQs */
 	write_ireg(idd, ~0, IOC3_W_IEC);
 	writel(~0, &idd->vma->sio_ir);
 
+	writel(0, &idd->vma->emcr);		/* Shutup */
+	writel(0, &idd->vma->eier);		/* Disable interrupts */
+	(void) readl(&idd->vma->eier);		/* Flush */
+
 	/* Set up IRQs */
 	if (idd->class == IOC3_CLASS_BASE_IP30 ||
 	    idd->class == IOC3_CLASS_BASE_IP27) {
 
-		writel(0, &idd->vma->eier);
-		writel(~0, &idd->vma->eisr);
-
 		idd->dual_irq = 1;
 		if (!request_irq(pdev->irq, ioc3_intr_eth, IRQF_SHARED,
 				 "ioc3-eth", (void *)idd)) {


[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux