Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Remote processor messaging transport (OMAP platform-specific bits)
0004  *
0005  * Copyright (C) 2011 Texas Instruments, Inc.
0006  * Copyright (C) 2011 Google, Inc.
0007  *
0008  * Ohad Ben-Cohen <ohad@wizery.com>
0009  * Brian Swetland <swetland@google.com>
0010  */
0011 
0012 #include <linux/dma-map-ops.h>
0013 #include <linux/export.h>
0014 #include <linux/of_reserved_mem.h>
0015 #include <linux/remoteproc.h>
0016 #include <linux/virtio.h>
0017 #include <linux/virtio_config.h>
0018 #include <linux/virtio_ids.h>
0019 #include <linux/virtio_ring.h>
0020 #include <linux/err.h>
0021 #include <linux/kref.h>
0022 #include <linux/slab.h>
0023 
0024 #include "remoteproc_internal.h"
0025 
0026 static struct rproc_vdev *vdev_to_rvdev(struct virtio_device *vdev)
0027 {
0028     return container_of(vdev->dev.parent, struct rproc_vdev, dev);
0029 }
0030 
0031 static  struct rproc *vdev_to_rproc(struct virtio_device *vdev)
0032 {
0033     struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
0034 
0035     return rvdev->rproc;
0036 }
0037 
0038 /* kick the remote processor, and let it know which virtqueue to poke at */
0039 static bool rproc_virtio_notify(struct virtqueue *vq)
0040 {
0041     struct rproc_vring *rvring = vq->priv;
0042     struct rproc *rproc = rvring->rvdev->rproc;
0043     int notifyid = rvring->notifyid;
0044 
0045     dev_dbg(&rproc->dev, "kicking vq index: %d\n", notifyid);
0046 
0047     rproc->ops->kick(rproc, notifyid);
0048     return true;
0049 }
0050 
0051 /**
0052  * rproc_vq_interrupt() - tell remoteproc that a virtqueue is interrupted
0053  * @rproc: handle to the remote processor
0054  * @notifyid: index of the signalled virtqueue (unique per this @rproc)
0055  *
0056  * This function should be called by the platform-specific rproc driver,
0057  * when the remote processor signals that a specific virtqueue has pending
0058  * messages available.
0059  *
0060  * Return: IRQ_NONE if no message was found in the @notifyid virtqueue,
0061  * and otherwise returns IRQ_HANDLED.
0062  */
0063 irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int notifyid)
0064 {
0065     struct rproc_vring *rvring;
0066 
0067     dev_dbg(&rproc->dev, "vq index %d is interrupted\n", notifyid);
0068 
0069     rvring = idr_find(&rproc->notifyids, notifyid);
0070     if (!rvring || !rvring->vq)
0071         return IRQ_NONE;
0072 
0073     return vring_interrupt(0, rvring->vq);
0074 }
0075 EXPORT_SYMBOL(rproc_vq_interrupt);
0076 
0077 static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
0078                     unsigned int id,
0079                     void (*callback)(struct virtqueue *vq),
0080                     const char *name, bool ctx)
0081 {
0082     struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
0083     struct rproc *rproc = vdev_to_rproc(vdev);
0084     struct device *dev = &rproc->dev;
0085     struct rproc_mem_entry *mem;
0086     struct rproc_vring *rvring;
0087     struct fw_rsc_vdev *rsc;
0088     struct virtqueue *vq;
0089     void *addr;
0090     int num, size;
0091 
0092     /* we're temporarily limited to two virtqueues per rvdev */
0093     if (id >= ARRAY_SIZE(rvdev->vring))
0094         return ERR_PTR(-EINVAL);
0095 
0096     if (!name)
0097         return NULL;
0098 
0099     /* Search allocated memory region by name */
0100     mem = rproc_find_carveout_by_name(rproc, "vdev%dvring%d", rvdev->index,
0101                       id);
0102     if (!mem || !mem->va)
0103         return ERR_PTR(-ENOMEM);
0104 
0105     rvring = &rvdev->vring[id];
0106     addr = mem->va;
0107     num = rvring->num;
0108 
0109     /* zero vring */
0110     size = vring_size(num, rvring->align);
0111     memset(addr, 0, size);
0112 
0113     dev_dbg(dev, "vring%d: va %pK qsz %d notifyid %d\n",
0114         id, addr, num, rvring->notifyid);
0115 
0116     /*
0117      * Create the new vq, and tell virtio we're not interested in
0118      * the 'weak' smp barriers, since we're talking with a real device.
0119      */
0120     vq = vring_new_virtqueue(id, num, rvring->align, vdev, false, ctx,
0121                  addr, rproc_virtio_notify, callback, name);
0122     if (!vq) {
0123         dev_err(dev, "vring_new_virtqueue %s failed\n", name);
0124         rproc_free_vring(rvring);
0125         return ERR_PTR(-ENOMEM);
0126     }
0127 
0128     vq->num_max = num;
0129 
0130     rvring->vq = vq;
0131     vq->priv = rvring;
0132 
0133     /* Update vring in resource table */
0134     rsc = (void *)rproc->table_ptr + rvdev->rsc_offset;
0135     rsc->vring[id].da = mem->da;
0136 
0137     return vq;
0138 }
0139 
0140 static void __rproc_virtio_del_vqs(struct virtio_device *vdev)
0141 {
0142     struct virtqueue *vq, *n;
0143     struct rproc_vring *rvring;
0144 
0145     list_for_each_entry_safe(vq, n, &vdev->vqs, list) {
0146         rvring = vq->priv;
0147         rvring->vq = NULL;
0148         vring_del_virtqueue(vq);
0149     }
0150 }
0151 
0152 static void rproc_virtio_del_vqs(struct virtio_device *vdev)
0153 {
0154     __rproc_virtio_del_vqs(vdev);
0155 }
0156 
0157 static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
0158                  struct virtqueue *vqs[],
0159                  vq_callback_t *callbacks[],
0160                  const char * const names[],
0161                  const bool * ctx,
0162                  struct irq_affinity *desc)
0163 {
0164     int i, ret, queue_idx = 0;
0165 
0166     for (i = 0; i < nvqs; ++i) {
0167         if (!names[i]) {
0168             vqs[i] = NULL;
0169             continue;
0170         }
0171 
0172         vqs[i] = rp_find_vq(vdev, queue_idx++, callbacks[i], names[i],
0173                     ctx ? ctx[i] : false);
0174         if (IS_ERR(vqs[i])) {
0175             ret = PTR_ERR(vqs[i]);
0176             goto error;
0177         }
0178     }
0179 
0180     return 0;
0181 
0182 error:
0183     __rproc_virtio_del_vqs(vdev);
0184     return ret;
0185 }
0186 
0187 static u8 rproc_virtio_get_status(struct virtio_device *vdev)
0188 {
0189     struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
0190     struct fw_rsc_vdev *rsc;
0191 
0192     rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset;
0193 
0194     return rsc->status;
0195 }
0196 
0197 static void rproc_virtio_set_status(struct virtio_device *vdev, u8 status)
0198 {
0199     struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
0200     struct fw_rsc_vdev *rsc;
0201 
0202     rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset;
0203 
0204     rsc->status = status;
0205     dev_dbg(&vdev->dev, "status: %d\n", status);
0206 }
0207 
0208 static void rproc_virtio_reset(struct virtio_device *vdev)
0209 {
0210     struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
0211     struct fw_rsc_vdev *rsc;
0212 
0213     rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset;
0214 
0215     rsc->status = 0;
0216     dev_dbg(&vdev->dev, "reset !\n");
0217 }
0218 
0219 /* provide the vdev features as retrieved from the firmware */
0220 static u64 rproc_virtio_get_features(struct virtio_device *vdev)
0221 {
0222     struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
0223     struct fw_rsc_vdev *rsc;
0224 
0225     rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset;
0226 
0227     return rsc->dfeatures;
0228 }
0229 
0230 static void rproc_transport_features(struct virtio_device *vdev)
0231 {
0232     /*
0233      * Packed ring isn't enabled on remoteproc for now,
0234      * because remoteproc uses vring_new_virtqueue() which
0235      * creates virtio rings on preallocated memory.
0236      */
0237     __virtio_clear_bit(vdev, VIRTIO_F_RING_PACKED);
0238 }
0239 
0240 static int rproc_virtio_finalize_features(struct virtio_device *vdev)
0241 {
0242     struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
0243     struct fw_rsc_vdev *rsc;
0244 
0245     rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset;
0246 
0247     /* Give virtio_ring a chance to accept features */
0248     vring_transport_features(vdev);
0249 
0250     /* Give virtio_rproc a chance to accept features. */
0251     rproc_transport_features(vdev);
0252 
0253     /* Make sure we don't have any features > 32 bits! */
0254     BUG_ON((u32)vdev->features != vdev->features);
0255 
0256     /*
0257      * Remember the finalized features of our vdev, and provide it
0258      * to the remote processor once it is powered on.
0259      */
0260     rsc->gfeatures = vdev->features;
0261 
0262     return 0;
0263 }
0264 
0265 static void rproc_virtio_get(struct virtio_device *vdev, unsigned int offset,
0266                  void *buf, unsigned int len)
0267 {
0268     struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
0269     struct fw_rsc_vdev *rsc;
0270     void *cfg;
0271 
0272     rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset;
0273     cfg = &rsc->vring[rsc->num_of_vrings];
0274 
0275     if (offset + len > rsc->config_len || offset + len < len) {
0276         dev_err(&vdev->dev, "rproc_virtio_get: access out of bounds\n");
0277         return;
0278     }
0279 
0280     memcpy(buf, cfg + offset, len);
0281 }
0282 
0283 static void rproc_virtio_set(struct virtio_device *vdev, unsigned int offset,
0284                  const void *buf, unsigned int len)
0285 {
0286     struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
0287     struct fw_rsc_vdev *rsc;
0288     void *cfg;
0289 
0290     rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset;
0291     cfg = &rsc->vring[rsc->num_of_vrings];
0292 
0293     if (offset + len > rsc->config_len || offset + len < len) {
0294         dev_err(&vdev->dev, "rproc_virtio_set: access out of bounds\n");
0295         return;
0296     }
0297 
0298     memcpy(cfg + offset, buf, len);
0299 }
0300 
0301 static const struct virtio_config_ops rproc_virtio_config_ops = {
0302     .get_features   = rproc_virtio_get_features,
0303     .finalize_features = rproc_virtio_finalize_features,
0304     .find_vqs   = rproc_virtio_find_vqs,
0305     .del_vqs    = rproc_virtio_del_vqs,
0306     .reset      = rproc_virtio_reset,
0307     .set_status = rproc_virtio_set_status,
0308     .get_status = rproc_virtio_get_status,
0309     .get        = rproc_virtio_get,
0310     .set        = rproc_virtio_set,
0311 };
0312 
0313 /*
0314  * This function is called whenever vdev is released, and is responsible
0315  * to decrement the remote processor's refcount which was taken when vdev was
0316  * added.
0317  *
0318  * Never call this function directly; it will be called by the driver
0319  * core when needed.
0320  */
0321 static void rproc_virtio_dev_release(struct device *dev)
0322 {
0323     struct virtio_device *vdev = dev_to_virtio(dev);
0324     struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
0325     struct rproc *rproc = vdev_to_rproc(vdev);
0326 
0327     kfree(vdev);
0328 
0329     kref_put(&rvdev->refcount, rproc_vdev_release);
0330 
0331     put_device(&rproc->dev);
0332 }
0333 
0334 /**
0335  * rproc_add_virtio_dev() - register an rproc-induced virtio device
0336  * @rvdev: the remote vdev
0337  * @id: the device type identification (used to match it with a driver).
0338  *
0339  * This function registers a virtio device. This vdev's partent is
0340  * the rproc device.
0341  *
0342  * Return: 0 on success or an appropriate error value otherwise
0343  */
0344 int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id)
0345 {
0346     struct rproc *rproc = rvdev->rproc;
0347     struct device *dev = &rvdev->dev;
0348     struct virtio_device *vdev;
0349     struct rproc_mem_entry *mem;
0350     int ret;
0351 
0352     if (rproc->ops->kick == NULL) {
0353         ret = -EINVAL;
0354         dev_err(dev, ".kick method not defined for %s\n", rproc->name);
0355         goto out;
0356     }
0357 
0358     /* Try to find dedicated vdev buffer carveout */
0359     mem = rproc_find_carveout_by_name(rproc, "vdev%dbuffer", rvdev->index);
0360     if (mem) {
0361         phys_addr_t pa;
0362 
0363         if (mem->of_resm_idx != -1) {
0364             struct device_node *np = rproc->dev.parent->of_node;
0365 
0366             /* Associate reserved memory to vdev device */
0367             ret = of_reserved_mem_device_init_by_idx(dev, np,
0368                                  mem->of_resm_idx);
0369             if (ret) {
0370                 dev_err(dev, "Can't associate reserved memory\n");
0371                 goto out;
0372             }
0373         } else {
0374             if (mem->va) {
0375                 dev_warn(dev, "vdev %d buffer already mapped\n",
0376                      rvdev->index);
0377                 pa = rproc_va_to_pa(mem->va);
0378             } else {
0379                 /* Use dma address as carveout no memmapped yet */
0380                 pa = (phys_addr_t)mem->dma;
0381             }
0382 
0383             /* Associate vdev buffer memory pool to vdev subdev */
0384             ret = dma_declare_coherent_memory(dev, pa,
0385                                mem->da,
0386                                mem->len);
0387             if (ret < 0) {
0388                 dev_err(dev, "Failed to associate buffer\n");
0389                 goto out;
0390             }
0391         }
0392     } else {
0393         struct device_node *np = rproc->dev.parent->of_node;
0394 
0395         /*
0396          * If we don't have dedicated buffer, just attempt to re-assign
0397          * the reserved memory from our parent. A default memory-region
0398          * at index 0 from the parent's memory-regions is assigned for
0399          * the rvdev dev to allocate from. Failure is non-critical and
0400          * the allocations will fall back to global pools, so don't
0401          * check return value either.
0402          */
0403         of_reserved_mem_device_init_by_idx(dev, np, 0);
0404     }
0405 
0406     /* Allocate virtio device */
0407     vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
0408     if (!vdev) {
0409         ret = -ENOMEM;
0410         goto out;
0411     }
0412     vdev->id.device = id,
0413     vdev->config = &rproc_virtio_config_ops,
0414     vdev->dev.parent = dev;
0415     vdev->dev.release = rproc_virtio_dev_release;
0416 
0417     /*
0418      * We're indirectly making a non-temporary copy of the rproc pointer
0419      * here, because drivers probed with this vdev will indirectly
0420      * access the wrapping rproc.
0421      *
0422      * Therefore we must increment the rproc refcount here, and decrement
0423      * it _only_ when the vdev is released.
0424      */
0425     get_device(&rproc->dev);
0426 
0427     /* Reference the vdev and vring allocations */
0428     kref_get(&rvdev->refcount);
0429 
0430     ret = register_virtio_device(vdev);
0431     if (ret) {
0432         put_device(&vdev->dev);
0433         dev_err(dev, "failed to register vdev: %d\n", ret);
0434         goto out;
0435     }
0436 
0437     dev_info(dev, "registered %s (type %d)\n", dev_name(&vdev->dev), id);
0438 
0439 out:
0440     return ret;
0441 }
0442 
0443 /**
0444  * rproc_remove_virtio_dev() - remove an rproc-induced virtio device
0445  * @dev: the virtio device
0446  * @data: must be null
0447  *
0448  * This function unregisters an existing virtio device.
0449  *
0450  * Return: 0
0451  */
0452 int rproc_remove_virtio_dev(struct device *dev, void *data)
0453 {
0454     struct virtio_device *vdev = dev_to_virtio(dev);
0455 
0456     unregister_virtio_device(vdev);
0457     return 0;
0458 }