]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
dmaengine: idxd: Remove shadow Event Log head stored in idxd
authorFenghua Yu <fenghua.yu@intel.com>
Thu, 15 Feb 2024 02:49:31 +0000 (18:49 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 6 Mar 2024 14:48:43 +0000 (14:48 +0000)
[ Upstream commit ecec7c9f29a7114a3e23a14020b1149ea7dffb4f ]

head is defined in idxd->evl as a shadow of head in the EVLSTATUS register.
There are two issues related to the shadow head:

1. Mismatch between the shadow head and the state of the EVLSTATUS
   register:
   If Event Log is supported, upon completion of the Enable Device command,
   the Event Log head in the variable idxd->evl->head should be cleared to
   match the state of the EVLSTATUS register. But the variable is not reset
   currently, leading mismatch between the variable and the register state.
   The mismatch causes incorrect processing of Event Log entries.

2. Unnecessary shadow head definition:
   The shadow head is unnecessary as head can be read directly from the
   EVLSTATUS register. Reading head from the register incurs no additional
   cost because event log head and tail are always read together and
   tail is already read directly from the register as required by hardware.

Remove the shadow Event Log head stored in idxd->evl to address the
mentioned issues.

Fixes: 244da66cda35 ("dmaengine: idxd: setup event log configuration")
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Link: https://lore.kernel.org/r/20240215024931.1739621-1-fenghua.yu@intel.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/dma/idxd/cdev.c
drivers/dma/idxd/debugfs.c
drivers/dma/idxd/idxd.h
drivers/dma/idxd/irq.c

index d32deb9b4e3dee466fd056230596aa42198d8285..4eeec95a667517c9e1ea685d0728fee387dd429e 100644 (file)
@@ -345,7 +345,7 @@ static void idxd_cdev_evl_drain_pasid(struct idxd_wq *wq, u32 pasid)
        spin_lock(&evl->lock);
        status.bits = ioread64(idxd->reg_base + IDXD_EVLSTATUS_OFFSET);
        t = status.tail;
-       h = evl->head;
+       h = status.head;
        size = evl->size;
 
        while (h != t) {
index 9cfbd9b14c4c43306326e857b8b3d982c612314f..f3f25ee676f30eb283989586d458a5c8b8c01f9f 100644 (file)
@@ -68,9 +68,9 @@ static int debugfs_evl_show(struct seq_file *s, void *d)
 
        spin_lock(&evl->lock);
 
-       h = evl->head;
        evl_status.bits = ioread64(idxd->reg_base + IDXD_EVLSTATUS_OFFSET);
        t = evl_status.tail;
+       h = evl_status.head;
        evl_size = evl->size;
 
        seq_printf(s, "Event Log head %u tail %u interrupt pending %u\n\n",
index e269ca1f48625513fb03df0f678919db5ccc3c48..6fc79deb99bfd7571204073d3607c00ce823e1c0 100644 (file)
@@ -286,7 +286,6 @@ struct idxd_evl {
        unsigned int log_size;
        /* The number of entries in the event log. */
        u16 size;
-       u16 head;
        unsigned long *bmap;
        bool batch_fail[IDXD_MAX_BATCH_IDENT];
 };
index b501320a9c7ad06f52ae6202c45968605d084405..0bbc6bdc6145ef254d35bff62de3123551a2d6d4 100644 (file)
@@ -367,9 +367,9 @@ static void process_evl_entries(struct idxd_device *idxd)
        /* Clear interrupt pending bit */
        iowrite32(evl_status.bits_upper32,
                  idxd->reg_base + IDXD_EVLSTATUS_OFFSET + sizeof(u32));
-       h = evl->head;
        evl_status.bits = ioread64(idxd->reg_base + IDXD_EVLSTATUS_OFFSET);
        t = evl_status.tail;
+       h = evl_status.head;
        size = idxd->evl->size;
 
        while (h != t) {
@@ -378,7 +378,6 @@ static void process_evl_entries(struct idxd_device *idxd)
                h = (h + 1) % size;
        }
 
-       evl->head = h;
        evl_status.head = h;
        iowrite32(evl_status.bits_lower32, idxd->reg_base + IDXD_EVLSTATUS_OFFSET);
        spin_unlock(&evl->lock);