[Prism54-devel] Interrupt Polling
Rodel Miguel
rodel.miguel at eazix.com
Thu Aug 5 03:44:06 UTC 2004
Hi!
I am trying to port the driver on a uClinux/ARM7 platform. My
device can't handle "too much interrupts", i.e., the network application
hangs on high data rates. The prism54 module displays kernel bug at
isl38xx:401! I would like to re-design the driver for my platform. I
am currently using March 18 2004 version of the driver for 2.4 kernels.
I tried to "poll" the reg & ISL38XX_INT_IDENT_UPDATE condition of the
islpci_interrupt interrupt handler of islpci_dev.c, using a fixed count
(500) and re-reading the ISL38XX_INT_IDENT_REG and check if the register
is updated. I am still having the same interrupt handling problem.
Could somebody help me to create a polling function for the prism54
driver to minimize calls to the interrupt handler routine? Or should I
register the interrupt on a polling timer (fast_poll_add - from
asm/fast_timer.h) instead of using the interrupt request? Are there
groups porting the driver on MMU-less devices? Could someone tell me if
they already did some optimization codes for the driver on embedded
linux systems?
Here's the polling routine snippet I did on the driver but this does not
seem to work. Please help!
i.e.:
int max_interrupt_work = 500;
/* check for each bit in the register separately */
do { // rodel
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);
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 */
}
while (isl38xx_in_queue(priv->control_block,
ISL38XX_CB_RX_DATA_LQ)
!= 0) {
#if VERBOSE > SHOW_ERROR_MESSAGES
DEBUG(SHOW_TRACING,
"Received frame in Data Low Queue
\n");
#endif
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;
}
}
}
/* rodel - trying to poll */
reg &= ~ISL38XX_INT_IDENT_UPDATE;
reg |= readl(device + ISL38XX_INT_IDENT_REG);
isl38xx_w32_flush(device, ISL38XX_INT_IDENT_UPDATE,
ISL38XX_INT_ACK_REG);
max_interrupt_work--;
} while(max_interrupt_work >= 0);
Regards,
Rodel
More information about the Prism54-devel
mailing list