diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h
index 5e8da9019c46..b1d94463fce5 100644
--- a/drivers/dma/idxd/idxd.h
+++ b/drivers/dma/idxd/idxd.h
@@ -50,10 +50,17 @@ enum idxd_type {
 #define IDXD_NAME_SIZE		128
 #define IDXD_PMU_EVENT_MAX	64
 
+struct idxd_wq;
+
+struct idxd_device_ops {
+	void (*notify_error)(struct idxd_wq *wq);
+};
+
 struct idxd_device_driver {
 	const char *name;
 	int (*probe)(struct device *dev);
 	void (*remove)(struct device *dev);
+	struct idxd_device_ops *ops;
 	struct device_driver drv;
 };
 
diff --git a/drivers/dma/idxd/irq.c b/drivers/dma/idxd/irq.c
index d1a635ecc7f3..b8b6c93f4480 100644
--- a/drivers/dma/idxd/irq.c
+++ b/drivers/dma/idxd/irq.c
@@ -104,6 +104,7 @@ static int idxd_device_schedule_fault_process(struct idxd_device *idxd,
 
 static int process_misc_interrupts(struct idxd_device *idxd, u32 cause)
 {
+	struct idxd_device_driver *wq_drv;
 	struct device *dev = &idxd->pdev->dev;
 	union gensts_reg gensts;
 	u32 val = 0;
@@ -123,16 +124,32 @@ static int process_misc_interrupts(struct idxd_device *idxd, u32 cause)
 			int id = idxd->sw_err.wq_idx;
 			struct idxd_wq *wq = idxd->wqs[id];
 
-			if (wq->type == IDXD_WQT_USER)
+			if (is_idxd_wq_user(wq)) {
 				wake_up_interruptible(&wq->err_queue);
+			} else if (is_idxd_wq_mdev(wq)) {
+				struct device *conf_dev = wq_confdev(wq);
+				struct device_driver *drv = conf_dev->driver;
+
+				wq_drv = container_of(drv, struct idxd_device_driver, drv);
+				if (wq_drv)
+					wq_drv->ops->notify_error(wq);
+			}
 		} else {
 			int i;
 
 			for (i = 0; i < idxd->max_wqs; i++) {
 				struct idxd_wq *wq = idxd->wqs[i];
 
-				if (wq->type == IDXD_WQT_USER)
+				if (is_idxd_wq_user(wq)) {
 					wake_up_interruptible(&wq->err_queue);
+				} else if (is_idxd_wq_mdev(wq)) {
+					struct device *conf_dev = wq_confdev(wq);
+					struct device_driver *drv = conf_dev->driver;
+
+					wq_drv = container_of(drv, struct idxd_device_driver, drv);
+					if (wq_drv)
+						wq_drv->ops->notify_error(wq);
+				}
 			}
 		}
 
diff --git a/drivers/vfio/mdev/idxd/mdev.c b/drivers/vfio/mdev/idxd/mdev.c
index 3257505fb7c7..25d1ac67b0c9 100644
--- a/drivers/vfio/mdev/idxd/mdev.c
+++ b/drivers/vfio/mdev/idxd/mdev.c
@@ -904,10 +904,15 @@ static void idxd_mdev_drv_remove(struct device *dev)
 	put_device(dev);
 }
 
+static struct idxd_device_ops mdev_wq_ops = {
+	.notify_error = idxd_wq_vidxd_send_errors,
+};
+
 static struct idxd_device_driver idxd_mdev_driver = {
 	.probe = idxd_mdev_drv_probe,
 	.remove = idxd_mdev_drv_remove,
 	.name = idxd_mdev_drv_name,
+	.ops = &mdev_wq_ops,
 };
 
 static int __init idxd_mdev_init(void)
diff --git a/drivers/vfio/mdev/idxd/mdev.h b/drivers/vfio/mdev/idxd/mdev.h
index dd4290bce772..10358831da6a 100644
--- a/drivers/vfio/mdev/idxd/mdev.h
+++ b/drivers/vfio/mdev/idxd/mdev.h
@@ -107,5 +107,6 @@ int vidxd_cfg_read(struct vdcm_idxd *vidxd, unsigned int pos, void *buf, unsigne
 int vidxd_cfg_write(struct vdcm_idxd *vidxd, unsigned int pos, void *buf, unsigned int size);
 int vidxd_mmio_write(struct vdcm_idxd *vidxd, u64 pos, void *buf, unsigned int size);
 int vidxd_mmio_read(struct vdcm_idxd *vidxd, u64 pos, void *buf, unsigned int size);
+void idxd_wq_vidxd_send_errors(struct idxd_wq *wq);
 
 #endif
diff --git a/drivers/vfio/mdev/idxd/vdev.c b/drivers/vfio/mdev/idxd/vdev.c
index a444a0af8b5f..2a066e483dd8 100644
--- a/drivers/vfio/mdev/idxd/vdev.c
+++ b/drivers/vfio/mdev/idxd/vdev.c
@@ -151,6 +151,29 @@ static void vidxd_report_swerror(struct vdcm_idxd *vidxd, unsigned int error)
 	send_swerr_interrupt(vidxd);
 }
 
+void idxd_wq_vidxd_send_errors(struct idxd_wq *wq)
+{
+	struct vdcm_idxd *vidxd = wq->vidxd;
+	struct idxd_device *idxd = vidxd->idxd;
+	u8 *bar0 = vidxd->bar0;
+	union sw_err_reg *swerr = (union sw_err_reg *)(bar0 + IDXD_SWERR_OFFSET);
+	int i;
+
+	if (swerr->valid) {
+		if (!swerr->overflow) {
+			swerr->overflow = 1;
+			send_swerr_interrupt(vidxd);
+		}
+		return;
+	}
+
+	lockdep_assert_held(&idxd->dev_lock);
+	for (i = 0; i < 4; i++)
+		swerr->bits[i] = idxd->sw_err.bits[i];
+
+	send_swerr_interrupt(vidxd);
+}
+
 int vidxd_mmio_write(struct vdcm_idxd *vidxd, u64 pos, void *buf, unsigned int size)
 {
 	u32 offset = pos & (vidxd->bar_size[0] - 1);
