diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-06 20:03:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-06 20:03:49 -0400 |
commit | 521f3970853a4b2ff7f833763532bdba2ea11257 (patch) | |
tree | 671b7ae7f048c8ae1a00ad1e491716563dc236cf | |
parent | d880e5ad0df3c2e1d69bb356737a46abb5087d42 (diff) | |
parent | 395317bbc200fbc164e65cc8ec31fa9d766aeaf1 (diff) |
Merge tag 'rpmsg-v4.9' of git://github.com/andersson/remoteproc
Pull rpmsg updates from Bjorn Andersson:
"The bulk of these patches involve splitting the rpmsg implementation
into a framework/API part and a virtio specific backend part. It then
adds the Qualcomm Shared Memory Device (SMD) as an additional
supported wire format.
Also included is a set of code style cleanups that have been lingering
for a while"
* tag 'rpmsg-v4.9' of git://github.com/andersson/remoteproc: (26 commits)
rpmsg: smd: fix dependency on QCOM_SMD=n
rpmsg: Introduce Qualcomm SMD backend
rpmsg: Allow callback to return errors
rpmsg: Move virtio specifics from public header
rpmsg: virtio: Hide vrp pointer from the public API
rpmsg: Hide rpmsg indirection tables
rpmsg: Split rpmsg core and virtio backend
rpmsg: Split off generic tail of create_channel()
rpmsg: Move helper for finding rpmsg devices to core
rpmsg: Move endpoint related interface to rpmsg core
rpmsg: Indirection table for rpmsg_endpoint operations
rpmsg: Move rpmsg_device API to new file
rpmsg: Introduce indirection table for rpmsg_device operations
rpmsg: Clean up rpmsg device vs channel naming
rpmsg: Make rpmsg_create_ept() take channel_info struct
rpmsg: rpmsg_send() operations takes rpmsg_endpoint
rpmsg: Name rpmsg devices based on channel id
rpmsg: Enable matching devices with drivers based on DT
rpmsg: Drop prototypes for non-existing functions
samples/rpmsg: add support for multiple instances
...
-rw-r--r-- | drivers/remoteproc/Kconfig | 4 | ||||
-rw-r--r-- | drivers/rpmsg/Kconfig | 14 | ||||
-rw-r--r-- | drivers/rpmsg/Makefile | 4 | ||||
-rw-r--r-- | drivers/rpmsg/qcom_smd.c | 1434 | ||||
-rw-r--r-- | drivers/rpmsg/rpmsg_core.c | 498 | ||||
-rw-r--r-- | drivers/rpmsg/rpmsg_internal.h | 82 | ||||
-rw-r--r-- | drivers/rpmsg/virtio_rpmsg_bus.c | 541 | ||||
-rw-r--r-- | include/linux/rpmsg.h | 248 | ||||
-rw-r--r-- | samples/rpmsg/rpmsg_client_sample.c | 32 |
9 files changed, 2308 insertions, 549 deletions
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index f76b3b1dca1a..f396bfef5d42 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig | |||
@@ -17,7 +17,7 @@ config OMAP_REMOTEPROC | |||
17 | select REMOTEPROC | 17 | select REMOTEPROC |
18 | select MAILBOX | 18 | select MAILBOX |
19 | select OMAP2PLUS_MBOX | 19 | select OMAP2PLUS_MBOX |
20 | select RPMSG | 20 | select RPMSG_VIRTIO |
21 | help | 21 | help |
22 | Say y here to support OMAP's remote processors (dual M3 | 22 | Say y here to support OMAP's remote processors (dual M3 |
23 | and DSP on OMAP4) via the remote processor framework. | 23 | and DSP on OMAP4) via the remote processor framework. |
@@ -59,7 +59,7 @@ config DA8XX_REMOTEPROC | |||
59 | depends on ARCH_DAVINCI_DA8XX | 59 | depends on ARCH_DAVINCI_DA8XX |
60 | select CMA if MMU | 60 | select CMA if MMU |
61 | select REMOTEPROC | 61 | select REMOTEPROC |
62 | select RPMSG | 62 | select RPMSG_VIRTIO |
63 | help | 63 | help |
64 | Say y here to support DA8xx/OMAP-L13x remote processors via the | 64 | Say y here to support DA8xx/OMAP-L13x remote processors via the |
65 | remote processor framework. | 65 | remote processor framework. |
diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig index 69a219387582..de31c5f14dd9 100644 --- a/drivers/rpmsg/Kconfig +++ b/drivers/rpmsg/Kconfig | |||
@@ -3,6 +3,20 @@ menu "Rpmsg drivers" | |||
3 | # RPMSG always gets selected by whoever wants it | 3 | # RPMSG always gets selected by whoever wants it |
4 | config RPMSG | 4 | config RPMSG |
5 | tristate | 5 | tristate |
6 | |||
7 | config RPMSG_QCOM_SMD | ||
8 | tristate "Qualcomm Shared Memory Driver (SMD)" | ||
9 | depends on QCOM_SMEM | ||
10 | depends on QCOM_SMD=n | ||
11 | select RPMSG | ||
12 | help | ||
13 | Say y here to enable support for the Qualcomm Shared Memory Driver | ||
14 | providing communication channels to remote processors in Qualcomm | ||
15 | platforms. | ||
16 | |||
17 | config RPMSG_VIRTIO | ||
18 | tristate | ||
19 | select RPMSG | ||
6 | select VIRTIO | 20 | select VIRTIO |
7 | select VIRTUALIZATION | 21 | select VIRTUALIZATION |
8 | 22 | ||
diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile index 7617fcb8259f..ae9c9132cf76 100644 --- a/drivers/rpmsg/Makefile +++ b/drivers/rpmsg/Makefile | |||
@@ -1 +1,3 @@ | |||
1 | obj-$(CONFIG_RPMSG) += virtio_rpmsg_bus.o | 1 | obj-$(CONFIG_RPMSG) += rpmsg_core.o |
2 | obj-$(CONFIG_RPMSG_QCOM_SMD) += qcom_smd.o | ||
3 | obj-$(CONFIG_RPMSG_VIRTIO) += virtio_rpmsg_bus.o | ||
diff --git a/drivers/rpmsg/qcom_smd.c b/drivers/rpmsg/qcom_smd.c new file mode 100644 index 000000000000..06fef2b4c814 --- /dev/null +++ b/drivers/rpmsg/qcom_smd.c | |||
@@ -0,0 +1,1434 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2015, Sony Mobile Communications AB. | ||
3 | * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 and | ||
7 | * only version 2 as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | */ | ||
14 | |||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/mfd/syscon.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/of_irq.h> | ||
20 | #include <linux/of_platform.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/regmap.h> | ||
23 | #include <linux/sched.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/soc/qcom/smem.h> | ||
26 | #include <linux/wait.h> | ||
27 | #include <linux/rpmsg.h> | ||
28 | |||
29 | #include "rpmsg_internal.h" | ||
30 | |||
31 | /* | ||
32 | * The Qualcomm Shared Memory communication solution provides point-to-point | ||
33 | * channels for clients to send and receive streaming or packet based data. | ||
34 | * | ||
35 | * Each channel consists of a control item (channel info) and a ring buffer | ||
36 | * pair. The channel info carry information related to channel state, flow | ||
37 | * control and the offsets within the ring buffer. | ||
38 | * | ||
39 | * All allocated channels are listed in an allocation table, identifying the | ||
40 | * pair of items by name, type and remote processor. | ||
41 | * | ||
42 | * Upon creating a new channel the remote processor allocates channel info and | ||
43 | * ring buffer items from the smem heap and populate the allocation table. An | ||
44 | * interrupt is sent to the other end of the channel and a scan for new | ||
45 | * channels should be done. A channel never goes away, it will only change | ||
46 | * state. | ||
47 | * | ||
48 | * The remote processor signals it intent for bring up the communication | ||
49 | * channel by setting the state of its end of the channel to "opening" and | ||
50 | * sends out an interrupt. We detect this change and register a smd device to | ||
51 | * consume the channel. Upon finding a consumer we finish the handshake and the | ||
52 | * channel is up. | ||
53 | * | ||
54 | * Upon closing a channel, the remote processor will update the state of its | ||
55 | * end of the channel and signal us, we will then unregister any attached | ||
56 | * device and close our end of the channel. | ||
57 | * | ||
58 | * Devices attached to a channel can use the qcom_smd_send function to push | ||
59 | * data to the channel, this is done by copying the data into the tx ring | ||
60 | * buffer, updating the pointers in the channel info and signaling the remote | ||
61 | * processor. | ||
62 | * | ||
63 | * The remote processor does the equivalent when it transfer data and upon | ||
64 | * receiving the interrupt we check the channel info for new data and delivers | ||
65 | * this to the attached device. If the device is not ready to receive the data | ||
66 | * we leave it in the ring buffer for now. | ||
67 | */ | ||
68 | |||
69 | struct smd_channel_info; | ||
70 | struct smd_channel_info_pair; | ||
71 | struct smd_channel_info_word; | ||
72 | struct smd_channel_info_word_pair; | ||
73 | |||
74 | static const struct rpmsg_endpoint_ops qcom_smd_endpoint_ops; | ||
75 | |||
76 | #define SMD_ALLOC_TBL_COUNT 2 | ||
77 | #define SMD_ALLOC_TBL_SIZE 64 | ||
78 | |||
79 | /* | ||
80 | * This lists the various smem heap items relevant for the allocation table and | ||
81 | * smd channel entries. | ||
82 | */ | ||
83 | static const struct { | ||
84 | unsigned alloc_tbl_id; | ||
85 | unsigned info_base_id; | ||
86 | unsigned fifo_base_id; | ||
87 | } smem_items[SMD_ALLOC_TBL_COUNT] = { | ||
88 | { | ||
89 | .alloc_tbl_id = 13, | ||
90 | .info_base_id = 14, | ||
91 | .fifo_base_id = 338 | ||
92 | }, | ||
93 | { | ||
94 | .alloc_tbl_id = 266, | ||
95 | .info_base_id = 138, | ||
96 | .fifo_base_id = 202, | ||
97 | }, | ||
98 | }; | ||
99 | |||
100 | /** | ||
101 | * struct qcom_smd_edge - representing a remote processor | ||
102 | * @of_node: of_node handle for information related to this edge | ||
103 | * @edge_id: identifier of this edge | ||
104 | * @remote_pid: identifier of remote processor | ||
105 | * @irq: interrupt for signals on this edge | ||
106 | * @ipc_regmap: regmap handle holding the outgoing ipc register | ||
107 | * @ipc_offset: offset within @ipc_regmap of the register for ipc | ||
108 | * @ipc_bit: bit in the register at @ipc_offset of @ipc_regmap | ||
109 | * @channels: list of all channels detected on this edge | ||
110 | * @channels_lock: guard for modifications of @channels | ||
111 | * @allocated: array of bitmaps representing already allocated channels | ||
112 | * @smem_available: last available amount of smem triggering a channel scan | ||
113 | * @scan_work: work item for discovering new channels | ||
114 | * @state_work: work item for edge state changes | ||
115 | */ | ||
116 | struct qcom_smd_edge { | ||
117 | struct device dev; | ||
118 | |||
119 | struct device_node *of_node; | ||
120 | unsigned edge_id; | ||
121 | unsigned remote_pid; | ||
122 | |||
123 | int irq; | ||
124 | |||
125 | struct regmap *ipc_regmap; | ||
126 | int ipc_offset; | ||
127 | int ipc_bit; | ||
128 | |||
129 | struct list_head channels; | ||
130 | spinlock_t channels_lock; | ||
131 | |||
132 | DECLARE_BITMAP(allocated[SMD_ALLOC_TBL_COUNT], SMD_ALLOC_TBL_SIZE); | ||
133 | |||
134 | unsigned smem_available; | ||
135 | |||
136 | wait_queue_head_t new_channel_event; | ||
137 | |||
138 | struct work_struct scan_work; | ||
139 | struct work_struct state_work; | ||
140 | }; | ||
141 | |||
142 | /* | ||
143 | * SMD channel states. | ||
144 | */ | ||
145 | enum smd_channel_state { | ||
146 | SMD_CHANNEL_CLOSED, | ||
147 | SMD_CHANNEL_OPENING, | ||
148 | SMD_CHANNEL_OPENED, | ||
149 | SMD_CHANNEL_FLUSHING, | ||
150 | SMD_CHANNEL_CLOSING, | ||
151 | SMD_CHANNEL_RESET, | ||
152 | SMD_CHANNEL_RESET_OPENING | ||
153 | }; | ||
154 | |||
155 | struct qcom_smd_device { | ||
156 | struct rpmsg_device rpdev; | ||
157 | |||
158 | struct qcom_smd_edge *edge; | ||
159 | }; | ||
160 | |||
161 | struct qcom_smd_endpoint { | ||
162 | struct rpmsg_endpoint ept; | ||
163 | |||
164 | struct qcom_smd_channel *qsch; | ||
165 | }; | ||
166 | |||
167 | #define to_smd_device(_rpdev) container_of(_rpdev, struct qcom_smd_device, rpdev) | ||
168 | #define to_smd_edge(d) container_of(d, struct qcom_smd_edge, dev) | ||
169 | #define to_smd_endpoint(ept) container_of(ept, struct qcom_smd_endpoint, ept) | ||
170 | |||
171 | /** | ||
172 | * struct qcom_smd_channel - smd channel struct | ||
173 | * @edge: qcom_smd_edge this channel is living on | ||
174 | * @qsdev: reference to a associated smd client device | ||
175 | * @name: name of the channel | ||
176 | * @state: local state of the channel | ||
177 | * @remote_state: remote state of the channel | ||
178 | * @info: byte aligned outgoing/incoming channel info | ||
179 | * @info_word: word aligned outgoing/incoming channel info | ||
180 | * @tx_lock: lock to make writes to the channel mutually exclusive | ||
181 | * @fblockread_event: wakeup event tied to tx fBLOCKREADINTR | ||
182 | * @tx_fifo: pointer to the outgoing ring buffer | ||
183 | * @rx_fifo: pointer to the incoming ring buffer | ||
184 | * @fifo_size: size of each ring buffer | ||
185 | * @bounce_buffer: bounce buffer for reading wrapped packets | ||
186 | * @cb: callback function registered for this channel | ||
187 | * @recv_lock: guard for rx info modifications and cb pointer | ||
188 | * @pkt_size: size of the currently handled packet | ||
189 | * @list: lite entry for @channels in qcom_smd_edge | ||
190 | */ | ||
191 | struct qcom_smd_channel { | ||
192 | struct qcom_smd_edge *edge; | ||
193 | |||
194 | struct qcom_smd_endpoint *qsept; | ||
195 | bool registered; | ||
196 | |||
197 | char *name; | ||
198 | enum smd_channel_state state; | ||
199 | enum smd_channel_state remote_state; | ||
200 | |||
201 | struct smd_channel_info_pair *info; | ||
202 | struct smd_channel_info_word_pair *info_word; | ||
203 | |||
204 | struct mutex tx_lock; | ||
205 | wait_queue_head_t fblockread_event; | ||
206 | |||
207 | void *tx_fifo; | ||
208 | void *rx_fifo; | ||
209 | int fifo_size; | ||
210 | |||
211 | void *bounce_buffer; | ||
212 | |||
213 | spinlock_t recv_lock; | ||
214 | |||
215 | int pkt_size; | ||
216 | |||
217 | void *drvdata; | ||
218 | |||
219 | struct list_head list; | ||
220 | }; | ||
221 | |||
222 | /* | ||
223 | * Format of the smd_info smem items, for byte aligned channels. | ||
224 | */ | ||
225 | struct smd_channel_info { | ||
226 | __le32 state; | ||
227 | u8 fDSR; | ||
228 | u8 fCTS; | ||
229 | u8 fCD; | ||
230 | u8 fRI; | ||
231 | u8 fHEAD; | ||
232 | u8 fTAIL; | ||
233 | u8 fSTATE; | ||
234 | u8 fBLOCKREADINTR; | ||
235 | __le32 tail; | ||
236 | __le32 head; | ||
237 | }; | ||
238 | |||
239 | struct smd_channel_info_pair { | ||
240 | struct smd_channel_info tx; | ||
241 | struct smd_channel_info rx; | ||
242 | }; | ||
243 | |||
244 | /* | ||
245 | * Format of the smd_info smem items, for word aligned channels. | ||
246 | */ | ||
247 | struct smd_channel_info_word { | ||
248 | __le32 state; | ||
249 | __le32 fDSR; | ||
250 | __le32 fCTS; | ||
251 | __le32 fCD; | ||
252 | __le32 fRI; | ||
253 | __le32 fHEAD; | ||
254 | __le32 fTAIL; | ||
255 | __le32 fSTATE; | ||
256 | __le32 fBLOCKREADINTR; | ||
257 | __le32 tail; | ||
258 | __le32 head; | ||
259 | }; | ||
260 | |||
261 | struct smd_channel_info_word_pair { | ||
262 | struct smd_channel_info_word tx; | ||
263 | struct smd_channel_info_word rx; | ||
264 | }; | ||
265 | |||
266 | #define GET_RX_CHANNEL_FLAG(channel, param) \ | ||
267 | ({ \ | ||
268 | BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u8)); \ | ||
269 | channel->info_word ? \ | ||
270 | le32_to_cpu(channel->info_word->rx.param) : \ | ||
271 | channel->info->rx.param; \ | ||
272 | }) | ||
273 | |||
274 | #define GET_RX_CHANNEL_INFO(channel, param) \ | ||
275 | ({ \ | ||
276 | BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u32)); \ | ||
277 | le32_to_cpu(channel->info_word ? \ | ||
278 | channel->info_word->rx.param : \ | ||
279 | channel->info->rx.param); \ | ||
280 | }) | ||
281 | |||
282 | #define SET_RX_CHANNEL_FLAG(channel, param, value) \ | ||
283 | ({ \ | ||
284 | BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u8)); \ | ||
285 | if (channel->info_word) \ | ||
286 | channel->info_word->rx.param = cpu_to_le32(value); \ | ||
287 | else \ | ||
288 | channel->info->rx.param = value; \ | ||
289 | }) | ||
290 | |||
291 | #define SET_RX_CHANNEL_INFO(channel, param, value) \ | ||
292 | ({ \ | ||
293 | BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u32)); \ | ||
294 | if (channel->info_word) \ | ||
295 | channel->info_word->rx.param = cpu_to_le32(value); \ | ||
296 | else \ | ||
297 | channel->info->rx.param = cpu_to_le32(value); \ | ||
298 | }) | ||
299 | |||
300 | #define GET_TX_CHANNEL_FLAG(channel, param) \ | ||
301 | ({ \ | ||
302 | BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u8)); \ | ||
303 | channel->info_word ? \ | ||
304 | le32_to_cpu(channel->info_word->tx.param) : \ | ||
305 | channel->info->tx.param; \ | ||
306 | }) | ||
307 | |||
308 | #define GET_TX_CHANNEL_INFO(channel, param) \ | ||
309 | ({ \ | ||
310 | BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u32)); \ | ||
311 | le32_to_cpu(channel->info_word ? \ | ||
312 | channel->info_word->tx.param : \ | ||
313 | channel->info->tx.param); \ | ||
314 | }) | ||
315 | |||
316 | #define SET_TX_CHANNEL_FLAG(channel, param, value) \ | ||
317 | ({ \ | ||
318 | BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u8)); \ | ||
319 | if (channel->info_word) \ | ||
320 | channel->info_word->tx.param = cpu_to_le32(value); \ | ||
321 | else \ | ||
322 | channel->info->tx.param = value; \ | ||
323 | }) | ||
324 | |||
325 | #define SET_TX_CHANNEL_INFO(channel, param, value) \ | ||
326 | ({ \ | ||
327 | BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u32)); \ | ||
328 | if (channel->info_word) \ | ||
329 | channel->info_word->tx.param = cpu_to_le32(value); \ | ||
330 | else \ | ||
331 | channel->info->tx.param = cpu_to_le32(value); \ | ||
332 | }) | ||
333 | |||
334 | /** | ||
335 | * struct qcom_smd_alloc_entry - channel allocation entry | ||
336 | * @name: channel name | ||
337 | * @cid: channel index | ||
338 | * @flags: channel flags and edge id | ||
339 | * @ref_count: reference count of the channel | ||
340 | */ | ||
341 | struct qcom_smd_alloc_entry { | ||
342 | u8 name[20]; | ||
343 | __le32 cid; | ||
344 | __le32 flags; | ||
345 | __le32 ref_count; | ||
346 | } __packed; | ||
347 | |||
348 | #define SMD_CHANNEL_FLAGS_EDGE_MASK 0xff | ||
349 | #define SMD_CHANNEL_FLAGS_STREAM BIT(8) | ||
350 | #define SMD_CHANNEL_FLAGS_PACKET BIT(9) | ||
351 | |||
352 | /* | ||
353 | * Each smd packet contains a 20 byte header, with the first 4 being the length | ||
354 | * of the packet. | ||
355 | */ | ||
356 | #define SMD_PACKET_HEADER_LEN 20 | ||
357 | |||
358 | /* | ||
359 | * Signal the remote processor associated with 'channel'. | ||
360 | */ | ||
361 | static void qcom_smd_signal_channel(struct qcom_smd_channel *channel) | ||
362 | { | ||
363 | struct qcom_smd_edge *edge = channel->edge; | ||
364 | |||
365 | regmap_write(edge->ipc_regmap, edge->ipc_offset, BIT(edge->ipc_bit)); | ||
366 | } | ||
367 | |||
368 | /* | ||
369 | * Initialize the tx channel info | ||
370 | */ | ||
371 | static void qcom_smd_channel_reset(struct qcom_smd_channel *channel) | ||
372 | { | ||
373 | SET_TX_CHANNEL_INFO(channel, state, SMD_CHANNEL_CLOSED); | ||
374 | SET_TX_CHANNEL_FLAG(channel, fDSR, 0); | ||
375 | SET_TX_CHANNEL_FLAG(channel, fCTS, 0); | ||
376 | SET_TX_CHANNEL_FLAG(channel, fCD, 0); | ||
377 | SET_TX_CHANNEL_FLAG(channel, fRI, 0); | ||
378 | SET_TX_CHANNEL_FLAG(channel, fHEAD, 0); | ||
379 | SET_TX_CHANNEL_FLAG(channel, fTAIL, 0); | ||
380 | SET_TX_CHANNEL_FLAG(channel, fSTATE, 1); | ||
381 | SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 1); | ||
382 | SET_TX_CHANNEL_INFO(channel, head, 0); | ||
383 | SET_RX_CHANNEL_INFO(channel, tail, 0); | ||
384 | |||
385 | qcom_smd_signal_channel(channel); | ||
386 | |||
387 | channel->state = SMD_CHANNEL_CLOSED; | ||
388 | channel->pkt_size = 0; | ||
389 | } | ||
390 | |||
391 | /* | ||
392 | * Set the callback for a channel, with appropriate locking | ||
393 | */ | ||
394 | static void qcom_smd_channel_set_callback(struct qcom_smd_channel *channel, | ||
395 | rpmsg_rx_cb_t cb) | ||
396 | { | ||
397 | struct rpmsg_endpoint *ept = &channel->qsept->ept; | ||
398 | unsigned long flags; | ||
399 | |||
400 | spin_lock_irqsave(&channel->recv_lock, flags); | ||
401 | ept->cb = cb; | ||
402 | spin_unlock_irqrestore(&channel->recv_lock, flags); | ||
403 | }; | ||
404 | |||
405 | /* | ||
406 | * Calculate the amount of data available in the rx fifo | ||
407 | */ | ||
408 | static size_t qcom_smd_channel_get_rx_avail(struct qcom_smd_channel *channel) | ||
409 | { | ||
410 | unsigned head; | ||
411 | unsigned tail; | ||
412 | |||
413 | head = GET_RX_CHANNEL_INFO(channel, head); | ||
414 | tail = GET_RX_CHANNEL_INFO(channel, tail); | ||
415 | |||
416 | return (head - tail) & (channel->fifo_size - 1); | ||
417 | } | ||
418 | |||
419 | /* | ||
420 | * Set tx channel state and inform the remote processor | ||
421 | */ | ||
422 | static void qcom_smd_channel_set_state(struct qcom_smd_channel *channel, | ||
423 | int state) | ||
424 | { | ||
425 | struct qcom_smd_edge *edge = channel->edge; | ||
426 | bool is_open = state == SMD_CHANNEL_OPENED; | ||
427 | |||
428 | if (channel->state == state) | ||
429 | return; | ||
430 | |||
431 | dev_dbg(&edge->dev, "set_state(%s, %d)\n", channel->name, state); | ||
432 | |||
433 | SET_TX_CHANNEL_FLAG(channel, fDSR, is_open); | ||
434 | SET_TX_CHANNEL_FLAG(channel, fCTS, is_open); | ||
435 | SET_TX_CHANNEL_FLAG(channel, fCD, is_open); | ||
436 | |||
437 | SET_TX_CHANNEL_INFO(channel, state, state); | ||
438 | SET_TX_CHANNEL_FLAG(channel, fSTATE, 1); | ||
439 | |||
440 | channel->state = state; | ||
441 | qcom_smd_signal_channel(channel); | ||
442 | } | ||
443 | |||
444 | /* | ||
445 | * Copy count bytes of data using 32bit accesses, if that's required. | ||
446 | */ | ||
447 | static void smd_copy_to_fifo(void __iomem *dst, | ||
448 | const void *src, | ||
449 | size_t count, | ||
450 | bool word_aligned) | ||
451 | { | ||
452 | if (word_aligned) { | ||
453 | __iowrite32_copy(dst, src, count / sizeof(u32)); | ||
454 | } else { | ||
455 | memcpy_toio(dst, src, count); | ||
456 | } | ||
457 | } | ||
458 | |||
459 | /* | ||
460 | * Copy count bytes of data using 32bit accesses, if that is required. | ||
461 | */ | ||
462 | static void smd_copy_from_fifo(void *dst, | ||
463 | const void __iomem *src, | ||
464 | size_t count, | ||
465 | bool word_aligned) | ||
466 | { | ||
467 | if (word_aligned) { | ||
468 | __ioread32_copy(dst, src, count / sizeof(u32)); | ||
469 | } else { | ||
470 | memcpy_fromio(dst, src, count); | ||
471 | } | ||
472 | } | ||
473 | |||
474 | /* | ||
475 | * Read count bytes of data from the rx fifo into buf, but don't advance the | ||
476 | * tail. | ||
477 | */ | ||
478 | static size_t qcom_smd_channel_peek(struct qcom_smd_channel *channel, | ||
479 | void *buf, size_t count) | ||
480 | { | ||
481 | bool word_aligned; | ||
482 | unsigned tail; | ||
483 | size_t len; | ||
484 | |||
485 | word_aligned = channel->info_word; | ||
486 | tail = GET_RX_CHANNEL_INFO(channel, tail); | ||
487 | |||
488 | len = min_t(size_t, count, channel->fifo_size - tail); | ||
489 | if (len) { | ||
490 | smd_copy_from_fifo(buf, | ||
491 | channel->rx_fifo + tail, | ||
492 | len, | ||
493 | word_aligned); | ||
494 | } | ||
495 | |||
496 | if (len != count) { | ||
497 | smd_copy_from_fifo(buf + len, | ||
498 | channel->rx_fifo, | ||
499 | count - len, | ||
500 | word_aligned); | ||
501 | } | ||
502 | |||
503 | return count; | ||
504 | } | ||
505 | |||
506 | /* | ||
507 | * Advance the rx tail by count bytes. | ||
508 | */ | ||
509 | static void qcom_smd_channel_advance(struct qcom_smd_channel *channel, | ||
510 | size_t count) | ||
511 | { | ||
512 | unsigned tail; | ||
513 | |||
514 | tail = GET_RX_CHANNEL_INFO(channel, tail); | ||
515 | tail += count; | ||
516 | tail &= (channel->fifo_size - 1); | ||
517 | SET_RX_CHANNEL_INFO(channel, tail, tail); | ||
518 | } | ||
519 | |||
520 | /* | ||
521 | * Read out a single packet from the rx fifo and deliver it to the device | ||
522 | */ | ||
523 | static int qcom_smd_channel_recv_single(struct qcom_smd_channel *channel) | ||
524 | { | ||
525 | struct rpmsg_endpoint *ept = &channel->qsept->ept; | ||
526 | unsigned tail; | ||
527 | size_t len; | ||
528 | void *ptr; | ||
529 | int ret; | ||
530 | |||
531 | tail = GET_RX_CHANNEL_INFO(channel, tail); | ||
532 | |||
533 | /* Use bounce buffer if the data wraps */ | ||
534 | if (tail + channel->pkt_size >= channel->fifo_size) { | ||
535 | ptr = channel->bounce_buffer; | ||
536 | len = qcom_smd_channel_peek(channel, ptr, channel->pkt_size); | ||
537 | } else { | ||
538 | ptr = channel->rx_fifo + tail; | ||
539 | len = channel->pkt_size; | ||
540 | } | ||
541 | |||
542 | ret = ept->cb(ept->rpdev, ptr, len, ept->priv, RPMSG_ADDR_ANY); | ||
543 | if (ret < 0) | ||
544 | return ret; | ||
545 | |||
546 | /* Only forward the tail if the client consumed the data */ | ||
547 | qcom_smd_channel_advance(channel, len); | ||
548 | |||
549 | channel->pkt_size = 0; | ||
550 | |||
551 | return 0; | ||
552 | } | ||
553 | |||
554 | /* | ||
555 | * Per channel interrupt handling | ||
556 | */ | ||
557 | static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel) | ||
558 | { | ||
559 | bool need_state_scan = false; | ||
560 | int remote_state; | ||
561 | __le32 pktlen; | ||
562 | int avail; | ||
563 | int ret; | ||
564 | |||
565 | /* Handle state changes */ | ||
566 | remote_state = GET_RX_CHANNEL_INFO(channel, state); | ||
567 | if (remote_state != channel->remote_state) { | ||
568 | channel->remote_state = remote_state; | ||
569 | need_state_scan = true; | ||
570 | } | ||
571 | /* Indicate that we have seen any state change */ | ||
572 | SET_RX_CHANNEL_FLAG(channel, fSTATE, 0); | ||
573 | |||
574 | /* Signal waiting qcom_smd_send() about the interrupt */ | ||
575 | if (!GET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR)) | ||
576 | wake_up_interruptible(&channel->fblockread_event); | ||
577 | |||
578 | /* Don't consume any data until we've opened the channel */ | ||
579 | if (channel->state != SMD_CHANNEL_OPENED) | ||
580 | goto out; | ||
581 | |||
582 | /* Indicate that we've seen the new data */ | ||
583 | SET_RX_CHANNEL_FLAG(channel, fHEAD, 0); | ||
584 | |||
585 | /* Consume data */ | ||
586 | for (;;) { | ||
587 | avail = qcom_smd_channel_get_rx_avail(channel); | ||
588 | |||
589 | if (!channel->pkt_size && avail >= SMD_PACKET_HEADER_LEN) { | ||
590 | qcom_smd_channel_peek(channel, &pktlen, sizeof(pktlen)); | ||
591 | qcom_smd_channel_advance(channel, SMD_PACKET_HEADER_LEN); | ||
592 | channel->pkt_size = le32_to_cpu(pktlen); | ||
593 | } else if (channel->pkt_size && avail >= channel->pkt_size) { | ||
594 | ret = qcom_smd_channel_recv_single(channel); | ||
595 | if (ret) | ||
596 | break; | ||
597 | } else { | ||
598 | break; | ||
599 | } | ||
600 | } | ||
601 | |||
602 | /* Indicate that we have seen and updated tail */ | ||
603 | SET_RX_CHANNEL_FLAG(channel, fTAIL, 1); | ||
604 | |||
605 | /* Signal the remote that we've consumed the data (if requested) */ | ||
606 | if (!GET_RX_CHANNEL_FLAG(channel, fBLOCKREADINTR)) { | ||
607 | /* Ensure ordering of channel info updates */ | ||
608 | wmb(); | ||
609 | |||
610 | qcom_smd_signal_channel(channel); | ||
611 | } | ||
612 | |||
613 | out: | ||
614 | return need_state_scan; | ||
615 | } | ||
616 | |||
617 | /* | ||
618 | * The edge interrupts are triggered by the remote processor on state changes, | ||
619 | * channel info updates or when new channels are created. | ||
620 | */ | ||
621 | static irqreturn_t qcom_smd_edge_intr(int irq, void *data) | ||
622 | { | ||
623 | struct qcom_smd_edge *edge = data; | ||
624 | struct qcom_smd_channel *channel; | ||
625 | unsigned available; | ||
626 | bool kick_scanner = false; | ||
627 | bool kick_state = false; | ||
628 | |||
629 | /* | ||
630 | * Handle state changes or data on each of the channels on this edge | ||
631 | */ | ||
632 | spin_lock(&edge->channels_lock); | ||
633 | list_for_each_entry(channel, &edge->channels, list) { | ||
634 | spin_lock(&channel->recv_lock); | ||
635 | kick_state |= qcom_smd_channel_intr(channel); | ||
636 | spin_unlock(&channel->recv_lock); | ||
637 | } | ||
638 | spin_unlock(&edge->channels_lock); | ||
639 | |||
640 | /* | ||
641 | * Creating a new channel requires allocating an smem entry, so we only | ||
642 | * have to scan if the amount of available space in smem have changed | ||
643 | * since last scan. | ||
644 | */ | ||
645 | available = qcom_smem_get_free_space(edge->remote_pid); | ||
646 | if (available != edge->smem_available) { | ||
647 | edge->smem_available = available; | ||
648 | kick_scanner = true; | ||
649 | } | ||
650 | |||
651 | if (kick_scanner) | ||
652 | schedule_work(&edge->scan_work); | ||
653 | if (kick_state) | ||
654 | schedule_work(&edge->state_work); | ||
655 | |||
656 | return IRQ_HANDLED; | ||
657 | } | ||
658 | |||
659 | /* | ||
660 | * Calculate how much space is available in the tx fifo. | ||
661 | */ | ||
662 | static size_t qcom_smd_get_tx_avail(struct qcom_smd_channel *channel) | ||
663 | { | ||
664 | unsigned head; | ||
665 | unsigned tail; | ||
666 | unsigned mask = channel->fifo_size - 1; | ||
667 | |||
668 | head = GET_TX_CHANNEL_INFO(channel, head); | ||
669 | tail = GET_TX_CHANNEL_INFO(channel, tail); | ||
670 | |||
671 | return mask - ((head - tail) & mask); | ||
672 | } | ||
673 | |||
674 | /* | ||
675 | * Write count bytes of data into channel, possibly wrapping in the ring buffer | ||
676 | */ | ||
677 | static int qcom_smd_write_fifo(struct qcom_smd_channel *channel, | ||
678 | const void *data, | ||
679 | size_t count) | ||
680 | { | ||
681 | bool word_aligned; | ||
682 | unsigned head; | ||
683 | size_t len; | ||
684 | |||
685 | word_aligned = channel->info_word; | ||
686 | head = GET_TX_CHANNEL_INFO(channel, head); | ||
687 | |||
688 | len = min_t(size_t, count, channel->fifo_size - head); | ||
689 | if (len) { | ||
690 | smd_copy_to_fifo(channel->tx_fifo + head, | ||
691 | data, | ||
692 | len, | ||
693 | word_aligned); | ||
694 | } | ||
695 | |||
696 | if (len != count) { | ||
697 | smd_copy_to_fifo(channel->tx_fifo, | ||
698 | data + len, | ||
699 | count - len, | ||
700 | word_aligned); | ||
701 | } | ||
702 | |||
703 | head += count; | ||
704 | head &= (channel->fifo_size - 1); | ||
705 | SET_TX_CHANNEL_INFO(channel, head, head); | ||
706 | |||
707 | return count; | ||
708 | } | ||
709 | |||
710 | /** | ||
711 | * qcom_smd_send - write data to smd channel | ||
712 | * @channel: channel handle | ||
713 | * @data: buffer of data to write | ||
714 | * @len: number of bytes to write | ||
715 | * | ||
716 | * This is a blocking write of len bytes into the channel's tx ring buffer and | ||
717 | * signal the remote end. It will sleep until there is enough space available | ||
718 | * in the tx buffer, utilizing the fBLOCKREADINTR signaling mechanism to avoid | ||
719 | * polling. | ||
720 | */ | ||
721 | static int __qcom_smd_send(struct qcom_smd_channel *channel, const void *data, | ||
722 | int len, bool wait) | ||
723 | { | ||
724 | __le32 hdr[5] = { cpu_to_le32(len), }; | ||
725 | int tlen = sizeof(hdr) + len; | ||
726 | int ret; | ||
727 | |||
728 | /* Word aligned channels only accept word size aligned data */ | ||
729 | if (channel->info_word && len % 4) | ||
730 | return -EINVAL; | ||
731 | |||
732 | /* Reject packets that are too big */ | ||
733 | if (tlen >= channel->fifo_size) | ||
734 | return -EINVAL; | ||
735 | |||
736 | ret = mutex_lock_interruptible(&channel->tx_lock); | ||
737 | if (ret) | ||
738 | return ret; | ||
739 | |||
740 | while (qcom_smd_get_tx_avail(channel) < tlen) { | ||
741 | if (!wait) { | ||
742 | ret = -ENOMEM; | ||
743 | goto out; | ||
744 | } | ||
745 | |||
746 | if (channel->state != SMD_CHANNEL_OPENED) { | ||
747 | ret = -EPIPE; | ||
748 | goto out; | ||
749 | } | ||
750 | |||
751 | SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 0); | ||
752 | |||
753 | ret = wait_event_interruptible(channel->fblockread_event, | ||
754 | qcom_smd_get_tx_avail(channel) >= tlen || | ||
755 | channel->state != SMD_CHANNEL_OPENED); | ||
756 | if (ret) | ||
757 | goto out; | ||
758 | |||
759 | SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 1); | ||
760 | } | ||
761 | |||
762 | SET_TX_CHANNEL_FLAG(channel, fTAIL, 0); | ||
763 | |||
764 | qcom_smd_write_fifo(channel, hdr, sizeof(hdr)); | ||
765 | qcom_smd_write_fifo(channel, data, len); | ||
766 | |||
767 | SET_TX_CHANNEL_FLAG(channel, fHEAD, 1); | ||
768 | |||
769 | /* Ensure ordering of channel info updates */ | ||
770 | wmb(); | ||
771 | |||
772 | qcom_smd_signal_channel(channel); | ||
773 | |||
774 | out: | ||
775 | mutex_unlock(&channel->tx_lock); | ||
776 | |||
777 | return ret; | ||
778 | } | ||
779 | |||
780 | /* | ||
781 | * Helper for opening a channel | ||
782 | */ | ||
783 | static int qcom_smd_channel_open(struct qcom_smd_channel *channel, | ||
784 | rpmsg_rx_cb_t cb) | ||
785 | { | ||
786 | size_t bb_size; | ||
787 | |||
788 | /* | ||
789 | * Packets are maximum 4k, but reduce if the fifo is smaller | ||
790 | */ | ||
791 | bb_size = min(channel->fifo_size, SZ_4K); | ||
792 | channel->bounce_buffer = kmalloc(bb_size, GFP_KERNEL); | ||
793 | if (!channel->bounce_buffer) | ||
794 | return -ENOMEM; | ||
795 | |||
796 | qcom_smd_channel_set_callback(channel, cb); | ||
797 | qcom_smd_channel_set_state(channel, SMD_CHANNEL_OPENING); | ||
798 | qcom_smd_channel_set_state(channel, SMD_CHANNEL_OPENED); | ||
799 | |||
800 | return 0; | ||
801 | } | ||
802 | |||
803 | /* | ||
804 | * Helper for closing and resetting a channel | ||
805 | */ | ||
806 | static void qcom_smd_channel_close(struct qcom_smd_channel *channel) | ||
807 | { | ||
808 | qcom_smd_channel_set_callback(channel, NULL); | ||
809 | |||
810 | kfree(channel->bounce_buffer); | ||
811 | channel->bounce_buffer = NULL; | ||
812 | |||
813 | qcom_smd_channel_set_state(channel, SMD_CHANNEL_CLOSED); | ||
814 | qcom_smd_channel_reset(channel); | ||
815 | } | ||
816 | |||
817 | static struct qcom_smd_channel * | ||
818 | qcom_smd_find_channel(struct qcom_smd_edge *edge, const char *name) | ||
819 | { | ||
820 | struct qcom_smd_channel *channel; | ||
821 | struct qcom_smd_channel *ret = NULL; | ||
822 | unsigned long flags; | ||
823 | unsigned state; | ||
824 | |||
825 | spin_lock_irqsave(&edge->channels_lock, flags); | ||
826 | list_for_each_entry(channel, &edge->channels, list) { | ||
827 | if (strcmp(channel->name, name)) | ||
828 | continue; | ||
829 | |||
830 | state = GET_RX_CHANNEL_INFO(channel, state); | ||
831 | if (state != SMD_CHANNEL_OPENING && | ||
832 | state != SMD_CHANNEL_OPENED) | ||
833 | continue; | ||
834 | |||
835 | ret = channel; | ||
836 | break; | ||
837 | } | ||
838 | spin_unlock_irqrestore(&edge->channels_lock, flags); | ||
839 | |||
840 | return ret; | ||
841 | } | ||
842 | |||
843 | static void __ept_release(struct kref *kref) | ||
844 | { | ||
845 | struct rpmsg_endpoint *ept = container_of(kref, struct rpmsg_endpoint, | ||
846 | refcount); | ||
847 | kfree(to_smd_endpoint(ept)); | ||
848 | } | ||
849 | |||
850 | static struct rpmsg_endpoint *qcom_smd_create_ept(struct rpmsg_device *rpdev, | ||
851 | rpmsg_rx_cb_t cb, void *priv, | ||
852 | struct rpmsg_channel_info chinfo) | ||
853 | { | ||
854 | struct qcom_smd_endpoint *qsept; | ||
855 | struct qcom_smd_channel *channel; | ||
856 | struct qcom_smd_device *qsdev = to_smd_device(rpdev); | ||
857 | struct qcom_smd_edge *edge = qsdev->edge; | ||
858 | struct rpmsg_endpoint *ept; | ||
859 | const char *name = chinfo.name; | ||
860 | int ret; | ||
861 | |||
862 | /* Wait up to HZ for the channel to appear */ | ||
863 | ret = wait_event_interruptible_timeout(edge->new_channel_event, | ||
864 | (channel = qcom_smd_find_channel(edge, name)) != NULL, | ||
865 | HZ); | ||
866 | if (!ret) | ||
867 | return NULL; | ||
868 | |||
869 | if (channel->state != SMD_CHANNEL_CLOSED) { | ||
870 | dev_err(&rpdev->dev, "channel %s is busy\n", channel->name); | ||
871 | return NULL; | ||
872 | } | ||
873 | |||
874 | qsept = kzalloc(sizeof(*qsept), GFP_KERNEL); | ||
875 | if (!qsept) | ||
876 | return NULL; | ||
877 | |||
878 | ept = &qsept->ept; | ||
879 | |||
880 | kref_init(&ept->refcount); | ||
881 | |||
882 | ept->rpdev = rpdev; | ||
883 | ept->cb = cb; | ||
884 | ept->priv = priv; | ||
885 | ept->ops = &qcom_smd_endpoint_ops; | ||
886 | |||
887 | channel->qsept = qsept; | ||
888 | qsept->qsch = channel; | ||
889 | |||
890 | ret = qcom_smd_channel_open(channel, cb); | ||
891 | if (ret) | ||
892 | goto free_ept; | ||
893 | |||
894 | return ept; | ||
895 | |||
896 | free_ept: | ||
897 | channel->qsept = NULL; | ||
898 | kref_put(&ept->refcount, __ept_release); | ||
899 | return NULL; | ||
900 | } | ||
901 | |||
902 | static void qcom_smd_destroy_ept(struct rpmsg_endpoint *ept) | ||
903 | { | ||
904 | struct qcom_smd_endpoint *qsept = to_smd_endpoint(ept); | ||
905 | struct qcom_smd_channel *ch = qsept->qsch; | ||
906 | |||
907 | qcom_smd_channel_close(ch); | ||
908 | ch->qsept = NULL; | ||
909 | kref_put(&ept->refcount, __ept_release); | ||
910 | } | ||
911 | |||
912 | static int qcom_smd_send(struct rpmsg_endpoint *ept, void *data, int len) | ||
913 | { | ||
914 | struct qcom_smd_endpoint *qsept = to_smd_endpoint(ept); | ||
915 | |||
916 | return __qcom_smd_send(qsept->qsch, data, len, true); | ||
917 | } | ||
918 | |||
919 | static int qcom_smd_trysend(struct rpmsg_endpoint *ept, void *data, int len) | ||
920 | { | ||
921 | struct qcom_smd_endpoint *qsept = to_smd_endpoint(ept); | ||
922 | |||
923 | return __qcom_smd_send(qsept->qsch, data, len, false); | ||
924 | } | ||
925 | |||
926 | /* | ||
927 | * Finds the device_node for the smd child interested in this channel. | ||
928 | */ | ||
929 | static struct device_node *qcom_smd_match_channel(struct device_node *edge_node, | ||
930 | const char *channel) | ||
931 | { | ||
932 | struct device_node *child; | ||
933 | const char *name; | ||
934 | const char *key; | ||
935 | int ret; | ||
936 | |||
937 | for_each_available_child_of_node(edge_node, child) { | ||
938 | key = "qcom,smd-channels"; | ||
939 | ret = of_property_read_string(child, key, &name); | ||
940 | if (ret) | ||
941 | continue; | ||
942 | |||
943 | if (strcmp(name, channel) == 0) | ||
944 | return child; | ||
945 | } | ||
946 | |||
947 | return NULL; | ||
948 | } | ||
949 | |||
950 | static const struct rpmsg_device_ops qcom_smd_device_ops = { | ||
951 | .create_ept = qcom_smd_create_ept, | ||
952 | }; | ||
953 | |||
954 | static const struct rpmsg_endpoint_ops qcom_smd_endpoint_ops = { | ||
955 | .destroy_ept = qcom_smd_destroy_ept, | ||
956 | .send = qcom_smd_send, | ||
957 | .trysend = qcom_smd_trysend, | ||
958 | }; | ||
959 | |||
960 | /* | ||
961 | * Create a smd client device for channel that is being opened. | ||
962 | */ | ||
963 | static int qcom_smd_create_device(struct qcom_smd_channel *channel) | ||
964 | { | ||
965 | struct qcom_smd_device *qsdev; | ||
966 | struct rpmsg_device *rpdev; | ||
967 | struct qcom_smd_edge *edge = channel->edge; | ||
968 | |||
969 | dev_dbg(&edge->dev, "registering '%s'\n", channel->name); | ||
970 | |||
971 | qsdev = kzalloc(sizeof(*qsdev), GFP_KERNEL); | ||
972 | if (!qsdev) | ||
973 | return -ENOMEM; | ||
974 | |||
975 | /* Link qsdev to our SMD edge */ | ||
976 | qsdev->edge = edge; | ||
977 | |||
978 | /* Assign callbacks for rpmsg_device */ | ||
979 | qsdev->rpdev.ops = &qcom_smd_device_ops; | ||
980 | |||
981 | /* Assign public information to the rpmsg_device */ | ||
982 | rpdev = &qsdev->rpdev; | ||
983 | strncpy(rpdev->id.name, channel->name, RPMSG_NAME_SIZE); | ||
984 | rpdev->src = RPMSG_ADDR_ANY; | ||
985 | rpdev->dst = RPMSG_ADDR_ANY; | ||
986 | |||
987 | rpdev->dev.of_node = qcom_smd_match_channel(edge->of_node, channel->name); | ||
988 | rpdev->dev.parent = &edge->dev; | ||
989 | |||
990 | return rpmsg_register_device(rpdev); | ||
991 | } | ||
992 | |||
993 | /* | ||
994 | * Allocate the qcom_smd_channel object for a newly found smd channel, | ||
995 | * retrieving and validating the smem items involved. | ||
996 | */ | ||
997 | static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *edge, | ||
998 | unsigned smem_info_item, | ||
999 | unsigned smem_fifo_item, | ||
1000 | char *name) | ||
1001 | { | ||
1002 | struct qcom_smd_channel *channel; | ||
1003 | size_t fifo_size; | ||
1004 | size_t info_size; | ||
1005 | void *fifo_base; | ||
1006 | void *info; | ||
1007 | int ret; | ||
1008 | |||
1009 | channel = devm_kzalloc(&edge->dev, sizeof(*channel), GFP_KERNEL); | ||
1010 | if (!channel) | ||
1011 | return ERR_PTR(-ENOMEM); | ||
1012 | |||
1013 | channel->edge = edge; | ||
1014 | channel->name = devm_kstrdup(&edge->dev, name, GFP_KERNEL); | ||
1015 | if (!channel->name) | ||
1016 | return ERR_PTR(-ENOMEM); | ||
1017 | |||
1018 | mutex_init(&channel->tx_lock); | ||
1019 | spin_lock_init(&channel->recv_lock); | ||
1020 | init_waitqueue_head(&channel->fblockread_event); | ||
1021 | |||
1022 | info = qcom_smem_get(edge->remote_pid, smem_info_item, &info_size); | ||
1023 | if (IS_ERR(info)) { | ||
1024 | ret = PTR_ERR(info); | ||
1025 | goto free_name_and_channel; | ||
1026 | } | ||
1027 | |||
1028 | /* | ||
1029 | * Use the size of the item to figure out which channel info struct to | ||
1030 | * use. | ||
1031 | */ | ||
1032 | if (info_size == 2 * sizeof(struct smd_channel_info_word)) { | ||
1033 | channel->info_word = info; | ||
1034 | } else if (info_size == 2 * sizeof(struct smd_channel_info)) { | ||
1035 | channel->info = info; | ||
1036 | } else { | ||
1037 | dev_err(&edge->dev, | ||
1038 | "channel info of size %zu not supported\n", info_size); | ||
1039 | ret = -EINVAL; | ||
1040 | goto free_name_and_channel; | ||
1041 | } | ||
1042 | |||
1043 | fifo_base = qcom_smem_get(edge->remote_pid, smem_fifo_item, &fifo_size); | ||
1044 | if (IS_ERR(fifo_base)) { | ||
1045 | ret = PTR_ERR(fifo_base); | ||
1046 | goto free_name_and_channel; | ||
1047 | } | ||
1048 | |||
1049 | /* The channel consist of a rx and tx fifo of equal size */ | ||
1050 | fifo_size /= 2; | ||
1051 | |||
1052 | dev_dbg(&edge->dev, "new channel '%s' info-size: %zu fifo-size: %zu\n", | ||
1053 | name, info_size, fifo_size); | ||
1054 | |||
1055 | channel->tx_fifo = fifo_base; | ||
1056 | channel->rx_fifo = fifo_base + fifo_size; | ||
1057 | channel->fifo_size = fifo_size; | ||
1058 | |||
1059 | qcom_smd_channel_reset(channel); | ||
1060 | |||
1061 | return channel; | ||
1062 | |||
1063 | free_name_and_channel: | ||
1064 | devm_kfree(&edge->dev, channel->name); | ||
1065 | devm_kfree(&edge->dev, channel); | ||
1066 | |||
1067 | return ERR_PTR(ret); | ||
1068 | } | ||
1069 | |||
1070 | /* | ||
1071 | * Scans the allocation table for any newly allocated channels, calls | ||
1072 | * qcom_smd_create_channel() to create representations of these and add | ||
1073 | * them to the edge's list of channels. | ||
1074 | */ | ||
1075 | static void qcom_channel_scan_worker(struct work_struct *work) | ||
1076 | { | ||
1077 | struct qcom_smd_edge *edge = container_of(work, struct qcom_smd_edge, scan_work); | ||
1078 | struct qcom_smd_alloc_entry *alloc_tbl; | ||
1079 | struct qcom_smd_alloc_entry *entry; | ||
1080 | struct qcom_smd_channel *channel; | ||
1081 | unsigned long flags; | ||
1082 | unsigned fifo_id; | ||
1083 | unsigned info_id; | ||
1084 | int tbl; | ||
1085 | int i; | ||
1086 | u32 eflags, cid; | ||
1087 | |||
1088 | for (tbl = 0; tbl < SMD_ALLOC_TBL_COUNT; tbl++) { | ||
1089 | alloc_tbl = qcom_smem_get(edge->remote_pid, | ||
1090 | smem_items[tbl].alloc_tbl_id, NULL); | ||
1091 | if (IS_ERR(alloc_tbl)) | ||
1092 | continue; | ||
1093 | |||
1094 | for (i = 0; i < SMD_ALLOC_TBL_SIZE; i++) { | ||
1095 | entry = &alloc_tbl[i]; | ||
1096 | eflags = le32_to_cpu(entry->flags); | ||
1097 | if (test_bit(i, edge->allocated[tbl])) | ||
1098 | continue; | ||
1099 | |||
1100 | if (entry->ref_count == 0) | ||
1101 | continue; | ||
1102 | |||
1103 | if (!entry->name[0]) | ||
1104 | continue; | ||
1105 | |||
1106 | if (!(eflags & SMD_CHANNEL_FLAGS_PACKET)) | ||
1107 | continue; | ||
1108 | |||
1109 | if ((eflags & SMD_CHANNEL_FLAGS_EDGE_MASK) != edge->edge_id) | ||
1110 | continue; | ||
1111 | |||
1112 | cid = le32_to_cpu(entry->cid); | ||
1113 | info_id = smem_items[tbl].info_base_id + cid; | ||
1114 | fifo_id = smem_items[tbl].fifo_base_id + cid; | ||
1115 | |||
1116 | channel = qcom_smd_create_channel(edge, info_id, fifo_id, entry->name); | ||
1117 | if (IS_ERR(channel)) | ||
1118 | continue; | ||
1119 | |||
1120 | spin_lock_irqsave(&edge->channels_lock, flags); | ||
1121 | list_add(&channel->list, &edge->channels); | ||
1122 | spin_unlock_irqrestore(&edge->channels_lock, flags); | ||
1123 | |||
1124 | dev_dbg(&edge->dev, "new channel found: '%s'\n", channel->name); | ||
1125 | set_bit(i, edge->allocated[tbl]); | ||
1126 | |||
1127 | wake_up_interruptible(&edge->new_channel_event); | ||
1128 | } | ||
1129 | } | ||
1130 | |||
1131 | schedule_work(&edge->state_work); | ||
1132 | } | ||
1133 | |||
1134 | /* | ||
1135 | * This per edge worker scans smem for any new channels and register these. It | ||
1136 | * then scans all registered channels for state changes that should be handled | ||
1137 | * by creating or destroying smd client devices for the registered channels. | ||
1138 | * | ||
1139 | * LOCKING: edge->channels_lock only needs to cover the list operations, as the | ||
1140 | * worker is killed before any channels are deallocated | ||
1141 | */ | ||
1142 | static void qcom_channel_state_worker(struct work_struct *work) | ||
1143 | { | ||
1144 | struct qcom_smd_channel *channel; | ||
1145 | struct qcom_smd_edge *edge = container_of(work, | ||
1146 | struct qcom_smd_edge, | ||
1147 | state_work); | ||
1148 | struct rpmsg_channel_info chinfo; | ||
1149 | unsigned remote_state; | ||
1150 | unsigned long flags; | ||
1151 | |||
1152 | /* | ||
1153 | * Register a device for any closed channel where the remote processor | ||
1154 | * is showing interest in opening the channel. | ||
1155 | */ | ||
1156 | spin_lock_irqsave(&edge->channels_lock, flags); | ||
1157 | list_for_each_entry(channel, &edge->channels, list) { | ||
1158 | if (channel->state != SMD_CHANNEL_CLOSED) | ||
1159 | continue; | ||
1160 | |||
1161 | remote_state = GET_RX_CHANNEL_INFO(channel, state); | ||
1162 | if (remote_state != SMD_CHANNEL_OPENING && | ||
1163 | remote_state != SMD_CHANNEL_OPENED) | ||
1164 | continue; | ||
1165 | |||
1166 | if (channel->registered) | ||
1167 | continue; | ||
1168 | |||
1169 | spin_unlock_irqrestore(&edge->channels_lock, flags); | ||
1170 | qcom_smd_create_device(channel); | ||
1171 | channel->registered = true; | ||
1172 | spin_lock_irqsave(&edge->channels_lock, flags); | ||
1173 | |||
1174 | channel->registered = true; | ||
1175 | } | ||
1176 | |||
1177 | /* | ||
1178 | * Unregister the device for any channel that is opened where the | ||
1179 | * remote processor is closing the channel. | ||
1180 | */ | ||
1181 | list_for_each_entry(channel, &edge->channels, list) { | ||
1182 | if (channel->state != SMD_CHANNEL_OPENING && | ||
1183 | channel->state != SMD_CHANNEL_OPENED) | ||
1184 | continue; | ||
1185 | |||
1186 | remote_state = GET_RX_CHANNEL_INFO(channel, state); | ||
1187 | if (remote_state == SMD_CHANNEL_OPENING || | ||
1188 | remote_state == SMD_CHANNEL_OPENED) | ||
1189 | continue; | ||
1190 | |||
1191 | spin_unlock_irqrestore(&edge->channels_lock, flags); | ||
1192 | |||
1193 | strncpy(chinfo.name, channel->name, sizeof(chinfo.name)); | ||
1194 | chinfo.src = RPMSG_ADDR_ANY; | ||
1195 | chinfo.dst = RPMSG_ADDR_ANY; | ||
1196 | rpmsg_unregister_device(&edge->dev, &chinfo); | ||
1197 | channel->registered = false; | ||
1198 | spin_lock_irqsave(&edge->channels_lock, flags); | ||
1199 | } | ||
1200 | spin_unlock_irqrestore(&edge->channels_lock, flags); | ||
1201 | } | ||
1202 | |||
1203 | /* | ||
1204 | * Parses an of_node describing an edge. | ||
1205 | */ | ||
1206 | static int qcom_smd_parse_edge(struct device *dev, | ||
1207 | struct device_node *node, | ||
1208 | struct qcom_smd_edge *edge) | ||
1209 | { | ||
1210 | struct device_node *syscon_np; | ||
1211 | const char *key; | ||
1212 | int irq; | ||
1213 | int ret; | ||
1214 | |||
1215 | INIT_LIST_HEAD(&edge->channels); | ||
1216 | spin_lock_init(&edge->channels_lock); | ||
1217 | |||
1218 | INIT_WORK(&edge->scan_work, qcom_channel_scan_worker); | ||
1219 | INIT_WORK(&edge->state_work, qcom_channel_state_worker); | ||
1220 | |||
1221 | edge->of_node = of_node_get(node); | ||
1222 | |||
1223 | key = "qcom,smd-edge"; | ||
1224 | ret = of_property_read_u32(node, key, &edge->edge_id); | ||
1225 | if (ret) { | ||
1226 | dev_err(dev, "edge missing %s property\n", key); | ||
1227 | return -EINVAL; | ||
1228 | } | ||
1229 | |||
1230 | edge->remote_pid = QCOM_SMEM_HOST_ANY; | ||
1231 | key = "qcom,remote-pid"; | ||
1232 | of_property_read_u32(node, key, &edge->remote_pid); | ||
1233 | |||
1234 | syscon_np = of_parse_phandle(node, "qcom,ipc", 0); | ||
1235 | if (!syscon_np) { | ||
1236 | dev_err(dev, "no qcom,ipc node\n"); | ||
1237 | return -ENODEV; | ||
1238 | } | ||
1239 | |||
1240 | edge->ipc_regmap = syscon_node_to_regmap(syscon_np); | ||
1241 | if (IS_ERR(edge->ipc_regmap)) | ||
1242 | return PTR_ERR(edge->ipc_regmap); | ||
1243 | |||
1244 | key = "qcom,ipc"; | ||
1245 | ret = of_property_read_u32_index(node, key, 1, &edge->ipc_offset); | ||
1246 | if (ret < 0) { | ||
1247 | dev_err(dev, "no offset in %s\n", key); | ||
1248 | return -EINVAL; | ||
1249 | } | ||
1250 | |||
1251 | ret = of_property_read_u32_index(node, key, 2, &edge->ipc_bit); | ||
1252 | if (ret < 0) { | ||
1253 | dev_err(dev, "no bit in %s\n", key); | ||
1254 | return -EINVAL; | ||
1255 | } | ||
1256 | |||
1257 | irq = irq_of_parse_and_map(node, 0); | ||
1258 | if (irq < 0) { | ||
1259 | dev_err(dev, "required smd interrupt missing\n"); | ||
1260 | return -EINVAL; | ||
1261 | } | ||
1262 | |||
1263 | ret = devm_request_irq(dev, irq, | ||
1264 | qcom_smd_edge_intr, IRQF_TRIGGER_RISING, | ||
1265 | node->name, edge); | ||
1266 | if (ret) { | ||
1267 | dev_err(dev, "failed to request smd irq\n"); | ||
1268 | return ret; | ||
1269 | } | ||
1270 | |||
1271 | edge->irq = irq; | ||
1272 | |||
1273 | return 0; | ||
1274 | } | ||
1275 | |||
1276 | /* | ||
1277 | * Release function for an edge. | ||
1278 | * Reset the state of each associated channel and free the edge context. | ||
1279 | */ | ||
1280 | static void qcom_smd_edge_release(struct device *dev) | ||
1281 | { | ||
1282 | struct qcom_smd_channel *channel; | ||
1283 | struct qcom_smd_edge *edge = to_smd_edge(dev); | ||
1284 | |||
1285 | list_for_each_entry(channel, &edge->channels, list) { | ||
1286 | SET_RX_CHANNEL_INFO(channel, state, SMD_CHANNEL_CLOSED); | ||
1287 | SET_RX_CHANNEL_INFO(channel, head, 0); | ||
1288 | SET_RX_CHANNEL_INFO(channel, tail, 0); | ||
1289 | } | ||
1290 | |||
1291 | kfree(edge); | ||
1292 | } | ||
1293 | |||
1294 | /** | ||
1295 | * qcom_smd_register_edge() - register an edge based on an device_node | ||
1296 | * @parent: parent device for the edge | ||
1297 | * @node: device_node describing the edge | ||
1298 | * | ||
1299 | * Returns an edge reference, or negative ERR_PTR() on failure. | ||
1300 | */ | ||
1301 | struct qcom_smd_edge *qcom_smd_register_edge(struct device *parent, | ||
1302 | struct device_node *node) | ||
1303 | { | ||
1304 | struct qcom_smd_edge *edge; | ||
1305 | int ret; | ||
1306 | |||
1307 | edge = kzalloc(sizeof(*edge), GFP_KERNEL); | ||
1308 | if (!edge) | ||
1309 | return ERR_PTR(-ENOMEM); | ||
1310 | |||
1311 | init_waitqueue_head(&edge->new_channel_event); | ||
1312 | |||
1313 | edge->dev.parent = parent; | ||
1314 | edge->dev.release = qcom_smd_edge_release; | ||
1315 | dev_set_name(&edge->dev, "%s:%s", dev_name(parent), node->name); | ||
1316 | ret = device_register(&edge->dev); | ||
1317 | if (ret) { | ||
1318 | pr_err("failed to register smd edge\n"); | ||
1319 | return ERR_PTR(ret); | ||
1320 | } | ||
1321 | |||
1322 | ret = qcom_smd_parse_edge(&edge->dev, node, edge); | ||
1323 | if (ret) { | ||
1324 | dev_err(&edge->dev, "failed to parse smd edge\n"); | ||
1325 | goto unregister_dev; | ||
1326 | } | ||
1327 | |||
1328 | schedule_work(&edge->scan_work); | ||
1329 | |||
1330 | return edge; | ||
1331 | |||
1332 | unregister_dev: | ||
1333 | put_device(&edge->dev); | ||
1334 | return ERR_PTR(ret); | ||
1335 | } | ||
1336 | EXPORT_SYMBOL(qcom_smd_register_edge); | ||
1337 | |||
1338 | static int qcom_smd_remove_device(struct device *dev, void *data) | ||
1339 | { | ||
1340 | device_unregister(dev); | ||
1341 | |||
1342 | return 0; | ||
1343 | } | ||
1344 | |||
1345 | /** | ||
1346 | * qcom_smd_unregister_edge() - release an edge and its children | ||
1347 | * @edge: edge reference acquired from qcom_smd_register_edge | ||
1348 | */ | ||
1349 | int qcom_smd_unregister_edge(struct qcom_smd_edge *edge) | ||
1350 | { | ||
1351 | int ret; | ||
1352 | |||
1353 | disable_irq(edge->irq); | ||
1354 | cancel_work_sync(&edge->scan_work); | ||
1355 | cancel_work_sync(&edge->state_work); | ||
1356 | |||
1357 | ret = device_for_each_child(&edge->dev, NULL, qcom_smd_remove_device); | ||
1358 | if (ret) | ||
1359 | dev_warn(&edge->dev, "can't remove smd device: %d\n", ret); | ||
1360 | |||
1361 | device_unregister(&edge->dev); | ||
1362 | |||
1363 | return 0; | ||
1364 | } | ||
1365 | EXPORT_SYMBOL(qcom_smd_unregister_edge); | ||
1366 | |||
1367 | static int qcom_smd_probe(struct platform_device *pdev) | ||
1368 | { | ||
1369 | struct device_node *node; | ||
1370 | void *p; | ||
1371 | |||
1372 | /* Wait for smem */ | ||
1373 | p = qcom_smem_get(QCOM_SMEM_HOST_ANY, smem_items[0].alloc_tbl_id, NULL); | ||
1374 | if (PTR_ERR(p) == -EPROBE_DEFER) | ||
1375 | return PTR_ERR(p); | ||
1376 | |||
1377 | for_each_available_child_of_node(pdev->dev.of_node, node) | ||
1378 | qcom_smd_register_edge(&pdev->dev, node); | ||
1379 | |||
1380 | return 0; | ||
1381 | } | ||
1382 | |||
1383 | static int qcom_smd_remove_edge(struct device *dev, void *data) | ||
1384 | { | ||
1385 | struct qcom_smd_edge *edge = to_smd_edge(dev); | ||
1386 | |||
1387 | return qcom_smd_unregister_edge(edge); | ||
1388 | } | ||
1389 | |||
1390 | /* | ||
1391 | * Shut down all smd clients by making sure that each edge stops processing | ||
1392 | * events and scanning for new channels, then call destroy on the devices. | ||
1393 | */ | ||
1394 | static int qcom_smd_remove(struct platform_device *pdev) | ||
1395 | { | ||
1396 | int ret; | ||
1397 | |||
1398 | ret = device_for_each_child(&pdev->dev, NULL, qcom_smd_remove_edge); | ||
1399 | if (ret) | ||
1400 | dev_warn(&pdev->dev, "can't remove smd device: %d\n", ret); | ||
1401 | |||
1402 | return ret; | ||
1403 | } | ||
1404 | |||
1405 | static const struct of_device_id qcom_smd_of_match[] = { | ||
1406 | { .compatible = "qcom,smd" }, | ||
1407 | {} | ||
1408 | }; | ||
1409 | MODULE_DEVICE_TABLE(of, qcom_smd_of_match); | ||
1410 | |||
1411 | static struct platform_driver qcom_smd_driver = { | ||
1412 | .probe = qcom_smd_probe, | ||
1413 | .remove = qcom_smd_remove, | ||
1414 | .driver = { | ||
1415 | .name = "qcom-smd", | ||
1416 | .of_match_table = qcom_smd_of_match, | ||
1417 | }, | ||
1418 | }; | ||
1419 | |||
1420 | static int __init qcom_smd_init(void) | ||
1421 | { | ||
1422 | return platform_driver_register(&qcom_smd_driver); | ||
1423 | } | ||
1424 | subsys_initcall(qcom_smd_init); | ||
1425 | |||
1426 | static void __exit qcom_smd_exit(void) | ||
1427 | { | ||
1428 | platform_driver_unregister(&qcom_smd_driver); | ||
1429 | } | ||
1430 | module_exit(qcom_smd_exit); | ||
1431 | |||
1432 | MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>"); | ||
1433 | MODULE_DESCRIPTION("Qualcomm Shared Memory Driver"); | ||
1434 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c new file mode 100644 index 000000000000..b6ea9ffa7381 --- /dev/null +++ b/drivers/rpmsg/rpmsg_core.c | |||
@@ -0,0 +1,498 @@ | |||
1 | /* | ||
2 | * remote processor messaging bus | ||
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 | #define pr_fmt(fmt) "%s: " fmt, __func__ | ||
21 | |||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/rpmsg.h> | ||
25 | #include <linux/of_device.h> | ||
26 | #include <linux/slab.h> | ||
27 | |||
28 | #include "rpmsg_internal.h" | ||
29 | |||
30 | /** | ||
31 | * rpmsg_create_ept() - create a new rpmsg_endpoint | ||
32 | * @rpdev: rpmsg channel device | ||
33 | * @cb: rx callback handler | ||
34 | * @priv: private data for the driver's use | ||
35 | * @chinfo: channel_info with the local rpmsg address to bind with @cb | ||
36 | * | ||
37 | * Every rpmsg address in the system is bound to an rx callback (so when | ||
38 | * inbound messages arrive, they are dispatched by the rpmsg bus using the | ||
39 | * appropriate callback handler) by means of an rpmsg_endpoint struct. | ||
40 | * | ||
41 | * This function allows drivers to create such an endpoint, and by that, | ||
42 | * bind a callback, and possibly some private data too, to an rpmsg address | ||
43 | * (either one that is known in advance, or one that will be dynamically | ||
44 | * assigned for them). | ||
45 | * | ||
46 | * Simple rpmsg drivers need not call rpmsg_create_ept, because an endpoint | ||
47 | * is already created for them when they are probed by the rpmsg bus | ||
48 | * (using the rx callback provided when they registered to the rpmsg bus). | ||
49 | * | ||
50 | * So things should just work for simple drivers: they already have an | ||
51 | * endpoint, their rx callback is bound to their rpmsg address, and when | ||
52 | * relevant inbound messages arrive (i.e. messages which their dst address | ||
53 | * equals to the src address of their rpmsg channel), the driver's handler | ||
54 | * is invoked to process it. | ||
55 | * | ||
56 | * That said, more complicated drivers might do need to allocate | ||
57 | * additional rpmsg addresses, and bind them to different rx callbacks. | ||
58 | * To accomplish that, those drivers need to call this function. | ||
59 | * | ||
60 | * Drivers should provide their @rpdev channel (so the new endpoint would belong | ||
61 | * to the same remote processor their channel belongs to), an rx callback | ||
62 | * function, an optional private data (which is provided back when the | ||
63 | * rx callback is invoked), and an address they want to bind with the | ||
64 | * callback. If @addr is RPMSG_ADDR_ANY, then rpmsg_create_ept will | ||
65 | * dynamically assign them an available rpmsg address (drivers should have | ||
66 | * a very good reason why not to always use RPMSG_ADDR_ANY here). | ||
67 | * | ||
68 | * Returns a pointer to the endpoint on success, or NULL on error. | ||
69 | */ | ||
70 | struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev, | ||
71 | rpmsg_rx_cb_t cb, void *priv, | ||
72 | struct rpmsg_channel_info chinfo) | ||
73 | { | ||
74 | return rpdev->ops->create_ept(rpdev, cb, priv, chinfo); | ||
75 | } | ||
76 | EXPORT_SYMBOL(rpmsg_create_ept); | ||
77 | |||
78 | /** | ||
79 | * rpmsg_destroy_ept() - destroy an existing rpmsg endpoint | ||
80 | * @ept: endpoing to destroy | ||
81 | * | ||
82 | * Should be used by drivers to destroy an rpmsg endpoint previously | ||
83 | * created with rpmsg_create_ept(). | ||
84 | */ | ||
85 | void rpmsg_destroy_ept(struct rpmsg_endpoint *ept) | ||
86 | { | ||
87 | ept->ops->destroy_ept(ept); | ||
88 | } | ||
89 | EXPORT_SYMBOL(rpmsg_destroy_ept); | ||
90 | |||
91 | /** | ||
92 | * rpmsg_send() - send a message across to the remote processor | ||
93 | * @ept: the rpmsg endpoint | ||
94 | * @data: payload of message | ||
95 | * @len: length of payload | ||
96 | * | ||
97 | * This function sends @data of length @len on the @ept endpoint. | ||
98 | * The message will be sent to the remote processor which the @ept | ||
99 | * endpoint belongs to, using @ept's address and its associated rpmsg | ||
100 | * device destination addresses. | ||
101 | * In case there are no TX buffers available, the function will block until | ||
102 | * one becomes available, or a timeout of 15 seconds elapses. When the latter | ||
103 | * happens, -ERESTARTSYS is returned. | ||
104 | * | ||
105 | * Can only be called from process context (for now). | ||
106 | * | ||
107 | * Returns 0 on success and an appropriate error value on failure. | ||
108 | */ | ||
109 | int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len) | ||
110 | { | ||
111 | return ept->ops->send(ept, data, len); | ||
112 | } | ||
113 | EXPORT_SYMBOL(rpmsg_send); | ||
114 | |||
115 | /** | ||
116 | * rpmsg_sendto() - send a message across to the remote processor, specify dst | ||
117 | * @ept: the rpmsg endpoint | ||
118 | * @data: payload of message | ||
119 | * @len: length of payload | ||
120 | * @dst: destination address | ||
121 | * | ||
122 | * This function sends @data of length @len to the remote @dst address. | ||
123 | * The message will be sent to the remote processor which the @ept | ||
124 | * endpoint belongs to, using @ept's address as source. | ||
125 | * In case there are no TX buffers available, the function will block until | ||
126 | * one becomes available, or a timeout of 15 seconds elapses. When the latter | ||
127 | * happens, -ERESTARTSYS is returned. | ||
128 | * | ||
129 | * Can only be called from process context (for now). | ||
130 | * | ||
131 | * Returns 0 on success and an appropriate error value on failure. | ||
132 | */ | ||
133 | int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst) | ||
134 | { | ||
135 | return ept->ops->sendto(ept, data, len, dst); | ||
136 | } | ||
137 | EXPORT_SYMBOL(rpmsg_sendto); | ||
138 | |||
139 | /** | ||
140 | * rpmsg_send_offchannel() - send a message using explicit src/dst addresses | ||
141 | * @ept: the rpmsg endpoint | ||
142 | * @src: source address | ||
143 | * @dst: destination address | ||
144 | * @data: payload of message | ||
145 | * @len: length of payload | ||
146 | * | ||
147 | * This function sends @data of length @len to the remote @dst address, | ||
148 | * and uses @src as the source address. | ||
149 | * The message will be sent to the remote processor which the @ept | ||
150 | * endpoint belongs to. | ||
151 | * In case there are no TX buffers available, the function will block until | ||
152 | * one becomes available, or a timeout of 15 seconds elapses. When the latter | ||
153 | * happens, -ERESTARTSYS is returned. | ||
154 | * | ||
155 | * Can only be called from process context (for now). | ||
156 | * | ||
157 | * Returns 0 on success and an appropriate error value on failure. | ||
158 | */ | ||
159 | int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst, | ||
160 | void *data, int len) | ||
161 | { | ||
162 | return ept->ops->send_offchannel(ept, src, dst, data, len); | ||
163 | } | ||
164 | EXPORT_SYMBOL(rpmsg_send_offchannel); | ||
165 | |||
166 | /** | ||
167 | * rpmsg_send() - send a message across to the remote processor | ||
168 | * @ept: the rpmsg endpoint | ||
169 | * @data: payload of message | ||
170 | * @len: length of payload | ||
171 | * | ||
172 | * This function sends @data of length @len on the @ept endpoint. | ||
173 | * The message will be sent to the remote processor which the @ept | ||
174 | * endpoint belongs to, using @ept's address as source and its associated | ||
175 | * rpdev's address as destination. | ||
176 | * In case there are no TX buffers available, the function will immediately | ||
177 | * return -ENOMEM without waiting until one becomes available. | ||
178 | * | ||
179 | * Can only be called from process context (for now). | ||
180 | * | ||
181 | * Returns 0 on success and an appropriate error value on failure. | ||
182 | */ | ||
183 | int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len) | ||
184 | { | ||
185 | return ept->ops->trysend(ept, data, len); | ||
186 | } | ||
187 | EXPORT_SYMBOL(rpmsg_trysend); | ||
188 | |||
189 | /** | ||
190 | * rpmsg_sendto() - send a message across to the remote processor, specify dst | ||
191 | * @ept: the rpmsg endpoint | ||
192 | * @data: payload of message | ||
193 | * @len: length of payload | ||
194 | * @dst: destination address | ||
195 | * | ||
196 | * This function sends @data of length @len to the remote @dst address. | ||
197 | * The message will be sent to the remote processor which the @ept | ||
198 | * endpoint belongs to, using @ept's address as source. | ||
199 | * In case there are no TX buffers available, the function will immediately | ||
200 | * return -ENOMEM without waiting until one becomes available. | ||
201 | * | ||
202 | * Can only be called from process context (for now). | ||
203 | * | ||
204 | * Returns 0 on success and an appropriate error value on failure. | ||
205 | */ | ||
206 | int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst) | ||
207 | { | ||
208 | return ept->ops->trysendto(ept, data, len, dst); | ||
209 | } | ||
210 | EXPORT_SYMBOL(rpmsg_trysendto); | ||
211 | |||
212 | /** | ||
213 | * rpmsg_send_offchannel() - send a message using explicit src/dst addresses | ||
214 | * @ept: the rpmsg endpoint | ||
215 | * @src: source address | ||
216 | * @dst: destination address | ||
217 | * @data: payload of message | ||
218 | * @len: length of payload | ||
219 | * | ||
220 | * This function sends @data of length @len to the remote @dst address, | ||
221 | * and uses @src as the source address. | ||
222 | * The message will be sent to the remote processor which the @ept | ||
223 | * endpoint belongs to. | ||
224 | * In case there are no TX buffers available, the function will immediately | ||
225 | * return -ENOMEM without waiting until one becomes available. | ||
226 | * | ||
227 | * Can only be called from process context (for now). | ||
228 | * | ||
229 | * Returns 0 on success and an appropriate error value on failure. | ||
230 | */ | ||
231 | int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst, | ||
232 | void *data, int len) | ||
233 | { | ||
234 | return ept->ops->trysend_offchannel(ept, src, dst, data, len); | ||
235 | } | ||
236 | EXPORT_SYMBOL(rpmsg_trysend_offchannel); | ||
237 | |||
238 | /* | ||
239 | * match an rpmsg channel with a channel info struct. | ||
240 | * this is used to make sure we're not creating rpmsg devices for channels | ||
241 | * that already exist. | ||
242 | */ | ||
243 | static int rpmsg_device_match(struct device *dev, void *data) | ||
244 | { | ||
245 | struct rpmsg_channel_info *chinfo = data; | ||
246 | struct rpmsg_device *rpdev = to_rpmsg_device(dev); | ||
247 | |||
248 | if (chinfo->src != RPMSG_ADDR_ANY && chinfo->src != rpdev->src) | ||
249 | return 0; | ||
250 | |||
251 | if (chinfo->dst != RPMSG_ADDR_ANY && chinfo->dst != rpdev->dst) | ||
252 | return 0; | ||
253 | |||
254 | if (strncmp(chinfo->name, rpdev->id.name, RPMSG_NAME_SIZE)) | ||
255 | return 0; | ||
256 | |||
257 | /* found a match ! */ | ||
258 | return 1; | ||
259 | } | ||
260 | |||
261 | struct device *rpmsg_find_device(struct device *parent, | ||
262 | struct rpmsg_channel_info *chinfo) | ||
263 | { | ||
264 | return device_find_child(parent, chinfo, rpmsg_device_match); | ||
265 | |||
266 | } | ||
267 | EXPORT_SYMBOL(rpmsg_find_device); | ||
268 | |||
269 | /* sysfs show configuration fields */ | ||
270 | #define rpmsg_show_attr(field, path, format_string) \ | ||
271 | static ssize_t \ | ||
272 | field##_show(struct device *dev, \ | ||
273 | struct device_attribute *attr, char *buf) \ | ||
274 | { \ | ||
275 | struct rpmsg_device *rpdev = to_rpmsg_device(dev); \ | ||
276 | \ | ||
277 | return sprintf(buf, format_string, rpdev->path); \ | ||
278 | } | ||
279 | |||
280 | /* for more info, see Documentation/ABI/testing/sysfs-bus-rpmsg */ | ||
281 | rpmsg_show_attr(name, id.name, "%s\n"); | ||
282 | rpmsg_show_attr(src, src, "0x%x\n"); | ||
283 | rpmsg_show_attr(dst, dst, "0x%x\n"); | ||
284 | rpmsg_show_attr(announce, announce ? "true" : "false", "%s\n"); | ||
285 | |||
286 | static ssize_t modalias_show(struct device *dev, | ||
287 | struct device_attribute *attr, char *buf) | ||
288 | { | ||
289 | struct rpmsg_device *rpdev = to_rpmsg_device(dev); | ||
290 | |||
291 | return sprintf(buf, RPMSG_DEVICE_MODALIAS_FMT "\n", rpdev->id.name); | ||
292 | } | ||
293 | |||
294 | static struct device_attribute rpmsg_dev_attrs[] = { | ||
295 | __ATTR_RO(name), | ||
296 | __ATTR_RO(modalias), | ||
297 | __ATTR_RO(dst), | ||
298 | __ATTR_RO(src), | ||
299 | __ATTR_RO(announce), | ||
300 | __ATTR_NULL | ||
301 | }; | ||
302 | |||
303 | /* rpmsg devices and drivers are matched using the service name */ | ||
304 | static inline int rpmsg_id_match(const struct rpmsg_device *rpdev, | ||
305 | const struct rpmsg_device_id *id) | ||
306 | { | ||
307 | return strncmp(id->name, rpdev->id.name, RPMSG_NAME_SIZE) == 0; | ||
308 | } | ||
309 | |||
310 | /* match rpmsg channel and rpmsg driver */ | ||
311 | static int rpmsg_dev_match(struct device *dev, struct device_driver *drv) | ||
312 | { | ||
313 | struct rpmsg_device *rpdev = to_rpmsg_device(dev); | ||
314 | struct rpmsg_driver *rpdrv = to_rpmsg_driver(drv); | ||
315 | const struct rpmsg_device_id *ids = rpdrv->id_table; | ||
316 | unsigned int i; | ||
317 | |||
318 | if (ids) | ||
319 | for (i = 0; ids[i].name[0]; i++) | ||
320 | if (rpmsg_id_match(rpdev, &ids[i])) | ||
321 | return 1; | ||
322 | |||
323 | return of_driver_match_device(dev, drv); | ||
324 | } | ||
325 | |||
326 | static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env) | ||
327 | { | ||
328 | struct rpmsg_device *rpdev = to_rpmsg_device(dev); | ||
329 | |||
330 | return add_uevent_var(env, "MODALIAS=" RPMSG_DEVICE_MODALIAS_FMT, | ||
331 | rpdev->id.name); | ||
332 | } | ||
333 | |||
334 | /* | ||
335 | * when an rpmsg driver is probed with a channel, we seamlessly create | ||
336 | * it an endpoint, binding its rx callback to a unique local rpmsg | ||
337 | * address. | ||
338 | * | ||
339 | * if we need to, we also announce about this channel to the remote | ||
340 | * processor (needed in case the driver is exposing an rpmsg service). | ||
341 | */ | ||
342 | static int rpmsg_dev_probe(struct device *dev) | ||
343 | { | ||
344 | struct rpmsg_device *rpdev = to_rpmsg_device(dev); | ||
345 | struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver); | ||
346 | struct rpmsg_channel_info chinfo = {}; | ||
347 | struct rpmsg_endpoint *ept; | ||
348 | int err; | ||
349 | |||
350 | strncpy(chinfo.name, rpdev->id.name, RPMSG_NAME_SIZE); | ||
351 | chinfo.src = rpdev->src; | ||
352 | chinfo.dst = RPMSG_ADDR_ANY; | ||
353 | |||
354 | ept = rpmsg_create_ept(rpdev, rpdrv->callback, NULL, chinfo); | ||
355 | if (!ept) { | ||
356 | dev_err(dev, "failed to create endpoint\n"); | ||
357 | err = -ENOMEM; | ||
358 | goto out; | ||
359 | } | ||
360 | |||
361 | rpdev->ept = ept; | ||
362 | rpdev->src = ept->addr; | ||
363 | |||
364 | err = rpdrv->probe(rpdev); | ||
365 | if (err) { | ||
366 | dev_err(dev, "%s: failed: %d\n", __func__, err); | ||
367 | rpmsg_destroy_ept(ept); | ||
368 | goto out; | ||
369 | } | ||
370 | |||
371 | if (rpdev->ops->announce_create) | ||
372 | err = rpdev->ops->announce_create(rpdev); | ||
373 | out: | ||
374 | return err; | ||
375 | } | ||
376 | |||
377 | static int rpmsg_dev_remove(struct device *dev) | ||
378 | { | ||
379 | struct rpmsg_device *rpdev = to_rpmsg_device(dev); | ||
380 | struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver); | ||
381 | int err = 0; | ||
382 | |||
383 | if (rpdev->ops->announce_destroy) | ||
384 | err = rpdev->ops->announce_destroy(rpdev); | ||
385 | |||
386 | rpdrv->remove(rpdev); | ||
387 | |||
388 | rpmsg_destroy_ept(rpdev->ept); | ||
389 | |||
390 | return err; | ||
391 | } | ||
392 | |||
393 | static struct bus_type rpmsg_bus = { | ||
394 | .name = "rpmsg", | ||
395 | .match = rpmsg_dev_match, | ||
396 | .dev_attrs = rpmsg_dev_attrs, | ||
397 | .uevent = rpmsg_uevent, | ||
398 | .probe = rpmsg_dev_probe, | ||
399 | .remove = rpmsg_dev_remove, | ||
400 | }; | ||
401 | |||
402 | static void rpmsg_release_device(struct device *dev) | ||
403 | { | ||
404 | struct rpmsg_device *rpdev = to_rpmsg_device(dev); | ||
405 | |||
406 | kfree(rpdev); | ||
407 | } | ||
408 | |||
409 | int rpmsg_register_device(struct rpmsg_device *rpdev) | ||
410 | { | ||
411 | struct device *dev = &rpdev->dev; | ||
412 | int ret; | ||
413 | |||
414 | dev_set_name(&rpdev->dev, "%s:%s", | ||
415 | dev_name(dev->parent), rpdev->id.name); | ||
416 | |||
417 | rpdev->dev.bus = &rpmsg_bus; | ||
418 | rpdev->dev.release = rpmsg_release_device; | ||
419 | |||
420 | ret = device_register(&rpdev->dev); | ||
421 | if (ret) { | ||
422 | dev_err(dev, "device_register failed: %d\n", ret); | ||
423 | put_device(&rpdev->dev); | ||
424 | } | ||
425 | |||
426 | return ret; | ||
427 | } | ||
428 | EXPORT_SYMBOL(rpmsg_register_device); | ||
429 | |||
430 | /* | ||
431 | * find an existing channel using its name + address properties, | ||
432 | * and destroy it | ||
433 | */ | ||
434 | int rpmsg_unregister_device(struct device *parent, | ||
435 | struct rpmsg_channel_info *chinfo) | ||
436 | { | ||
437 | struct device *dev; | ||
438 | |||
439 | dev = rpmsg_find_device(parent, chinfo); | ||
440 | if (!dev) | ||
441 | return -EINVAL; | ||
442 | |||
443 | device_unregister(dev); | ||
444 | |||
445 | put_device(dev); | ||
446 | |||
447 | return 0; | ||
448 | } | ||
449 | EXPORT_SYMBOL(rpmsg_unregister_device); | ||
450 | |||
451 | /** | ||
452 | * __register_rpmsg_driver() - register an rpmsg driver with the rpmsg bus | ||
453 | * @rpdrv: pointer to a struct rpmsg_driver | ||
454 | * @owner: owning module/driver | ||
455 | * | ||
456 | * Returns 0 on success, and an appropriate error value on failure. | ||
457 | */ | ||
458 | int __register_rpmsg_driver(struct rpmsg_driver *rpdrv, struct module *owner) | ||
459 | { | ||
460 | rpdrv->drv.bus = &rpmsg_bus; | ||
461 | rpdrv->drv.owner = owner; | ||
462 | return driver_register(&rpdrv->drv); | ||
463 | } | ||
464 | EXPORT_SYMBOL(__register_rpmsg_driver); | ||
465 | |||
466 | /** | ||
467 | * unregister_rpmsg_driver() - unregister an rpmsg driver from the rpmsg bus | ||
468 | * @rpdrv: pointer to a struct rpmsg_driver | ||
469 | * | ||
470 | * Returns 0 on success, and an appropriate error value on failure. | ||
471 | */ | ||
472 | void unregister_rpmsg_driver(struct rpmsg_driver *rpdrv) | ||
473 | { | ||
474 | driver_unregister(&rpdrv->drv); | ||
475 | } | ||
476 | EXPORT_SYMBOL(unregister_rpmsg_driver); | ||
477 | |||
478 | |||
479 | static int __init rpmsg_init(void) | ||
480 | { | ||
481 | int ret; | ||
482 | |||
483 | ret = bus_register(&rpmsg_bus); | ||
484 | if (ret) | ||
485 | pr_err("failed to register rpmsg bus: %d\n", ret); | ||
486 | |||
487 | return ret; | ||
488 | } | ||
489 | postcore_initcall(rpmsg_init); | ||
490 | |||
491 | static void __exit rpmsg_fini(void) | ||
492 | { | ||
493 | bus_unregister(&rpmsg_bus); | ||
494 | } | ||
495 | module_exit(rpmsg_fini); | ||
496 | |||
497 | MODULE_DESCRIPTION("remote processor messaging bus"); | ||
498 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h new file mode 100644 index 000000000000..8075a20f919b --- /dev/null +++ b/drivers/rpmsg/rpmsg_internal.h | |||
@@ -0,0 +1,82 @@ | |||
1 | /* | ||
2 | * remote processor messaging bus internals | ||
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 | #ifndef __RPMSG_INTERNAL_H__ | ||
21 | #define __RPMSG_INTERNAL_H__ | ||
22 | |||
23 | #include <linux/rpmsg.h> | ||
24 | |||
25 | #define to_rpmsg_device(d) container_of(d, struct rpmsg_device, dev) | ||
26 | #define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv) | ||
27 | |||
28 | /** | ||
29 | * struct rpmsg_device_ops - indirection table for the rpmsg_device operations | ||
30 | * @create_ept: create backend-specific endpoint, requried | ||
31 | * @announce_create: announce presence of new channel, optional | ||
32 | * @announce_destroy: announce destruction of channel, optional | ||
33 | * | ||
34 | * Indirection table for the operations that a rpmsg backend should implement. | ||
35 | * @announce_create and @announce_destroy are optional as the backend might | ||
36 | * advertise new channels implicitly by creating the endpoints. | ||
37 | */ | ||
38 | struct rpmsg_device_ops { | ||
39 | struct rpmsg_endpoint *(*create_ept)(struct rpmsg_device *rpdev, | ||
40 | rpmsg_rx_cb_t cb, void *priv, | ||
41 | struct rpmsg_channel_info chinfo); | ||
42 | |||
43 | int (*announce_create)(struct rpmsg_device *ept); | ||
44 | int (*announce_destroy)(struct rpmsg_device *ept); | ||
45 | }; | ||
46 | |||
47 | /** | ||
48 | * struct rpmsg_endpoint_ops - indirection table for rpmsg_endpoint operations | ||
49 | * @destroy_ept: destroy the given endpoint, required | ||
50 | * @send: see @rpmsg_send(), required | ||
51 | * @sendto: see @rpmsg_sendto(), optional | ||
52 | * @send_offchannel: see @rpmsg_send_offchannel(), optional | ||
53 | * @trysend: see @rpmsg_trysend(), required | ||
54 | * @trysendto: see @rpmsg_trysendto(), optional | ||
55 | * @trysend_offchannel: see @rpmsg_trysend_offchannel(), optional | ||
56 | * | ||
57 | * Indirection table for the operations that a rpmsg backend should implement. | ||
58 | * In addition to @destroy_ept, the backend must at least implement @send and | ||
59 | * @trysend, while the variants sending data off-channel are optional. | ||
60 | */ | ||
61 | struct rpmsg_endpoint_ops { | ||
62 | void (*destroy_ept)(struct rpmsg_endpoint *ept); | ||
63 | |||
64 | int (*send)(struct rpmsg_endpoint *ept, void *data, int len); | ||
65 | int (*sendto)(struct rpmsg_endpoint *ept, void *data, int len, u32 dst); | ||
66 | int (*send_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32 dst, | ||
67 | void *data, int len); | ||
68 | |||
69 | int (*trysend)(struct rpmsg_endpoint *ept, void *data, int len); | ||
70 | int (*trysendto)(struct rpmsg_endpoint *ept, void *data, int len, u32 dst); | ||
71 | int (*trysend_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32 dst, | ||
72 | void *data, int len); | ||
73 | }; | ||
74 | |||
75 | int rpmsg_register_device(struct rpmsg_device *rpdev); | ||
76 | int rpmsg_unregister_device(struct device *parent, | ||
77 | struct rpmsg_channel_info *chinfo); | ||
78 | |||
79 | struct device *rpmsg_find_device(struct device *parent, | ||
80 | struct rpmsg_channel_info *chinfo); | ||
81 | |||
82 | #endif | ||
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c index fe03b2aef450..3090b0d3072f 100644 --- a/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/drivers/rpmsg/virtio_rpmsg_bus.c | |||
@@ -33,6 +33,9 @@ | |||
33 | #include <linux/wait.h> | 33 | #include <linux/wait.h> |
34 | #include <linux/rpmsg.h> | 34 | #include <linux/rpmsg.h> |
35 | #include <linux/mutex.h> | 35 | #include <linux/mutex.h> |
36 | #include <linux/of_device.h> | ||
37 | |||
38 | #include "rpmsg_internal.h" | ||
36 | 39 | ||
37 | /** | 40 | /** |
38 | * struct virtproc_info - virtual remote processor state | 41 | * struct virtproc_info - virtual remote processor state |
@@ -72,20 +75,69 @@ struct virtproc_info { | |||
72 | struct rpmsg_endpoint *ns_ept; | 75 | struct rpmsg_endpoint *ns_ept; |
73 | }; | 76 | }; |
74 | 77 | ||
78 | /* The feature bitmap for virtio rpmsg */ | ||
79 | #define VIRTIO_RPMSG_F_NS 0 /* RP supports name service notifications */ | ||
80 | |||
75 | /** | 81 | /** |
76 | * struct rpmsg_channel_info - internal channel info representation | 82 | * struct rpmsg_hdr - common header for all rpmsg messages |
77 | * @name: name of service | 83 | * @src: source address |
78 | * @src: local address | ||
79 | * @dst: destination address | 84 | * @dst: destination address |
85 | * @reserved: reserved for future use | ||
86 | * @len: length of payload (in bytes) | ||
87 | * @flags: message flags | ||
88 | * @data: @len bytes of message payload data | ||
89 | * | ||
90 | * Every message sent(/received) on the rpmsg bus begins with this header. | ||
80 | */ | 91 | */ |
81 | struct rpmsg_channel_info { | 92 | struct rpmsg_hdr { |
82 | char name[RPMSG_NAME_SIZE]; | ||
83 | u32 src; | 93 | u32 src; |
84 | u32 dst; | 94 | u32 dst; |
95 | u32 reserved; | ||
96 | u16 len; | ||
97 | u16 flags; | ||
98 | u8 data[0]; | ||
99 | } __packed; | ||
100 | |||
101 | /** | ||
102 | * struct rpmsg_ns_msg - dynamic name service announcement message | ||
103 | * @name: name of remote service that is published | ||
104 | * @addr: address of remote service that is published | ||
105 | * @flags: indicates whether service is created or destroyed | ||
106 | * | ||
107 | * This message is sent across to publish a new service, or announce | ||
108 | * about its removal. When we receive these messages, an appropriate | ||
109 | * rpmsg channel (i.e device) is created/destroyed. In turn, the ->probe() | ||
110 | * or ->remove() handler of the appropriate rpmsg driver will be invoked | ||
111 | * (if/as-soon-as one is registered). | ||
112 | */ | ||
113 | struct rpmsg_ns_msg { | ||
114 | char name[RPMSG_NAME_SIZE]; | ||
115 | u32 addr; | ||
116 | u32 flags; | ||
117 | } __packed; | ||
118 | |||
119 | /** | ||
120 | * enum rpmsg_ns_flags - dynamic name service announcement flags | ||
121 | * | ||
122 | * @RPMSG_NS_CREATE: a new remote service was just created | ||
123 | * @RPMSG_NS_DESTROY: a known remote service was just destroyed | ||
124 | */ | ||
125 | enum rpmsg_ns_flags { | ||
126 | RPMSG_NS_CREATE = 0, | ||
127 | RPMSG_NS_DESTROY = 1, | ||
128 | }; | ||
129 | |||
130 | /** | ||
131 | * @vrp: the remote processor this channel belongs to | ||
132 | */ | ||
133 | struct virtio_rpmsg_channel { | ||
134 | struct rpmsg_device rpdev; | ||
135 | |||
136 | struct virtproc_info *vrp; | ||
85 | }; | 137 | }; |
86 | 138 | ||
87 | #define to_rpmsg_channel(d) container_of(d, struct rpmsg_channel, dev) | 139 | #define to_virtio_rpmsg_channel(_rpdev) \ |
88 | #define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv) | 140 | container_of(_rpdev, struct virtio_rpmsg_channel, rpdev) |
89 | 141 | ||
90 | /* | 142 | /* |
91 | * We're allocating buffers of 512 bytes each for communications. The | 143 | * We're allocating buffers of 512 bytes each for communications. The |
@@ -118,78 +170,28 @@ struct rpmsg_channel_info { | |||
118 | /* Address 53 is reserved for advertising remote services */ | 170 | /* Address 53 is reserved for advertising remote services */ |
119 | #define RPMSG_NS_ADDR (53) | 171 | #define RPMSG_NS_ADDR (53) |
120 | 172 | ||
121 | /* sysfs show configuration fields */ | 173 | static void virtio_rpmsg_destroy_ept(struct rpmsg_endpoint *ept); |
122 | #define rpmsg_show_attr(field, path, format_string) \ | 174 | static int virtio_rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len); |
123 | static ssize_t \ | 175 | static int virtio_rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, |
124 | field##_show(struct device *dev, \ | 176 | u32 dst); |
125 | struct device_attribute *attr, char *buf) \ | 177 | static int virtio_rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, |
126 | { \ | 178 | u32 dst, void *data, int len); |
127 | struct rpmsg_channel *rpdev = to_rpmsg_channel(dev); \ | 179 | static int virtio_rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len); |
128 | \ | 180 | static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, |
129 | return sprintf(buf, format_string, rpdev->path); \ | 181 | int len, u32 dst); |
130 | } | 182 | static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, |
131 | 183 | u32 dst, void *data, int len); | |
132 | /* for more info, see Documentation/ABI/testing/sysfs-bus-rpmsg */ | 184 | |
133 | rpmsg_show_attr(name, id.name, "%s\n"); | 185 | static const struct rpmsg_endpoint_ops virtio_endpoint_ops = { |
134 | rpmsg_show_attr(src, src, "0x%x\n"); | 186 | .destroy_ept = virtio_rpmsg_destroy_ept, |
135 | rpmsg_show_attr(dst, dst, "0x%x\n"); | 187 | .send = virtio_rpmsg_send, |
136 | rpmsg_show_attr(announce, announce ? "true" : "false", "%s\n"); | 188 | .sendto = virtio_rpmsg_sendto, |
137 | 189 | .send_offchannel = virtio_rpmsg_send_offchannel, | |
138 | /* | 190 | .trysend = virtio_rpmsg_trysend, |
139 | * Unique (and free running) index for rpmsg devices. | 191 | .trysendto = virtio_rpmsg_trysendto, |
140 | * | 192 | .trysend_offchannel = virtio_rpmsg_trysend_offchannel, |
141 | * Yeah, we're not recycling those numbers (yet?). will be easy | ||
142 | * to change if/when we want to. | ||
143 | */ | ||
144 | static unsigned int rpmsg_dev_index; | ||
145 | |||
146 | static ssize_t modalias_show(struct device *dev, | ||
147 | struct device_attribute *attr, char *buf) | ||
148 | { | ||
149 | struct rpmsg_channel *rpdev = to_rpmsg_channel(dev); | ||
150 | |||
151 | return sprintf(buf, RPMSG_DEVICE_MODALIAS_FMT "\n", rpdev->id.name); | ||
152 | } | ||
153 | |||
154 | static struct device_attribute rpmsg_dev_attrs[] = { | ||
155 | __ATTR_RO(name), | ||
156 | __ATTR_RO(modalias), | ||
157 | __ATTR_RO(dst), | ||
158 | __ATTR_RO(src), | ||
159 | __ATTR_RO(announce), | ||
160 | __ATTR_NULL | ||
161 | }; | 193 | }; |
162 | 194 | ||
163 | /* rpmsg devices and drivers are matched using the service name */ | ||
164 | static inline int rpmsg_id_match(const struct rpmsg_channel *rpdev, | ||
165 | const struct rpmsg_device_id *id) | ||
166 | { | ||
167 | return strncmp(id->name, rpdev->id.name, RPMSG_NAME_SIZE) == 0; | ||
168 | } | ||
169 | |||
170 | /* match rpmsg channel and rpmsg driver */ | ||
171 | static int rpmsg_dev_match(struct device *dev, struct device_driver *drv) | ||
172 | { | ||
173 | struct rpmsg_channel *rpdev = to_rpmsg_channel(dev); | ||
174 | struct rpmsg_driver *rpdrv = to_rpmsg_driver(drv); | ||
175 | const struct rpmsg_device_id *ids = rpdrv->id_table; | ||
176 | unsigned int i; | ||
177 | |||
178 | for (i = 0; ids[i].name[0]; i++) | ||
179 | if (rpmsg_id_match(rpdev, &ids[i])) | ||
180 | return 1; | ||
181 | |||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env) | ||
186 | { | ||
187 | struct rpmsg_channel *rpdev = to_rpmsg_channel(dev); | ||
188 | |||
189 | return add_uevent_var(env, "MODALIAS=" RPMSG_DEVICE_MODALIAS_FMT, | ||
190 | rpdev->id.name); | ||
191 | } | ||
192 | |||
193 | /** | 195 | /** |
194 | * __ept_release() - deallocate an rpmsg endpoint | 196 | * __ept_release() - deallocate an rpmsg endpoint |
195 | * @kref: the ept's reference count | 197 | * @kref: the ept's reference count |
@@ -212,18 +214,17 @@ static void __ept_release(struct kref *kref) | |||
212 | 214 | ||
213 | /* for more info, see below documentation of rpmsg_create_ept() */ | 215 | /* for more info, see below documentation of rpmsg_create_ept() */ |
214 | static struct rpmsg_endpoint *__rpmsg_create_ept(struct virtproc_info *vrp, | 216 | static struct rpmsg_endpoint *__rpmsg_create_ept(struct virtproc_info *vrp, |
215 | struct rpmsg_channel *rpdev, rpmsg_rx_cb_t cb, | 217 | struct rpmsg_device *rpdev, |
216 | void *priv, u32 addr) | 218 | rpmsg_rx_cb_t cb, |
219 | void *priv, u32 addr) | ||
217 | { | 220 | { |
218 | int id_min, id_max, id; | 221 | int id_min, id_max, id; |
219 | struct rpmsg_endpoint *ept; | 222 | struct rpmsg_endpoint *ept; |
220 | struct device *dev = rpdev ? &rpdev->dev : &vrp->vdev->dev; | 223 | struct device *dev = rpdev ? &rpdev->dev : &vrp->vdev->dev; |
221 | 224 | ||
222 | ept = kzalloc(sizeof(*ept), GFP_KERNEL); | 225 | ept = kzalloc(sizeof(*ept), GFP_KERNEL); |
223 | if (!ept) { | 226 | if (!ept) |
224 | dev_err(dev, "failed to kzalloc a new ept\n"); | ||
225 | return NULL; | 227 | return NULL; |
226 | } | ||
227 | 228 | ||
228 | kref_init(&ept->refcount); | 229 | kref_init(&ept->refcount); |
229 | mutex_init(&ept->cb_lock); | 230 | mutex_init(&ept->cb_lock); |
@@ -231,6 +232,7 @@ static struct rpmsg_endpoint *__rpmsg_create_ept(struct virtproc_info *vrp, | |||
231 | ept->rpdev = rpdev; | 232 | ept->rpdev = rpdev; |
232 | ept->cb = cb; | 233 | ept->cb = cb; |
233 | ept->priv = priv; | 234 | ept->priv = priv; |
235 | ept->ops = &virtio_endpoint_ops; | ||
234 | 236 | ||
235 | /* do we need to allocate a local address ? */ | 237 | /* do we need to allocate a local address ? */ |
236 | if (addr == RPMSG_ADDR_ANY) { | 238 | if (addr == RPMSG_ADDR_ANY) { |
@@ -261,52 +263,15 @@ free_ept: | |||
261 | return NULL; | 263 | return NULL; |
262 | } | 264 | } |
263 | 265 | ||
264 | /** | 266 | static struct rpmsg_endpoint *virtio_rpmsg_create_ept(struct rpmsg_device *rpdev, |
265 | * rpmsg_create_ept() - create a new rpmsg_endpoint | 267 | rpmsg_rx_cb_t cb, |
266 | * @rpdev: rpmsg channel device | 268 | void *priv, |
267 | * @cb: rx callback handler | 269 | struct rpmsg_channel_info chinfo) |
268 | * @priv: private data for the driver's use | ||
269 | * @addr: local rpmsg address to bind with @cb | ||
270 | * | ||
271 | * Every rpmsg address in the system is bound to an rx callback (so when | ||
272 | * inbound messages arrive, they are dispatched by the rpmsg bus using the | ||
273 | * appropriate callback handler) by means of an rpmsg_endpoint struct. | ||
274 | * | ||
275 | * This function allows drivers to create such an endpoint, and by that, | ||
276 | * bind a callback, and possibly some private data too, to an rpmsg address | ||
277 | * (either one that is known in advance, or one that will be dynamically | ||
278 | * assigned for them). | ||
279 | * | ||
280 | * Simple rpmsg drivers need not call rpmsg_create_ept, because an endpoint | ||
281 | * is already created for them when they are probed by the rpmsg bus | ||
282 | * (using the rx callback provided when they registered to the rpmsg bus). | ||
283 | * | ||
284 | * So things should just work for simple drivers: they already have an | ||
285 | * endpoint, their rx callback is bound to their rpmsg address, and when | ||
286 | * relevant inbound messages arrive (i.e. messages which their dst address | ||
287 | * equals to the src address of their rpmsg channel), the driver's handler | ||
288 | * is invoked to process it. | ||
289 | * | ||
290 | * That said, more complicated drivers might do need to allocate | ||
291 | * additional rpmsg addresses, and bind them to different rx callbacks. | ||
292 | * To accomplish that, those drivers need to call this function. | ||
293 | * | ||
294 | * Drivers should provide their @rpdev channel (so the new endpoint would belong | ||
295 | * to the same remote processor their channel belongs to), an rx callback | ||
296 | * function, an optional private data (which is provided back when the | ||
297 | * rx callback is invoked), and an address they want to bind with the | ||
298 | * callback. If @addr is RPMSG_ADDR_ANY, then rpmsg_create_ept will | ||
299 | * dynamically assign them an available rpmsg address (drivers should have | ||
300 | * a very good reason why not to always use RPMSG_ADDR_ANY here). | ||
301 | * | ||
302 | * Returns a pointer to the endpoint on success, or NULL on error. | ||
303 | */ | ||
304 | struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_channel *rpdev, | ||
305 | rpmsg_rx_cb_t cb, void *priv, u32 addr) | ||
306 | { | 270 | { |
307 | return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, addr); | 271 | struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(rpdev); |
272 | |||
273 | return __rpmsg_create_ept(vch->vrp, rpdev, cb, priv, chinfo.src); | ||
308 | } | 274 | } |
309 | EXPORT_SYMBOL(rpmsg_create_ept); | ||
310 | 275 | ||
311 | /** | 276 | /** |
312 | * __rpmsg_destroy_ept() - destroy an existing rpmsg endpoint | 277 | * __rpmsg_destroy_ept() - destroy an existing rpmsg endpoint |
@@ -334,178 +299,82 @@ __rpmsg_destroy_ept(struct virtproc_info *vrp, struct rpmsg_endpoint *ept) | |||
334 | kref_put(&ept->refcount, __ept_release); | 299 | kref_put(&ept->refcount, __ept_release); |
335 | } | 300 | } |
336 | 301 | ||
337 | /** | 302 | static void virtio_rpmsg_destroy_ept(struct rpmsg_endpoint *ept) |
338 | * rpmsg_destroy_ept() - destroy an existing rpmsg endpoint | ||
339 | * @ept: endpoing to destroy | ||
340 | * | ||
341 | * Should be used by drivers to destroy an rpmsg endpoint previously | ||
342 | * created with rpmsg_create_ept(). | ||
343 | */ | ||
344 | void rpmsg_destroy_ept(struct rpmsg_endpoint *ept) | ||
345 | { | 303 | { |
346 | __rpmsg_destroy_ept(ept->rpdev->vrp, ept); | 304 | struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(ept->rpdev); |
305 | |||
306 | __rpmsg_destroy_ept(vch->vrp, ept); | ||
347 | } | 307 | } |
348 | EXPORT_SYMBOL(rpmsg_destroy_ept); | ||
349 | 308 | ||
350 | /* | 309 | static int virtio_rpmsg_announce_create(struct rpmsg_device *rpdev) |
351 | * when an rpmsg driver is probed with a channel, we seamlessly create | ||
352 | * it an endpoint, binding its rx callback to a unique local rpmsg | ||
353 | * address. | ||
354 | * | ||
355 | * if we need to, we also announce about this channel to the remote | ||
356 | * processor (needed in case the driver is exposing an rpmsg service). | ||
357 | */ | ||
358 | static int rpmsg_dev_probe(struct device *dev) | ||
359 | { | 310 | { |
360 | struct rpmsg_channel *rpdev = to_rpmsg_channel(dev); | 311 | struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(rpdev); |
361 | struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver); | 312 | struct virtproc_info *vrp = vch->vrp; |
362 | struct virtproc_info *vrp = rpdev->vrp; | 313 | struct device *dev = &rpdev->dev; |
363 | struct rpmsg_endpoint *ept; | 314 | int err = 0; |
364 | int err; | ||
365 | |||
366 | ept = rpmsg_create_ept(rpdev, rpdrv->callback, NULL, rpdev->src); | ||
367 | if (!ept) { | ||
368 | dev_err(dev, "failed to create endpoint\n"); | ||
369 | err = -ENOMEM; | ||
370 | goto out; | ||
371 | } | ||
372 | |||
373 | rpdev->ept = ept; | ||
374 | rpdev->src = ept->addr; | ||
375 | |||
376 | err = rpdrv->probe(rpdev); | ||
377 | if (err) { | ||
378 | dev_err(dev, "%s: failed: %d\n", __func__, err); | ||
379 | rpmsg_destroy_ept(ept); | ||
380 | goto out; | ||
381 | } | ||
382 | 315 | ||
383 | /* need to tell remote processor's name service about this channel ? */ | 316 | /* need to tell remote processor's name service about this channel ? */ |
384 | if (rpdev->announce && | 317 | if (rpdev->announce && |
385 | virtio_has_feature(vrp->vdev, VIRTIO_RPMSG_F_NS)) { | 318 | virtio_has_feature(vrp->vdev, VIRTIO_RPMSG_F_NS)) { |
386 | struct rpmsg_ns_msg nsm; | 319 | struct rpmsg_ns_msg nsm; |
387 | 320 | ||
388 | strncpy(nsm.name, rpdev->id.name, RPMSG_NAME_SIZE); | 321 | strncpy(nsm.name, rpdev->id.name, RPMSG_NAME_SIZE); |
389 | nsm.addr = rpdev->src; | 322 | nsm.addr = rpdev->ept->addr; |
390 | nsm.flags = RPMSG_NS_CREATE; | 323 | nsm.flags = RPMSG_NS_CREATE; |
391 | 324 | ||
392 | err = rpmsg_sendto(rpdev, &nsm, sizeof(nsm), RPMSG_NS_ADDR); | 325 | err = rpmsg_sendto(rpdev->ept, &nsm, sizeof(nsm), RPMSG_NS_ADDR); |
393 | if (err) | 326 | if (err) |
394 | dev_err(dev, "failed to announce service %d\n", err); | 327 | dev_err(dev, "failed to announce service %d\n", err); |
395 | } | 328 | } |
396 | 329 | ||
397 | out: | ||
398 | return err; | 330 | return err; |
399 | } | 331 | } |
400 | 332 | ||
401 | static int rpmsg_dev_remove(struct device *dev) | 333 | static int virtio_rpmsg_announce_destroy(struct rpmsg_device *rpdev) |
402 | { | 334 | { |
403 | struct rpmsg_channel *rpdev = to_rpmsg_channel(dev); | 335 | struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(rpdev); |
404 | struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver); | 336 | struct virtproc_info *vrp = vch->vrp; |
405 | struct virtproc_info *vrp = rpdev->vrp; | 337 | struct device *dev = &rpdev->dev; |
406 | int err = 0; | 338 | int err = 0; |
407 | 339 | ||
408 | /* tell remote processor's name service we're removing this channel */ | 340 | /* tell remote processor's name service we're removing this channel */ |
409 | if (rpdev->announce && | 341 | if (rpdev->announce && |
410 | virtio_has_feature(vrp->vdev, VIRTIO_RPMSG_F_NS)) { | 342 | virtio_has_feature(vrp->vdev, VIRTIO_RPMSG_F_NS)) { |
411 | struct rpmsg_ns_msg nsm; | 343 | struct rpmsg_ns_msg nsm; |
412 | 344 | ||
413 | strncpy(nsm.name, rpdev->id.name, RPMSG_NAME_SIZE); | 345 | strncpy(nsm.name, rpdev->id.name, RPMSG_NAME_SIZE); |
414 | nsm.addr = rpdev->src; | 346 | nsm.addr = rpdev->src; |
415 | nsm.flags = RPMSG_NS_DESTROY; | 347 | nsm.flags = RPMSG_NS_DESTROY; |
416 | 348 | ||
417 | err = rpmsg_sendto(rpdev, &nsm, sizeof(nsm), RPMSG_NS_ADDR); | 349 | err = rpmsg_sendto(rpdev->ept, &nsm, sizeof(nsm), RPMSG_NS_ADDR); |
418 | if (err) | 350 | if (err) |
419 | dev_err(dev, "failed to announce service %d\n", err); | 351 | dev_err(dev, "failed to announce service %d\n", err); |
420 | } | 352 | } |
421 | 353 | ||
422 | rpdrv->remove(rpdev); | ||
423 | |||
424 | rpmsg_destroy_ept(rpdev->ept); | ||
425 | |||
426 | return err; | 354 | return err; |
427 | } | 355 | } |
428 | 356 | ||
429 | static struct bus_type rpmsg_bus = { | 357 | static const struct rpmsg_device_ops virtio_rpmsg_ops = { |
430 | .name = "rpmsg", | 358 | .create_ept = virtio_rpmsg_create_ept, |
431 | .match = rpmsg_dev_match, | 359 | .announce_create = virtio_rpmsg_announce_create, |
432 | .dev_attrs = rpmsg_dev_attrs, | 360 | .announce_destroy = virtio_rpmsg_announce_destroy, |
433 | .uevent = rpmsg_uevent, | ||
434 | .probe = rpmsg_dev_probe, | ||
435 | .remove = rpmsg_dev_remove, | ||
436 | }; | 361 | }; |
437 | 362 | ||
438 | /** | ||
439 | * __register_rpmsg_driver() - register an rpmsg driver with the rpmsg bus | ||
440 | * @rpdrv: pointer to a struct rpmsg_driver | ||
441 | * @owner: owning module/driver | ||
442 | * | ||
443 | * Returns 0 on success, and an appropriate error value on failure. | ||
444 | */ | ||
445 | int __register_rpmsg_driver(struct rpmsg_driver *rpdrv, struct module *owner) | ||
446 | { | ||
447 | rpdrv->drv.bus = &rpmsg_bus; | ||
448 | rpdrv->drv.owner = owner; | ||
449 | return driver_register(&rpdrv->drv); | ||
450 | } | ||
451 | EXPORT_SYMBOL(__register_rpmsg_driver); | ||
452 | |||
453 | /** | ||
454 | * unregister_rpmsg_driver() - unregister an rpmsg driver from the rpmsg bus | ||
455 | * @rpdrv: pointer to a struct rpmsg_driver | ||
456 | * | ||
457 | * Returns 0 on success, and an appropriate error value on failure. | ||
458 | */ | ||
459 | void unregister_rpmsg_driver(struct rpmsg_driver *rpdrv) | ||
460 | { | ||
461 | driver_unregister(&rpdrv->drv); | ||
462 | } | ||
463 | EXPORT_SYMBOL(unregister_rpmsg_driver); | ||
464 | |||
465 | static void rpmsg_release_device(struct device *dev) | ||
466 | { | ||
467 | struct rpmsg_channel *rpdev = to_rpmsg_channel(dev); | ||
468 | |||
469 | kfree(rpdev); | ||
470 | } | ||
471 | |||
472 | /* | ||
473 | * match an rpmsg channel with a channel info struct. | ||
474 | * this is used to make sure we're not creating rpmsg devices for channels | ||
475 | * that already exist. | ||
476 | */ | ||
477 | static int rpmsg_channel_match(struct device *dev, void *data) | ||
478 | { | ||
479 | struct rpmsg_channel_info *chinfo = data; | ||
480 | struct rpmsg_channel *rpdev = to_rpmsg_channel(dev); | ||
481 | |||
482 | if (chinfo->src != RPMSG_ADDR_ANY && chinfo->src != rpdev->src) | ||
483 | return 0; | ||
484 | |||
485 | if (chinfo->dst != RPMSG_ADDR_ANY && chinfo->dst != rpdev->dst) | ||
486 | return 0; | ||
487 | |||
488 | if (strncmp(chinfo->name, rpdev->id.name, RPMSG_NAME_SIZE)) | ||
489 | return 0; | ||
490 | |||
491 | /* found a match ! */ | ||
492 | return 1; | ||
493 | } | ||
494 | |||
495 | /* | 363 | /* |
496 | * create an rpmsg channel using its name and address info. | 364 | * create an rpmsg channel using its name and address info. |
497 | * this function will be used to create both static and dynamic | 365 | * this function will be used to create both static and dynamic |
498 | * channels. | 366 | * channels. |
499 | */ | 367 | */ |
500 | static struct rpmsg_channel *rpmsg_create_channel(struct virtproc_info *vrp, | 368 | static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp, |
501 | struct rpmsg_channel_info *chinfo) | 369 | struct rpmsg_channel_info *chinfo) |
502 | { | 370 | { |
503 | struct rpmsg_channel *rpdev; | 371 | struct virtio_rpmsg_channel *vch; |
372 | struct rpmsg_device *rpdev; | ||
504 | struct device *tmp, *dev = &vrp->vdev->dev; | 373 | struct device *tmp, *dev = &vrp->vdev->dev; |
505 | int ret; | 374 | int ret; |
506 | 375 | ||
507 | /* make sure a similar channel doesn't already exist */ | 376 | /* make sure a similar channel doesn't already exist */ |
508 | tmp = device_find_child(dev, chinfo, rpmsg_channel_match); | 377 | tmp = rpmsg_find_device(dev, chinfo); |
509 | if (tmp) { | 378 | if (tmp) { |
510 | /* decrement the matched device's refcount back */ | 379 | /* decrement the matched device's refcount back */ |
511 | put_device(tmp); | 380 | put_device(tmp); |
@@ -514,62 +383,38 @@ static struct rpmsg_channel *rpmsg_create_channel(struct virtproc_info *vrp, | |||
514 | return NULL; | 383 | return NULL; |
515 | } | 384 | } |
516 | 385 | ||
517 | rpdev = kzalloc(sizeof(struct rpmsg_channel), GFP_KERNEL); | 386 | vch = kzalloc(sizeof(*vch), GFP_KERNEL); |
518 | if (!rpdev) { | 387 | if (!vch) |
519 | pr_err("kzalloc failed\n"); | ||
520 | return NULL; | 388 | return NULL; |
521 | } | ||
522 | 389 | ||
523 | rpdev->vrp = vrp; | 390 | /* Link the channel to our vrp */ |
391 | vch->vrp = vrp; | ||
392 | |||
393 | /* Assign callbacks for rpmsg_channel */ | ||
394 | vch->rpdev.ops = &virtio_rpmsg_ops; | ||
395 | |||
396 | /* Assign public information to the rpmsg_device */ | ||
397 | rpdev = &vch->rpdev; | ||
524 | rpdev->src = chinfo->src; | 398 | rpdev->src = chinfo->src; |
525 | rpdev->dst = chinfo->dst; | 399 | rpdev->dst = chinfo->dst; |
400 | rpdev->ops = &virtio_rpmsg_ops; | ||
526 | 401 | ||
527 | /* | 402 | /* |
528 | * rpmsg server channels has predefined local address (for now), | 403 | * rpmsg server channels has predefined local address (for now), |
529 | * and their existence needs to be announced remotely | 404 | * and their existence needs to be announced remotely |
530 | */ | 405 | */ |
531 | rpdev->announce = rpdev->src != RPMSG_ADDR_ANY ? true : false; | 406 | rpdev->announce = rpdev->src != RPMSG_ADDR_ANY; |
532 | 407 | ||
533 | strncpy(rpdev->id.name, chinfo->name, RPMSG_NAME_SIZE); | 408 | strncpy(rpdev->id.name, chinfo->name, RPMSG_NAME_SIZE); |
534 | 409 | ||
535 | /* very simple device indexing plumbing which is enough for now */ | ||
536 | dev_set_name(&rpdev->dev, "rpmsg%d", rpmsg_dev_index++); | ||
537 | |||
538 | rpdev->dev.parent = &vrp->vdev->dev; | 410 | rpdev->dev.parent = &vrp->vdev->dev; |
539 | rpdev->dev.bus = &rpmsg_bus; | 411 | ret = rpmsg_register_device(rpdev); |
540 | rpdev->dev.release = rpmsg_release_device; | 412 | if (ret) |
541 | |||
542 | ret = device_register(&rpdev->dev); | ||
543 | if (ret) { | ||
544 | dev_err(dev, "device_register failed: %d\n", ret); | ||
545 | put_device(&rpdev->dev); | ||
546 | return NULL; | 413 | return NULL; |
547 | } | ||
548 | 414 | ||
549 | return rpdev; | 415 | return rpdev; |
550 | } | 416 | } |
551 | 417 | ||
552 | /* | ||
553 | * find an existing channel using its name + address properties, | ||
554 | * and destroy it | ||
555 | */ | ||
556 | static int rpmsg_destroy_channel(struct virtproc_info *vrp, | ||
557 | struct rpmsg_channel_info *chinfo) | ||
558 | { | ||
559 | struct virtio_device *vdev = vrp->vdev; | ||
560 | struct device *dev; | ||
561 | |||
562 | dev = device_find_child(&vdev->dev, chinfo, rpmsg_channel_match); | ||
563 | if (!dev) | ||
564 | return -EINVAL; | ||
565 | |||
566 | device_unregister(dev); | ||
567 | |||
568 | put_device(dev); | ||
569 | |||
570 | return 0; | ||
571 | } | ||
572 | |||
573 | /* super simple buffer "allocator" that is just enough for now */ | 418 | /* super simple buffer "allocator" that is just enough for now */ |
574 | static void *get_a_tx_buf(struct virtproc_info *vrp) | 419 | static void *get_a_tx_buf(struct virtproc_info *vrp) |
575 | { | 420 | { |
@@ -684,10 +529,12 @@ static void rpmsg_downref_sleepers(struct virtproc_info *vrp) | |||
684 | * | 529 | * |
685 | * Returns 0 on success and an appropriate error value on failure. | 530 | * Returns 0 on success and an appropriate error value on failure. |
686 | */ | 531 | */ |
687 | int rpmsg_send_offchannel_raw(struct rpmsg_channel *rpdev, u32 src, u32 dst, | 532 | static int rpmsg_send_offchannel_raw(struct rpmsg_device *rpdev, |
688 | void *data, int len, bool wait) | 533 | u32 src, u32 dst, |
534 | void *data, int len, bool wait) | ||
689 | { | 535 | { |
690 | struct virtproc_info *vrp = rpdev->vrp; | 536 | struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(rpdev); |
537 | struct virtproc_info *vrp = vch->vrp; | ||
691 | struct device *dev = &rpdev->dev; | 538 | struct device *dev = &rpdev->dev; |
692 | struct scatterlist sg; | 539 | struct scatterlist sg; |
693 | struct rpmsg_hdr *msg; | 540 | struct rpmsg_hdr *msg; |
@@ -751,10 +598,11 @@ int rpmsg_send_offchannel_raw(struct rpmsg_channel *rpdev, u32 src, u32 dst, | |||
751 | memcpy(msg->data, data, len); | 598 | memcpy(msg->data, data, len); |
752 | 599 | ||
753 | dev_dbg(dev, "TX From 0x%x, To 0x%x, Len %d, Flags %d, Reserved %d\n", | 600 | dev_dbg(dev, "TX From 0x%x, To 0x%x, Len %d, Flags %d, Reserved %d\n", |
754 | msg->src, msg->dst, msg->len, | 601 | msg->src, msg->dst, msg->len, msg->flags, msg->reserved); |
755 | msg->flags, msg->reserved); | 602 | #if defined(CONFIG_DYNAMIC_DEBUG) |
756 | print_hex_dump(KERN_DEBUG, "rpmsg_virtio TX: ", DUMP_PREFIX_NONE, 16, 1, | 603 | dynamic_hex_dump("rpmsg_virtio TX: ", DUMP_PREFIX_NONE, 16, 1, |
757 | msg, sizeof(*msg) + msg->len, true); | 604 | msg, sizeof(*msg) + msg->len, true); |
605 | #endif | ||
758 | 606 | ||
759 | sg_init_one(&sg, msg, sizeof(*msg) + len); | 607 | sg_init_one(&sg, msg, sizeof(*msg) + len); |
760 | 608 | ||
@@ -780,6 +628,56 @@ out: | |||
780 | } | 628 | } |
781 | EXPORT_SYMBOL(rpmsg_send_offchannel_raw); | 629 | EXPORT_SYMBOL(rpmsg_send_offchannel_raw); |
782 | 630 | ||
631 | static int virtio_rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len) | ||
632 | { | ||
633 | struct rpmsg_device *rpdev = ept->rpdev; | ||
634 | u32 src = ept->addr, dst = rpdev->dst; | ||
635 | |||
636 | return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true); | ||
637 | } | ||
638 | |||
639 | static int virtio_rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, | ||
640 | u32 dst) | ||
641 | { | ||
642 | struct rpmsg_device *rpdev = ept->rpdev; | ||
643 | u32 src = ept->addr; | ||
644 | |||
645 | return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true); | ||
646 | } | ||
647 | |||
648 | static int virtio_rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, | ||
649 | u32 dst, void *data, int len) | ||
650 | { | ||
651 | struct rpmsg_device *rpdev = ept->rpdev; | ||
652 | |||
653 | return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true); | ||
654 | } | ||
655 | |||
656 | static int virtio_rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len) | ||
657 | { | ||
658 | struct rpmsg_device *rpdev = ept->rpdev; | ||
659 | u32 src = ept->addr, dst = rpdev->dst; | ||
660 | |||
661 | return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false); | ||
662 | } | ||
663 | |||
664 | static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, | ||
665 | int len, u32 dst) | ||
666 | { | ||
667 | struct rpmsg_device *rpdev = ept->rpdev; | ||
668 | u32 src = ept->addr; | ||
669 | |||
670 | return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false); | ||
671 | } | ||
672 | |||
673 | static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, | ||
674 | u32 dst, void *data, int len) | ||
675 | { | ||
676 | struct rpmsg_device *rpdev = ept->rpdev; | ||
677 | |||
678 | return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false); | ||
679 | } | ||
680 | |||
783 | static int rpmsg_recv_single(struct virtproc_info *vrp, struct device *dev, | 681 | static int rpmsg_recv_single(struct virtproc_info *vrp, struct device *dev, |
784 | struct rpmsg_hdr *msg, unsigned int len) | 682 | struct rpmsg_hdr *msg, unsigned int len) |
785 | { | 683 | { |
@@ -788,17 +686,18 @@ static int rpmsg_recv_single(struct virtproc_info *vrp, struct device *dev, | |||
788 | int err; | 686 | int err; |
789 | 687 | ||
790 | dev_dbg(dev, "From: 0x%x, To: 0x%x, Len: %d, Flags: %d, Reserved: %d\n", | 688 | dev_dbg(dev, "From: 0x%x, To: 0x%x, Len: %d, Flags: %d, Reserved: %d\n", |
791 | msg->src, msg->dst, msg->len, | 689 | msg->src, msg->dst, msg->len, msg->flags, msg->reserved); |
792 | msg->flags, msg->reserved); | 690 | #if defined(CONFIG_DYNAMIC_DEBUG) |
793 | print_hex_dump(KERN_DEBUG, "rpmsg_virtio RX: ", DUMP_PREFIX_NONE, 16, 1, | 691 | dynamic_hex_dump("rpmsg_virtio RX: ", DUMP_PREFIX_NONE, 16, 1, |
794 | msg, sizeof(*msg) + msg->len, true); | 692 | msg, sizeof(*msg) + msg->len, true); |
693 | #endif | ||
795 | 694 | ||
796 | /* | 695 | /* |
797 | * We currently use fixed-sized buffers, so trivially sanitize | 696 | * We currently use fixed-sized buffers, so trivially sanitize |
798 | * the reported payload length. | 697 | * the reported payload length. |
799 | */ | 698 | */ |
800 | if (len > RPMSG_BUF_SIZE || | 699 | if (len > RPMSG_BUF_SIZE || |
801 | msg->len > (len - sizeof(struct rpmsg_hdr))) { | 700 | msg->len > (len - sizeof(struct rpmsg_hdr))) { |
802 | dev_warn(dev, "inbound msg too big: (%d, %d)\n", len, msg->len); | 701 | dev_warn(dev, "inbound msg too big: (%d, %d)\n", len, msg->len); |
803 | return -EINVAL; | 702 | return -EINVAL; |
804 | } | 703 | } |
@@ -865,7 +764,7 @@ static void rpmsg_recv_done(struct virtqueue *rvq) | |||
865 | msgs_received++; | 764 | msgs_received++; |
866 | 765 | ||
867 | msg = virtqueue_get_buf(rvq, &len); | 766 | msg = virtqueue_get_buf(rvq, &len); |
868 | }; | 767 | } |
869 | 768 | ||
870 | dev_dbg(dev, "Received %u messages\n", msgs_received); | 769 | dev_dbg(dev, "Received %u messages\n", msgs_received); |
871 | 770 | ||
@@ -892,23 +791,24 @@ static void rpmsg_xmit_done(struct virtqueue *svq) | |||
892 | } | 791 | } |
893 | 792 | ||
894 | /* invoked when a name service announcement arrives */ | 793 | /* invoked when a name service announcement arrives */ |
895 | static void rpmsg_ns_cb(struct rpmsg_channel *rpdev, void *data, int len, | 794 | static int rpmsg_ns_cb(struct rpmsg_device *rpdev, void *data, int len, |
896 | void *priv, u32 src) | 795 | void *priv, u32 src) |
897 | { | 796 | { |
898 | struct rpmsg_ns_msg *msg = data; | 797 | struct rpmsg_ns_msg *msg = data; |
899 | struct rpmsg_channel *newch; | 798 | struct rpmsg_device *newch; |
900 | struct rpmsg_channel_info chinfo; | 799 | struct rpmsg_channel_info chinfo; |
901 | struct virtproc_info *vrp = priv; | 800 | struct virtproc_info *vrp = priv; |
902 | struct device *dev = &vrp->vdev->dev; | 801 | struct device *dev = &vrp->vdev->dev; |
903 | int ret; | 802 | int ret; |
904 | 803 | ||
905 | print_hex_dump(KERN_DEBUG, "NS announcement: ", | 804 | #if defined(CONFIG_DYNAMIC_DEBUG) |
906 | DUMP_PREFIX_NONE, 16, 1, | 805 | dynamic_hex_dump("NS announcement: ", DUMP_PREFIX_NONE, 16, 1, |
907 | data, len, true); | 806 | data, len, true); |
807 | #endif | ||
908 | 808 | ||
909 | if (len != sizeof(*msg)) { | 809 | if (len != sizeof(*msg)) { |
910 | dev_err(dev, "malformed ns msg (%d)\n", len); | 810 | dev_err(dev, "malformed ns msg (%d)\n", len); |
911 | return; | 811 | return -EINVAL; |
912 | } | 812 | } |
913 | 813 | ||
914 | /* | 814 | /* |
@@ -919,22 +819,22 @@ static void rpmsg_ns_cb(struct rpmsg_channel *rpdev, void *data, int len, | |||
919 | */ | 819 | */ |
920 | if (rpdev) { | 820 | if (rpdev) { |
921 | dev_err(dev, "anomaly: ns ept has an rpdev handle\n"); | 821 | dev_err(dev, "anomaly: ns ept has an rpdev handle\n"); |
922 | return; | 822 | return -EINVAL; |
923 | } | 823 | } |
924 | 824 | ||
925 | /* don't trust the remote processor for null terminating the name */ | 825 | /* don't trust the remote processor for null terminating the name */ |
926 | msg->name[RPMSG_NAME_SIZE - 1] = '\0'; | 826 | msg->name[RPMSG_NAME_SIZE - 1] = '\0'; |
927 | 827 | ||
928 | dev_info(dev, "%sing channel %s addr 0x%x\n", | 828 | dev_info(dev, "%sing channel %s addr 0x%x\n", |
929 | msg->flags & RPMSG_NS_DESTROY ? "destroy" : "creat", | 829 | msg->flags & RPMSG_NS_DESTROY ? "destroy" : "creat", |
930 | msg->name, msg->addr); | 830 | msg->name, msg->addr); |
931 | 831 | ||
932 | strncpy(chinfo.name, msg->name, sizeof(chinfo.name)); | 832 | strncpy(chinfo.name, msg->name, sizeof(chinfo.name)); |
933 | chinfo.src = RPMSG_ADDR_ANY; | 833 | chinfo.src = RPMSG_ADDR_ANY; |
934 | chinfo.dst = msg->addr; | 834 | chinfo.dst = msg->addr; |
935 | 835 | ||
936 | if (msg->flags & RPMSG_NS_DESTROY) { | 836 | if (msg->flags & RPMSG_NS_DESTROY) { |
937 | ret = rpmsg_destroy_channel(vrp, &chinfo); | 837 | ret = rpmsg_unregister_device(&vrp->vdev->dev, &chinfo); |
938 | if (ret) | 838 | if (ret) |
939 | dev_err(dev, "rpmsg_destroy_channel failed: %d\n", ret); | 839 | dev_err(dev, "rpmsg_destroy_channel failed: %d\n", ret); |
940 | } else { | 840 | } else { |
@@ -942,6 +842,8 @@ static void rpmsg_ns_cb(struct rpmsg_channel *rpdev, void *data, int len, | |||
942 | if (!newch) | 842 | if (!newch) |
943 | dev_err(dev, "rpmsg_create_channel failed\n"); | 843 | dev_err(dev, "rpmsg_create_channel failed\n"); |
944 | } | 844 | } |
845 | |||
846 | return 0; | ||
945 | } | 847 | } |
946 | 848 | ||
947 | static int rpmsg_probe(struct virtio_device *vdev) | 849 | static int rpmsg_probe(struct virtio_device *vdev) |
@@ -995,8 +897,8 @@ static int rpmsg_probe(struct virtio_device *vdev) | |||
995 | goto vqs_del; | 897 | goto vqs_del; |
996 | } | 898 | } |
997 | 899 | ||
998 | dev_dbg(&vdev->dev, "buffers: va %p, dma 0x%llx\n", bufs_va, | 900 | dev_dbg(&vdev->dev, "buffers: va %p, dma %pad\n", |
999 | (unsigned long long)vrp->bufs_dma); | 901 | bufs_va, &vrp->bufs_dma); |
1000 | 902 | ||
1001 | /* half of the buffers is dedicated for RX */ | 903 | /* half of the buffers is dedicated for RX */ |
1002 | vrp->rbufs = bufs_va; | 904 | vrp->rbufs = bufs_va; |
@@ -1012,7 +914,7 @@ static int rpmsg_probe(struct virtio_device *vdev) | |||
1012 | sg_init_one(&sg, cpu_addr, RPMSG_BUF_SIZE); | 914 | sg_init_one(&sg, cpu_addr, RPMSG_BUF_SIZE); |
1013 | 915 | ||
1014 | err = virtqueue_add_inbuf(vrp->rvq, &sg, 1, cpu_addr, | 916 | err = virtqueue_add_inbuf(vrp->rvq, &sg, 1, cpu_addr, |
1015 | GFP_KERNEL); | 917 | GFP_KERNEL); |
1016 | WARN_ON(err); /* sanity check; this can't really happen */ | 918 | WARN_ON(err); /* sanity check; this can't really happen */ |
1017 | } | 919 | } |
1018 | 920 | ||
@@ -1119,17 +1021,9 @@ static int __init rpmsg_init(void) | |||
1119 | { | 1021 | { |
1120 | int ret; | 1022 | int ret; |
1121 | 1023 | ||
1122 | ret = bus_register(&rpmsg_bus); | ||
1123 | if (ret) { | ||
1124 | pr_err("failed to register rpmsg bus: %d\n", ret); | ||
1125 | return ret; | ||
1126 | } | ||
1127 | |||
1128 | ret = register_virtio_driver(&virtio_ipc_driver); | 1024 | ret = register_virtio_driver(&virtio_ipc_driver); |
1129 | if (ret) { | 1025 | if (ret) |
1130 | pr_err("failed to register virtio driver: %d\n", ret); | 1026 | pr_err("failed to register virtio driver: %d\n", ret); |
1131 | bus_unregister(&rpmsg_bus); | ||
1132 | } | ||
1133 | 1027 | ||
1134 | return ret; | 1028 | return ret; |
1135 | } | 1029 | } |
@@ -1138,7 +1032,6 @@ subsys_initcall(rpmsg_init); | |||
1138 | static void __exit rpmsg_fini(void) | 1032 | static void __exit rpmsg_fini(void) |
1139 | { | 1033 | { |
1140 | unregister_virtio_driver(&virtio_ipc_driver); | 1034 | unregister_virtio_driver(&virtio_ipc_driver); |
1141 | bus_unregister(&rpmsg_bus); | ||
1142 | } | 1035 | } |
1143 | module_exit(rpmsg_fini); | 1036 | module_exit(rpmsg_fini); |
1144 | 1037 | ||
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h index ada50ff36da0..452d393cc8dd 100644 --- a/include/linux/rpmsg.h +++ b/include/linux/rpmsg.h | |||
@@ -41,65 +41,27 @@ | |||
41 | #include <linux/kref.h> | 41 | #include <linux/kref.h> |
42 | #include <linux/mutex.h> | 42 | #include <linux/mutex.h> |
43 | 43 | ||
44 | /* The feature bitmap for virtio rpmsg */ | 44 | #define RPMSG_ADDR_ANY 0xFFFFFFFF |
45 | #define VIRTIO_RPMSG_F_NS 0 /* RP supports name service notifications */ | 45 | |
46 | struct rpmsg_device; | ||
47 | struct rpmsg_endpoint; | ||
48 | struct rpmsg_device_ops; | ||
49 | struct rpmsg_endpoint_ops; | ||
46 | 50 | ||
47 | /** | 51 | /** |
48 | * struct rpmsg_hdr - common header for all rpmsg messages | 52 | * struct rpmsg_channel_info - channel info representation |
49 | * @src: source address | 53 | * @name: name of service |
54 | * @src: local address | ||
50 | * @dst: destination address | 55 | * @dst: destination address |
51 | * @reserved: reserved for future use | ||
52 | * @len: length of payload (in bytes) | ||
53 | * @flags: message flags | ||
54 | * @data: @len bytes of message payload data | ||
55 | * | ||
56 | * Every message sent(/received) on the rpmsg bus begins with this header. | ||
57 | */ | 56 | */ |
58 | struct rpmsg_hdr { | 57 | struct rpmsg_channel_info { |
58 | char name[RPMSG_NAME_SIZE]; | ||
59 | u32 src; | 59 | u32 src; |
60 | u32 dst; | 60 | u32 dst; |
61 | u32 reserved; | ||
62 | u16 len; | ||
63 | u16 flags; | ||
64 | u8 data[0]; | ||
65 | } __packed; | ||
66 | |||
67 | /** | ||
68 | * struct rpmsg_ns_msg - dynamic name service announcement message | ||
69 | * @name: name of remote service that is published | ||
70 | * @addr: address of remote service that is published | ||
71 | * @flags: indicates whether service is created or destroyed | ||
72 | * | ||
73 | * This message is sent across to publish a new service, or announce | ||
74 | * about its removal. When we receive these messages, an appropriate | ||
75 | * rpmsg channel (i.e device) is created/destroyed. In turn, the ->probe() | ||
76 | * or ->remove() handler of the appropriate rpmsg driver will be invoked | ||
77 | * (if/as-soon-as one is registered). | ||
78 | */ | ||
79 | struct rpmsg_ns_msg { | ||
80 | char name[RPMSG_NAME_SIZE]; | ||
81 | u32 addr; | ||
82 | u32 flags; | ||
83 | } __packed; | ||
84 | |||
85 | /** | ||
86 | * enum rpmsg_ns_flags - dynamic name service announcement flags | ||
87 | * | ||
88 | * @RPMSG_NS_CREATE: a new remote service was just created | ||
89 | * @RPMSG_NS_DESTROY: a known remote service was just destroyed | ||
90 | */ | ||
91 | enum rpmsg_ns_flags { | ||
92 | RPMSG_NS_CREATE = 0, | ||
93 | RPMSG_NS_DESTROY = 1, | ||
94 | }; | 61 | }; |
95 | 62 | ||
96 | #define RPMSG_ADDR_ANY 0xFFFFFFFF | ||
97 | |||
98 | struct virtproc_info; | ||
99 | |||
100 | /** | 63 | /** |
101 | * rpmsg_channel - devices that belong to the rpmsg bus are called channels | 64 | * rpmsg_device - device that belong to the rpmsg bus |
102 | * @vrp: the remote processor this channel belongs to | ||
103 | * @dev: the device struct | 65 | * @dev: the device struct |
104 | * @id: device id (used to match between rpmsg drivers and devices) | 66 | * @id: device id (used to match between rpmsg drivers and devices) |
105 | * @src: local address | 67 | * @src: local address |
@@ -107,17 +69,18 @@ struct virtproc_info; | |||
107 | * @ept: the rpmsg endpoint of this channel | 69 | * @ept: the rpmsg endpoint of this channel |
108 | * @announce: if set, rpmsg will announce the creation/removal of this channel | 70 | * @announce: if set, rpmsg will announce the creation/removal of this channel |
109 | */ | 71 | */ |
110 | struct rpmsg_channel { | 72 | struct rpmsg_device { |
111 | struct virtproc_info *vrp; | ||
112 | struct device dev; | 73 | struct device dev; |
113 | struct rpmsg_device_id id; | 74 | struct rpmsg_device_id id; |
114 | u32 src; | 75 | u32 src; |
115 | u32 dst; | 76 | u32 dst; |
116 | struct rpmsg_endpoint *ept; | 77 | struct rpmsg_endpoint *ept; |
117 | bool announce; | 78 | bool announce; |
79 | |||
80 | const struct rpmsg_device_ops *ops; | ||
118 | }; | 81 | }; |
119 | 82 | ||
120 | typedef void (*rpmsg_rx_cb_t)(struct rpmsg_channel *, void *, int, void *, u32); | 83 | typedef int (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32); |
121 | 84 | ||
122 | /** | 85 | /** |
123 | * struct rpmsg_endpoint - binds a local rpmsg address to its user | 86 | * struct rpmsg_endpoint - binds a local rpmsg address to its user |
@@ -143,12 +106,14 @@ typedef void (*rpmsg_rx_cb_t)(struct rpmsg_channel *, void *, int, void *, u32); | |||
143 | * create additional endpoints by themselves (see rpmsg_create_ept()). | 106 | * create additional endpoints by themselves (see rpmsg_create_ept()). |
144 | */ | 107 | */ |
145 | struct rpmsg_endpoint { | 108 | struct rpmsg_endpoint { |
146 | struct rpmsg_channel *rpdev; | 109 | struct rpmsg_device *rpdev; |
147 | struct kref refcount; | 110 | struct kref refcount; |
148 | rpmsg_rx_cb_t cb; | 111 | rpmsg_rx_cb_t cb; |
149 | struct mutex cb_lock; | 112 | struct mutex cb_lock; |
150 | u32 addr; | 113 | u32 addr; |
151 | void *priv; | 114 | void *priv; |
115 | |||
116 | const struct rpmsg_endpoint_ops *ops; | ||
152 | }; | 117 | }; |
153 | 118 | ||
154 | /** | 119 | /** |
@@ -162,20 +127,19 @@ struct rpmsg_endpoint { | |||
162 | struct rpmsg_driver { | 127 | struct rpmsg_driver { |
163 | struct device_driver drv; | 128 | struct device_driver drv; |
164 | const struct rpmsg_device_id *id_table; | 129 | const struct rpmsg_device_id *id_table; |
165 | int (*probe)(struct rpmsg_channel *dev); | 130 | int (*probe)(struct rpmsg_device *dev); |
166 | void (*remove)(struct rpmsg_channel *dev); | 131 | void (*remove)(struct rpmsg_device *dev); |
167 | void (*callback)(struct rpmsg_channel *, void *, int, void *, u32); | 132 | int (*callback)(struct rpmsg_device *, void *, int, void *, u32); |
168 | }; | 133 | }; |
169 | 134 | ||
170 | int register_rpmsg_device(struct rpmsg_channel *dev); | 135 | int register_rpmsg_device(struct rpmsg_device *dev); |
171 | void unregister_rpmsg_device(struct rpmsg_channel *dev); | 136 | void unregister_rpmsg_device(struct rpmsg_device *dev); |
172 | int __register_rpmsg_driver(struct rpmsg_driver *drv, struct module *owner); | 137 | int __register_rpmsg_driver(struct rpmsg_driver *drv, struct module *owner); |
173 | void unregister_rpmsg_driver(struct rpmsg_driver *drv); | 138 | void unregister_rpmsg_driver(struct rpmsg_driver *drv); |
174 | void rpmsg_destroy_ept(struct rpmsg_endpoint *); | 139 | void rpmsg_destroy_ept(struct rpmsg_endpoint *); |
175 | struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_channel *, | 140 | struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *, |
176 | rpmsg_rx_cb_t cb, void *priv, u32 addr); | 141 | rpmsg_rx_cb_t cb, void *priv, |
177 | int | 142 | struct rpmsg_channel_info chinfo); |
178 | rpmsg_send_offchannel_raw(struct rpmsg_channel *, u32, u32, void *, int, bool); | ||
179 | 143 | ||
180 | /* use a macro to avoid include chaining to get THIS_MODULE */ | 144 | /* use a macro to avoid include chaining to get THIS_MODULE */ |
181 | #define register_rpmsg_driver(drv) \ | 145 | #define register_rpmsg_driver(drv) \ |
@@ -193,156 +157,14 @@ rpmsg_send_offchannel_raw(struct rpmsg_channel *, u32, u32, void *, int, bool); | |||
193 | module_driver(__rpmsg_driver, register_rpmsg_driver, \ | 157 | module_driver(__rpmsg_driver, register_rpmsg_driver, \ |
194 | unregister_rpmsg_driver) | 158 | unregister_rpmsg_driver) |
195 | 159 | ||
196 | /** | 160 | int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len); |
197 | * rpmsg_send() - send a message across to the remote processor | 161 | int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst); |
198 | * @rpdev: the rpmsg channel | 162 | int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst, |
199 | * @data: payload of message | 163 | void *data, int len); |
200 | * @len: length of payload | ||
201 | * | ||
202 | * This function sends @data of length @len on the @rpdev channel. | ||
203 | * The message will be sent to the remote processor which the @rpdev | ||
204 | * channel belongs to, using @rpdev's source and destination addresses. | ||
205 | * In case there are no TX buffers available, the function will block until | ||
206 | * one becomes available, or a timeout of 15 seconds elapses. When the latter | ||
207 | * happens, -ERESTARTSYS is returned. | ||
208 | * | ||
209 | * Can only be called from process context (for now). | ||
210 | * | ||
211 | * Returns 0 on success and an appropriate error value on failure. | ||
212 | */ | ||
213 | static inline int rpmsg_send(struct rpmsg_channel *rpdev, void *data, int len) | ||
214 | { | ||
215 | u32 src = rpdev->src, dst = rpdev->dst; | ||
216 | |||
217 | return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true); | ||
218 | } | ||
219 | |||
220 | /** | ||
221 | * rpmsg_sendto() - send a message across to the remote processor, specify dst | ||
222 | * @rpdev: the rpmsg channel | ||
223 | * @data: payload of message | ||
224 | * @len: length of payload | ||
225 | * @dst: destination address | ||
226 | * | ||
227 | * This function sends @data of length @len to the remote @dst address. | ||
228 | * The message will be sent to the remote processor which the @rpdev | ||
229 | * channel belongs to, using @rpdev's source address. | ||
230 | * In case there are no TX buffers available, the function will block until | ||
231 | * one becomes available, or a timeout of 15 seconds elapses. When the latter | ||
232 | * happens, -ERESTARTSYS is returned. | ||
233 | * | ||
234 | * Can only be called from process context (for now). | ||
235 | * | ||
236 | * Returns 0 on success and an appropriate error value on failure. | ||
237 | */ | ||
238 | static inline | ||
239 | int rpmsg_sendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst) | ||
240 | { | ||
241 | u32 src = rpdev->src; | ||
242 | |||
243 | return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true); | ||
244 | } | ||
245 | |||
246 | /** | ||
247 | * rpmsg_send_offchannel() - send a message using explicit src/dst addresses | ||
248 | * @rpdev: the rpmsg channel | ||
249 | * @src: source address | ||
250 | * @dst: destination address | ||
251 | * @data: payload of message | ||
252 | * @len: length of payload | ||
253 | * | ||
254 | * This function sends @data of length @len to the remote @dst address, | ||
255 | * and uses @src as the source address. | ||
256 | * The message will be sent to the remote processor which the @rpdev | ||
257 | * channel belongs to. | ||
258 | * In case there are no TX buffers available, the function will block until | ||
259 | * one becomes available, or a timeout of 15 seconds elapses. When the latter | ||
260 | * happens, -ERESTARTSYS is returned. | ||
261 | * | ||
262 | * Can only be called from process context (for now). | ||
263 | * | ||
264 | * Returns 0 on success and an appropriate error value on failure. | ||
265 | */ | ||
266 | static inline | ||
267 | int rpmsg_send_offchannel(struct rpmsg_channel *rpdev, u32 src, u32 dst, | ||
268 | void *data, int len) | ||
269 | { | ||
270 | return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true); | ||
271 | } | ||
272 | |||
273 | /** | ||
274 | * rpmsg_send() - send a message across to the remote processor | ||
275 | * @rpdev: the rpmsg channel | ||
276 | * @data: payload of message | ||
277 | * @len: length of payload | ||
278 | * | ||
279 | * This function sends @data of length @len on the @rpdev channel. | ||
280 | * The message will be sent to the remote processor which the @rpdev | ||
281 | * channel belongs to, using @rpdev's source and destination addresses. | ||
282 | * In case there are no TX buffers available, the function will immediately | ||
283 | * return -ENOMEM without waiting until one becomes available. | ||
284 | * | ||
285 | * Can only be called from process context (for now). | ||
286 | * | ||
287 | * Returns 0 on success and an appropriate error value on failure. | ||
288 | */ | ||
289 | static inline | ||
290 | int rpmsg_trysend(struct rpmsg_channel *rpdev, void *data, int len) | ||
291 | { | ||
292 | u32 src = rpdev->src, dst = rpdev->dst; | ||
293 | 164 | ||
294 | return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false); | 165 | int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len); |
295 | } | 166 | int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst); |
296 | 167 | int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst, | |
297 | /** | 168 | void *data, int len); |
298 | * rpmsg_sendto() - send a message across to the remote processor, specify dst | ||
299 | * @rpdev: the rpmsg channel | ||
300 | * @data: payload of message | ||
301 | * @len: length of payload | ||
302 | * @dst: destination address | ||
303 | * | ||
304 | * This function sends @data of length @len to the remote @dst address. | ||
305 | * The message will be sent to the remote processor which the @rpdev | ||
306 | * channel belongs to, using @rpdev's source address. | ||
307 | * In case there are no TX buffers available, the function will immediately | ||
308 | * return -ENOMEM without waiting until one becomes available. | ||
309 | * | ||
310 | * Can only be called from process context (for now). | ||
311 | * | ||
312 | * Returns 0 on success and an appropriate error value on failure. | ||
313 | */ | ||
314 | static inline | ||
315 | int rpmsg_trysendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst) | ||
316 | { | ||
317 | u32 src = rpdev->src; | ||
318 | |||
319 | return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false); | ||
320 | } | ||
321 | |||
322 | /** | ||
323 | * rpmsg_send_offchannel() - send a message using explicit src/dst addresses | ||
324 | * @rpdev: the rpmsg channel | ||
325 | * @src: source address | ||
326 | * @dst: destination address | ||
327 | * @data: payload of message | ||
328 | * @len: length of payload | ||
329 | * | ||
330 | * This function sends @data of length @len to the remote @dst address, | ||
331 | * and uses @src as the source address. | ||
332 | * The message will be sent to the remote processor which the @rpdev | ||
333 | * channel belongs to. | ||
334 | * In case there are no TX buffers available, the function will immediately | ||
335 | * return -ENOMEM without waiting until one becomes available. | ||
336 | * | ||
337 | * Can only be called from process context (for now). | ||
338 | * | ||
339 | * Returns 0 on success and an appropriate error value on failure. | ||
340 | */ | ||
341 | static inline | ||
342 | int rpmsg_trysend_offchannel(struct rpmsg_channel *rpdev, u32 src, u32 dst, | ||
343 | void *data, int len) | ||
344 | { | ||
345 | return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false); | ||
346 | } | ||
347 | 169 | ||
348 | #endif /* _LINUX_RPMSG_H */ | 170 | #endif /* _LINUX_RPMSG_H */ |
diff --git a/samples/rpmsg/rpmsg_client_sample.c b/samples/rpmsg/rpmsg_client_sample.c index d0e249c90668..f161dfd3e70a 100644 --- a/samples/rpmsg/rpmsg_client_sample.c +++ b/samples/rpmsg/rpmsg_client_sample.c | |||
@@ -24,38 +24,52 @@ | |||
24 | #define MSG "hello world!" | 24 | #define MSG "hello world!" |
25 | #define MSG_LIMIT 100 | 25 | #define MSG_LIMIT 100 |
26 | 26 | ||
27 | static void rpmsg_sample_cb(struct rpmsg_channel *rpdev, void *data, int len, | 27 | struct instance_data { |
28 | int rx_count; | ||
29 | }; | ||
30 | |||
31 | static int rpmsg_sample_cb(struct rpmsg_device *rpdev, void *data, int len, | ||
28 | void *priv, u32 src) | 32 | void *priv, u32 src) |
29 | { | 33 | { |
30 | int ret; | 34 | int ret; |
31 | static int rx_count; | 35 | struct instance_data *idata = dev_get_drvdata(&rpdev->dev); |
32 | 36 | ||
33 | dev_info(&rpdev->dev, "incoming msg %d (src: 0x%x)\n", ++rx_count, src); | 37 | dev_info(&rpdev->dev, "incoming msg %d (src: 0x%x)\n", |
38 | ++idata->rx_count, src); | ||
34 | 39 | ||
35 | print_hex_dump(KERN_DEBUG, __func__, DUMP_PREFIX_NONE, 16, 1, | 40 | print_hex_dump(KERN_DEBUG, __func__, DUMP_PREFIX_NONE, 16, 1, |
36 | data, len, true); | 41 | data, len, true); |
37 | 42 | ||
38 | /* samples should not live forever */ | 43 | /* samples should not live forever */ |
39 | if (rx_count >= MSG_LIMIT) { | 44 | if (idata->rx_count >= MSG_LIMIT) { |
40 | dev_info(&rpdev->dev, "goodbye!\n"); | 45 | dev_info(&rpdev->dev, "goodbye!\n"); |
41 | return; | 46 | return 0; |
42 | } | 47 | } |
43 | 48 | ||
44 | /* send a new message now */ | 49 | /* send a new message now */ |
45 | ret = rpmsg_send(rpdev, MSG, strlen(MSG)); | 50 | ret = rpmsg_send(rpdev->ept, MSG, strlen(MSG)); |
46 | if (ret) | 51 | if (ret) |
47 | dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret); | 52 | dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret); |
53 | |||
54 | return 0; | ||
48 | } | 55 | } |
49 | 56 | ||
50 | static int rpmsg_sample_probe(struct rpmsg_channel *rpdev) | 57 | static int rpmsg_sample_probe(struct rpmsg_device *rpdev) |
51 | { | 58 | { |
52 | int ret; | 59 | int ret; |
60 | struct instance_data *idata; | ||
53 | 61 | ||
54 | dev_info(&rpdev->dev, "new channel: 0x%x -> 0x%x!\n", | 62 | dev_info(&rpdev->dev, "new channel: 0x%x -> 0x%x!\n", |
55 | rpdev->src, rpdev->dst); | 63 | rpdev->src, rpdev->dst); |
56 | 64 | ||
65 | idata = devm_kzalloc(&rpdev->dev, sizeof(*idata), GFP_KERNEL); | ||
66 | if (!idata) | ||
67 | return -ENOMEM; | ||
68 | |||
69 | dev_set_drvdata(&rpdev->dev, idata); | ||
70 | |||
57 | /* send a message to our remote processor */ | 71 | /* send a message to our remote processor */ |
58 | ret = rpmsg_send(rpdev, MSG, strlen(MSG)); | 72 | ret = rpmsg_send(rpdev->ept, MSG, strlen(MSG)); |
59 | if (ret) { | 73 | if (ret) { |
60 | dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret); | 74 | dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret); |
61 | return ret; | 75 | return ret; |
@@ -64,7 +78,7 @@ static int rpmsg_sample_probe(struct rpmsg_channel *rpdev) | |||
64 | return 0; | 78 | return 0; |
65 | } | 79 | } |
66 | 80 | ||
67 | static void rpmsg_sample_remove(struct rpmsg_channel *rpdev) | 81 | static void rpmsg_sample_remove(struct rpmsg_device *rpdev) |
68 | { | 82 | { |
69 | dev_info(&rpdev->dev, "rpmsg sample client driver is removed\n"); | 83 | dev_info(&rpdev->dev, "rpmsg sample client driver is removed\n"); |
70 | } | 84 | } |