Blame view

drivers/remoteproc/remoteproc_virtio.c 11.3 KB
9c92ab619   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
2
3
4
5
6
7
8
9
  /*
   * Remote processor messaging transport (OMAP platform-specific bits)
   *
   * Copyright (C) 2011 Texas Instruments, Inc.
   * Copyright (C) 2011 Google, Inc.
   *
   * Ohad Ben-Cohen <ohad@wizery.com>
   * Brian Swetland <swetland@google.com>
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
10
   */
0a0f0d8be   Christoph Hellwig   dma-mapping: spli...
11
  #include <linux/dma-map-ops.h>
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
12
  #include <linux/export.h>
086d08725   Loic Pallardy   remoteproc: creat...
13
  #include <linux/of_reserved_mem.h>
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
14
  #include <linux/remoteproc.h>
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
15
16
17
18
19
20
21
22
23
  #include <linux/virtio.h>
  #include <linux/virtio_config.h>
  #include <linux/virtio_ids.h>
  #include <linux/virtio_ring.h>
  #include <linux/err.h>
  #include <linux/kref.h>
  #include <linux/slab.h>
  
  #include "remoteproc_internal.h"
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
24
  /* kick the remote processor, and let it know which virtqueue to poke at */
46f9c2b92   Heinz Graalfs   virtio_ring: chan...
25
  static bool rproc_virtio_notify(struct virtqueue *vq)
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
26
  {
7a1869416   Ohad Ben-Cohen   remoteproc: remov...
27
28
29
  	struct rproc_vring *rvring = vq->priv;
  	struct rproc *rproc = rvring->rvdev->rproc;
  	int notifyid = rvring->notifyid;
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
30

b5ab5e24e   Ohad Ben-Cohen   remoteproc: maint...
31
32
  	dev_dbg(&rproc->dev, "kicking vq index: %d
  ", notifyid);
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
33

7a1869416   Ohad Ben-Cohen   remoteproc: remov...
34
  	rproc->ops->kick(rproc, notifyid);
46f9c2b92   Heinz Graalfs   virtio_ring: chan...
35
  	return true;
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
36
37
38
39
40
  }
  
  /**
   * rproc_vq_interrupt() - tell remoteproc that a virtqueue is interrupted
   * @rproc: handle to the remote processor
7a1869416   Ohad Ben-Cohen   remoteproc: remov...
41
   * @notifyid: index of the signalled virtqueue (unique per this @rproc)
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
42
43
44
45
46
   *
   * This function should be called by the platform-specific rproc driver,
   * when the remote processor signals that a specific virtqueue has pending
   * messages available.
   *
7a1869416   Ohad Ben-Cohen   remoteproc: remov...
47
   * Returns IRQ_NONE if no message was found in the @notifyid virtqueue,
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
48
49
   * and otherwise returns IRQ_HANDLED.
   */
7a1869416   Ohad Ben-Cohen   remoteproc: remov...
50
  irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int notifyid)
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
51
  {
7a1869416   Ohad Ben-Cohen   remoteproc: remov...
52
  	struct rproc_vring *rvring;
b5ab5e24e   Ohad Ben-Cohen   remoteproc: maint...
53
54
  	dev_dbg(&rproc->dev, "vq index %d is interrupted
  ", notifyid);
7a1869416   Ohad Ben-Cohen   remoteproc: remov...
55
56
57
58
59
60
  
  	rvring = idr_find(&rproc->notifyids, notifyid);
  	if (!rvring || !rvring->vq)
  		return IRQ_NONE;
  
  	return vring_interrupt(0, rvring->vq);
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
61
62
63
64
  }
  EXPORT_SYMBOL(rproc_vq_interrupt);
  
  static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
f145928d4   Anna, Suman   remoteproc: fix b...
65
  				    unsigned int id,
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
66
  				    void (*callback)(struct virtqueue *vq),
f94682dde   Michael S. Tsirkin   virtio: add conte...
67
  				    const char *name, bool ctx)
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
68
  {
7a1869416   Ohad Ben-Cohen   remoteproc: remov...
69
  	struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
70
  	struct rproc *rproc = vdev_to_rproc(vdev);
b5ab5e24e   Ohad Ben-Cohen   remoteproc: maint...
71
  	struct device *dev = &rproc->dev;
c6aed238b   Loic Pallardy   remoteproc: modif...
72
  	struct rproc_mem_entry *mem;
7a1869416   Ohad Ben-Cohen   remoteproc: remov...
73
  	struct rproc_vring *rvring;
c6aed238b   Loic Pallardy   remoteproc: modif...
74
  	struct fw_rsc_vdev *rsc;
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
75
76
  	struct virtqueue *vq;
  	void *addr;
a863af5d4   Bjorn Andersson   remoteproc: virti...
77
  	int len, size;
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
78

7a1869416   Ohad Ben-Cohen   remoteproc: remov...
79
80
81
  	/* we're temporarily limited to two virtqueues per rvdev */
  	if (id >= ARRAY_SIZE(rvdev->vring))
  		return ERR_PTR(-EINVAL);
6457f126c   Michael S. Tsirkin   virtio: support r...
82
83
  	if (!name)
  		return NULL;
c6aed238b   Loic Pallardy   remoteproc: modif...
84
85
86
87
88
  	/* Search allocated memory region by name */
  	mem = rproc_find_carveout_by_name(rproc, "vdev%dvring%d", rvdev->index,
  					  id);
  	if (!mem || !mem->va)
  		return ERR_PTR(-ENOMEM);
6db20ea8d   Ohad Ben-Cohen   remoteproc: alloc...
89
  	rvring = &rvdev->vring[id];
c6aed238b   Loic Pallardy   remoteproc: modif...
90
  	addr = mem->va;
7a1869416   Ohad Ben-Cohen   remoteproc: remov...
91
  	len = rvring->len;
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
92

7a1869416   Ohad Ben-Cohen   remoteproc: remov...
93
94
95
  	/* zero vring */
  	size = vring_size(len, rvring->align);
  	memset(addr, 0, size);
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
96

276ec9934   Loic Pallardy   remoteproc: repla...
97
98
  	dev_dbg(dev, "vring%d: va %pK qsz %d notifyid %d
  ",
730f84ce6   Anna, Suman   remoteproc: align...
99
  		id, addr, len, rvring->notifyid);
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
100

dd6da1c5e   Ohad Ben-Cohen   remoteproc: don't...
101
102
103
104
  	/*
  	 * Create the new vq, and tell virtio we're not interested in
  	 * the 'weak' smp barriers, since we're talking with a real device.
  	 */
f94682dde   Michael S. Tsirkin   virtio: add conte...
105
106
  	vq = vring_new_virtqueue(id, len, rvring->align, vdev, false, ctx,
  				 addr, rproc_virtio_notify, callback, name);
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
107
  	if (!vq) {
b5ab5e24e   Ohad Ben-Cohen   remoteproc: maint...
108
109
  		dev_err(dev, "vring_new_virtqueue %s failed
  ", name);
6db20ea8d   Ohad Ben-Cohen   remoteproc: alloc...
110
  		rproc_free_vring(rvring);
7a1869416   Ohad Ben-Cohen   remoteproc: remov...
111
  		return ERR_PTR(-ENOMEM);
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
112
  	}
7a1869416   Ohad Ben-Cohen   remoteproc: remov...
113
114
  	rvring->vq = vq;
  	vq->priv = rvring;
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
115

c6aed238b   Loic Pallardy   remoteproc: modif...
116
117
118
  	/* Update vring in resource table */
  	rsc = (void *)rproc->table_ptr + rvdev->rsc_offset;
  	rsc->vring[id].da = mem->da;
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
119
  	return vq;
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
120
  }
dab55bbaf   Ohad Ben-Cohen   remoteproc: fix e...
121
  static void __rproc_virtio_del_vqs(struct virtio_device *vdev)
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
122
123
  {
  	struct virtqueue *vq, *n;
7a1869416   Ohad Ben-Cohen   remoteproc: remov...
124
  	struct rproc_vring *rvring;
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
125
126
  
  	list_for_each_entry_safe(vq, n, &vdev->vqs, list) {
7a1869416   Ohad Ben-Cohen   remoteproc: remov...
127
128
  		rvring = vq->priv;
  		rvring->vq = NULL;
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
129
  		vring_del_virtqueue(vq);
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
130
  	}
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
131
  }
dab55bbaf   Ohad Ben-Cohen   remoteproc: fix e...
132
133
  static void rproc_virtio_del_vqs(struct virtio_device *vdev)
  {
dab55bbaf   Ohad Ben-Cohen   remoteproc: fix e...
134
135
  	__rproc_virtio_del_vqs(vdev);
  }
f145928d4   Anna, Suman   remoteproc: fix b...
136
  static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
730f84ce6   Anna, Suman   remoteproc: align...
137
138
  				 struct virtqueue *vqs[],
  				 vq_callback_t *callbacks[],
fb5e31d97   Christoph Hellwig   virtio: allow dri...
139
  				 const char * const names[],
f94682dde   Michael S. Tsirkin   virtio: add conte...
140
  				 const bool * ctx,
fb5e31d97   Christoph Hellwig   virtio: allow dri...
141
  				 struct irq_affinity *desc)
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
142
  {
a229989d9   Wei Wang   virtio: don't all...
143
  	int i, ret, queue_idx = 0;
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
144

ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
145
  	for (i = 0; i < nvqs; ++i) {
a229989d9   Wei Wang   virtio: don't all...
146
147
148
149
150
151
  		if (!names[i]) {
  			vqs[i] = NULL;
  			continue;
  		}
  
  		vqs[i] = rp_find_vq(vdev, queue_idx++, callbacks[i], names[i],
f94682dde   Michael S. Tsirkin   virtio: add conte...
152
  				    ctx ? ctx[i] : false);
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
153
154
155
156
157
158
159
160
161
  		if (IS_ERR(vqs[i])) {
  			ret = PTR_ERR(vqs[i]);
  			goto error;
  		}
  	}
  
  	return 0;
  
  error:
dab55bbaf   Ohad Ben-Cohen   remoteproc: fix e...
162
  	__rproc_virtio_del_vqs(vdev);
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
163
164
  	return ret;
  }
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
165
166
  static u8 rproc_virtio_get_status(struct virtio_device *vdev)
  {
92b38f851   Sjur Brændeland   remoteproc: suppo...
167
168
169
170
171
172
  	struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
  	struct fw_rsc_vdev *rsc;
  
  	rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset;
  
  	return rsc->status;
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
173
174
175
176
  }
  
  static void rproc_virtio_set_status(struct virtio_device *vdev, u8 status)
  {
92b38f851   Sjur Brændeland   remoteproc: suppo...
177
178
179
180
181
182
  	struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
  	struct fw_rsc_vdev *rsc;
  
  	rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset;
  
  	rsc->status = status;
7a1869416   Ohad Ben-Cohen   remoteproc: remov...
183
184
  	dev_dbg(&vdev->dev, "status: %d
  ", status);
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
185
186
187
188
  }
  
  static void rproc_virtio_reset(struct virtio_device *vdev)
  {
92b38f851   Sjur Brændeland   remoteproc: suppo...
189
190
191
192
193
194
  	struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
  	struct fw_rsc_vdev *rsc;
  
  	rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset;
  
  	rsc->status = 0;
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
195
196
197
198
199
  	dev_dbg(&vdev->dev, "reset !
  ");
  }
  
  /* provide the vdev features as retrieved from the firmware */
d02547736   Michael S. Tsirkin   virtio: add suppo...
200
  static u64 rproc_virtio_get_features(struct virtio_device *vdev)
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
201
  {
7a1869416   Ohad Ben-Cohen   remoteproc: remov...
202
  	struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
92b38f851   Sjur Brændeland   remoteproc: suppo...
203
204
205
  	struct fw_rsc_vdev *rsc;
  
  	rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset;
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
206

92b38f851   Sjur Brændeland   remoteproc: suppo...
207
  	return rsc->dfeatures;
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
208
  }
3a814fdf2   Tiwei Bie   virtio_ring: disa...
209
210
211
212
213
214
215
216
217
  static void rproc_transport_features(struct virtio_device *vdev)
  {
  	/*
  	 * Packed ring isn't enabled on remoteproc for now,
  	 * because remoteproc uses vring_new_virtqueue() which
  	 * creates virtio rings on preallocated memory.
  	 */
  	__virtio_clear_bit(vdev, VIRTIO_F_RING_PACKED);
  }
5c609a5ef   Michael S. Tsirkin   virtio: allow fin...
218
  static int rproc_virtio_finalize_features(struct virtio_device *vdev)
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
219
  {
7a1869416   Ohad Ben-Cohen   remoteproc: remov...
220
  	struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
92b38f851   Sjur Brændeland   remoteproc: suppo...
221
222
223
  	struct fw_rsc_vdev *rsc;
  
  	rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset;
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
224
225
226
  
  	/* Give virtio_ring a chance to accept features */
  	vring_transport_features(vdev);
3a814fdf2   Tiwei Bie   virtio_ring: disa...
227
228
  	/* Give virtio_rproc a chance to accept features. */
  	rproc_transport_features(vdev);
93d389f82   Michael S. Tsirkin   virtio: assert 32...
229
230
  	/* Make sure we don't have any features > 32 bits! */
  	BUG_ON((u32)vdev->features != vdev->features);
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
231
232
233
  	/*
  	 * Remember the finalized features of our vdev, and provide it
  	 * to the remote processor once it is powered on.
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
234
  	 */
e16e12be3   Michael S. Tsirkin   virtio: use u32, ...
235
  	rsc->gfeatures = vdev->features;
5c609a5ef   Michael S. Tsirkin   virtio: allow fin...
236
237
  
  	return 0;
92b38f851   Sjur Brændeland   remoteproc: suppo...
238
  }
f145928d4   Anna, Suman   remoteproc: fix b...
239
240
  static void rproc_virtio_get(struct virtio_device *vdev, unsigned int offset,
  			     void *buf, unsigned int len)
92b38f851   Sjur Brændeland   remoteproc: suppo...
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
  {
  	struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
  	struct fw_rsc_vdev *rsc;
  	void *cfg;
  
  	rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset;
  	cfg = &rsc->vring[rsc->num_of_vrings];
  
  	if (offset + len > rsc->config_len || offset + len < len) {
  		dev_err(&vdev->dev, "rproc_virtio_get: access out of bounds
  ");
  		return;
  	}
  
  	memcpy(buf, cfg + offset, len);
  }
f145928d4   Anna, Suman   remoteproc: fix b...
257
258
  static void rproc_virtio_set(struct virtio_device *vdev, unsigned int offset,
  			     const void *buf, unsigned int len)
92b38f851   Sjur Brændeland   remoteproc: suppo...
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
  {
  	struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
  	struct fw_rsc_vdev *rsc;
  	void *cfg;
  
  	rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset;
  	cfg = &rsc->vring[rsc->num_of_vrings];
  
  	if (offset + len > rsc->config_len || offset + len < len) {
  		dev_err(&vdev->dev, "rproc_virtio_set: access out of bounds
  ");
  		return;
  	}
  
  	memcpy(cfg + offset, buf, len);
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
274
  }
935039323   Stephen Hemminger   virtio: make conf...
275
  static const struct virtio_config_ops rproc_virtio_config_ops = {
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
276
277
278
279
280
281
282
  	.get_features	= rproc_virtio_get_features,
  	.finalize_features = rproc_virtio_finalize_features,
  	.find_vqs	= rproc_virtio_find_vqs,
  	.del_vqs	= rproc_virtio_del_vqs,
  	.reset		= rproc_virtio_reset,
  	.set_status	= rproc_virtio_set_status,
  	.get_status	= rproc_virtio_get_status,
92b38f851   Sjur Brændeland   remoteproc: suppo...
283
284
  	.get		= rproc_virtio_get,
  	.set		= rproc_virtio_set,
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
285
286
287
288
  };
  
  /*
   * This function is called whenever vdev is released, and is responsible
7183a2a79   Ohad Ben-Cohen   remoteproc: remov...
289
   * to decrement the remote processor's refcount which was taken when vdev was
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
290
291
292
293
294
   * added.
   *
   * Never call this function directly; it will be called by the driver
   * core when needed.
   */
aab8d8022   Bjorn Andersson   remoteproc: Assig...
295
  static void rproc_virtio_dev_release(struct device *dev)
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
296
297
  {
  	struct virtio_device *vdev = dev_to_virtio(dev);
6db20ea8d   Ohad Ben-Cohen   remoteproc: alloc...
298
  	struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
299
  	struct rproc *rproc = vdev_to_rproc(vdev);
d4c036fec   Loic Pallardy   remoteproc: fix r...
300
  	kfree(vdev);
aab8d8022   Bjorn Andersson   remoteproc: Assig...
301
  	kref_put(&rvdev->refcount, rproc_vdev_release);
6db20ea8d   Ohad Ben-Cohen   remoteproc: alloc...
302

7183a2a79   Ohad Ben-Cohen   remoteproc: remov...
303
  	put_device(&rproc->dev);
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
304
305
306
  }
  
  /**
7a1869416   Ohad Ben-Cohen   remoteproc: remov...
307
308
   * rproc_add_virtio_dev() - register an rproc-induced virtio device
   * @rvdev: the remote vdev
2e7d4c2c4   Arnaud Pouliquen   remoteproc: fix k...
309
   * @id: the device type identification (used to match it with a driver).
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
310
   *
7a1869416   Ohad Ben-Cohen   remoteproc: remov...
311
312
   * This function registers a virtio device. This vdev's partent is
   * the rproc device.
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
313
   *
7a1869416   Ohad Ben-Cohen   remoteproc: remov...
314
   * Returns 0 on success or an appropriate error value otherwise.
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
315
   */
7a1869416   Ohad Ben-Cohen   remoteproc: remov...
316
  int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id)
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
317
  {
7a1869416   Ohad Ben-Cohen   remoteproc: remov...
318
  	struct rproc *rproc = rvdev->rproc;
086d08725   Loic Pallardy   remoteproc: creat...
319
  	struct device *dev = &rvdev->dev;
d4c036fec   Loic Pallardy   remoteproc: fix r...
320
  	struct virtio_device *vdev;
086d08725   Loic Pallardy   remoteproc: creat...
321
  	struct rproc_mem_entry *mem;
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
322
  	int ret;
791c13b70   Nikita Shubin   remoteproc: Fix N...
323
324
  	if (rproc->ops->kick == NULL) {
  		ret = -EINVAL;
2fb75ceaf   Christophe JAILLET   remoteproc: Add m...
325
326
  		dev_err(dev, ".kick method not defined for %s
  ", rproc->name);
791c13b70   Nikita Shubin   remoteproc: Fix N...
327
328
  		goto out;
  	}
086d08725   Loic Pallardy   remoteproc: creat...
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
  	/* Try to find dedicated vdev buffer carveout */
  	mem = rproc_find_carveout_by_name(rproc, "vdev%dbuffer", rvdev->index);
  	if (mem) {
  		phys_addr_t pa;
  
  		if (mem->of_resm_idx != -1) {
  			struct device_node *np = rproc->dev.parent->of_node;
  
  			/* Associate reserved memory to vdev device */
  			ret = of_reserved_mem_device_init_by_idx(dev, np,
  								 mem->of_resm_idx);
  			if (ret) {
  				dev_err(dev, "Can't associate reserved memory
  ");
  				goto out;
  			}
  		} else {
  			if (mem->va) {
  				dev_warn(dev, "vdev %d buffer already mapped
  ",
  					 rvdev->index);
  				pa = rproc_va_to_pa(mem->va);
  			} else {
  				/* Use dma address as carveout no memmapped yet */
  				pa = (phys_addr_t)mem->dma;
  			}
  
  			/* Associate vdev buffer memory pool to vdev subdev */
  			ret = dma_declare_coherent_memory(dev, pa,
  							   mem->da,
d664ce75a   Stephen Rothwell   remoteproc: fix f...
359
  							   mem->len);
086d08725   Loic Pallardy   remoteproc: creat...
360
361
362
363
364
365
  			if (ret < 0) {
  				dev_err(dev, "Failed to associate buffer
  ");
  				goto out;
  			}
  		}
db9178a4f   Tero Kristo   remoteproc: Fall ...
366
367
368
369
370
371
372
373
374
375
376
377
  	} else {
  		struct device_node *np = rproc->dev.parent->of_node;
  
  		/*
  		 * If we don't have dedicated buffer, just attempt to re-assign
  		 * the reserved memory from our parent. A default memory-region
  		 * at index 0 from the parent's memory-regions is assigned for
  		 * the rvdev dev to allocate from. Failure is non-critical and
  		 * the allocations will fall back to global pools, so don't
  		 * check return value either.
  		 */
  		of_reserved_mem_device_init_by_idx(dev, np, 0);
086d08725   Loic Pallardy   remoteproc: creat...
378
  	}
d4c036fec   Loic Pallardy   remoteproc: fix r...
379
380
381
382
383
384
  	/* Allocate virtio device */
  	vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
  	if (!vdev) {
  		ret = -ENOMEM;
  		goto out;
  	}
7a1869416   Ohad Ben-Cohen   remoteproc: remov...
385
386
387
  	vdev->id.device	= id,
  	vdev->config = &rproc_virtio_config_ops,
  	vdev->dev.parent = dev;
aab8d8022   Bjorn Andersson   remoteproc: Assig...
388
  	vdev->dev.release = rproc_virtio_dev_release;
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
389
390
391
392
393
394
395
396
397
  
  	/*
  	 * We're indirectly making a non-temporary copy of the rproc pointer
  	 * here, because drivers probed with this vdev will indirectly
  	 * access the wrapping rproc.
  	 *
  	 * Therefore we must increment the rproc refcount here, and decrement
  	 * it _only_ when the vdev is released.
  	 */
7183a2a79   Ohad Ben-Cohen   remoteproc: remov...
398
  	get_device(&rproc->dev);
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
399

aab8d8022   Bjorn Andersson   remoteproc: Assig...
400
401
  	/* Reference the vdev and vring allocations */
  	kref_get(&rvdev->refcount);
7a1869416   Ohad Ben-Cohen   remoteproc: remov...
402
  	ret = register_virtio_device(vdev);
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
403
  	if (ret) {
900a163ed   weiping zhang   virtio_remoteproc...
404
  		put_device(&vdev->dev);
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
405
406
  		dev_err(dev, "failed to register vdev: %d
  ", ret);
7a1869416   Ohad Ben-Cohen   remoteproc: remov...
407
  		goto out;
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
408
  	}
7a1869416   Ohad Ben-Cohen   remoteproc: remov...
409
410
411
412
  	dev_info(dev, "registered %s (type %d)
  ", dev_name(&vdev->dev), id);
  
  out:
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
413
414
415
416
  	return ret;
  }
  
  /**
7a1869416   Ohad Ben-Cohen   remoteproc: remov...
417
   * rproc_remove_virtio_dev() - remove an rproc-induced virtio device
d4c036fec   Loic Pallardy   remoteproc: fix r...
418
419
   * @dev: the virtio device
   * @data: must be null
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
420
   *
7a1869416   Ohad Ben-Cohen   remoteproc: remov...
421
   * This function unregisters an existing virtio device.
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
422
   */
d4c036fec   Loic Pallardy   remoteproc: fix r...
423
  int rproc_remove_virtio_dev(struct device *dev, void *data)
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
424
  {
d4c036fec   Loic Pallardy   remoteproc: fix r...
425
426
427
428
  	struct virtio_device *vdev = dev_to_virtio(dev);
  
  	unregister_virtio_device(vdev);
  	return 0;
ac8954a41   Ohad Ben-Cohen   remoteproc: creat...
429
  }