forked from luck/tmp_suning_uos_patched
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: Ron Mercer <ron.mercer@qlogic.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
This commit is contained in:
parent
b6967eb9cb
commit
f67cac0190
@ -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 @@ 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);
|
||||
|
Loading…
Reference in New Issue
Block a user