@@ -377,4 +377,16 @@ void idxd_wq_del_cdev(struct idxd_wq *wq);
int idxd_mdev_host_init(struct idxd_device *idxd);
void idxd_mdev_host_release(struct idxd_device *idxd);
+#ifdef CONFIG_INTEL_IDXD_MDEV
+void idxd_vidxd_send_errors(struct idxd_device *idxd);
+void idxd_wq_vidxd_send_errors(struct idxd_wq *wq);
+#else
+static inline void idxd_vidxd_send_errors(struct idxd_device *idxd)
+{
+}
+static inline void idxd_wq_vidxd_send_errors(struct idxd_wq *wq)
+{
+}
+#endif /* CONFIG_INTEL_IDXD_MDEV */
+
#endif
@@ -148,6 +148,8 @@ irqreturn_t idxd_misc_thread(int vec, void *data)
if (wq->type == IDXD_WQT_USER)
wake_up_interruptible(&wq->idxd_cdev.err_queue);
+ else if (wq->type == IDXD_WQT_MDEV)
+ idxd_wq_vidxd_send_errors(wq);
} else {
int i;
@@ -156,6 +158,8 @@ irqreturn_t idxd_misc_thread(int vec, void *data)
if (wq->type == IDXD_WQT_USER)
wake_up_interruptible(&wq->idxd_cdev.err_queue);
+ else if (wq->type == IDXD_WQT_MDEV)
+ idxd_wq_vidxd_send_errors(wq);
}
}
@@ -926,3 +926,37 @@ void vidxd_do_command(struct vdcm_idxd *vidxd, u32 val)
break;
}
}
+
+static void vidxd_send_errors(struct vdcm_idxd *vidxd)
+{
+ struct idxd_device *idxd = vidxd->idxd;
+ u8 *bar0 = vidxd->bar0;
+ union sw_err_reg *swerr = (union sw_err_reg *)(bar0 + IDXD_SWERR_OFFSET);
+ union genctrl_reg *genctrl = (union genctrl_reg *)(bar0 + IDXD_GENCTRL_OFFSET);
+ int i;
+ unsigned long flags;
+
+ if (swerr->valid) {
+ if (!swerr->overflow)
+ swerr->overflow = 1;
+ return;
+ }
+
+ spin_lock_irqsave(&idxd->dev_lock, flags);
+ for (i = 0; i < 4; i++) {
+ swerr->bits[i] = idxd->sw_err.bits[i];
+ swerr++;
+ }
+ spin_unlock_irqrestore(&idxd->dev_lock, flags);
+
+ if (genctrl->softerr_int_en)
+ vidxd_send_interrupt(vidxd, 0);
+}
+
+void idxd_wq_vidxd_send_errors(struct idxd_wq *wq)
+{
+ struct vdcm_idxd *vidxd;
+
+ list_for_each_entry(vidxd, &wq->vdcm_list, list)
+ vidxd_send_errors(vidxd);
+}
@@ -23,5 +23,6 @@ int vidxd_disable_host_ims_pasid(struct vdcm_idxd *vidxd, int ims_idx);
int vidxd_enable_host_ims_pasid(struct vdcm_idxd *vidxd, int ims_idx);
int vidxd_send_interrupt(struct vdcm_idxd *vidxd, int msix_idx);
void vidxd_do_command(struct vdcm_idxd *vidxd, u32 val);
+void idxd_wq_vidxd_send_errors(struct idxd_wq *wq);
#endif