]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.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)
committerStefan Bader <stefan.bader@canonical.com>
Tue, 26 Nov 2019 12:16:28 +0000 (13:16 +0100)
BugLink: https://bugs.launchpad.net/bugs/1853915
[ Upstream commit b943f17e06493fd2c7fd00743093ad5dcdb90e7f ]

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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Khalid Elmously <khalid.elmously@canonical.com>
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 2c615ab09e6480bbba4e81f5a8777eaedc997e15..4b8d93e3defe37365da54f46160e1fa95bd60288 100644 (file)
@@ -1457,8 +1457,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 81c98768294174a44d7150d4a6ee08938a90f5f3..56d761b1a690ab54d74affb6b917d55507d7bf95 100644 (file)
@@ -84,6 +84,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 fd5e33fe81dce61170f14c78847186001e416d9d..97468b223f9143e979ffeb0fef8ac8e0cce5a6b8 100644 (file)
@@ -122,6 +122,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);
@@ -486,6 +487,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;
                }