Commit b0bac46b authored by Rick Farrington's avatar Rick Farrington Committed by Greg Kroah-Hartman

liquidio: fix race condition in instruction completion processing

[ Upstream commit b943f17e ]

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: default avatarRick Farrington <ricardo.farrington@cavium.com>
Signed-off-by: default avatarFelix Manlunas <felix.manlunas@cavium.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent b2e427c2
...@@ -1450,8 +1450,9 @@ void lio_enable_irq(struct octeon_droq *droq, struct octeon_instr_queue *iq) ...@@ -1450,8 +1450,9 @@ void lio_enable_irq(struct octeon_droq *droq, struct octeon_instr_queue *iq)
} }
if (iq) { if (iq) {
spin_lock_bh(&iq->lock); spin_lock_bh(&iq->lock);
writel(iq->pkt_in_done, iq->inst_cnt_reg); writel(iq->pkts_processed, iq->inst_cnt_reg);
iq->pkt_in_done = 0; iq->pkt_in_done -= iq->pkts_processed;
iq->pkts_processed = 0;
/* this write needs to be flushed before we release the lock */ /* this write needs to be flushed before we release the lock */
mmiowb(); mmiowb();
spin_unlock_bh(&iq->lock); spin_unlock_bh(&iq->lock);
......
...@@ -94,6 +94,8 @@ struct octeon_instr_queue { ...@@ -94,6 +94,8 @@ struct octeon_instr_queue {
u32 pkt_in_done; u32 pkt_in_done;
u32 pkts_processed;
/** A spinlock to protect access to the input ring.*/ /** A spinlock to protect access to the input ring.*/
spinlock_t iq_flush_running_lock; spinlock_t iq_flush_running_lock;
......
...@@ -123,6 +123,7 @@ int octeon_init_instr_queue(struct octeon_device *oct, ...@@ -123,6 +123,7 @@ int octeon_init_instr_queue(struct octeon_device *oct,
iq->do_auto_flush = 1; iq->do_auto_flush = 1;
iq->db_timeout = (u32)conf->db_timeout; iq->db_timeout = (u32)conf->db_timeout;
atomic_set(&iq->instr_pending, 0); atomic_set(&iq->instr_pending, 0);
iq->pkts_processed = 0;
/* Initialize the spinlock for this instruction queue */ /* Initialize the spinlock for this instruction queue */
spin_lock_init(&iq->lock); spin_lock_init(&iq->lock);
...@@ -497,6 +498,7 @@ octeon_flush_iq(struct octeon_device *oct, struct octeon_instr_queue *iq, ...@@ -497,6 +498,7 @@ octeon_flush_iq(struct octeon_device *oct, struct octeon_instr_queue *iq,
lio_process_iq_request_list(oct, iq, 0); lio_process_iq_request_list(oct, iq, 0);
if (inst_processed) { if (inst_processed) {
iq->pkts_processed += inst_processed;
atomic_sub(inst_processed, &iq->instr_pending); atomic_sub(inst_processed, &iq->instr_pending);
iq->stats.instr_processed += inst_processed; iq->stats.instr_processed += inst_processed;
} }
......
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