[Prism54-devel] [patch 3/6] [prism54 svn trunk] various fixes for prism54 svn

jean-baptiste.note at wanadoo.fr jean-baptiste.note at wanadoo.fr
Sun May 15 11:44:12 UTC 2005


Index: trunk/ksrc/islpci_dev.c
===================================================================
--- trunk.orig/ksrc/islpci_dev.c	2005-05-15 11:03:35.000000000 +0200
+++ trunk/ksrc/islpci_dev.c	2005-05-15 11:43:55.000000000 +0200
@@ -1,5 +1,5 @@
 /*
- *  
+ *
  *  Copyright (C) 2002 Intersil Americas Inc.
  *  Copyright (C) 2003 Herbert Valerio Riedel <hvr at gnu.org>
  *  Copyright (C) 2003 Luis R. Rodriguez <mcgrof at ruslug.rutgers.edu>
@@ -185,17 +185,9 @@
     Device Interrupt Handler
 ******************************************************************************/
 
-irqreturn_t
-islpci_interrupt(int irq, void *config, struct pt_regs *regs)
-{
+static
+u32 check_irqs(void __iomem *device) {
 	u32 reg;
-	islpci_private *priv = config;
-	struct net_device *ndev = priv->ndev;
-	void __iomem *device = priv->device_base;
-	int powerstate = ISL38XX_PSM_POWERSAVE_STATE;
-
-	/* lock the interrupt handler */
-	spin_lock(&priv->slock);
 
 	/* received an interrupt request on a shared IRQ line
 	 * first check whether the device is in sleep mode */
@@ -206,8 +198,7 @@
 #if VERBOSE > SHOW_ERROR_MESSAGES
 		DEBUG(SHOW_TRACING, "Assuming someone else called the IRQ\n");
 #endif
-		spin_unlock(&priv->slock);
-		return IRQ_NONE;
+		return 0;
 	}
 
 
@@ -219,145 +210,173 @@
 	reg &= readl(device + ISL38XX_INT_EN_REG);
 	reg &= ISL38XX_INT_SOURCES;
 
-	if (reg != 0) {
-		if (islpci_get_state(priv) != PRV_STATE_SLEEP)
-			powerstate = ISL38XX_PSM_ACTIVE_STATE;
-
-		/* reset the request bits in the Identification register */
-		isl38xx_w32_flush(device, reg, ISL38XX_INT_ACK_REG);
-
-#if VERBOSE > SHOW_ERROR_MESSAGES
-		DEBUG(SHOW_FUNCTION_CALLS,
-		      "IRQ: Identification register 0x%p 0x%x \n", device, reg);
-#endif
-
-		/* check for each bit in the register separately */
-		if (reg & ISL38XX_INT_IDENT_UPDATE) {
-#if VERBOSE > SHOW_ERROR_MESSAGES
-			/* Queue has been updated */
-			DEBUG(SHOW_TRACING, "IRQ: Update flag \n");
-
-			DEBUG(SHOW_QUEUE_INDEXES,
-			      "CB drv Qs: [%i][%i][%i][%i][%i][%i]\n",
-			      le32_to_cpu(priv->control_block->
-					  driver_curr_frag[0]),
-			      le32_to_cpu(priv->control_block->
-					  driver_curr_frag[1]),
-			      le32_to_cpu(priv->control_block->
-					  driver_curr_frag[2]),
-			      le32_to_cpu(priv->control_block->
-					  driver_curr_frag[3]),
-			      le32_to_cpu(priv->control_block->
-					  driver_curr_frag[4]),
-			      le32_to_cpu(priv->control_block->
-					  driver_curr_frag[5])
-			    );
-
-			DEBUG(SHOW_QUEUE_INDEXES,
-			      "CB dev Qs: [%i][%i][%i][%i][%i][%i]\n",
-			      le32_to_cpu(priv->control_block->
-					  device_curr_frag[0]),
-			      le32_to_cpu(priv->control_block->
-					  device_curr_frag[1]),
-			      le32_to_cpu(priv->control_block->
-					  device_curr_frag[2]),
-			      le32_to_cpu(priv->control_block->
-					  device_curr_frag[3]),
-			      le32_to_cpu(priv->control_block->
-					  device_curr_frag[4]),
-			      le32_to_cpu(priv->control_block->
-					  device_curr_frag[5])
-			    );
-#endif
-
-			/* cleanup the data low transmit queue */
-			islpci_eth_cleanup_transmit(priv, priv->control_block);
-
-			/* device is in active state, update the
-			 * powerstate flag if necessary */
-			powerstate = ISL38XX_PSM_ACTIVE_STATE;
-
-			/* check all three queues in priority order
-			 * call the PIMFOR receive function until the
-			 * queue is empty */
-			if (isl38xx_in_queue(priv->control_block,
-						ISL38XX_CB_RX_MGMTQ) != 0) {
-#if VERBOSE > SHOW_ERROR_MESSAGES
-				DEBUG(SHOW_TRACING,
-				      "Received frame in Management Queue\n");
-#endif
-				islpci_mgt_receive(ndev);
+	return reg;
+}
 
-				islpci_mgt_cleanup_transmit(ndev);
+irqreturn_t
+islpci_interrupt(int irq, void *config, struct pt_regs *regs)
+{
+	u32 irqs;
+	islpci_private *priv = config;
+	struct net_device *ndev = priv->ndev;
+	int powerstate = ISL38XX_PSM_POWERSAVE_STATE;
+
+	/* lock the interrupt handler */
+	spin_lock(&priv->slock);
 
-				/* Refill slots in receive queue */
-				islpci_mgmt_rx_fill(ndev);
+	irqs = check_irqs(priv->device_base);
 
-				/* no need to trigger the device, next
-                                   islpci_mgt_transaction does it */
-			}
+	if (!irqs)
+		goto out_none;
+
+	if (islpci_get_state(priv) != PRV_STATE_SLEEP)
+		powerstate = ISL38XX_PSM_ACTIVE_STATE;
 
-			while (isl38xx_in_queue(priv->control_block,
-						ISL38XX_CB_RX_DATA_LQ) != 0) {
+	/* reset the request bits in the Identification register */
+	isl38xx_w32_flush(priv->device_base, irqs, ISL38XX_INT_ACK_REG);
+
+#if VERBOSE > SHOW_ERROR_MESSAGES
+	DEBUG(SHOW_FUNCTION_CALLS,
+	      "IRQ: Identification register 0x%p 0x%x \n", priv->device_base, irqs);
+#endif
+
+	/* check for each bit in the register separately */
+	/* service important irqs first and return ASAP */
+
+	if (irqs & ISL38XX_INT_IDENT_UPDATE) {
+#if VERBOSE > SHOW_ERROR_MESSAGES
+		/* Queue has been updated */
+		DEBUG(SHOW_TRACING, "IRQ: Update flag \n");
+
+		DEBUG(SHOW_QUEUE_INDEXES,
+		      "CB drv Qs: [%i][%i][%i][%i][%i][%i]\n",
+		      le32_to_cpu(priv->control_block->
+				  driver_curr_frag[0]),
+		      le32_to_cpu(priv->control_block->
+				  driver_curr_frag[1]),
+		      le32_to_cpu(priv->control_block->
+				  driver_curr_frag[2]),
+		      le32_to_cpu(priv->control_block->
+				  driver_curr_frag[3]),
+		      le32_to_cpu(priv->control_block->
+				  driver_curr_frag[4]),
+		      le32_to_cpu(priv->control_block->
+				  driver_curr_frag[5])
+			);
+
+		DEBUG(SHOW_QUEUE_INDEXES,
+		      "CB dev Qs: [%i][%i][%i][%i][%i][%i]\n",
+		      le32_to_cpu(priv->control_block->
+				  device_curr_frag[0]),
+		      le32_to_cpu(priv->control_block->
+				  device_curr_frag[1]),
+		      le32_to_cpu(priv->control_block->
+				  device_curr_frag[2]),
+		      le32_to_cpu(priv->control_block->
+				  device_curr_frag[3]),
+		      le32_to_cpu(priv->control_block->
+				  device_curr_frag[4]),
+		      le32_to_cpu(priv->control_block->
+				  device_curr_frag[5])
+			);
+#endif
+
+		/* cleanup the data low transmit queue */
+		islpci_eth_cleanup_transmit(priv, priv->control_block);
+
+		/* device is in active state, update the
+		 * powerstate flag if necessary */
+		powerstate = ISL38XX_PSM_ACTIVE_STATE;
+
+		/* check all three queues in priority order
+		 * call the PIMFOR receive function until the
+		 * queue is empty */
+		if (isl38xx_in_queue(priv->control_block,
+				     ISL38XX_CB_RX_MGMTQ) != 0) {
 #if VERBOSE > SHOW_ERROR_MESSAGES
-				DEBUG(SHOW_TRACING,
-				      "Received frame in Data Low Queue \n");
+			DEBUG(SHOW_TRACING,
+			      "Received frame in Management Queue\n");
 #endif
-				islpci_eth_receive(priv);
-			}
+			islpci_mgt_receive(ndev);
 
-			/* check whether the data transmit queues were full */
-			if (priv->data_low_tx_full) {
-				/* check whether the transmit is not full anymore */
-				if (ISL38XX_CB_TX_QSIZE -
-				    isl38xx_in_queue(priv->control_block,
-						     ISL38XX_CB_TX_DATA_LQ) >=
-				    ISL38XX_MIN_QTHRESHOLD) {
-					/* nope, the driver is ready for more network frames */
-					netif_wake_queue(priv->ndev);
-
-					/* reset the full flag */
-					priv->data_low_tx_full = 0;
-				}
-			}
+			islpci_mgt_cleanup_transmit(ndev);
+
+			/* Refill slots in receive queue */
+			islpci_mgmt_rx_fill(ndev);
+
+			/* no need to trigger the device, next
+			   islpci_mgt_transaction does it */
 		}
 
-		if (reg & ISL38XX_INT_IDENT_INIT) {
-			/* Device has been initialized */
+		while (isl38xx_in_queue(priv->control_block,
+					ISL38XX_CB_RX_DATA_LQ) != 0) {
 #if VERBOSE > SHOW_ERROR_MESSAGES
 			DEBUG(SHOW_TRACING,
-			      "IRQ: Init flag, device initialized \n");
+			      "Received frame in Data Low Queue \n");
 #endif
-			wake_up(&priv->reset_done);
+			islpci_eth_receive(priv);
+		}
+
+		/* check whether the data transmit queues were full */
+		if (priv->data_low_tx_full) {
+			/* check whether the transmit is not full anymore */
+			if (ISL38XX_CB_TX_QSIZE -
+			    isl38xx_in_queue(priv->control_block,
+					     ISL38XX_CB_TX_DATA_LQ) >=
+			    ISL38XX_MIN_QTHRESHOLD) {
+				/* nope, the driver is ready for more network frames */
+				netif_wake_queue(priv->ndev);
+
+				/* reset the full flag */
+				priv->data_low_tx_full = 0;
+			}
 		}
 
-		if (reg & ISL38XX_INT_IDENT_SLEEP) {
-			/* Device intends to move to powersave state */
+		irqs &= ~ISL38XX_INT_IDENT_UPDATE;
+		if (!irqs)
+			goto out_handled;
+	}
+
+	if (irqs & ISL38XX_INT_IDENT_WAKEUP) {
+		/* Device has been woken up to active state */
 #if VERBOSE > SHOW_ERROR_MESSAGES
-			DEBUG(SHOW_TRACING, "IRQ: Sleep flag \n");
+		DEBUG(SHOW_TRACING, "IRQ: Wakeup flag \n");
 #endif
-			isl38xx_handle_sleep_request(priv->control_block,
-						     &powerstate,
-						     priv->device_base);
-		}
 
-		if (reg & ISL38XX_INT_IDENT_WAKEUP) {
-			/* Device has been woken up to active state */
+		isl38xx_handle_wakeup(priv->control_block,
+				      &powerstate, priv->device_base);
+
+		irqs &= ~ISL38XX_INT_IDENT_WAKEUP;
+		if (!irqs)
+			goto out_handled;
+	}
+
+	if (irqs & ISL38XX_INT_IDENT_SLEEP) {
+		/* Device intends to move to powersave state */
 #if VERBOSE > SHOW_ERROR_MESSAGES
-			DEBUG(SHOW_TRACING, "IRQ: Wakeup flag \n");
+		DEBUG(SHOW_TRACING, "IRQ: Sleep flag \n");
 #endif
+		isl38xx_handle_sleep_request(priv->control_block,
+					     &powerstate,
+					     priv->device_base);
 
-			isl38xx_handle_wakeup(priv->control_block,
-					      &powerstate, priv->device_base);
-		}
-	} else {
+		irqs &= ~ISL38XX_INT_IDENT_SLEEP;
+		if (!irqs)
+			goto out_handled;
+	}
+
+	if (irqs & ISL38XX_INT_IDENT_INIT) {
+		/* Device has been initialized */
 #if VERBOSE > SHOW_ERROR_MESSAGES
-		DEBUG(SHOW_TRACING, "Assuming someone else called the IRQ\n");
+		DEBUG(SHOW_TRACING,
+		      "IRQ: Init flag, device initialized \n");
 #endif
-		spin_unlock(&priv->slock);
-		return IRQ_NONE;
+		wake_up(&priv->reset_done);
+
+		irqs &= ~ISL38XX_INT_IDENT_INIT;
 	}
 
+ out_handled:
 	/* sleep -> ready */
 	if (islpci_get_state(priv) == PRV_STATE_SLEEP
 	    && powerstate == ISL38XX_PSM_ACTIVE_STATE)
@@ -372,6 +391,13 @@
 	spin_unlock(&priv->slock);
 
 	return IRQ_HANDLED;
+
+ out_none:
+#if VERBOSE > SHOW_ERROR_MESSAGES
+	DEBUG(SHOW_TRACING, "Assuming someone else called the IRQ\n");
+#endif
+	spin_unlock(&priv->slock);
+	return IRQ_NONE;
 }
 
 /******************************************************************************
@@ -417,7 +443,7 @@
 	islpci_set_state(priv, PRV_STATE_PREBOOT);
 
 	/* disable all device interrupts in case they weren't */
-	isl38xx_disable_interrupts(priv->device_base);  
+	isl38xx_disable_interrupts(priv->device_base);
 
 	/* For safety reasons, we may want to ensure that no DMA transfer is
 	 * currently in progress by emptying the TX and RX queues. */
@@ -484,7 +510,7 @@
 
 	DEFINE_WAIT(wait);
 	prepare_to_wait(&priv->reset_done, &wait, TASK_UNINTERRUPTIBLE);
-	
+
 	/* now the last step is to reset the interface */
 	isl38xx_interface_reset(priv->device_base, priv->device_host_address);
 	islpci_set_state(priv, PRV_STATE_PREINIT);
@@ -492,7 +518,7 @@
         for(count = 0; count < 2 && result; count++) {
 		/* The software reset acknowledge needs about 220 msec here.
 		 * Be conservative and wait for up to one second. */
-	
+
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		remaining = schedule_timeout(HZ);
 
@@ -501,7 +527,7 @@
 			break;
 		}
 
-		/* If we're here it's because our IRQ hasn't yet gone through. 
+		/* If we're here it's because our IRQ hasn't yet gone through.
 		 * Retry a bit more...
 		 */
 		printk(KERN_ERR "%s: no 'reset complete' IRQ seen - retrying\n",
@@ -519,7 +545,7 @@
 
 	/* Now that the device is 100% up, let's allow
 	 * for the other interrupts --
-	 * NOTE: this is not *yet* true since we've only allowed the 
+	 * NOTE: this is not *yet* true since we've only allowed the
 	 * INIT interrupt on the IRQ line. We can perhaps poll
 	 * the IRQ line until we know for sure the reset went through */
 	isl38xx_enable_common_interrupts(priv->device_base);
@@ -721,7 +747,7 @@
 
 	prism54_acl_init(&priv->acl);
 	prism54_wpa_ie_init(priv);
-	if (mgt_init(priv)) 
+	if (mgt_init(priv))
 		goto out_free;
 
 	return 0;

--
Jean-Baptiste Note
+33 (0)6 83 03 42 38
jean-baptiste.note at wanadoo.fr


More information about the Prism54-devel mailing list