0001
0002
0003
0004
0005
0006
0007
0008
0009
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
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
0053
0054
0055
0056
0057
0058
0059
0060
0061
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
0093 if (id >= ARRAY_SIZE(rvdev->vring))
0094 return ERR_PTR(-EINVAL);
0095
0096 if (!name)
0097 return NULL;
0098
0099
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
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
0118
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
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
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
0234
0235
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
0248 vring_transport_features(vdev);
0249
0250
0251 rproc_transport_features(vdev);
0252
0253
0254 BUG_ON((u32)vdev->features != vdev->features);
0255
0256
0257
0258
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
0315
0316
0317
0318
0319
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
0336
0337
0338
0339
0340
0341
0342
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
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
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
0380 pa = (phys_addr_t)mem->dma;
0381 }
0382
0383
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
0397
0398
0399
0400
0401
0402
0403 of_reserved_mem_device_init_by_idx(dev, np, 0);
0404 }
0405
0406
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
0419
0420
0421
0422
0423
0424
0425 get_device(&rproc->dev);
0426
0427
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
0445
0446
0447
0448
0449
0450
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 }