Commit f67cac01 authored by Ron Mercer's avatar Ron Mercer Committed by Jeff Garzik

qla3xxx: bugfix: Dropping interrupt under heavy network load.

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: default avatarRon Mercer <ron.mercer@qlogic.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent b6967eb9
......@@ -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.
*/
......@@ -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);
}
}
......@@ -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;
......@@ -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)
......@@ -2059,9 +2047,10 @@ quit_polling:
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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment