Skip to content

Commit

Permalink
liquidio: fix race condition in instruction completion processing
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Rick Farrington authored and David S. Miller committed Aug 30, 2018
1 parent 9ecc660 commit b943f17
Show file tree
Hide file tree
Showing 3 changed files with 7 additions and 2 deletions.
5 changes: 3 additions & 2 deletions drivers/net/ethernet/cavium/liquidio/octeon_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/cavium/liquidio/octeon_iq.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/cavium/liquidio/request_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down

0 comments on commit b943f17

Please sign in to comment.