[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