Skip to content

Commit 2f431ba

Browse files
davejiangvinodkoul
authored andcommitted
dmaengine: idxd: add interrupt handling for event log
An event log interrupt is raised in the misc interrupt INTCAUSE register when an event is written by the hardware. Add basic event log processing support to the interrupt handler. The event log is a ring where the hardware owns the tail and the software owns the head. The hardware will advance the tail index when an additional event has been pushed to memory. The software will process the log entry and then advances the head. The log is full when (tail + 1) % log_size = head. The hardware will stop writing when the log is full. The user is expected to create a log size large enough to handle all the expected events. Tested-by: Tony Zhu <tony.zhu@intel.com> Signed-off-by: Dave Jiang <dave.jiang@intel.com> Co-developed-by: Fenghua Yu <fenghua.yu@intel.com> Signed-off-by: Fenghua Yu <fenghua.yu@intel.com> Link: https://lore.kernel.org/r/20230407203143.2189681-5-fenghua.yu@intel.com Signed-off-by: Vinod Koul <vkoul@kernel.org>
1 parent 244da66 commit 2f431ba

3 files changed

Lines changed: 68 additions & 0 deletions

File tree

drivers/dma/idxd/irq.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,49 @@ static void idxd_int_handle_revoke(struct work_struct *work)
217217
kfree(revoke);
218218
}
219219

220+
static void process_evl_entry(struct idxd_device *idxd, struct __evl_entry *entry_head)
221+
{
222+
struct device *dev = &idxd->pdev->dev;
223+
u8 status;
224+
225+
status = DSA_COMP_STATUS(entry_head->error);
226+
dev_warn_ratelimited(dev, "Device error %#x operation: %#x fault addr: %#llx\n",
227+
status, entry_head->operation, entry_head->fault_addr);
228+
}
229+
230+
static void process_evl_entries(struct idxd_device *idxd)
231+
{
232+
union evl_status_reg evl_status;
233+
unsigned int h, t;
234+
struct idxd_evl *evl = idxd->evl;
235+
struct __evl_entry *entry_head;
236+
unsigned int ent_size = evl_ent_size(idxd);
237+
u32 size;
238+
239+
evl_status.bits = 0;
240+
evl_status.int_pending = 1;
241+
242+
spin_lock(&evl->lock);
243+
/* Clear interrupt pending bit */
244+
iowrite32(evl_status.bits_upper32,
245+
idxd->reg_base + IDXD_EVLSTATUS_OFFSET + sizeof(u32));
246+
h = evl->head;
247+
evl_status.bits = ioread64(idxd->reg_base + IDXD_EVLSTATUS_OFFSET);
248+
t = evl_status.tail;
249+
size = idxd->evl->size;
250+
251+
while (h != t) {
252+
entry_head = (struct __evl_entry *)(evl->log + (h * ent_size));
253+
process_evl_entry(idxd, entry_head);
254+
h = (h + 1) % size;
255+
}
256+
257+
evl->head = h;
258+
evl_status.head = h;
259+
iowrite32(evl_status.bits_lower32, idxd->reg_base + IDXD_EVLSTATUS_OFFSET);
260+
spin_unlock(&evl->lock);
261+
}
262+
220263
irqreturn_t idxd_misc_thread(int vec, void *data)
221264
{
222265
struct idxd_irq_entry *irq_entry = data;
@@ -304,6 +347,11 @@ irqreturn_t idxd_misc_thread(int vec, void *data)
304347
perfmon_counter_overflow(idxd);
305348
}
306349

350+
if (cause & IDXD_INTC_EVL) {
351+
val |= IDXD_INTC_EVL;
352+
process_evl_entries(idxd);
353+
}
354+
307355
val ^= cause;
308356
if (val)
309357
dev_warn_once(dev, "Unexpected interrupt cause bits set: %#x\n",

drivers/dma/idxd/registers.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ enum idxd_device_reset_type {
168168
#define IDXD_INTC_OCCUPY 0x04
169169
#define IDXD_INTC_PERFMON_OVFL 0x08
170170
#define IDXD_INTC_HALT_STATE 0x10
171+
#define IDXD_INTC_EVL 0x20
171172
#define IDXD_INTC_INT_HANDLE_REVOKED 0x80000000
172173

173174
#define IDXD_CMD_OFFSET 0xa0
@@ -558,6 +559,24 @@ union filter_cfg {
558559
u64 val;
559560
} __packed;
560561

562+
#define IDXD_EVLSTATUS_OFFSET 0xf0
563+
564+
union evl_status_reg {
565+
struct {
566+
u32 head:16;
567+
u32 rsvd:16;
568+
u32 tail:16;
569+
u32 rsvd2:14;
570+
u32 int_pending:1;
571+
u32 rsvd3:1;
572+
};
573+
struct {
574+
u32 bits_lower32;
575+
u32 bits_upper32;
576+
};
577+
u64 bits;
578+
} __packed;
579+
561580
struct __evl_entry {
562581
u64 rsvd:2;
563582
u64 desc_valid:1;

include/uapi/linux/idxd.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ enum iax_completion_status {
170170

171171
#define DSA_COMP_STATUS_MASK 0x7f
172172
#define DSA_COMP_STATUS_WRITE 0x80
173+
#define DSA_COMP_STATUS(status) ((status) & DSA_COMP_STATUS_MASK)
173174

174175
struct dsa_hw_desc {
175176
uint32_t pasid:20;

0 commit comments

Comments
 (0)