aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRick Farrington <ricardo.farrington@cavium.com>2018-08-28 11:32:55 -0700
committerDavid S. Miller <davem@davemloft.net>2018-08-29 19:47:52 -0700
commitb943f17e06493fd2c7fd00743093ad5dcdb90e7f (patch)
treec11e87c4f0720b3b86a99c01a19b24b58f162606
parentliquidio: remove unnecessary delay when processing IQ responses (diff)
downloadlinux-dev-b943f17e06493fd2c7fd00743093ad5dcdb90e7f.tar.xz
linux-dev-b943f17e06493fd2c7fd00743093ad5dcdb90e7f.zip
liquidio: fix race condition in instruction completion processing
In lio_enable_irq, the pkt_in_done count register was being cleared to zero. However, there could be some completed instructions which were not yet processed due to budget and limit constraints. So, only write this register with the number of actual completions that were processed. Signed-off-by: Rick Farrington <ricardo.farrington@cavium.com> Signed-off-by: Felix Manlunas <felix.manlunas@cavium.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to '')
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_device.c5
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_iq.h2
-rw-r--r--drivers/net/ethernet/cavium/liquidio/request_manager.c2
3 files changed, 7 insertions, 2 deletions
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_device.c b/drivers/net/ethernet/cavium/liquidio/octeon_device.c
index f878a552fef3..d0ed6c4f9e1a 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_device.c
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_device.c
@@ -1450,8 +1450,9 @@ void lio_enable_irq(struct octeon_droq *droq, struct octeon_instr_queue *iq)
}
if (iq) {
spin_lock_bh(&iq->lock);
- writel(iq->pkt_in_done, iq->inst_cnt_reg);
- iq->pkt_in_done = 0;
+ writel(iq->pkts_processed, iq->inst_cnt_reg);
+ iq->pkt_in_done -= iq->pkts_processed;
+ iq->pkts_processed = 0;
/* this write needs to be flushed before we release the lock */
mmiowb();
spin_unlock_bh(&iq->lock);
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_iq.h b/drivers/net/ethernet/cavium/liquidio/octeon_iq.h
index 2327062e8af6..aecd0d36d634 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_iq.h
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_iq.h
@@ -94,6 +94,8 @@ struct octeon_instr_queue {
u32 pkt_in_done;
+ u32 pkts_processed;
+
/** A spinlock to protect access to the input ring.*/
spinlock_t iq_flush_running_lock;
diff --git a/drivers/net/ethernet/cavium/liquidio/request_manager.c b/drivers/net/ethernet/cavium/liquidio/request_manager.c
index 0a06fbb4ff8a..5de5ce9a8f54 100644
--- a/drivers/net/ethernet/cavium/liquidio/request_manager.c
+++ b/drivers/net/ethernet/cavium/liquidio/request_manager.c
@@ -123,6 +123,7 @@ int octeon_init_instr_queue(struct octeon_device *oct,
iq->do_auto_flush = 1;
iq->db_timeout = (u32)conf->db_timeout;
atomic_set(&iq->instr_pending, 0);
+ iq->pkts_processed = 0;
/* Initialize the spinlock for this instruction queue */
spin_lock_init(&iq->lock);
@@ -495,6 +496,7 @@ octeon_flush_iq(struct octeon_device *oct, struct octeon_instr_queue *iq,
lio_process_iq_request_list(oct, iq, 0);
if (inst_processed) {
+ iq->pkts_processed += inst_processed;
atomic_sub(inst_processed, &iq->instr_pending);
iq->stats.instr_processed += inst_processed;
}