1 /* 2 * Remote processor messaging transport (OMAP platform-specific bits) 3 * 4 * Copyright (C) 2011 Texas Instruments, Inc. 5 * Copyright (C) 2011 Google, Inc. 6 * 7 * Ohad Ben-Cohen <ohad@wizery.com> 8 * Brian Swetland <swetland@google.com> 9 * 10 * This software is licensed under the terms of the GNU General Public 11 * License version 2, as published by the Free Software Foundation, and 12 * may be copied, distributed, and modified under those terms. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 */ 19 20 #include <linux/dma-mapping.h> 21 #include <linux/export.h> 22 #include <linux/of_reserved_mem.h> 23 #include <linux/remoteproc.h> 24 #include <linux/virtio.h> 25 #include <linux/virtio_config.h> 26 #include <linux/virtio_ids.h> 27 #include <linux/virtio_ring.h> 28 #include <linux/err.h> 29 #include <linux/kref.h> 30 #include <linux/slab.h> 31 32 #include "remoteproc_internal.h" 33 34 /* kick the remote processor, and let it know which virtqueue to poke at */ 35 static bool rproc_virtio_notify(struct virtqueue *vq) 36 { 37 struct rproc_vring *rvring = vq->priv; 38 struct rproc *rproc = rvring->rvdev->rproc; 39 int notifyid = rvring->notifyid; 40 41 dev_dbg(&rproc->dev, "kicking vq index: %d\n", notifyid); 42 43 rproc->ops->kick(rproc, notifyid); 44 return true; 45 } 46 47 /** 48 * rproc_vq_interrupt() - tell remoteproc that a virtqueue is interrupted 49 * @rproc: handle to the remote processor 50 * @notifyid: index of the signalled virtqueue (unique per this @rproc) 51 * 52 * This function should be called by the platform-specific rproc driver, 53 * when the remote processor signals that a specific virtqueue has pending 54 * messages available. 55 * 56 * Returns IRQ_NONE if no message was found in the @notifyid virtqueue, 57 * and otherwise returns IRQ_HANDLED. 58 */ 59 irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int notifyid) 60 { 61 struct rproc_vring *rvring; 62 63 dev_dbg(&rproc->dev, "vq index %d is interrupted\n", notifyid); 64 65 rvring = idr_find(&rproc->notifyids, notifyid); 66 if (!rvring || !rvring->vq) 67 return IRQ_NONE; 68 69 return vring_interrupt(0, rvring->vq); 70 } 71 EXPORT_SYMBOL(rproc_vq_interrupt); 72 73 static struct virtqueue *rp_find_vq(struct virtio_device *vdev, 74 unsigned int id, 75 void (*callback)(struct virtqueue *vq), 76 const char *name, bool ctx) 77 { 78 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); 79 struct rproc *rproc = vdev_to_rproc(vdev); 80 struct device *dev = &rproc->dev; 81 struct rproc_mem_entry *mem; 82 struct rproc_vring *rvring; 83 struct fw_rsc_vdev *rsc; 84 struct virtqueue *vq; 85 void *addr; 86 int len, size; 87 88 /* we're temporarily limited to two virtqueues per rvdev */ 89 if (id >= ARRAY_SIZE(rvdev->vring)) 90 return ERR_PTR(-EINVAL); 91 92 if (!name) 93 return NULL; 94 95 /* Search allocated memory region by name */ 96 mem = rproc_find_carveout_by_name(rproc, "vdev%dvring%d", rvdev->index, 97 id); 98 if (!mem || !mem->va) 99 return ERR_PTR(-ENOMEM); 100 101 rvring = &rvdev->vring[id]; 102 addr = mem->va; 103 len = rvring->len; 104 105 /* zero vring */ 106 size = vring_size(len, rvring->align); 107 memset(addr, 0, size); 108 109 dev_dbg(dev, "vring%d: va %pK qsz %d notifyid %d\n", 110 id, addr, len, rvring->notifyid); 111 112 /* 113 * Create the new vq, and tell virtio we're not interested in 114 * the 'weak' smp barriers, since we're talking with a real device. 115 */ 116 vq = vring_new_virtqueue(id, len, rvring->align, vdev, false, ctx, 117 addr, rproc_virtio_notify, callback, name); 118 if (!vq) { 119 dev_err(dev, "vring_new_virtqueue %s failed\n", name); 120 rproc_free_vring(rvring); 121 return ERR_PTR(-ENOMEM); 122 } 123 124 rvring->vq = vq; 125 vq->priv = rvring; 126 127 /* Update vring in resource table */ 128 rsc = (void *)rproc->table_ptr + rvdev->rsc_offset; 129 rsc->vring[id].da = mem->da; 130 131 return vq; 132 } 133 134 static void __rproc_virtio_del_vqs(struct virtio_device *vdev) 135 { 136 struct virtqueue *vq, *n; 137 struct rproc_vring *rvring; 138 139 list_for_each_entry_safe(vq, n, &vdev->vqs, list) { 140 rvring = vq->priv; 141 rvring->vq = NULL; 142 vring_del_virtqueue(vq); 143 } 144 } 145 146 static void rproc_virtio_del_vqs(struct virtio_device *vdev) 147 { 148 __rproc_virtio_del_vqs(vdev); 149 } 150 151 static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs, 152 struct virtqueue *vqs[], 153 vq_callback_t *callbacks[], 154 const char * const names[], 155 const bool * ctx, 156 struct irq_affinity *desc) 157 { 158 int i, ret; 159 160 for (i = 0; i < nvqs; ++i) { 161 vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i], 162 ctx ? ctx[i] : false); 163 if (IS_ERR(vqs[i])) { 164 ret = PTR_ERR(vqs[i]); 165 goto error; 166 } 167 } 168 169 return 0; 170 171 error: 172 __rproc_virtio_del_vqs(vdev); 173 return ret; 174 } 175 176 static u8 rproc_virtio_get_status(struct virtio_device *vdev) 177 { 178 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); 179 struct fw_rsc_vdev *rsc; 180 181 rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset; 182 183 return rsc->status; 184 } 185 186 static void rproc_virtio_set_status(struct virtio_device *vdev, u8 status) 187 { 188 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); 189 struct fw_rsc_vdev *rsc; 190 191 rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset; 192 193 rsc->status = status; 194 dev_dbg(&vdev->dev, "status: %d\n", status); 195 } 196 197 static void rproc_virtio_reset(struct virtio_device *vdev) 198 { 199 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); 200 struct fw_rsc_vdev *rsc; 201 202 rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset; 203 204 rsc->status = 0; 205 dev_dbg(&vdev->dev, "reset !\n"); 206 } 207 208 /* provide the vdev features as retrieved from the firmware */ 209 static u64 rproc_virtio_get_features(struct virtio_device *vdev) 210 { 211 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); 212 struct fw_rsc_vdev *rsc; 213 214 rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset; 215 216 return rsc->dfeatures; 217 } 218 219 static void rproc_transport_features(struct virtio_device *vdev) 220 { 221 /* 222 * Packed ring isn't enabled on remoteproc for now, 223 * because remoteproc uses vring_new_virtqueue() which 224 * creates virtio rings on preallocated memory. 225 */ 226 __virtio_clear_bit(vdev, VIRTIO_F_RING_PACKED); 227 } 228 229 static int rproc_virtio_finalize_features(struct virtio_device *vdev) 230 { 231 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); 232 struct fw_rsc_vdev *rsc; 233 234 rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset; 235 236 /* Give virtio_ring a chance to accept features */ 237 vring_transport_features(vdev); 238 239 /* Give virtio_rproc a chance to accept features. */ 240 rproc_transport_features(vdev); 241 242 /* Make sure we don't have any features > 32 bits! */ 243 BUG_ON((u32)vdev->features != vdev->features); 244 245 /* 246 * Remember the finalized features of our vdev, and provide it 247 * to the remote processor once it is powered on. 248 */ 249 rsc->gfeatures = vdev->features; 250 251 return 0; 252 } 253 254 static void rproc_virtio_get(struct virtio_device *vdev, unsigned int offset, 255 void *buf, unsigned int len) 256 { 257 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); 258 struct fw_rsc_vdev *rsc; 259 void *cfg; 260 261 rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset; 262 cfg = &rsc->vring[rsc->num_of_vrings]; 263 264 if (offset + len > rsc->config_len || offset + len < len) { 265 dev_err(&vdev->dev, "rproc_virtio_get: access out of bounds\n"); 266 return; 267 } 268 269 memcpy(buf, cfg + offset, len); 270 } 271 272 static void rproc_virtio_set(struct virtio_device *vdev, unsigned int offset, 273 const void *buf, unsigned int len) 274 { 275 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); 276 struct fw_rsc_vdev *rsc; 277 void *cfg; 278 279 rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset; 280 cfg = &rsc->vring[rsc->num_of_vrings]; 281 282 if (offset + len > rsc->config_len || offset + len < len) { 283 dev_err(&vdev->dev, "rproc_virtio_set: access out of bounds\n"); 284 return; 285 } 286 287 memcpy(cfg + offset, buf, len); 288 } 289 290 static const struct virtio_config_ops rproc_virtio_config_ops = { 291 .get_features = rproc_virtio_get_features, 292 .finalize_features = rproc_virtio_finalize_features, 293 .find_vqs = rproc_virtio_find_vqs, 294 .del_vqs = rproc_virtio_del_vqs, 295 .reset = rproc_virtio_reset, 296 .set_status = rproc_virtio_set_status, 297 .get_status = rproc_virtio_get_status, 298 .get = rproc_virtio_get, 299 .set = rproc_virtio_set, 300 }; 301 302 /* 303 * This function is called whenever vdev is released, and is responsible 304 * to decrement the remote processor's refcount which was taken when vdev was 305 * added. 306 * 307 * Never call this function directly; it will be called by the driver 308 * core when needed. 309 */ 310 static void rproc_virtio_dev_release(struct device *dev) 311 { 312 struct virtio_device *vdev = dev_to_virtio(dev); 313 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); 314 struct rproc *rproc = vdev_to_rproc(vdev); 315 316 kref_put(&rvdev->refcount, rproc_vdev_release); 317 318 put_device(&rproc->dev); 319 } 320 321 /** 322 * rproc_add_virtio_dev() - register an rproc-induced virtio device 323 * @rvdev: the remote vdev 324 * 325 * This function registers a virtio device. This vdev's partent is 326 * the rproc device. 327 * 328 * Returns 0 on success or an appropriate error value otherwise. 329 */ 330 int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id) 331 { 332 struct rproc *rproc = rvdev->rproc; 333 struct device *dev = &rvdev->dev; 334 struct virtio_device *vdev = &rvdev->vdev; 335 struct rproc_mem_entry *mem; 336 int ret; 337 338 /* Try to find dedicated vdev buffer carveout */ 339 mem = rproc_find_carveout_by_name(rproc, "vdev%dbuffer", rvdev->index); 340 if (mem) { 341 phys_addr_t pa; 342 343 if (mem->of_resm_idx != -1) { 344 struct device_node *np = rproc->dev.parent->of_node; 345 346 /* Associate reserved memory to vdev device */ 347 ret = of_reserved_mem_device_init_by_idx(dev, np, 348 mem->of_resm_idx); 349 if (ret) { 350 dev_err(dev, "Can't associate reserved memory\n"); 351 goto out; 352 } 353 } else { 354 if (mem->va) { 355 dev_warn(dev, "vdev %d buffer already mapped\n", 356 rvdev->index); 357 pa = rproc_va_to_pa(mem->va); 358 } else { 359 /* Use dma address as carveout no memmapped yet */ 360 pa = (phys_addr_t)mem->dma; 361 } 362 363 /* Associate vdev buffer memory pool to vdev subdev */ 364 ret = dma_declare_coherent_memory(dev, pa, 365 mem->da, 366 mem->len, 367 DMA_MEMORY_EXCLUSIVE); 368 if (ret < 0) { 369 dev_err(dev, "Failed to associate buffer\n"); 370 goto out; 371 } 372 } 373 } 374 375 vdev->id.device = id, 376 vdev->config = &rproc_virtio_config_ops, 377 vdev->dev.parent = dev; 378 vdev->dev.release = rproc_virtio_dev_release; 379 380 /* 381 * We're indirectly making a non-temporary copy of the rproc pointer 382 * here, because drivers probed with this vdev will indirectly 383 * access the wrapping rproc. 384 * 385 * Therefore we must increment the rproc refcount here, and decrement 386 * it _only_ when the vdev is released. 387 */ 388 get_device(&rproc->dev); 389 390 /* Reference the vdev and vring allocations */ 391 kref_get(&rvdev->refcount); 392 393 ret = register_virtio_device(vdev); 394 if (ret) { 395 put_device(&vdev->dev); 396 dev_err(dev, "failed to register vdev: %d\n", ret); 397 goto out; 398 } 399 400 dev_info(dev, "registered %s (type %d)\n", dev_name(&vdev->dev), id); 401 402 out: 403 return ret; 404 } 405 406 /** 407 * rproc_remove_virtio_dev() - remove an rproc-induced virtio device 408 * @rvdev: the remote vdev 409 * 410 * This function unregisters an existing virtio device. 411 */ 412 void rproc_remove_virtio_dev(struct rproc_vdev *rvdev) 413 { 414 unregister_virtio_device(&rvdev->vdev); 415 } 416