Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rpmsg: Introduce Qualcomm SMD backend

This introduces a new rpmsg backend for the Qualcomm SMD system,
allowing communication with various remote processors found in Qualcomm
platforms. The implementation is based on, and intends to replace,
drivers/soc/qcom/smd.c with the necessary adaptions for fitting with the
rpmsg core.

Based on original work by Sricharan R <sricharan@codeaurora.org>

Cc: Sricharan R <sricharan@codeaurora.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>

+1445
+10
drivers/rpmsg/Kconfig
··· 4 4 config RPMSG 5 5 tristate 6 6 7 + config RPMSG_QCOM_SMD 8 + tristate "Qualcomm Shared Memory Driver (SMD)" 9 + depends on QCOM_SMEM 10 + depends on !QCOM_SMD 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 + 7 17 config RPMSG_VIRTIO 8 18 tristate 9 19 select RPMSG
+1
drivers/rpmsg/Makefile
··· 1 1 obj-$(CONFIG_RPMSG) += rpmsg_core.o 2 + obj-$(CONFIG_RPMSG_QCOM_SMD) += qcom_smd.o 2 3 obj-$(CONFIG_RPMSG_VIRTIO) += virtio_rpmsg_bus.o
+1434
drivers/rpmsg/qcom_smd.c
··· 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");