blob: a08c4bfde4a25c5091a6fb0565f254ebabfab701 [file] [log] [blame]
Chris Lew4039ef92017-01-31 16:16:20 -08001/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
Chris Lewfa6135e2016-08-01 13:29:46 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/delay.h>
14#include <linux/err.h>
15#include <linux/gfp.h>
16#include <linux/kernel.h>
17#include <linux/kthread.h>
18#include <linux/list.h>
19#include <linux/module.h>
20#include <linux/mutex.h>
21#include <linux/of.h>
22#include <linux/platform_device.h>
23#include <linux/printk.h>
24#include <linux/sched.h>
25#include <linux/seq_file.h>
26#include <linux/slab.h>
27#include <linux/spi/spi.h>
28#include <linux/spinlock.h>
29#include <linux/srcu.h>
30#include <linux/wait.h>
31#include <linux/component.h>
32#include <soc/qcom/tracer_pkt.h>
33#include <sound/wcd-dsp-mgr.h>
34#include <sound/wcd-spi.h>
35#include "glink_core_if.h"
36#include "glink_private.h"
37#include "glink_xprt_if.h"
38
39#define XPRT_NAME "spi"
40#define FIFO_ALIGNMENT 16
41#define FIFO_FULL_RESERVE 8
42#define TX_BLOCKED_CMD_RESERVE 16
43#define TRACER_PKT_FEATURE BIT(2)
44#define DEFAULT_FIFO_SIZE 1024
45#define SHORT_PKT_SIZE 16
46#define XPRT_ALIGNMENT 4
47
48#define MAX_INACTIVE_CYCLES 50
49#define POLL_INTERVAL_US 500
50
51#define ACTIVE_TX BIT(0)
52#define ACTIVE_RX BIT(1)
53
54#define ID_MASK 0xFFFFFF
55/**
56 * enum command_types - definition of the types of commands sent/received
57 * @VERSION_CMD: Version and feature set supported
58 * @VERSION_ACK_CMD: Response for @VERSION_CMD
59 * @OPEN_CMD: Open a channel
60 * @CLOSE_CMD: Close a channel
61 * @OPEN_ACK_CMD: Response to @OPEN_CMD
62 * @CLOSE_ACK_CMD: Response for @CLOSE_CMD
63 * @RX_INTENT_CMD: RX intent for a channel is queued
64 * @RX_DONE_CMD: Use of RX intent for a channel is complete
65 * @RX_DONE_W_REUSE_CMD: Same as @RX_DONE but also reuse the used intent
66 * @RX_INTENT_REQ_CMD: Request to have RX intent queued
67 * @RX_INTENT_REQ_ACK_CMD: Response for @RX_INTENT_REQ_CMD
68 * @TX_DATA_CMD: Start of a data transfer
69 * @TX_DATA_CONT_CMD: Continuation or end of a data transfer
70 * @READ_NOTIF_CMD: Request for a notification when this cmd is read
71 * @SIGNALS_CMD: Sideband signals
72 * @TRACER_PKT_CMD: Start of a Tracer Packet Command
73 * @TRACER_PKT_CONT_CMD: Continuation or end of a Tracer Packet Command
74 * @TX_SHORT_DATA_CMD: Transmit short packets
75 */
76enum command_types {
77 VERSION_CMD,
78 VERSION_ACK_CMD,
79 OPEN_CMD,
80 CLOSE_CMD,
81 OPEN_ACK_CMD,
82 CLOSE_ACK_CMD,
83 RX_INTENT_CMD,
84 RX_DONE_CMD,
85 RX_DONE_W_REUSE_CMD,
86 RX_INTENT_REQ_CMD,
87 RX_INTENT_REQ_ACK_CMD,
88 TX_DATA_CMD,
89 TX_DATA_CONT_CMD,
90 READ_NOTIF_CMD,
91 SIGNALS_CMD,
92 TRACER_PKT_CMD,
93 TRACER_PKT_CONT_CMD,
94 TX_SHORT_DATA_CMD,
95};
96
97/**
98 * struct glink_cmpnt - Component to cache WDSP component and its operations
99 * @master_dev: Device structure corresponding to WDSP device.
100 * @master_ops: Operations supported by the WDSP device.
101 */
102struct glink_cmpnt {
103 struct device *master_dev;
104 struct wdsp_mgr_ops *master_ops;
105};
106
107/**
108 * struct edge_info - local information for managing a single complete edge
109 * @xprt_if: The transport interface registered with the
110 * glink core associated with this edge.
111 * @xprt_cfg: The transport configuration for the glink core
112 * assocaited with this edge.
113 * @subsys_name: Name of the remote subsystem in the edge.
Chris Lewbb58f022017-06-27 16:54:11 -0700114 * @spi_ops: Function pointers for ops provided by spi.
Chris Lewfa6135e2016-08-01 13:29:46 -0700115 * @fifo_size: Size of the FIFO at the remote end.
116 * @tx_fifo_start: Base Address of the TX FIFO.
117 * @tx_fifo_end: End Address of the TX FIFO.
118 * @rx_fifo_start: Base Address of the RX FIFO.
119 * @rx_fifo_end: End Address of the RX FIFO.
120 * @tx_fifo_read_reg_addr: Address of the TX FIFO Read Index Register.
121 * @tx_fifo_write_reg_addr: Address of the TX FIFO Write Index Register.
122 * @rx_fifo_read_reg_addr: Address of the RX FIFO Read Index Register.
123 * @rx_fifo_write_reg_addr: Address of the RX FIFO Write Index Register.
Chris Lewcd4f9e52017-05-24 16:16:38 -0700124 * @tx_fifo_write: Internal write index for TX FIFO.
125 * @rx_fifo_read: Internal read index for RX FIFO.
Chris Lewfa6135e2016-08-01 13:29:46 -0700126 * @kwork: Work to be executed when receiving data.
127 * @kworker: Handle to the entity processing @kwork.
128 * @task: Handle to the task context that runs @kworker.
129 * @use_ref: Active users of this transport grab a
130 * reference. Used for SSR synchronization.
131 * @in_ssr: Signals if this transport is in ssr.
132 * @write_lock: Lock to serialize write/tx operation.
133 * @tx_blocked_queue: Queue of entities waiting for the remote side to
134 * signal the resumption of TX.
135 * @tx_resume_needed: A tx resume signal needs to be sent to the glink
136 * core.
137 * @tx_blocked_signal_sent: Flag to indicate the flush signal has already
138 * been sent, and a response is pending from the
139 * remote side. Protected by @write_lock.
140 * @num_pw_states: Size of @ramp_time_us.
141 * @ramp_time_us: Array of ramp times in microseconds where array
142 * index position represents a power state.
143 * @activity_flag: Flag indicating active TX and RX.
144 * @activity_lock: Lock to synchronize access to activity flag.
145 * @cmpnt: Component to interface with the remote device.
146 */
147struct edge_info {
148 struct list_head list;
149 struct glink_transport_if xprt_if;
150 struct glink_core_transport_cfg xprt_cfg;
151 char subsys_name[GLINK_NAME_SIZE];
Chris Lewbb58f022017-06-27 16:54:11 -0700152 struct wcd_spi_ops spi_ops;
Chris Lewfa6135e2016-08-01 13:29:46 -0700153
154 uint32_t fifo_size;
155 uint32_t tx_fifo_start;
156 uint32_t tx_fifo_end;
157 uint32_t rx_fifo_start;
158 uint32_t rx_fifo_end;
159 unsigned int tx_fifo_read_reg_addr;
160 unsigned int tx_fifo_write_reg_addr;
161 unsigned int rx_fifo_read_reg_addr;
162 unsigned int rx_fifo_write_reg_addr;
Chris Lewcd4f9e52017-05-24 16:16:38 -0700163 uint32_t tx_fifo_write;
164 uint32_t rx_fifo_read;
Chris Lewfa6135e2016-08-01 13:29:46 -0700165
166 struct kthread_work kwork;
167 struct kthread_worker kworker;
168 struct task_struct *task;
169 struct srcu_struct use_ref;
170 bool in_ssr;
171 struct mutex write_lock;
172 wait_queue_head_t tx_blocked_queue;
173 bool tx_resume_needed;
174 bool tx_blocked_signal_sent;
175
176 uint32_t num_pw_states;
177 unsigned long *ramp_time_us;
178
179 uint32_t activity_flag;
180 spinlock_t activity_lock;
181
182 struct glink_cmpnt cmpnt;
183};
184
185static uint32_t negotiate_features_v1(struct glink_transport_if *if_ptr,
186 const struct glink_core_version *version,
187 uint32_t features);
188static DEFINE_SPINLOCK(edge_infos_lock);
189static LIST_HEAD(edge_infos);
190static struct glink_core_version versions[] = {
191 {1, TRACER_PKT_FEATURE, negotiate_features_v1},
192};
193
194/**
195 * negotiate_features_v1() - determine what features of a version can be used
196 * @if_ptr: The transport for which features are negotiated for.
197 * @version: The version negotiated.
198 * @features: The set of requested features.
199 *
200 * Return: What set of the requested features can be supported.
201 */
202static uint32_t negotiate_features_v1(struct glink_transport_if *if_ptr,
203 const struct glink_core_version *version,
204 uint32_t features)
205{
206 return features & version->features;
207}
208
209/**
210 * wdsp_suspend() - Vote for the WDSP device suspend
211 * @cmpnt: Component to identify the WDSP device.
212 *
213 * Return: 0 on success, standard Linux error codes on failure.
214 */
215static int wdsp_suspend(struct glink_cmpnt *cmpnt)
216{
217 int rc = 0;
218
219 if (cmpnt && cmpnt->master_dev &&
220 cmpnt->master_ops && cmpnt->master_ops->suspend)
221 rc = cmpnt->master_ops->suspend(cmpnt->master_dev);
222 return rc;
223}
224
225/**
226 * wdsp_resume() - Vote for the WDSP device resume
227 * @cmpnt: Component to identify the WDSP device.
228 *
229 * Return: 0 on success, standard Linux error codes on failure.
230 */
231static int wdsp_resume(struct glink_cmpnt *cmpnt)
232{
233 int rc = 0;
234
235 if (cmpnt && cmpnt->master_dev &&
236 cmpnt->master_ops && cmpnt->master_ops->resume)
237 rc = cmpnt->master_ops->resume(cmpnt->master_dev);
238 return rc;
239}
240
241/**
242 * glink_spi_xprt_set_poll_mode() - Set the transport to polling mode
243 * @einfo: Edge information corresponding to the transport.
244 *
245 * This helper function indicates the start of RX polling. This will
246 * prevent the system from suspending and keeps polling for RX for a
247 * pre-defined duration.
248 */
249static void glink_spi_xprt_set_poll_mode(struct edge_info *einfo)
250{
251 unsigned long flags;
252
253 spin_lock_irqsave(&einfo->activity_lock, flags);
254 einfo->activity_flag |= ACTIVE_RX;
255 spin_unlock_irqrestore(&einfo->activity_lock, flags);
256 if (!strcmp(einfo->xprt_cfg.edge, "wdsp"))
257 wdsp_resume(&einfo->cmpnt);
258}
259
260/**
261 * glink_spi_xprt_set_irq_mode() - Set the transport to IRQ mode
262 * @einfo: Edge information corresponding to the transport.
263 *
264 * This helper indicates the end of RX polling. This will allow the
265 * system to suspend and new RX data can be handled only through an IRQ.
266 */
267static void glink_spi_xprt_set_irq_mode(struct edge_info *einfo)
268{
269 unsigned long flags;
270
271 spin_lock_irqsave(&einfo->activity_lock, flags);
272 einfo->activity_flag &= ~ACTIVE_RX;
273 spin_unlock_irqrestore(&einfo->activity_lock, flags);
274}
275
276/**
277 * glink_spi_xprt_rx_data() - Receive data over SPI bus
278 * @einfo: Edge from which the data has to be received.
279 * @src: Source Address of the RX data.
280 * @dst: Address of the destination RX buffer.
281 * @size: Size of the RX data.
282 *
283 * This function is used to receive data or command as a byte stream from
284 * the remote subsystem over the SPI bus.
285 *
286 * Return: 0 on success, standard Linux error codes on failure.
287 */
288static int glink_spi_xprt_rx_data(struct edge_info *einfo, void *src,
289 void *dst, uint32_t size)
290{
291 struct wcd_spi_msg spi_msg;
292
Chris Lewbb58f022017-06-27 16:54:11 -0700293 if (unlikely(!einfo->spi_ops.read_dev))
294 return -EINVAL;
295
Chris Lewfa6135e2016-08-01 13:29:46 -0700296 memset(&spi_msg, 0, sizeof(spi_msg));
297 spi_msg.data = dst;
298 spi_msg.remote_addr = (uint32_t)(size_t)src;
299 spi_msg.len = (size_t)size;
Chris Lewbb58f022017-06-27 16:54:11 -0700300 return einfo->spi_ops.read_dev(einfo->spi_ops.spi_dev, &spi_msg);
Chris Lewfa6135e2016-08-01 13:29:46 -0700301}
302
303/**
304 * glink_spi_xprt_tx_data() - Transmit data over SPI bus
305 * @einfo: Edge from which the data has to be received.
306 * @src: Address of the TX buffer.
307 * @dst: Destination Address of the TX Date.
308 * @size: Size of the TX data.
309 *
310 * This function is used to transmit data or command as a byte stream to
311 * the remote subsystem over the SPI bus.
312 *
313 * Return: 0 on success, standard Linux error codes on failure.
314 */
315static int glink_spi_xprt_tx_data(struct edge_info *einfo, void *src,
316 void *dst, uint32_t size)
317{
318 struct wcd_spi_msg spi_msg;
319
Chris Lewbb58f022017-06-27 16:54:11 -0700320 if (unlikely(!einfo->spi_ops.write_dev))
321 return -EINVAL;
322
Chris Lewfa6135e2016-08-01 13:29:46 -0700323 memset(&spi_msg, 0, sizeof(spi_msg));
324 spi_msg.data = src;
325 spi_msg.remote_addr = (uint32_t)(size_t)dst;
326 spi_msg.len = (size_t)size;
Chris Lewbb58f022017-06-27 16:54:11 -0700327 return einfo->spi_ops.write_dev(einfo->spi_ops.spi_dev, &spi_msg);
Chris Lewfa6135e2016-08-01 13:29:46 -0700328}
329
330/**
331 * glink_spi_xprt_reg_read() - Read the TX/RX FIFO Read/Write Index registers
332 * @einfo: Edge from which the registers have to be read.
333 * @reg_addr: Address of the register to be read.
334 * @data: Buffer into which the register data has to be read.
335 *
336 * Return: 0 on success, standard Linux error codes on failure.
337 */
338static int glink_spi_xprt_reg_read(struct edge_info *einfo, u32 reg_addr,
339 uint32_t *data)
340{
341 int rc;
342
343 rc = glink_spi_xprt_rx_data(einfo, (void *)(unsigned long)reg_addr,
344 data, sizeof(*data));
345 if (!rc)
346 *data = *data & ID_MASK;
347 return rc;
348}
349
350/**
351 * glink_spi_xprt_reg_write() - Write the TX/RX FIFO Read/Write Index registers
352 * @einfo: Edge to which the registers have to be written.
353 * @reg_addr: Address of the registers to be written.
354 * @data: Data to be written to the registers.
355 *
356 * Return: 0 on success, standard Linux error codes on failure.
357 */
358static int glink_spi_xprt_reg_write(struct edge_info *einfo, u32 reg_addr,
359 uint32_t data)
360{
361 return glink_spi_xprt_tx_data(einfo, &data,
362 (void *)(unsigned long)reg_addr, sizeof(data));
363}
364
365/**
366 * glink_spi_xprt_write_avail() - Available Write Space in the remote side
367 * @einfo: Edge information corresponding to the remote side.
368 *
369 * This function reads the TX FIFO Read & Write Index registers from the
370 * remote subsystem and calculate the available write space.
371 *
372 * Return: 0 on error, available write space on success.
373 */
374static int glink_spi_xprt_write_avail(struct edge_info *einfo)
375{
376 uint32_t read_id;
377 uint32_t write_id;
378 int write_avail;
379 int ret;
380
Chris Lewcd4f9e52017-05-24 16:16:38 -0700381 if (unlikely(!einfo->tx_fifo_start)) {
382 ret = glink_spi_xprt_reg_read(einfo,
383 einfo->tx_fifo_write_reg_addr, &einfo->tx_fifo_write);
384 if (ret < 0) {
385 pr_err("%s: Error %d reading %s tx_fifo_write_reg_addr %d\n",
386 __func__, ret, einfo->xprt_cfg.edge,
387 einfo->tx_fifo_write_reg_addr);
388 return 0;
389 }
390 einfo->tx_fifo_start = einfo->tx_fifo_write;
391 }
392 write_id = einfo->tx_fifo_write;
393
Chris Lewfa6135e2016-08-01 13:29:46 -0700394 ret = glink_spi_xprt_reg_read(einfo, einfo->tx_fifo_read_reg_addr,
395 &read_id);
396 if (ret < 0) {
397 pr_err("%s: Error %d reading %s tx_fifo_read_reg_addr %d\n",
398 __func__, ret, einfo->xprt_cfg.edge,
399 einfo->tx_fifo_read_reg_addr);
400 return 0;
401 }
402
Chris Lewfa6135e2016-08-01 13:29:46 -0700403 if (!read_id || !write_id)
404 return 0;
405
Chris Lewfa6135e2016-08-01 13:29:46 -0700406 if (read_id > write_id)
407 write_avail = read_id - write_id;
408 else
409 write_avail = einfo->fifo_size - (write_id - read_id);
410
411 if (write_avail < FIFO_FULL_RESERVE + TX_BLOCKED_CMD_RESERVE)
412 write_avail = 0;
413 else
414 write_avail -= FIFO_FULL_RESERVE + TX_BLOCKED_CMD_RESERVE;
415
416 return write_avail;
417}
418
419/**
420 * glink_spi_xprt_read_avail() - Available Read Data from the remote side
421 * @einfo: Edge information corresponding to the remote side.
422 *
423 * This function reads the RX FIFO Read & Write Index registers from the
424 * remote subsystem and calculate the available read data size.
425 *
426 * Return: 0 on error, available read data on success.
427 */
428static int glink_spi_xprt_read_avail(struct edge_info *einfo)
429{
430 uint32_t read_id;
431 uint32_t write_id;
432 int read_avail;
433 int ret;
434
Chris Lewcd4f9e52017-05-24 16:16:38 -0700435 if (unlikely(!einfo->rx_fifo_start)) {
436 ret = glink_spi_xprt_reg_read(einfo,
437 einfo->rx_fifo_read_reg_addr, &einfo->rx_fifo_read);
438 if (ret < 0) {
439 pr_err("%s: Error %d reading %s rx_fifo_read_reg_addr %d\n",
440 __func__, ret, einfo->xprt_cfg.edge,
441 einfo->rx_fifo_read_reg_addr);
442 return 0;
443 }
444 einfo->rx_fifo_start = einfo->rx_fifo_read;
Chris Lewfa6135e2016-08-01 13:29:46 -0700445 }
Chris Lewcd4f9e52017-05-24 16:16:38 -0700446 read_id = einfo->rx_fifo_read;
Chris Lewfa6135e2016-08-01 13:29:46 -0700447
448 ret = glink_spi_xprt_reg_read(einfo, einfo->rx_fifo_write_reg_addr,
449 &write_id);
450 if (ret < 0) {
451 pr_err("%s: Error %d reading %s rx_fifo_write_reg_addr %d\n",
452 __func__, ret, einfo->xprt_cfg.edge,
453 einfo->rx_fifo_write_reg_addr);
454 return 0;
455 }
456
457 if (!read_id || !write_id)
458 return 0;
459
Chris Lewfa6135e2016-08-01 13:29:46 -0700460 if (read_id <= write_id)
461 read_avail = write_id - read_id;
462 else
463 read_avail = einfo->fifo_size - (read_id - write_id);
464 return read_avail;
465}
466
467/**
468 * glink_spi_xprt_rx_cmd() - Receive G-Link commands
469 * @einfo: Edge information corresponding to the remote side.
470 * @dst: Destination buffer where the commands have to be read into.
471 * @size: Size of the data to be read.
472 *
473 * This function is used to receive the commands from the RX FIFO. This
474 * function updates the RX FIFO Read Index after reading the data.
475 *
476 * Return: 0 on success, standard Linux error codes on error.
477 */
478static int glink_spi_xprt_rx_cmd(struct edge_info *einfo, void *dst,
479 uint32_t size)
480{
481 uint32_t read_id;
482 uint32_t size_to_read = size;
483 uint32_t offset = 0;
484 int ret;
485
Chris Lewcd4f9e52017-05-24 16:16:38 -0700486 read_id = einfo->rx_fifo_read;
Chris Lewfa6135e2016-08-01 13:29:46 -0700487 do {
488 if ((read_id + size_to_read) >=
489 (einfo->rx_fifo_start + einfo->fifo_size))
490 size_to_read = einfo->rx_fifo_start + einfo->fifo_size
491 - read_id;
492 ret = glink_spi_xprt_rx_data(einfo, (void *)(size_t)read_id,
493 dst + offset, size_to_read);
494 if (ret < 0) {
495 pr_err("%s: Error %d reading data\n", __func__, ret);
496 return ret;
497 }
498 read_id += size_to_read;
499 offset += size_to_read;
500 if (read_id >= (einfo->rx_fifo_start + einfo->fifo_size))
501 read_id = einfo->rx_fifo_start;
502 size_to_read = size - offset;
503 } while (size_to_read);
504
505 ret = glink_spi_xprt_reg_write(einfo, einfo->rx_fifo_read_reg_addr,
506 read_id);
507 if (ret < 0)
508 pr_err("%s: Error %d writing %s rx_fifo_read_reg_addr %d\n",
509 __func__, ret, einfo->xprt_cfg.edge,
510 einfo->rx_fifo_read_reg_addr);
Chris Lewcd4f9e52017-05-24 16:16:38 -0700511 else
512 einfo->rx_fifo_read = read_id;
513
Chris Lewfa6135e2016-08-01 13:29:46 -0700514 return ret;
515}
516
517/**
518 * glink_spi_xprt_tx_cmd_safe() - Transmit G-Link commands
519 * @einfo: Edge information corresponding to the remote subsystem.
520 * @src: Source buffer containing the G-Link command.
521 * @size: Size of the command to transmit.
522 *
523 * This function is used to transmit the G-Link commands. This function
524 * must be called with einfo->write_lock locked.
525 *
526 * Return: 0 on success, standard Linux error codes on error.
527 */
528static int glink_spi_xprt_tx_cmd_safe(struct edge_info *einfo, void *src,
529 uint32_t size)
530{
531 uint32_t write_id;
532 uint32_t size_to_write = size;
533 uint32_t offset = 0;
534 int ret;
535
Chris Lewcd4f9e52017-05-24 16:16:38 -0700536 write_id = einfo->tx_fifo_write;
Chris Lewfa6135e2016-08-01 13:29:46 -0700537 do {
538 if ((write_id + size_to_write) >=
539 (einfo->tx_fifo_start + einfo->fifo_size))
540 size_to_write = einfo->tx_fifo_start + einfo->fifo_size
541 - write_id;
542 ret = glink_spi_xprt_tx_data(einfo, src + offset,
543 (void *)(size_t)write_id, size_to_write);
544 if (ret < 0) {
545 pr_err("%s: Error %d writing data\n", __func__, ret);
546 return ret;
547 }
548 write_id += size_to_write;
549 offset += size_to_write;
550 if (write_id >= (einfo->tx_fifo_start + einfo->fifo_size))
551 write_id = einfo->tx_fifo_start;
552 size_to_write = size - offset;
553 } while (size_to_write);
554
555 ret = glink_spi_xprt_reg_write(einfo, einfo->tx_fifo_write_reg_addr,
556 write_id);
557 if (ret < 0)
558 pr_err("%s: Error %d writing %s tx_fifo_write_reg_addr %d\n",
559 __func__, ret, einfo->xprt_cfg.edge,
560 einfo->tx_fifo_write_reg_addr);
Chris Lewcd4f9e52017-05-24 16:16:38 -0700561 else
562 einfo->tx_fifo_write = write_id;
563
Chris Lewfa6135e2016-08-01 13:29:46 -0700564 return ret;
565}
566
567/**
568 * send_tx_blocked_signal() - Send flow control request message
569 * @einfo: Edge information corresponding to the remote subsystem.
570 *
571 * This function is used to send a message to the remote subsystem indicating
572 * that the local subsystem is waiting for the write space. The remote
573 * subsystem on receiving this message will send a resume tx message.
574 */
575static void send_tx_blocked_signal(struct edge_info *einfo)
576{
577 struct read_notif_request {
578 uint16_t cmd;
579 uint16_t reserved;
580 uint32_t reserved2;
581 uint64_t reserved3;
582 };
583 struct read_notif_request read_notif_req = {0};
584
585 read_notif_req.cmd = READ_NOTIF_CMD;
586
587 if (!einfo->tx_blocked_signal_sent) {
588 einfo->tx_blocked_signal_sent = true;
589 glink_spi_xprt_tx_cmd_safe(einfo, &read_notif_req,
590 sizeof(read_notif_req));
591 }
592}
593
594/**
595 * glink_spi_xprt_tx_cmd() - Transmit G-Link commands
596 * @einfo: Edge information corresponding to the remote subsystem.
597 * @src: Source buffer containing the G-Link command.
598 * @size: Size of the command to transmit.
599 *
600 * This function is used to transmit the G-Link commands. This function
601 * might sleep if the space is not available to transmit the command.
602 *
603 * Return: 0 on success, standard Linux error codes on error.
604 */
605static int glink_spi_xprt_tx_cmd(struct edge_info *einfo, void *src,
606 uint32_t size)
607{
608 int ret;
609 DEFINE_WAIT(wait);
610
611 mutex_lock(&einfo->write_lock);
612 while (glink_spi_xprt_write_avail(einfo) < size) {
613 send_tx_blocked_signal(einfo);
614 prepare_to_wait(&einfo->tx_blocked_queue, &wait,
615 TASK_UNINTERRUPTIBLE);
616 if (glink_spi_xprt_write_avail(einfo) < size &&
617 !einfo->in_ssr) {
618 mutex_unlock(&einfo->write_lock);
619 schedule();
620 mutex_lock(&einfo->write_lock);
621 }
622 finish_wait(&einfo->tx_blocked_queue, &wait);
623 if (einfo->in_ssr) {
624 mutex_unlock(&einfo->write_lock);
625 return -EFAULT;
626 }
627 }
628 ret = glink_spi_xprt_tx_cmd_safe(einfo, src, size);
629 mutex_unlock(&einfo->write_lock);
630 return ret;
631}
632
633/**
634 * process_rx_data() - process received data from an edge
635 * @einfo: The edge the data is received on.
636 * @cmd_id: ID to specify the type of data.
637 * @rcid: The remote channel id associated with the data.
638 * @intend_id: The intent the data should be put in.
639 * @src: Address of the source buffer from which the data
640 * is read.
641 * @frag_size: Size of the data fragment to read.
642 * @size_remaining: Size of data left to be read in this packet.
643 */
644static void process_rx_data(struct edge_info *einfo, uint16_t cmd_id,
645 uint32_t rcid, uint32_t intent_id, void *src,
646 uint32_t frag_size, uint32_t size_remaining)
647{
648 struct glink_core_rx_intent *intent;
649 int rc = 0;
650
651 intent = einfo->xprt_if.glink_core_if_ptr->rx_get_pkt_ctx(
652 &einfo->xprt_if, rcid, intent_id);
653 if (intent == NULL) {
654 GLINK_ERR("%s: no intent for ch %d liid %d\n", __func__, rcid,
655 intent_id);
656 return;
657 } else if (intent->data == NULL) {
658 GLINK_ERR("%s: intent for ch %d liid %d has no data buff\n",
659 __func__, rcid, intent_id);
660 return;
661 } else if (intent->intent_size - intent->write_offset < frag_size ||
662 intent->write_offset + size_remaining > intent->intent_size) {
663 GLINK_ERR("%s: rx data size:%d and remaining:%d %s %d %s:%d\n",
664 __func__, frag_size, size_remaining,
665 "will overflow ch", rcid, "intent", intent_id);
666 return;
667 }
668
669 if (cmd_id == TX_SHORT_DATA_CMD)
670 memcpy(intent->data + intent->write_offset, src, frag_size);
671 else
672 rc = glink_spi_xprt_rx_data(einfo, src,
673 intent->data + intent->write_offset, frag_size);
674 if (rc < 0) {
675 GLINK_ERR("%s: Error %d receiving data %d:%d:%d:%d\n",
676 __func__, rc, rcid, intent_id, frag_size,
677 size_remaining);
678 size_remaining += frag_size;
679 } else {
680 intent->write_offset += frag_size;
681 intent->pkt_size += frag_size;
682
683 if (unlikely((cmd_id == TRACER_PKT_CMD ||
684 cmd_id == TRACER_PKT_CONT_CMD) && !size_remaining)) {
685 tracer_pkt_log_event(intent->data, GLINK_XPRT_RX);
686 intent->tracer_pkt = true;
687 }
688 }
689 einfo->xprt_if.glink_core_if_ptr->rx_put_pkt_ctx(&einfo->xprt_if,
690 rcid, intent, size_remaining ? false : true);
691}
692
693/**
694 * process_rx_cmd() - Process incoming G-Link commands
695 * @einfo: Edge information corresponding to the remote subsystem.
696 * @rx_data: Buffer which contains the G-Link commands to be processed.
697 * @rx_size: Size of the buffer containing the series of G-Link commands.
698 *
699 * This function is used to parse and process a series of G-Link commands
700 * received in a buffer.
701 */
702static void process_rx_cmd(struct edge_info *einfo,
703 void *rx_data, int rx_size)
704{
705 struct command {
706 uint16_t id;
707 uint16_t param1;
708 uint32_t param2;
709 uint32_t param3;
710 uint32_t param4;
711 };
712 struct intent_desc {
713 uint32_t size;
714 uint32_t id;
715 uint64_t addr;
716 };
717 struct rx_desc {
718 uint32_t size;
719 uint32_t size_left;
720 uint64_t addr;
721 };
722 struct rx_short_data_desc {
723 unsigned char data[SHORT_PKT_SIZE];
724 };
725 struct command *cmd;
726 struct intent_desc *intents;
727 struct rx_desc *rx_descp;
728 struct rx_short_data_desc *rx_sd_descp;
729 int offset = 0;
730 int rcu_id;
731 uint16_t rcid;
732 uint16_t name_len;
733 uint16_t prio;
734 char *name;
735 bool granted;
736 int i;
737
738 rcu_id = srcu_read_lock(&einfo->use_ref);
739 if (einfo->in_ssr) {
740 srcu_read_unlock(&einfo->use_ref, rcu_id);
741 return;
742 }
743
744 while (offset < rx_size) {
745 cmd = (struct command *)(rx_data + offset);
746 offset += sizeof(*cmd);
747 switch (cmd->id) {
748 case VERSION_CMD:
749 if (cmd->param3)
750 einfo->fifo_size = cmd->param3;
751 einfo->xprt_if.glink_core_if_ptr->rx_cmd_version(
752 &einfo->xprt_if, cmd->param1, cmd->param2);
753 break;
754
755 case VERSION_ACK_CMD:
756 einfo->xprt_if.glink_core_if_ptr->rx_cmd_version_ack(
757 &einfo->xprt_if, cmd->param1, cmd->param2);
758 break;
759
760 case OPEN_CMD:
761 rcid = cmd->param1;
762 name_len = (uint16_t)(cmd->param2 & 0xFFFF);
763 prio = (uint16_t)((cmd->param2 & 0xFFFF0000) >> 16);
764 name = (char *)(rx_data + offset);
765 offset += ALIGN(name_len, FIFO_ALIGNMENT);
766 einfo->xprt_if.glink_core_if_ptr->rx_cmd_ch_remote_open(
767 &einfo->xprt_if, rcid, name, prio);
768 break;
769
770 case CLOSE_CMD:
771 einfo->xprt_if.glink_core_if_ptr->
772 rx_cmd_ch_remote_close(
773 &einfo->xprt_if, cmd->param1);
774 break;
775
776 case OPEN_ACK_CMD:
777 prio = (uint16_t)(cmd->param2 & 0xFFFF);
778 einfo->xprt_if.glink_core_if_ptr->rx_cmd_ch_open_ack(
779 &einfo->xprt_if, cmd->param1, prio);
780 break;
781
782 case CLOSE_ACK_CMD:
783 einfo->xprt_if.glink_core_if_ptr->rx_cmd_ch_close_ack(
784 &einfo->xprt_if, cmd->param1);
785 break;
786
787 case RX_INTENT_CMD:
788 for (i = 0; i < cmd->param2; i++) {
789 intents = (struct intent_desc *)
790 (rx_data + offset);
791 offset += sizeof(*intents);
792 einfo->xprt_if.glink_core_if_ptr->
793 rx_cmd_remote_rx_intent_put_cookie(
Dhoat Harpaldf33d122017-01-05 18:51:00 +0530794 &einfo->xprt_if, cmd->param1,
795 intents->id, intents->size,
796 (void *)(uintptr_t)(intents->addr));
Chris Lewfa6135e2016-08-01 13:29:46 -0700797 }
798 break;
799
800 case RX_DONE_CMD:
801 einfo->xprt_if.glink_core_if_ptr->rx_cmd_tx_done(
802 &einfo->xprt_if, cmd->param1, cmd->param2,
803 false);
804 break;
805
806 case RX_INTENT_REQ_CMD:
807 einfo->xprt_if.glink_core_if_ptr->
808 rx_cmd_remote_rx_intent_req(
809 &einfo->xprt_if, cmd->param1,
810 cmd->param2);
811 break;
812
813 case RX_INTENT_REQ_ACK_CMD:
814 granted = cmd->param2 == 1 ? true : false;
815 einfo->xprt_if.glink_core_if_ptr->
816 rx_cmd_rx_intent_req_ack(&einfo->xprt_if,
817 cmd->param1, granted);
818 break;
819
820 case TX_DATA_CMD:
821 case TX_DATA_CONT_CMD:
822 case TRACER_PKT_CMD:
823 case TRACER_PKT_CONT_CMD:
824 rx_descp = (struct rx_desc *)(rx_data + offset);
825 offset += sizeof(*rx_descp);
Dhoat Harpaldf33d122017-01-05 18:51:00 +0530826 process_rx_data(einfo, cmd->id, cmd->param1,
827 cmd->param2,
828 (void *)(uintptr_t)(rx_descp->addr),
829 rx_descp->size, rx_descp->size_left);
Chris Lewfa6135e2016-08-01 13:29:46 -0700830 break;
831
832 case TX_SHORT_DATA_CMD:
833 rx_sd_descp = (struct rx_short_data_desc *)
834 (rx_data + offset);
835 offset += sizeof(*rx_sd_descp);
836 process_rx_data(einfo, cmd->id, cmd->param1,
837 cmd->param2, (void *)rx_sd_descp->data,
838 cmd->param3, cmd->param4);
839 break;
840
841 case READ_NOTIF_CMD:
842 break;
843
844 case SIGNALS_CMD:
845 einfo->xprt_if.glink_core_if_ptr->rx_cmd_remote_sigs(
846 &einfo->xprt_if, cmd->param1, cmd->param2);
847 break;
848
849 case RX_DONE_W_REUSE_CMD:
850 einfo->xprt_if.glink_core_if_ptr->rx_cmd_tx_done(
851 &einfo->xprt_if, cmd->param1,
852 cmd->param2, true);
853 break;
854
855 default:
856 pr_err("Unrecognized command: %d\n", cmd->id);
857 break;
858 }
859 }
860 srcu_read_unlock(&einfo->use_ref, rcu_id);
861}
862
863/**
864 * __rx_worker() - Receive commands on a specific edge
865 * @einfo: Edge to process commands on.
866 *
867 * This function checks the size of data to be received, allocates the
868 * buffer for that data and reads the data from the remote subsytem
869 * into that buffer. This function then calls the process_rx_cmd() to
870 * parse the received G-Link command sequence. This function will also
871 * poll for the data for a predefined duration for performance reasons.
872 */
873static void __rx_worker(struct edge_info *einfo)
874{
875 uint32_t inactive_cycles = 0;
876 int rx_avail, rc;
877 void *rx_data;
878 int rcu_id;
879
880 rcu_id = srcu_read_lock(&einfo->use_ref);
Karthikeyan Ramasubramaniane03039d2016-09-26 17:30:08 -0600881 if (einfo->in_ssr) {
882 srcu_read_unlock(&einfo->use_ref, rcu_id);
883 return;
884 }
885
Chris Lewfa6135e2016-08-01 13:29:46 -0700886 if (unlikely(!einfo->rx_fifo_start)) {
887 rx_avail = glink_spi_xprt_read_avail(einfo);
888 if (!rx_avail) {
889 srcu_read_unlock(&einfo->use_ref, rcu_id);
890 return;
891 }
Chris Lewfa6135e2016-08-01 13:29:46 -0700892 einfo->xprt_if.glink_core_if_ptr->link_up(&einfo->xprt_if);
893 }
894
Chris Lewfa6135e2016-08-01 13:29:46 -0700895 glink_spi_xprt_set_poll_mode(einfo);
Chris Lew67057ff2017-01-23 16:36:43 -0800896 do {
Chris Lewfa6135e2016-08-01 13:29:46 -0700897 if (einfo->tx_resume_needed &&
898 glink_spi_xprt_write_avail(einfo)) {
899 einfo->tx_resume_needed = false;
900 einfo->xprt_if.glink_core_if_ptr->tx_resume(
901 &einfo->xprt_if);
902 }
903 mutex_lock(&einfo->write_lock);
904 if (einfo->tx_blocked_signal_sent) {
905 wake_up_all(&einfo->tx_blocked_queue);
906 einfo->tx_blocked_signal_sent = false;
907 }
908 mutex_unlock(&einfo->write_lock);
909
910 rx_avail = glink_spi_xprt_read_avail(einfo);
911 if (!rx_avail) {
912 usleep_range(POLL_INTERVAL_US, POLL_INTERVAL_US + 50);
913 inactive_cycles++;
914 continue;
915 }
916 inactive_cycles = 0;
917
918 rx_data = kzalloc(rx_avail, GFP_KERNEL);
919 if (!rx_data)
920 break;
921
922 rc = glink_spi_xprt_rx_cmd(einfo, rx_data, rx_avail);
923 if (rc < 0) {
924 GLINK_ERR("%s: Error %d receiving data\n",
925 __func__, rc);
926 kfree(rx_data);
927 break;
928 }
929 process_rx_cmd(einfo, rx_data, rx_avail);
930 kfree(rx_data);
Chris Lew67057ff2017-01-23 16:36:43 -0800931 } while (inactive_cycles < MAX_INACTIVE_CYCLES && !einfo->in_ssr);
Chris Lewfa6135e2016-08-01 13:29:46 -0700932 glink_spi_xprt_set_irq_mode(einfo);
933 srcu_read_unlock(&einfo->use_ref, rcu_id);
934}
935
936/**
937 * rx_worker() - Worker function to process received commands
938 * @work: kwork associated with the edge to process commands on.
939 */
940static void rx_worker(struct kthread_work *work)
941{
942 struct edge_info *einfo;
943
944 einfo = container_of(work, struct edge_info, kwork);
945 __rx_worker(einfo);
946};
947
948/**
949 * tx_cmd_version() - Convert a version cmd to wire format and transmit
950 * @if_ptr: The transport to transmit on.
951 * @version: The version number to encode.
952 * @features: The features information to encode.
953 */
954static void tx_cmd_version(struct glink_transport_if *if_ptr, uint32_t version,
955 uint32_t features)
956{
957 struct command {
958 uint16_t id;
959 uint16_t version;
960 uint32_t features;
961 uint32_t fifo_size;
962 uint32_t reserved;
963 };
964 struct command cmd;
965 struct edge_info *einfo;
966 int rcu_id;
967
968 memset(&cmd, 0, sizeof(cmd));
969 einfo = container_of(if_ptr, struct edge_info, xprt_if);
970
971 rcu_id = srcu_read_lock(&einfo->use_ref);
972 if (einfo->in_ssr) {
973 srcu_read_unlock(&einfo->use_ref, rcu_id);
974 return;
975 }
976
977 cmd.id = VERSION_CMD;
978 cmd.version = version;
979 cmd.features = features;
980
981 glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
982 srcu_read_unlock(&einfo->use_ref, rcu_id);
983}
984
985/**
986 * tx_cmd_version_ack() - Convert a version ack cmd to wire format and transmit
987 * @if_ptr: The transport to transmit on.
988 * @version: The version number to encode.
989 * @features: The features information to encode.
990 */
991static void tx_cmd_version_ack(struct glink_transport_if *if_ptr,
992 uint32_t version,
993 uint32_t features)
994{
995 struct command {
996 uint16_t id;
997 uint16_t version;
998 uint32_t features;
999 uint32_t fifo_size;
1000 uint32_t reserved;
1001 };
1002 struct command cmd;
1003 struct edge_info *einfo;
1004 int rcu_id;
1005
1006 memset(&cmd, 0, sizeof(cmd));
1007 einfo = container_of(if_ptr, struct edge_info, xprt_if);
1008
1009 rcu_id = srcu_read_lock(&einfo->use_ref);
1010 if (einfo->in_ssr) {
1011 srcu_read_unlock(&einfo->use_ref, rcu_id);
1012 return;
1013 }
1014
1015 cmd.id = VERSION_ACK_CMD;
1016 cmd.version = version;
1017 cmd.features = features;
1018
1019 glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
1020 srcu_read_unlock(&einfo->use_ref, rcu_id);
1021}
1022
1023/**
1024 * set_version() - Activate a negotiated version and feature set
1025 * @if_ptr: The transport to configure.
1026 * @version: The version to use.
1027 * @features: The features to use.
1028 *
1029 * Return: The supported capabilities of the transport.
1030 */
1031static uint32_t set_version(struct glink_transport_if *if_ptr, uint32_t version,
1032 uint32_t features)
1033{
1034 struct edge_info *einfo;
1035 uint32_t ret;
1036 int rcu_id;
1037
1038 einfo = container_of(if_ptr, struct edge_info, xprt_if);
1039
1040 rcu_id = srcu_read_lock(&einfo->use_ref);
1041 if (einfo->in_ssr) {
1042 srcu_read_unlock(&einfo->use_ref, rcu_id);
1043 return 0;
1044 }
1045
1046 ret = GCAP_SIGNALS;
1047 if (features & TRACER_PKT_FEATURE)
1048 ret |= GCAP_TRACER_PKT;
1049
1050 srcu_read_unlock(&einfo->use_ref, rcu_id);
1051 return ret;
1052}
1053
1054/**
1055 * tx_cmd_ch_open() - Convert a channel open cmd to wire format and transmit
1056 * @if_ptr: The transport to transmit on.
1057 * @lcid: The local channel id to encode.
1058 * @name: The channel name to encode.
1059 * @req_xprt: The transport the core would like to migrate this channel to.
1060 *
1061 * Return: 0 on success or standard Linux error code.
1062 */
1063static int tx_cmd_ch_open(struct glink_transport_if *if_ptr, uint32_t lcid,
1064 const char *name, uint16_t req_xprt)
1065{
1066 struct command {
1067 uint16_t id;
1068 uint16_t lcid;
1069 uint16_t length;
1070 uint16_t req_xprt;
1071 uint64_t reserved;
1072 };
1073 struct command cmd;
1074 struct edge_info *einfo;
1075 uint32_t buf_size;
1076 void *buf;
1077 int rcu_id;
1078
1079 memset(&cmd, 0, sizeof(cmd));
1080 einfo = container_of(if_ptr, struct edge_info, xprt_if);
1081
1082 rcu_id = srcu_read_lock(&einfo->use_ref);
1083 if (einfo->in_ssr) {
1084 srcu_read_unlock(&einfo->use_ref, rcu_id);
1085 return -EFAULT;
1086 }
1087
1088 cmd.id = OPEN_CMD;
1089 cmd.lcid = lcid;
1090 cmd.length = (uint16_t)(strlen(name) + 1);
1091 cmd.req_xprt = req_xprt;
1092
1093 buf_size = ALIGN(sizeof(cmd) + cmd.length, FIFO_ALIGNMENT);
1094
1095 buf = kzalloc(buf_size, GFP_KERNEL);
1096 if (!buf) {
1097 srcu_read_unlock(&einfo->use_ref, rcu_id);
1098 return -ENOMEM;
1099 }
1100
1101 memcpy(buf, &cmd, sizeof(cmd));
1102 memcpy(buf + sizeof(cmd), name, cmd.length);
1103
1104 glink_spi_xprt_tx_cmd(einfo, buf, buf_size);
1105
1106 kfree(buf);
1107 srcu_read_unlock(&einfo->use_ref, rcu_id);
1108 return 0;
1109}
1110
1111/**
1112 * tx_cmd_ch_close() - Convert a channel close cmd to wire format and transmit
1113 * @if_ptr: The transport to transmit on.
1114 * @lcid: The local channel id to encode.
1115 *
1116 * Return: 0 on success or standard Linux error code.
1117 */
1118static int tx_cmd_ch_close(struct glink_transport_if *if_ptr, uint32_t lcid)
1119{
1120 struct command {
1121 uint16_t id;
1122 uint16_t lcid;
1123 uint32_t reserved1;
1124 uint64_t reserved2;
1125 };
1126 struct command cmd;
1127 struct edge_info *einfo;
1128 int rcu_id;
1129
1130 memset(&cmd, 0, sizeof(cmd));
1131 einfo = container_of(if_ptr, struct edge_info, xprt_if);
1132
1133 rcu_id = srcu_read_lock(&einfo->use_ref);
1134 if (einfo->in_ssr) {
1135 srcu_read_unlock(&einfo->use_ref, rcu_id);
1136 return -EFAULT;
1137 }
1138
1139 cmd.id = CLOSE_CMD;
1140 cmd.lcid = lcid;
1141
1142 glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
1143
1144 srcu_read_unlock(&einfo->use_ref, rcu_id);
1145 return 0;
1146}
1147
1148/**
1149 * tx_cmd_ch_remote_open_ack() - Convert a channel open ack cmd to wire format
1150 * and transmit
1151 * @if_ptr: The transport to transmit on.
1152 * @rcid: The remote channel id to encode.
1153 * @xprt_resp: The response to a transport migration request.
1154 */
1155static void tx_cmd_ch_remote_open_ack(struct glink_transport_if *if_ptr,
1156 uint32_t rcid, uint16_t xprt_resp)
1157{
1158 struct command {
1159 uint16_t id;
1160 uint16_t rcid;
1161 uint16_t reserved1;
1162 uint16_t xprt_resp;
1163 uint64_t reserved2;
1164 };
1165 struct command cmd;
1166 struct edge_info *einfo;
1167 int rcu_id;
1168
1169 memset(&cmd, 0, sizeof(cmd));
1170 einfo = container_of(if_ptr, struct edge_info, xprt_if);
1171
1172 rcu_id = srcu_read_lock(&einfo->use_ref);
1173 if (einfo->in_ssr) {
1174 srcu_read_unlock(&einfo->use_ref, rcu_id);
1175 return;
1176 }
1177
1178 cmd.id = OPEN_ACK_CMD;
1179 cmd.rcid = rcid;
1180 cmd.xprt_resp = xprt_resp;
1181
1182 glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
1183 srcu_read_unlock(&einfo->use_ref, rcu_id);
1184}
1185
1186/**
1187 * tx_cmd_ch_remote_close_ack() - Convert a channel close ack cmd to wire format
1188 * and transmit
1189 * @if_ptr: The transport to transmit on.
1190 * @rcid: The remote channel id to encode.
1191 */
1192static void tx_cmd_ch_remote_close_ack(struct glink_transport_if *if_ptr,
1193 uint32_t rcid)
1194{
1195 struct command {
1196 uint16_t id;
1197 uint16_t rcid;
1198 uint32_t reserved1;
1199 uint64_t reserved2;
1200 };
1201 struct command cmd;
1202 struct edge_info *einfo;
1203 int rcu_id;
1204
1205 memset(&cmd, 0, sizeof(cmd));
1206 einfo = container_of(if_ptr, struct edge_info, xprt_if);
1207
1208 rcu_id = srcu_read_lock(&einfo->use_ref);
1209 if (einfo->in_ssr) {
1210 srcu_read_unlock(&einfo->use_ref, rcu_id);
1211 return;
1212 }
1213
1214 cmd.id = CLOSE_ACK_CMD;
1215 cmd.rcid = rcid;
1216
1217 glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
1218 srcu_read_unlock(&einfo->use_ref, rcu_id);
1219}
1220
1221/**
1222 * ssr() - Process a subsystem restart notification of a transport
1223 * @if_ptr: The transport to restart
1224 *
1225 * Return: 0 on success or standard Linux error code.
1226 */
1227static int ssr(struct glink_transport_if *if_ptr)
1228{
1229 struct edge_info *einfo;
1230
1231 einfo = container_of(if_ptr, struct edge_info, xprt_if);
1232
1233 einfo->in_ssr = true;
1234 wake_up_all(&einfo->tx_blocked_queue);
1235
1236 synchronize_srcu(&einfo->use_ref);
1237 einfo->tx_resume_needed = false;
1238 einfo->tx_blocked_signal_sent = false;
1239 einfo->tx_fifo_start = 0;
1240 einfo->rx_fifo_start = 0;
Chris Lewcd4f9e52017-05-24 16:16:38 -07001241 einfo->tx_fifo_write = 0;
1242 einfo->rx_fifo_read = 0;
Chris Lewfa6135e2016-08-01 13:29:46 -07001243 einfo->fifo_size = DEFAULT_FIFO_SIZE;
1244 einfo->xprt_if.glink_core_if_ptr->link_down(&einfo->xprt_if);
1245
1246 return 0;
1247}
1248
1249/**
1250 * allocate_rx_intent() - Allocate/reserve space for RX Intent
1251 * @if_ptr: The transport the intent is associated with.
1252 * @size: size of intent.
1253 * @intent: Pointer to the intent structure.
1254 *
1255 * Assign "data" with the buffer created, since the transport creates
1256 * a linear buffer and "iovec" with the "intent" itself, so that
1257 * the data can be passed to a client that receives only vector buffer.
1258 * Note that returning NULL for the pointer is valid (it means that space has
1259 * been reserved, but the actual pointer will be provided later).
1260 *
1261 * Return: 0 on success or standard Linux error code.
1262 */
1263static int allocate_rx_intent(struct glink_transport_if *if_ptr, size_t size,
1264 struct glink_core_rx_intent *intent)
1265{
1266 void *t;
1267
1268 t = kzalloc(size, GFP_KERNEL);
1269 if (!t)
1270 return -ENOMEM;
1271
1272 intent->data = t;
1273 intent->iovec = (void *)intent;
1274 intent->vprovider = rx_linear_vbuf_provider;
1275 intent->pprovider = NULL;
1276 return 0;
1277}
1278
1279/**
1280 * deallocate_rx_intent() - Deallocate space created for RX Intent
1281 * @if_ptr: The transport the intent is associated with.
1282 * @intent: Pointer to the intent structure.
1283 *
1284 * Return: 0 on success or standard Linux error code.
1285 */
1286static int deallocate_rx_intent(struct glink_transport_if *if_ptr,
1287 struct glink_core_rx_intent *intent)
1288{
1289 if (!intent || !intent->data)
1290 return -EINVAL;
1291
1292 kfree(intent->data);
1293 intent->data = NULL;
1294 intent->iovec = NULL;
1295 intent->vprovider = NULL;
1296 return 0;
1297}
1298
1299/**
1300 * tx_cmd_local_rx_intent() - Convert an rx intent cmd to wire format and
1301 * transmit
1302 * @if_ptr: The transport to transmit on.
1303 * @lcid: The local channel id to encode.
1304 * @size: The intent size to encode.
1305 * @liid: The local intent id to encode.
1306 *
1307 * Return: 0 on success or standard Linux error code.
1308 */
1309static int tx_cmd_local_rx_intent(struct glink_transport_if *if_ptr,
1310 uint32_t lcid, size_t size, uint32_t liid)
1311{
1312 struct command {
1313 uint16_t id;
1314 uint16_t lcid;
1315 uint32_t count;
1316 uint64_t reserved;
1317 uint32_t size;
1318 uint32_t liid;
1319 uint64_t addr;
1320 };
1321 struct command cmd;
1322 struct edge_info *einfo;
1323 int rcu_id;
1324
1325 if (size > UINT_MAX) {
1326 pr_err("%s: size %zu is too large to encode\n", __func__, size);
1327 return -EMSGSIZE;
1328 }
1329
1330 memset(&cmd, 0, sizeof(cmd));
1331 einfo = container_of(if_ptr, struct edge_info, xprt_if);
1332
1333 rcu_id = srcu_read_lock(&einfo->use_ref);
1334 if (einfo->in_ssr) {
1335 srcu_read_unlock(&einfo->use_ref, rcu_id);
1336 return -EFAULT;
1337 }
1338
1339 cmd.id = RX_INTENT_CMD;
1340 cmd.lcid = lcid;
1341 cmd.count = 1;
1342 cmd.size = size;
1343 cmd.liid = liid;
1344
1345 glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
1346
1347 srcu_read_unlock(&einfo->use_ref, rcu_id);
1348 return 0;
1349}
1350
1351/**
1352 * tx_cmd_local_rx_done() - Convert an rx done cmd to wire format and transmit
1353 * @if_ptr: The transport to transmit on.
1354 * @lcid: The local channel id to encode.
1355 * @liid: The local intent id to encode.
1356 * @reuse: Reuse the consumed intent.
1357 */
1358static void tx_cmd_local_rx_done(struct glink_transport_if *if_ptr,
1359 uint32_t lcid, uint32_t liid, bool reuse)
1360{
1361 struct command {
1362 uint16_t id;
1363 uint16_t lcid;
1364 uint32_t liid;
1365 uint64_t reserved;
1366 };
1367 struct command cmd;
1368 struct edge_info *einfo;
1369 int rcu_id;
1370
1371 memset(&cmd, 0, sizeof(cmd));
1372 einfo = container_of(if_ptr, struct edge_info, xprt_if);
1373
1374 rcu_id = srcu_read_lock(&einfo->use_ref);
1375 if (einfo->in_ssr) {
1376 srcu_read_unlock(&einfo->use_ref, rcu_id);
1377 return;
1378 }
1379
1380 cmd.id = reuse ? RX_DONE_W_REUSE_CMD : RX_DONE_CMD;
1381 cmd.lcid = lcid;
1382 cmd.liid = liid;
1383
1384 glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
1385 srcu_read_unlock(&einfo->use_ref, rcu_id);
1386}
1387
1388/**
1389 * tx_cmd_rx_intent_req() - Convert an rx intent request cmd to wire format and
1390 * transmit
1391 * @if_ptr: The transport to transmit on.
1392 * @lcid: The local channel id to encode.
1393 * @size: The requested intent size to encode.
1394 *
1395 * Return: 0 on success or standard Linux error code.
1396 */
1397static int tx_cmd_rx_intent_req(struct glink_transport_if *if_ptr,
1398 uint32_t lcid, size_t size)
1399{
1400 struct command {
1401 uint16_t id;
1402 uint16_t lcid;
1403 uint32_t size;
1404 uint64_t reserved;
1405 };
1406 struct command cmd;
1407 struct edge_info *einfo;
1408 int rcu_id;
1409
1410 if (size > UINT_MAX) {
1411 pr_err("%s: size %zu is too large to encode\n", __func__, size);
1412 return -EMSGSIZE;
1413 }
1414
1415 memset(&cmd, 0, sizeof(cmd));
1416 einfo = container_of(if_ptr, struct edge_info, xprt_if);
1417
1418 rcu_id = srcu_read_lock(&einfo->use_ref);
1419 if (einfo->in_ssr) {
1420 srcu_read_unlock(&einfo->use_ref, rcu_id);
1421 return -EFAULT;
1422 }
1423
1424 cmd.id = RX_INTENT_REQ_CMD,
1425 cmd.lcid = lcid;
1426 cmd.size = size;
1427
1428 glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
1429
1430 srcu_read_unlock(&einfo->use_ref, rcu_id);
1431 return 0;
1432}
1433
1434/**
1435 * tx_cmd_rx_intent_req_ack() - Convert an rx intent request ack cmd to wire
1436 * format and transmit
1437 * @if_ptr: The transport to transmit on.
1438 * @lcid: The local channel id to encode.
1439 * @granted: The request response to encode.
1440 *
1441 * Return: 0 on success or standard Linux error code.
1442 */
1443static int tx_cmd_remote_rx_intent_req_ack(struct glink_transport_if *if_ptr,
1444 uint32_t lcid, bool granted)
1445{
1446 struct command {
1447 uint16_t id;
1448 uint16_t lcid;
1449 uint32_t response;
1450 uint64_t reserved;
1451 };
1452 struct command cmd;
1453 struct edge_info *einfo;
1454 int rcu_id;
1455
1456 memset(&cmd, 0, sizeof(cmd));
1457 einfo = container_of(if_ptr, struct edge_info, xprt_if);
1458
1459 rcu_id = srcu_read_lock(&einfo->use_ref);
1460 if (einfo->in_ssr) {
1461 srcu_read_unlock(&einfo->use_ref, rcu_id);
1462 return -EFAULT;
1463 }
1464
1465 cmd.id = RX_INTENT_REQ_ACK_CMD,
1466 cmd.lcid = lcid;
1467 if (granted)
1468 cmd.response = 1;
1469 else
1470 cmd.response = 0;
1471
1472 glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
1473
1474 srcu_read_unlock(&einfo->use_ref, rcu_id);
1475 return 0;
1476}
1477
1478/**
1479 * tx_cmd_set_sigs() - Convert a signals ack cmd to wire format and transmit
1480 * @if_ptr: The transport to transmit on.
1481 * @lcid: The local channel id to encode.
1482 * @sigs: The signals to encode.
1483 *
1484 * Return: 0 on success or standard Linux error code.
1485 */
1486static int tx_cmd_set_sigs(struct glink_transport_if *if_ptr, uint32_t lcid,
1487 uint32_t sigs)
1488{
1489 struct command {
1490 uint16_t id;
1491 uint16_t lcid;
1492 uint32_t sigs;
1493 uint64_t reserved;
1494 };
1495 struct command cmd;
1496 struct edge_info *einfo;
1497 int rcu_id;
1498
1499 memset(&cmd, 0, sizeof(cmd));
1500 einfo = container_of(if_ptr, struct edge_info, xprt_if);
1501
1502 rcu_id = srcu_read_lock(&einfo->use_ref);
1503 if (einfo->in_ssr) {
1504 srcu_read_unlock(&einfo->use_ref, rcu_id);
1505 return -EFAULT;
1506 }
1507
1508 cmd.id = SIGNALS_CMD,
1509 cmd.lcid = lcid;
1510 cmd.sigs = sigs;
1511
1512 glink_spi_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
1513
1514 srcu_read_unlock(&einfo->use_ref, rcu_id);
1515 return 0;
1516}
1517
1518/**
1519 * tx_data() - convert a data/tracer_pkt to wire format and transmit
1520 * @if_ptr: The transport to transmit on.
1521 * @cmd_id: The command ID to transmit.
1522 * @lcid: The local channel id to encode.
1523 * @pctx: The data to encode.
1524 *
1525 * Return: Number of bytes written or standard Linux error code.
1526 */
1527static int tx_data(struct glink_transport_if *if_ptr, uint16_t cmd_id,
1528 uint32_t lcid, struct glink_core_tx_pkt *pctx)
1529{
1530 struct command {
1531 uint16_t id;
1532 uint16_t lcid;
1533 uint32_t riid;
1534 uint64_t reserved;
1535 uint32_t size;
1536 uint32_t size_left;
1537 uint64_t addr;
1538 };
1539 struct command cmd;
1540 struct edge_info *einfo;
1541 uint32_t size;
1542 void *data_start, *dst = NULL;
1543 size_t tx_size = 0;
1544 int rcu_id;
1545
1546 if (pctx->size < pctx->size_remaining) {
1547 GLINK_ERR("%s: size remaining exceeds size. Resetting.\n",
1548 __func__);
1549 pctx->size_remaining = pctx->size;
1550 }
1551 if (!pctx->size_remaining)
1552 return 0;
1553
1554 memset(&cmd, 0, sizeof(cmd));
1555 einfo = container_of(if_ptr, struct edge_info, xprt_if);
1556
1557 rcu_id = srcu_read_lock(&einfo->use_ref);
1558 if (einfo->in_ssr) {
1559 srcu_read_unlock(&einfo->use_ref, rcu_id);
1560 return -EFAULT;
1561 }
1562
1563 if (cmd_id == TX_DATA_CMD) {
1564 if (pctx->size_remaining == pctx->size)
1565 cmd.id = TX_DATA_CMD;
1566 else
1567 cmd.id = TX_DATA_CONT_CMD;
1568 } else {
1569 if (pctx->size_remaining == pctx->size)
1570 cmd.id = TRACER_PKT_CMD;
1571 else
1572 cmd.id = TRACER_PKT_CONT_CMD;
1573 }
1574 cmd.lcid = lcid;
1575 cmd.riid = pctx->riid;
1576 data_start = get_tx_vaddr(pctx, pctx->size - pctx->size_remaining,
1577 &tx_size);
1578 if (unlikely(!data_start)) {
1579 GLINK_ERR("%s: invalid data_start\n", __func__);
1580 srcu_read_unlock(&einfo->use_ref, rcu_id);
1581 return -EINVAL;
1582 }
1583 if (tx_size & (XPRT_ALIGNMENT - 1))
1584 tx_size = ALIGN(tx_size - SHORT_PKT_SIZE, XPRT_ALIGNMENT);
1585 if (likely(pctx->cookie))
1586 dst = pctx->cookie + (pctx->size - pctx->size_remaining);
1587
1588 mutex_lock(&einfo->write_lock);
1589 size = glink_spi_xprt_write_avail(einfo);
1590 /* Need enough space to write the command */
1591 if (size <= sizeof(cmd)) {
1592 einfo->tx_resume_needed = true;
1593 mutex_unlock(&einfo->write_lock);
1594 srcu_read_unlock(&einfo->use_ref, rcu_id);
1595 return -EAGAIN;
1596 }
1597 cmd.addr = 0;
1598 cmd.size = tx_size;
1599 pctx->size_remaining -= tx_size;
1600 cmd.size_left = pctx->size_remaining;
1601 if (cmd.id == TRACER_PKT_CMD)
1602 tracer_pkt_log_event((void *)(pctx->data), GLINK_XPRT_TX);
1603
1604 if (!strcmp(einfo->xprt_cfg.edge, "wdsp"))
1605 wdsp_resume(&einfo->cmpnt);
1606 glink_spi_xprt_tx_data(einfo, data_start, dst, tx_size);
1607 glink_spi_xprt_tx_cmd_safe(einfo, &cmd, sizeof(cmd));
1608 GLINK_DBG("%s %s: lcid[%u] riid[%u] cmd[%d], size[%d], size_left[%d]\n",
1609 "<SPI>", __func__, cmd.lcid, cmd.riid, cmd.id, cmd.size,
1610 cmd.size_left);
1611 mutex_unlock(&einfo->write_lock);
1612 srcu_read_unlock(&einfo->use_ref, rcu_id);
1613 return cmd.size;
1614}
1615
1616/**
1617 * tx_short_data() - Tansmit a short packet in band along with command
1618 * @if_ptr: The transport to transmit on.
1619 * @cmd_id: The command ID to transmit.
1620 * @lcid: The local channel id to encode.
1621 * @pctx: The data to encode.
1622 *
1623 * Return: Number of bytes written or standard Linux error code.
1624 */
1625static int tx_short_data(struct glink_transport_if *if_ptr,
1626 uint32_t lcid, struct glink_core_tx_pkt *pctx)
1627{
1628 struct command {
1629 uint16_t id;
1630 uint16_t lcid;
1631 uint32_t riid;
1632 uint32_t size;
1633 uint32_t size_left;
1634 unsigned char data[SHORT_PKT_SIZE];
1635 };
1636 struct command cmd;
1637 struct edge_info *einfo;
1638 uint32_t size;
1639 void *data_start;
1640 size_t tx_size = 0;
1641 int rcu_id;
1642
1643 if (pctx->size < pctx->size_remaining) {
1644 GLINK_ERR("%s: size remaining exceeds size. Resetting.\n",
1645 __func__);
1646 pctx->size_remaining = pctx->size;
1647 }
1648 if (!pctx->size_remaining)
1649 return 0;
1650
1651 memset(&cmd, 0, sizeof(cmd));
1652 einfo = container_of(if_ptr, struct edge_info, xprt_if);
1653
1654 rcu_id = srcu_read_lock(&einfo->use_ref);
1655 if (einfo->in_ssr) {
1656 srcu_read_unlock(&einfo->use_ref, rcu_id);
1657 return -EFAULT;
1658 }
1659
1660 cmd.id = TX_SHORT_DATA_CMD;
1661 cmd.lcid = lcid;
1662 cmd.riid = pctx->riid;
1663 data_start = get_tx_vaddr(pctx, pctx->size - pctx->size_remaining,
1664 &tx_size);
1665 if (unlikely(!data_start || tx_size > SHORT_PKT_SIZE)) {
1666 GLINK_ERR("%s: invalid data_start %p or tx_size %zu\n",
1667 __func__, data_start, tx_size);
1668 srcu_read_unlock(&einfo->use_ref, rcu_id);
1669 return -EINVAL;
1670 }
1671
1672 mutex_lock(&einfo->write_lock);
1673 size = glink_spi_xprt_write_avail(einfo);
1674 /* Need enough space to write the command */
1675 if (size <= sizeof(cmd)) {
1676 einfo->tx_resume_needed = true;
1677 mutex_unlock(&einfo->write_lock);
1678 srcu_read_unlock(&einfo->use_ref, rcu_id);
1679 return -EAGAIN;
1680 }
1681 cmd.size = tx_size;
1682 pctx->size_remaining -= tx_size;
1683 cmd.size_left = pctx->size_remaining;
1684 memcpy(cmd.data, data_start, tx_size);
1685 if (!strcmp(einfo->xprt_cfg.edge, "wdsp"))
1686 wdsp_resume(&einfo->cmpnt);
1687 glink_spi_xprt_tx_cmd_safe(einfo, &cmd, sizeof(cmd));
1688 GLINK_DBG("%s %s: lcid[%u] riid[%u] cmd[%d], size[%d], size_left[%d]\n",
1689 "<SPI>", __func__, cmd.lcid, cmd.riid, cmd.id, cmd.size,
1690 cmd.size_left);
1691 mutex_unlock(&einfo->write_lock);
1692 srcu_read_unlock(&einfo->use_ref, rcu_id);
1693 return cmd.size;
1694}
1695
1696/**
1697 * tx() - convert a data transmit cmd to wire format and transmit
1698 * @if_ptr: The transport to transmit on.
1699 * @lcid: The local channel id to encode.
1700 * @pctx: The data to encode.
1701 *
1702 * Return: Number of bytes written or standard Linux error code.
1703 */
1704static int tx(struct glink_transport_if *if_ptr, uint32_t lcid,
1705 struct glink_core_tx_pkt *pctx)
1706{
1707 if (pctx->size_remaining <= SHORT_PKT_SIZE)
1708 return tx_short_data(if_ptr, lcid, pctx);
1709 return tx_data(if_ptr, TX_DATA_CMD, lcid, pctx);
1710}
1711
1712/**
1713 * tx_cmd_tracer_pkt() - convert a tracer packet cmd to wire format and transmit
1714 * @if_ptr: The transport to transmit on.
1715 * @lcid: The local channel id to encode.
1716 * @pctx: The data to encode.
1717 *
1718 * Return: Number of bytes written or standard Linux error code.
1719 */
1720static int tx_cmd_tracer_pkt(struct glink_transport_if *if_ptr, uint32_t lcid,
1721 struct glink_core_tx_pkt *pctx)
1722{
1723 return tx_data(if_ptr, TRACER_PKT_CMD, lcid, pctx);
1724}
1725
1726/**
1727 * int wait_link_down() - Check status of read/write indices
1728 * @if_ptr: The transport to check
1729 *
1730 * Return: 1 if indices are all zero, 0 otherwise
1731 */
1732static int wait_link_down(struct glink_transport_if *if_ptr)
1733{
1734 return 0;
1735}
1736
1737/**
1738 * get_power_vote_ramp_time() - Get the ramp time required for the power
1739 * votes to be applied
1740 * @if_ptr: The transport interface on which power voting is requested.
1741 * @state: The power state for which ramp time is required.
1742 *
1743 * Return: The ramp time specific to the power state, standard error otherwise.
1744 */
1745static unsigned long get_power_vote_ramp_time(
1746 struct glink_transport_if *if_ptr, uint32_t state)
1747{
1748 return 0;
1749}
1750
1751/**
1752 * power_vote() - Update the power votes to meet qos requirement
1753 * @if_ptr: The transport interface on which power voting is requested.
1754 * @state: The power state for which the voting should be done.
1755 *
1756 * Return: 0 on Success, standard error otherwise.
1757 */
1758static int power_vote(struct glink_transport_if *if_ptr, uint32_t state)
1759{
1760 unsigned long flags;
1761 struct edge_info *einfo;
1762
1763 einfo = container_of(if_ptr, struct edge_info, xprt_if);
1764 spin_lock_irqsave(&einfo->activity_lock, flags);
1765 einfo->activity_flag |= ACTIVE_TX;
1766 spin_unlock_irqrestore(&einfo->activity_lock, flags);
1767 return 0;
1768}
1769
1770/**
1771 * power_unvote() - Remove the all the power votes
1772 * @if_ptr: The transport interface on which power voting is requested.
1773 *
1774 * Return: 0 on Success, standard error otherwise.
1775 */
1776static int power_unvote(struct glink_transport_if *if_ptr)
1777{
1778 unsigned long flags;
1779 struct edge_info *einfo;
1780
1781 einfo = container_of(if_ptr, struct edge_info, xprt_if);
1782 spin_lock_irqsave(&einfo->activity_lock, flags);
1783 einfo->activity_flag &= ~ACTIVE_TX;
1784 spin_unlock_irqrestore(&einfo->activity_lock, flags);
1785 return 0;
1786}
1787
1788static int glink_wdsp_cmpnt_init(struct device *dev, void *priv_data)
1789{
1790 return 0;
1791}
1792
1793static int glink_wdsp_cmpnt_deinit(struct device *dev, void *priv_data)
1794{
1795 return 0;
1796}
1797
1798static int glink_wdsp_cmpnt_event_handler(struct device *dev,
1799 void *priv_data, enum wdsp_event_type event, void *data)
1800{
1801 struct edge_info *einfo = dev_get_drvdata(dev);
1802 struct glink_cmpnt *cmpnt = &einfo->cmpnt;
Chris Lewbb58f022017-06-27 16:54:11 -07001803 int rc = -EINVAL;
Chris Lewfa6135e2016-08-01 13:29:46 -07001804
1805 switch (event) {
1806 case WDSP_EVENT_PRE_BOOTUP:
1807 if (cmpnt && cmpnt->master_dev &&
1808 cmpnt->master_ops &&
Chris Lewbb58f022017-06-27 16:54:11 -07001809 cmpnt->master_ops->get_devops_for_cmpnt)
1810 rc = cmpnt->master_ops->get_devops_for_cmpnt(
1811 cmpnt->master_dev, WDSP_CMPNT_TRANSPORT,
1812 &einfo->spi_ops);
Chris Lewfa6135e2016-08-01 13:29:46 -07001813
Chris Lewbb58f022017-06-27 16:54:11 -07001814 if (rc)
Chris Lewfa6135e2016-08-01 13:29:46 -07001815 dev_err(dev, "%s: Failed to get transport device\n",
1816 __func__);
Chris Lewfa6135e2016-08-01 13:29:46 -07001817 break;
Karthikeyan Ramasubramaniane03039d2016-09-26 17:30:08 -06001818 case WDSP_EVENT_POST_BOOTUP:
1819 einfo->in_ssr = false;
1820 synchronize_srcu(&einfo->use_ref);
1821 /* No break here to trigger fake rx_worker */
Chris Lewfa6135e2016-08-01 13:29:46 -07001822 case WDSP_EVENT_IPC1_INTR:
Chris Lew4039ef92017-01-31 16:16:20 -08001823 kthread_queue_work(&einfo->kworker, &einfo->kwork);
Chris Lewfa6135e2016-08-01 13:29:46 -07001824 break;
Karthikeyan Ramasubramaniane03039d2016-09-26 17:30:08 -06001825 case WDSP_EVENT_PRE_SHUTDOWN:
1826 ssr(&einfo->xprt_if);
1827 break;
Chris Lewfa6135e2016-08-01 13:29:46 -07001828 default:
1829 pr_debug("%s: unhandled event %d", __func__, event);
1830 break;
1831 }
1832
1833 return 0;
1834}
1835
1836/* glink_wdsp_cmpnt_ops - Callback operations registered wtih WDSP framework */
1837static struct wdsp_cmpnt_ops glink_wdsp_cmpnt_ops = {
1838 .init = glink_wdsp_cmpnt_init,
1839 .deinit = glink_wdsp_cmpnt_deinit,
1840 .event_handler = glink_wdsp_cmpnt_event_handler,
1841};
1842
1843static int glink_component_bind(struct device *dev, struct device *master,
1844 void *data)
1845{
1846 struct edge_info *einfo = dev_get_drvdata(dev);
1847 struct glink_cmpnt *cmpnt = &einfo->cmpnt;
1848 int ret = 0;
1849
1850 cmpnt->master_dev = master;
1851 cmpnt->master_ops = data;
1852
1853 if (cmpnt->master_ops && cmpnt->master_ops->register_cmpnt_ops)
1854 ret = cmpnt->master_ops->register_cmpnt_ops(master, dev, einfo,
1855 &glink_wdsp_cmpnt_ops);
1856 else
1857 ret = -EINVAL;
1858
1859 if (ret)
1860 dev_err(dev, "%s: register_cmpnt_ops failed, err = %d\n",
1861 __func__, ret);
1862 return ret;
1863}
1864
1865static void glink_component_unbind(struct device *dev, struct device *master,
1866 void *data)
1867{
1868 struct edge_info *einfo = dev_get_drvdata(dev);
1869 struct glink_cmpnt *cmpnt = &einfo->cmpnt;
1870
1871 cmpnt->master_dev = NULL;
1872 cmpnt->master_ops = NULL;
1873}
1874
1875static const struct component_ops glink_component_ops = {
1876 .bind = glink_component_bind,
1877 .unbind = glink_component_unbind,
1878};
1879
1880/**
1881 * init_xprt_if() - Initialize the xprt_if for an edge
1882 * @einfo: The edge to initialize.
1883 */
1884static void init_xprt_if(struct edge_info *einfo)
1885{
1886 einfo->xprt_if.tx_cmd_version = tx_cmd_version;
1887 einfo->xprt_if.tx_cmd_version_ack = tx_cmd_version_ack;
1888 einfo->xprt_if.set_version = set_version;
1889 einfo->xprt_if.tx_cmd_ch_open = tx_cmd_ch_open;
1890 einfo->xprt_if.tx_cmd_ch_close = tx_cmd_ch_close;
1891 einfo->xprt_if.tx_cmd_ch_remote_open_ack = tx_cmd_ch_remote_open_ack;
1892 einfo->xprt_if.tx_cmd_ch_remote_close_ack = tx_cmd_ch_remote_close_ack;
1893 einfo->xprt_if.ssr = ssr;
1894 einfo->xprt_if.allocate_rx_intent = allocate_rx_intent;
1895 einfo->xprt_if.deallocate_rx_intent = deallocate_rx_intent;
1896 einfo->xprt_if.tx_cmd_local_rx_intent = tx_cmd_local_rx_intent;
1897 einfo->xprt_if.tx_cmd_local_rx_done = tx_cmd_local_rx_done;
1898 einfo->xprt_if.tx = tx;
1899 einfo->xprt_if.tx_cmd_rx_intent_req = tx_cmd_rx_intent_req;
1900 einfo->xprt_if.tx_cmd_remote_rx_intent_req_ack =
1901 tx_cmd_remote_rx_intent_req_ack;
1902 einfo->xprt_if.tx_cmd_set_sigs = tx_cmd_set_sigs;
1903 einfo->xprt_if.wait_link_down = wait_link_down;
1904 einfo->xprt_if.tx_cmd_tracer_pkt = tx_cmd_tracer_pkt;
1905 einfo->xprt_if.get_power_vote_ramp_time = get_power_vote_ramp_time;
1906 einfo->xprt_if.power_vote = power_vote;
1907 einfo->xprt_if.power_unvote = power_unvote;
1908}
1909
1910/**
1911 * init_xprt_cfg() - Initialize the xprt_cfg for an edge
1912 * @einfo: The edge to initialize.
1913 * @name: The name of the remote side this edge communicates to.
1914 */
1915static void init_xprt_cfg(struct edge_info *einfo, const char *name)
1916{
1917 einfo->xprt_cfg.name = XPRT_NAME;
1918 einfo->xprt_cfg.edge = name;
1919 einfo->xprt_cfg.versions = versions;
1920 einfo->xprt_cfg.versions_entries = ARRAY_SIZE(versions);
1921 einfo->xprt_cfg.max_cid = SZ_64K;
1922 einfo->xprt_cfg.max_iid = SZ_2G;
1923}
1924
1925/**
1926 * parse_qos_dt_params() - Parse the power states from DT
1927 * @dev: Reference to the platform device for a specific edge.
1928 * @einfo: Edge information for the edge probe function is called.
1929 *
1930 * Return: 0 on success, standard error code otherwise.
1931 */
1932static int parse_qos_dt_params(struct device_node *node,
1933 struct edge_info *einfo)
1934{
1935 int rc;
1936 int i;
1937 char *key;
1938 uint32_t *arr32;
1939 uint32_t num_states;
1940
1941 key = "qcom,ramp-time";
1942 if (!of_find_property(node, key, &num_states))
1943 return -ENODEV;
1944
1945 num_states /= sizeof(uint32_t);
1946
1947 einfo->num_pw_states = num_states;
1948
1949 arr32 = kmalloc_array(num_states, sizeof(uint32_t), GFP_KERNEL);
1950 if (!arr32)
1951 return -ENOMEM;
1952
1953 einfo->ramp_time_us = kmalloc_array(num_states, sizeof(unsigned long),
1954 GFP_KERNEL);
1955 if (!einfo->ramp_time_us) {
1956 rc = -ENOMEM;
1957 goto mem_alloc_fail;
1958 }
1959
1960 rc = of_property_read_u32_array(node, key, arr32, num_states);
1961 if (rc) {
1962 rc = -ENODEV;
1963 goto invalid_key;
1964 }
1965 for (i = 0; i < num_states; i++)
1966 einfo->ramp_time_us[i] = arr32[i];
1967
1968 kfree(arr32);
1969 return 0;
1970
1971invalid_key:
1972 kfree(einfo->ramp_time_us);
1973mem_alloc_fail:
1974 kfree(arr32);
1975 return rc;
1976}
1977
1978/**
1979 * parse_qos_dt_params() - Parse any remote FIFO configuration
1980 * @node: Reference to the platform device for a specific edge.
1981 * @einfo: Edge information for the edge probe function is called.
1982 *
1983 * Return: 0 on success, standard error code otherwise.
1984 */
1985static int parse_remote_fifo_cfg(struct device_node *node,
1986 struct edge_info *einfo)
1987{
1988 int rc;
1989 char *key;
1990
1991 key = "qcom,out-read-idx-reg";
1992 rc = of_property_read_u32(node, key, &einfo->tx_fifo_read_reg_addr);
1993 if (rc)
1994 goto key_error;
1995
1996 key = "qcom,out-write-idx-reg";
1997 rc = of_property_read_u32(node, key, &einfo->tx_fifo_write_reg_addr);
1998 if (rc)
1999 goto key_error;
2000
2001 key = "qcom,in-read-idx-reg";
2002 rc = of_property_read_u32(node, key, &einfo->rx_fifo_read_reg_addr);
2003 if (rc)
2004 goto key_error;
2005
2006 key = "qcom,in-write-idx-reg";
2007 rc = of_property_read_u32(node, key, &einfo->rx_fifo_write_reg_addr);
2008 if (rc)
2009 goto key_error;
2010 return 0;
2011
2012key_error:
2013 pr_err("%s: Error %d parsing key %s\n", __func__, rc, key);
2014 return rc;
2015}
2016
2017static int glink_spi_probe(struct platform_device *pdev)
2018{
2019 struct device_node *node;
2020 struct device_node *phandle_node;
2021 struct edge_info *einfo;
2022 int rc;
2023 char *key;
2024 const char *subsys_name;
2025 unsigned long flags;
2026
2027 node = pdev->dev.of_node;
2028
2029 einfo = kzalloc(sizeof(*einfo), GFP_KERNEL);
2030 if (!einfo) {
2031 rc = -ENOMEM;
2032 goto edge_info_alloc_fail;
2033 }
2034
2035 key = "label";
2036 subsys_name = of_get_property(node, key, NULL);
2037 if (!subsys_name) {
2038 pr_err("%s: missing key %s\n", __func__, key);
2039 rc = -ENODEV;
2040 goto missing_key;
2041 }
2042 strlcpy(einfo->subsys_name, subsys_name, sizeof(einfo->subsys_name));
2043
2044 init_xprt_cfg(einfo, subsys_name);
2045 init_xprt_if(einfo);
2046
Chris Lewfa6135e2016-08-01 13:29:46 -07002047 einfo->fifo_size = DEFAULT_FIFO_SIZE;
Chris Lew4039ef92017-01-31 16:16:20 -08002048 kthread_init_work(&einfo->kwork, rx_worker);
2049 kthread_init_worker(&einfo->kworker);
Chris Lewfa6135e2016-08-01 13:29:46 -07002050 init_srcu_struct(&einfo->use_ref);
2051 mutex_init(&einfo->write_lock);
2052 init_waitqueue_head(&einfo->tx_blocked_queue);
2053 spin_lock_init(&einfo->activity_lock);
2054
2055 spin_lock_irqsave(&edge_infos_lock, flags);
2056 list_add_tail(&einfo->list, &edge_infos);
2057 spin_unlock_irqrestore(&edge_infos_lock, flags);
2058
2059 einfo->task = kthread_run(kthread_worker_fn, &einfo->kworker,
2060 "spi_%s", subsys_name);
2061 if (IS_ERR(einfo->task)) {
2062 rc = PTR_ERR(einfo->task);
2063 pr_err("%s: kthread run failed %d\n", __func__, rc);
2064 goto kthread_fail;
2065 }
2066
2067 key = "qcom,remote-fifo-config";
2068 phandle_node = of_parse_phandle(node, key, 0);
2069 if (phandle_node)
2070 parse_remote_fifo_cfg(phandle_node, einfo);
2071
2072 key = "qcom,qos-config";
2073 phandle_node = of_parse_phandle(node, key, 0);
2074 if (phandle_node && !(of_get_glink_core_qos_cfg(phandle_node,
2075 &einfo->xprt_cfg)))
2076 parse_qos_dt_params(node, einfo);
2077
2078 rc = glink_core_register_transport(&einfo->xprt_if, &einfo->xprt_cfg);
2079 if (rc == -EPROBE_DEFER)
2080 goto reg_xprt_fail;
2081 if (rc) {
2082 pr_err("%s: glink core register transport failed: %d\n",
2083 __func__, rc);
2084 goto reg_xprt_fail;
2085 }
2086
2087 dev_set_drvdata(&pdev->dev, einfo);
2088 if (!strcmp(einfo->xprt_cfg.edge, "wdsp")) {
2089 rc = component_add(&pdev->dev, &glink_component_ops);
2090 if (rc) {
2091 pr_err("%s: component_add failed, err = %d\n",
2092 __func__, rc);
2093 rc = -ENODEV;
2094 goto reg_cmpnt_fail;
2095 }
2096 }
2097 return 0;
2098
2099reg_cmpnt_fail:
2100 dev_set_drvdata(&pdev->dev, NULL);
2101 glink_core_unregister_transport(&einfo->xprt_if);
2102reg_xprt_fail:
Chris Lew4039ef92017-01-31 16:16:20 -08002103 kthread_flush_worker(&einfo->kworker);
Chris Lewfa6135e2016-08-01 13:29:46 -07002104 kthread_stop(einfo->task);
2105 einfo->task = NULL;
2106kthread_fail:
2107 spin_lock_irqsave(&edge_infos_lock, flags);
2108 list_del(&einfo->list);
2109 spin_unlock_irqrestore(&edge_infos_lock, flags);
2110missing_key:
2111 kfree(einfo);
2112edge_info_alloc_fail:
2113 return rc;
2114}
2115
2116static int glink_spi_remove(struct platform_device *pdev)
2117{
2118 struct edge_info *einfo;
2119 unsigned long flags;
2120
2121 einfo = (struct edge_info *)dev_get_drvdata(&pdev->dev);
2122 glink_core_unregister_transport(&einfo->xprt_if);
Chris Lew4039ef92017-01-31 16:16:20 -08002123 kthread_flush_worker(&einfo->kworker);
Chris Lewfa6135e2016-08-01 13:29:46 -07002124 kthread_stop(einfo->task);
2125 einfo->task = NULL;
2126 spin_lock_irqsave(&edge_infos_lock, flags);
2127 list_del(&einfo->list);
2128 spin_unlock_irqrestore(&edge_infos_lock, flags);
2129 kfree(einfo);
2130 return 0;
2131}
2132
2133static int glink_spi_resume(struct platform_device *pdev)
2134{
2135 return 0;
2136}
2137
2138static int glink_spi_suspend(struct platform_device *pdev,
2139 pm_message_t state)
2140{
2141 unsigned long flags;
2142 struct edge_info *einfo;
2143 bool suspend;
2144 int rc = -EBUSY;
2145
2146 einfo = (struct edge_info *)dev_get_drvdata(&pdev->dev);
2147 if (strcmp(einfo->xprt_cfg.edge, "wdsp"))
2148 return 0;
2149
2150 spin_lock_irqsave(&einfo->activity_lock, flags);
2151 suspend = !(einfo->activity_flag);
2152 spin_unlock_irqrestore(&einfo->activity_lock, flags);
2153 if (suspend)
2154 rc = wdsp_suspend(&einfo->cmpnt);
2155 if (rc < 0)
2156 pr_err("%s: Could not suspend activity_flag %d, rc %d\n",
2157 __func__, einfo->activity_flag, rc);
2158 return rc;
2159}
2160
2161static const struct of_device_id spi_match_table[] = {
2162 { .compatible = "qcom,glink-spi-xprt" },
2163 {},
2164};
2165
2166static struct platform_driver glink_spi_driver = {
2167 .probe = glink_spi_probe,
2168 .remove = glink_spi_remove,
2169 .resume = glink_spi_resume,
2170 .suspend = glink_spi_suspend,
2171 .driver = {
2172 .name = "msm_glink_spi_xprt",
2173 .owner = THIS_MODULE,
2174 .of_match_table = spi_match_table,
2175 },
2176};
2177
2178static int __init glink_spi_xprt_init(void)
2179{
2180 int rc;
2181
2182 rc = platform_driver_register(&glink_spi_driver);
2183 if (rc)
2184 pr_err("%s: glink_spi register failed %d\n", __func__, rc);
2185
2186 return rc;
2187}
2188module_init(glink_spi_xprt_init);
2189
2190static void __exit glink_spi_xprt_exit(void)
2191{
2192 platform_driver_unregister(&glink_spi_driver);
2193}
2194module_exit(glink_spi_xprt_exit);
2195
2196MODULE_DESCRIPTION("MSM G-Link SPI Transport");
2197MODULE_LICENSE("GPL v2");