Skip to content

Commit

Permalink
qla3xxx: bugfix: Dropping interrupt under heavy network load.
Browse files Browse the repository at this point in the history
Update the rx queue pointer when exiting NAPI poll rather than
at the end of each iteration.  Remove unnecessary PCI flushes
that occurred after every write.  Now write all regs and
flush once.

Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
  • Loading branch information
Ron Mercer authored and Jeff Garzik committed Mar 28, 2007
1 parent b6967eb commit f67cac0
Showing 1 changed file with 30 additions and 41 deletions.
71 changes: 30 additions & 41 deletions drivers/net/qla3xxx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1688,6 +1688,27 @@ static int ql_populate_free_queue(struct ql3_adapter *qdev)
return 0;
}

/*
* Caller holds hw_lock.
*/
static void ql_update_small_bufq_prod_index(struct ql3_adapter *qdev)
{
struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
if (qdev->small_buf_release_cnt >= 16) {
while (qdev->small_buf_release_cnt >= 16) {
qdev->small_buf_q_producer_index++;

if (qdev->small_buf_q_producer_index ==
NUM_SBUFQ_ENTRIES)
qdev->small_buf_q_producer_index = 0;
qdev->small_buf_release_cnt -= 8;
}
wmb();
writel(qdev->small_buf_q_producer_index,
&port_regs->CommonRegs.rxSmallQProducerIndex);
}
}

/*
* Caller holds hw_lock.
*/
Expand Down Expand Up @@ -1732,13 +1753,10 @@ static void ql_update_lrg_bufq_prod_index(struct ql3_adapter *qdev)
lrg_buf_q_ele = qdev->lrg_buf_q_virt_addr;
}
}

wmb();
qdev->lrg_buf_next_free = lrg_buf_q_ele;

ql_write_common_reg(qdev,
&port_regs->CommonRegs.
rxLargeQProducerIndex,
qdev->lrg_buf_q_producer_index);
writel(qdev->lrg_buf_q_producer_index,
&port_regs->CommonRegs.rxLargeQProducerIndex);
}
}

Expand Down Expand Up @@ -1944,16 +1962,12 @@ static void ql_process_macip_rx_intr(struct ql3_adapter *qdev,
static int ql_tx_rx_clean(struct ql3_adapter *qdev,
int *tx_cleaned, int *rx_cleaned, int work_to_do)
{
struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
struct net_rsp_iocb *net_rsp;
struct net_device *ndev = qdev->ndev;
unsigned long hw_flags;
int work_done = 0;

u32 rsp_producer_index = le32_to_cpu(*(qdev->prsp_producer_index));

/* While there are entries in the completion queue. */
while ((rsp_producer_index !=
while ((le32_to_cpu(*(qdev->prsp_producer_index)) !=
qdev->rsp_consumer_index) && (work_done < work_to_do)) {

net_rsp = qdev->rsp_current;
Expand Down Expand Up @@ -2009,33 +2023,7 @@ static int ql_tx_rx_clean(struct ql3_adapter *qdev,
work_done = *tx_cleaned + *rx_cleaned;
}

if(work_done) {
spin_lock_irqsave(&qdev->hw_lock, hw_flags);

ql_update_lrg_bufq_prod_index(qdev);

if (qdev->small_buf_release_cnt >= 16) {
while (qdev->small_buf_release_cnt >= 16) {
qdev->small_buf_q_producer_index++;

if (qdev->small_buf_q_producer_index ==
NUM_SBUFQ_ENTRIES)
qdev->small_buf_q_producer_index = 0;
qdev->small_buf_release_cnt -= 8;
}

wmb();
ql_write_common_reg(qdev,
&port_regs->CommonRegs.
rxSmallQProducerIndex,
qdev->small_buf_q_producer_index);

}

spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
}

return *tx_cleaned + *rx_cleaned;
return work_done;
}

static int ql_poll(struct net_device *ndev, int *budget)
Expand All @@ -2059,9 +2047,10 @@ static int ql_poll(struct net_device *ndev, int *budget)
netif_rx_complete(ndev);

spin_lock_irqsave(&qdev->hw_lock, hw_flags);
ql_write_common_reg(qdev,
&port_regs->CommonRegs.rspQConsumerIndex,
qdev->rsp_consumer_index);
ql_update_small_bufq_prod_index(qdev);
ql_update_lrg_bufq_prod_index(qdev);
writel(qdev->rsp_consumer_index,
&port_regs->CommonRegs.rspQConsumerIndex);
spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);

ql_enable_interrupts(qdev);
Expand Down

0 comments on commit f67cac0

Please sign in to comment.