]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
liquidio: fix race condition in instruction completion processing
authorRick Farrington <ricardo.farrington@cavium.com>
Tue, 28 Aug 2018 18:32:55 +0000 (11:32 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 30 Aug 2018 02:47:52 +0000 (19:47 -0700)
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>
drivers/net/ethernet/cavium/liquidio/octeon_device.c
drivers/net/ethernet/cavium/liquidio/octeon_iq.h
drivers/net/ethernet/cavium/liquidio/request_manager.c

index f878a552fef3b36fcf98ee822d6e7a635401b92b..d0ed6c4f9e1a2922aee49e9e36256a3268671072 100644 (file)
@@ -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);
index 2327062e8af6b7af4b5cc146a88234ec60e89bb4..aecd0d36d6349869e8703f48b62f2e94fd18397c 100644 (file)
@@ -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;
 
index 0a06fbb4ff8a8de25aef922554ed75041da7407b..5de5ce9a8f54b19c82f8e155d354717123455f24 100644 (file)
@@ -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;
                }