On Fri, Nov 6, 2020 at 2:59 AM Peter Hilber <peter.hilber@xxxxxxxxxxxxxxx> wrote: > +static int scmi_vio_probe(struct virtio_device *vdev) > +{ > + struct device *dev = &vdev->dev; > + struct scmi_vio_channel **vioch; > + bool have_vq_rx; > + int vq_cnt; > + int i; > + struct virtqueue *vqs[VIRTIO_SCMI_VQ_MAX_CNT]; > + > + vioch = devm_kcalloc(dev, VIRTIO_SCMI_VQ_MAX_CNT, sizeof(*vioch), > + GFP_KERNEL); > + if (!vioch) > + return -ENOMEM; > + > + have_vq_rx = virtio_has_feature(vdev, VIRTIO_SCMI_F_P2A_CHANNELS); > + vq_cnt = have_vq_rx ? VIRTIO_SCMI_VQ_MAX_CNT : 1; > + > + for (i = 0; i < vq_cnt; i++) { > + vioch[i] = devm_kzalloc(dev, sizeof(**vioch), GFP_KERNEL); > + if (!vioch[i]) > + return -ENOMEM; > + } > + > + if (have_vq_rx) > + vioch[VIRTIO_SCMI_VQ_RX]->is_rx = true; > + > + if (virtio_find_vqs(vdev, vq_cnt, vqs, scmi_vio_complete_callbacks, > + scmi_vio_vqueue_names, NULL)) { > + dev_err(dev, "Failed to get %d virtqueue(s)\n", vq_cnt); > + return -1; > + } > + dev_info(dev, "Found %d virtqueue(s)\n", vq_cnt); > + > + for (i = 0; i < vq_cnt; i++) { > + spin_lock_init(&vioch[i]->lock); > + vioch[i]->vqueue = vqs[i]; > + vioch[i]->vqueue->priv = vioch[i]; The vqueue->priv field is used by core, you can't update it else notifications won't work. > + } > + > + vdev->priv = vioch; > + > + virtio_device_ready(vdev); > + > + return 0; > +} diff --git a/drivers/firmware/arm_scmi/virtio.c b/drivers/firmware/arm_scmi/virtio.c index f70aa72f34f1..b1af77341b30 100644 --- a/drivers/firmware/arm_scmi/virtio.c +++ b/drivers/firmware/arm_scmi/virtio.c @@ -80,7 +80,8 @@ static int scmi_vio_populate_vq_rx(struct scmi_vio_channel *vioch, static void scmi_vio_complete_cb(struct virtqueue *vqueue) { - struct scmi_vio_channel *vioch = vqueue->priv; + struct scmi_vio_channel **_vioch = vqueue->vdev->priv; + struct scmi_vio_channel *vioch = _vioch[vqueue->index]; unsigned long iflags; unsigned int length; @@ -454,7 +455,6 @@ static int scmi_vio_probe(struct virtio_device *vdev) for (i = 0; i < vq_cnt; i++) { spin_lock_init(&vioch[i]->lock); vioch[i]->vqueue = vqs[i]; - vioch[i]->vqueue->priv = vioch[i]; } vdev->priv = vioch;