Lines Matching refs:channel

255 #define GET_RX_CHANNEL_FLAG(channel, param)				     \  argument
257 BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u8)); \
258 channel->info_word ? \
259 le32_to_cpu(channel->info_word->rx.param) : \
260 channel->info->rx.param; \
263 #define GET_RX_CHANNEL_INFO(channel, param) \ argument
265 BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u32)); \
266 le32_to_cpu(channel->info_word ? \
267 channel->info_word->rx.param : \
268 channel->info->rx.param); \
271 #define SET_RX_CHANNEL_FLAG(channel, param, value) \ argument
273 BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u8)); \
274 if (channel->info_word) \
275 channel->info_word->rx.param = cpu_to_le32(value); \
277 channel->info->rx.param = value; \
280 #define SET_RX_CHANNEL_INFO(channel, param, value) \ argument
282 BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u32)); \
283 if (channel->info_word) \
284 channel->info_word->rx.param = cpu_to_le32(value); \
286 channel->info->rx.param = cpu_to_le32(value); \
289 #define GET_TX_CHANNEL_FLAG(channel, param) \ argument
291 BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u8)); \
292 channel->info_word ? \
293 le32_to_cpu(channel->info_word->tx.param) : \
294 channel->info->tx.param; \
297 #define GET_TX_CHANNEL_INFO(channel, param) \ argument
299 BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u32)); \
300 le32_to_cpu(channel->info_word ? \
301 channel->info_word->tx.param : \
302 channel->info->tx.param); \
305 #define SET_TX_CHANNEL_FLAG(channel, param, value) \ argument
307 BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u8)); \
308 if (channel->info_word) \
309 channel->info_word->tx.param = cpu_to_le32(value); \
311 channel->info->tx.param = value; \
314 #define SET_TX_CHANNEL_INFO(channel, param, value) \ argument
316 BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u32)); \
317 if (channel->info_word) \
318 channel->info_word->tx.param = cpu_to_le32(value); \
320 channel->info->tx.param = cpu_to_le32(value); \
350 static void qcom_smd_signal_channel(struct qcom_smd_channel *channel) in qcom_smd_signal_channel() argument
352 struct qcom_smd_edge *edge = channel->edge; in qcom_smd_signal_channel()
360 static void qcom_smd_channel_reset(struct qcom_smd_channel *channel) in qcom_smd_channel_reset() argument
362 SET_TX_CHANNEL_INFO(channel, state, SMD_CHANNEL_CLOSED); in qcom_smd_channel_reset()
363 SET_TX_CHANNEL_FLAG(channel, fDSR, 0); in qcom_smd_channel_reset()
364 SET_TX_CHANNEL_FLAG(channel, fCTS, 0); in qcom_smd_channel_reset()
365 SET_TX_CHANNEL_FLAG(channel, fCD, 0); in qcom_smd_channel_reset()
366 SET_TX_CHANNEL_FLAG(channel, fRI, 0); in qcom_smd_channel_reset()
367 SET_TX_CHANNEL_FLAG(channel, fHEAD, 0); in qcom_smd_channel_reset()
368 SET_TX_CHANNEL_FLAG(channel, fTAIL, 0); in qcom_smd_channel_reset()
369 SET_TX_CHANNEL_FLAG(channel, fSTATE, 1); in qcom_smd_channel_reset()
370 SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 1); in qcom_smd_channel_reset()
371 SET_TX_CHANNEL_INFO(channel, head, 0); in qcom_smd_channel_reset()
372 SET_TX_CHANNEL_INFO(channel, tail, 0); in qcom_smd_channel_reset()
374 qcom_smd_signal_channel(channel); in qcom_smd_channel_reset()
376 channel->state = SMD_CHANNEL_CLOSED; in qcom_smd_channel_reset()
377 channel->pkt_size = 0; in qcom_smd_channel_reset()
383 static size_t qcom_smd_channel_get_rx_avail(struct qcom_smd_channel *channel) in qcom_smd_channel_get_rx_avail() argument
388 head = GET_RX_CHANNEL_INFO(channel, head); in qcom_smd_channel_get_rx_avail()
389 tail = GET_RX_CHANNEL_INFO(channel, tail); in qcom_smd_channel_get_rx_avail()
391 return (head - tail) & (channel->fifo_size - 1); in qcom_smd_channel_get_rx_avail()
397 static void qcom_smd_channel_set_state(struct qcom_smd_channel *channel, in qcom_smd_channel_set_state() argument
400 struct qcom_smd_edge *edge = channel->edge; in qcom_smd_channel_set_state()
403 if (channel->state == state) in qcom_smd_channel_set_state()
406 dev_dbg(edge->smd->dev, "set_state(%s, %d)\n", channel->name, state); in qcom_smd_channel_set_state()
408 SET_TX_CHANNEL_FLAG(channel, fDSR, is_open); in qcom_smd_channel_set_state()
409 SET_TX_CHANNEL_FLAG(channel, fCTS, is_open); in qcom_smd_channel_set_state()
410 SET_TX_CHANNEL_FLAG(channel, fCD, is_open); in qcom_smd_channel_set_state()
412 SET_TX_CHANNEL_INFO(channel, state, state); in qcom_smd_channel_set_state()
413 SET_TX_CHANNEL_FLAG(channel, fSTATE, 1); in qcom_smd_channel_set_state()
415 channel->state = state; in qcom_smd_channel_set_state()
416 qcom_smd_signal_channel(channel); in qcom_smd_channel_set_state()
458 static size_t qcom_smd_channel_peek(struct qcom_smd_channel *channel, in qcom_smd_channel_peek() argument
465 word_aligned = channel->info_word; in qcom_smd_channel_peek()
466 tail = GET_RX_CHANNEL_INFO(channel, tail); in qcom_smd_channel_peek()
468 len = min_t(size_t, count, channel->fifo_size - tail); in qcom_smd_channel_peek()
471 channel->rx_fifo + tail, in qcom_smd_channel_peek()
478 channel->rx_fifo, in qcom_smd_channel_peek()
489 static void qcom_smd_channel_advance(struct qcom_smd_channel *channel, in qcom_smd_channel_advance() argument
494 tail = GET_RX_CHANNEL_INFO(channel, tail); in qcom_smd_channel_advance()
496 tail &= (channel->fifo_size - 1); in qcom_smd_channel_advance()
497 SET_RX_CHANNEL_INFO(channel, tail, tail); in qcom_smd_channel_advance()
503 static int qcom_smd_channel_recv_single(struct qcom_smd_channel *channel) in qcom_smd_channel_recv_single() argument
505 struct qcom_smd_device *qsdev = channel->qsdev; in qcom_smd_channel_recv_single()
511 if (!channel->cb) in qcom_smd_channel_recv_single()
514 tail = GET_RX_CHANNEL_INFO(channel, tail); in qcom_smd_channel_recv_single()
517 if (tail + channel->pkt_size >= channel->fifo_size) { in qcom_smd_channel_recv_single()
518 ptr = channel->bounce_buffer; in qcom_smd_channel_recv_single()
519 len = qcom_smd_channel_peek(channel, ptr, channel->pkt_size); in qcom_smd_channel_recv_single()
521 ptr = channel->rx_fifo + tail; in qcom_smd_channel_recv_single()
522 len = channel->pkt_size; in qcom_smd_channel_recv_single()
525 ret = channel->cb(qsdev, ptr, len); in qcom_smd_channel_recv_single()
530 qcom_smd_channel_advance(channel, len); in qcom_smd_channel_recv_single()
532 channel->pkt_size = 0; in qcom_smd_channel_recv_single()
540 static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel) in qcom_smd_channel_intr() argument
549 remote_state = GET_RX_CHANNEL_INFO(channel, state); in qcom_smd_channel_intr()
550 if (remote_state != channel->remote_state) { in qcom_smd_channel_intr()
551 channel->remote_state = remote_state; in qcom_smd_channel_intr()
555 SET_RX_CHANNEL_FLAG(channel, fSTATE, 0); in qcom_smd_channel_intr()
558 if (!GET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR)) in qcom_smd_channel_intr()
559 wake_up_interruptible(&channel->fblockread_event); in qcom_smd_channel_intr()
562 if (channel->state != SMD_CHANNEL_OPENED) in qcom_smd_channel_intr()
566 SET_RX_CHANNEL_FLAG(channel, fHEAD, 0); in qcom_smd_channel_intr()
570 avail = qcom_smd_channel_get_rx_avail(channel); in qcom_smd_channel_intr()
572 if (!channel->pkt_size && avail >= SMD_PACKET_HEADER_LEN) { in qcom_smd_channel_intr()
573 qcom_smd_channel_peek(channel, &pktlen, sizeof(pktlen)); in qcom_smd_channel_intr()
574 qcom_smd_channel_advance(channel, SMD_PACKET_HEADER_LEN); in qcom_smd_channel_intr()
575 channel->pkt_size = le32_to_cpu(pktlen); in qcom_smd_channel_intr()
576 } else if (channel->pkt_size && avail >= channel->pkt_size) { in qcom_smd_channel_intr()
577 ret = qcom_smd_channel_recv_single(channel); in qcom_smd_channel_intr()
586 SET_RX_CHANNEL_FLAG(channel, fTAIL, 1); in qcom_smd_channel_intr()
589 if (!GET_RX_CHANNEL_FLAG(channel, fBLOCKREADINTR)) { in qcom_smd_channel_intr()
593 qcom_smd_signal_channel(channel); in qcom_smd_channel_intr()
607 struct qcom_smd_channel *channel; in qcom_smd_edge_intr() local
615 list_for_each_entry(channel, &edge->channels, list) { in qcom_smd_edge_intr()
616 spin_lock(&channel->recv_lock); in qcom_smd_edge_intr()
617 kick_worker |= qcom_smd_channel_intr(channel); in qcom_smd_edge_intr()
618 spin_unlock(&channel->recv_lock); in qcom_smd_edge_intr()
645 static void qcom_smd_channel_resume(struct qcom_smd_channel *channel) in qcom_smd_channel_resume() argument
649 spin_lock_irqsave(&channel->recv_lock, flags); in qcom_smd_channel_resume()
650 qcom_smd_channel_intr(channel); in qcom_smd_channel_resume()
651 spin_unlock_irqrestore(&channel->recv_lock, flags); in qcom_smd_channel_resume()
657 static size_t qcom_smd_get_tx_avail(struct qcom_smd_channel *channel) in qcom_smd_get_tx_avail() argument
661 unsigned mask = channel->fifo_size - 1; in qcom_smd_get_tx_avail()
663 head = GET_TX_CHANNEL_INFO(channel, head); in qcom_smd_get_tx_avail()
664 tail = GET_TX_CHANNEL_INFO(channel, tail); in qcom_smd_get_tx_avail()
672 static int qcom_smd_write_fifo(struct qcom_smd_channel *channel, in qcom_smd_write_fifo() argument
680 word_aligned = channel->info_word; in qcom_smd_write_fifo()
681 head = GET_TX_CHANNEL_INFO(channel, head); in qcom_smd_write_fifo()
683 len = min_t(size_t, count, channel->fifo_size - head); in qcom_smd_write_fifo()
685 smd_copy_to_fifo(channel->tx_fifo + head, in qcom_smd_write_fifo()
692 smd_copy_to_fifo(channel->tx_fifo, in qcom_smd_write_fifo()
699 head &= (channel->fifo_size - 1); in qcom_smd_write_fifo()
700 SET_TX_CHANNEL_INFO(channel, head, head); in qcom_smd_write_fifo()
716 int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len) in qcom_smd_send() argument
723 if (channel->info_word && len % 4) in qcom_smd_send()
727 if (tlen >= channel->fifo_size) in qcom_smd_send()
730 ret = mutex_lock_interruptible(&channel->tx_lock); in qcom_smd_send()
734 while (qcom_smd_get_tx_avail(channel) < tlen) { in qcom_smd_send()
735 if (channel->state != SMD_CHANNEL_OPENED) { in qcom_smd_send()
740 SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 0); in qcom_smd_send()
742 ret = wait_event_interruptible(channel->fblockread_event, in qcom_smd_send()
743 qcom_smd_get_tx_avail(channel) >= tlen || in qcom_smd_send()
744 channel->state != SMD_CHANNEL_OPENED); in qcom_smd_send()
748 SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 1); in qcom_smd_send()
751 SET_TX_CHANNEL_FLAG(channel, fTAIL, 0); in qcom_smd_send()
753 qcom_smd_write_fifo(channel, hdr, sizeof(hdr)); in qcom_smd_send()
754 qcom_smd_write_fifo(channel, data, len); in qcom_smd_send()
756 SET_TX_CHANNEL_FLAG(channel, fHEAD, 1); in qcom_smd_send()
761 qcom_smd_signal_channel(channel); in qcom_smd_send()
764 mutex_unlock(&channel->tx_lock); in qcom_smd_send()
787 const char *name = qsdev->channel->name; in qcom_smd_dev_match()
810 struct qcom_smd_channel *channel = qsdev->channel; in qcom_smd_dev_probe() local
817 bb_size = min(channel->fifo_size, SZ_4K); in qcom_smd_dev_probe()
818 channel->bounce_buffer = kmalloc(bb_size, GFP_KERNEL); in qcom_smd_dev_probe()
819 if (!channel->bounce_buffer) in qcom_smd_dev_probe()
822 channel->cb = qsdrv->callback; in qcom_smd_dev_probe()
824 qcom_smd_channel_set_state(channel, SMD_CHANNEL_OPENING); in qcom_smd_dev_probe()
826 qcom_smd_channel_set_state(channel, SMD_CHANNEL_OPENED); in qcom_smd_dev_probe()
832 qcom_smd_channel_resume(channel); in qcom_smd_dev_probe()
839 channel->cb = NULL; in qcom_smd_dev_probe()
840 kfree(channel->bounce_buffer); in qcom_smd_dev_probe()
841 channel->bounce_buffer = NULL; in qcom_smd_dev_probe()
843 qcom_smd_channel_set_state(channel, SMD_CHANNEL_CLOSED); in qcom_smd_dev_probe()
857 struct qcom_smd_channel *channel = qsdev->channel; in qcom_smd_dev_remove() local
860 qcom_smd_channel_set_state(channel, SMD_CHANNEL_CLOSING); in qcom_smd_dev_remove()
865 spin_lock_irqsave(&channel->recv_lock, flags); in qcom_smd_dev_remove()
866 channel->cb = NULL; in qcom_smd_dev_remove()
867 spin_unlock_irqrestore(&channel->recv_lock, flags); in qcom_smd_dev_remove()
870 wake_up_interruptible(&channel->fblockread_event); in qcom_smd_dev_remove()
882 channel->qsdev = NULL; in qcom_smd_dev_remove()
883 kfree(channel->bounce_buffer); in qcom_smd_dev_remove()
884 channel->bounce_buffer = NULL; in qcom_smd_dev_remove()
886 qcom_smd_channel_set_state(channel, SMD_CHANNEL_CLOSED); in qcom_smd_dev_remove()
888 qcom_smd_channel_reset(channel); in qcom_smd_dev_remove()
914 const char *channel) in qcom_smd_match_channel() argument
927 if (strcmp(name, channel) == 0) in qcom_smd_match_channel()
937 static int qcom_smd_create_device(struct qcom_smd_channel *channel) in qcom_smd_create_device() argument
940 struct qcom_smd_edge *edge = channel->edge; in qcom_smd_create_device()
945 if (channel->qsdev) in qcom_smd_create_device()
948 dev_dbg(smd->dev, "registering '%s'\n", channel->name); in qcom_smd_create_device()
954 node = qcom_smd_match_channel(edge->of_node, channel->name); in qcom_smd_create_device()
957 node ? node->name : channel->name); in qcom_smd_create_device()
964 qsdev->channel = channel; in qcom_smd_create_device()
966 channel->qsdev = qsdev; in qcom_smd_create_device()
980 static void qcom_smd_destroy_device(struct qcom_smd_channel *channel) in qcom_smd_destroy_device() argument
984 BUG_ON(!channel->qsdev); in qcom_smd_destroy_device()
986 dev = &channel->qsdev->dev; in qcom_smd_destroy_device()
1023 struct qcom_smd_channel *channel; in qcom_smd_create_channel() local
1031 channel = devm_kzalloc(smd->dev, sizeof(*channel), GFP_KERNEL); in qcom_smd_create_channel()
1032 if (!channel) in qcom_smd_create_channel()
1035 channel->edge = edge; in qcom_smd_create_channel()
1036 channel->name = devm_kstrdup(smd->dev, name, GFP_KERNEL); in qcom_smd_create_channel()
1037 if (!channel->name) in qcom_smd_create_channel()
1040 mutex_init(&channel->tx_lock); in qcom_smd_create_channel()
1041 spin_lock_init(&channel->recv_lock); in qcom_smd_create_channel()
1042 init_waitqueue_head(&channel->fblockread_event); in qcom_smd_create_channel()
1055 channel->info_word = info; in qcom_smd_create_channel()
1057 channel->info = info; in qcom_smd_create_channel()
1077 channel->tx_fifo = fifo_base; in qcom_smd_create_channel()
1078 channel->rx_fifo = fifo_base + fifo_size; in qcom_smd_create_channel()
1079 channel->fifo_size = fifo_size; in qcom_smd_create_channel()
1081 qcom_smd_channel_reset(channel); in qcom_smd_create_channel()
1083 return channel; in qcom_smd_create_channel()
1086 devm_kfree(smd->dev, channel->name); in qcom_smd_create_channel()
1087 devm_kfree(smd->dev, channel); in qcom_smd_create_channel()
1101 struct qcom_smd_channel *channel; in qcom_discover_channels() local
1138 channel = qcom_smd_create_channel(edge, info_id, fifo_id, entry->name); in qcom_discover_channels()
1139 if (IS_ERR(channel)) in qcom_discover_channels()
1143 list_add(&channel->list, &edge->channels); in qcom_discover_channels()
1146 dev_dbg(smd->dev, "new channel found: '%s'\n", channel->name); in qcom_discover_channels()
1164 struct qcom_smd_channel *channel; in qcom_channel_state_worker() local
1182 list_for_each_entry(channel, &edge->channels, list) { in qcom_channel_state_worker()
1183 if (channel->state != SMD_CHANNEL_CLOSED) in qcom_channel_state_worker()
1186 remote_state = GET_RX_CHANNEL_INFO(channel, state); in qcom_channel_state_worker()
1191 qcom_smd_create_device(channel); in qcom_channel_state_worker()
1198 list_for_each_entry(channel, &edge->channels, list) { in qcom_channel_state_worker()
1199 if (channel->state != SMD_CHANNEL_OPENING && in qcom_channel_state_worker()
1200 channel->state != SMD_CHANNEL_OPENED) in qcom_channel_state_worker()
1203 remote_state = GET_RX_CHANNEL_INFO(channel, state); in qcom_channel_state_worker()
1208 qcom_smd_destroy_device(channel); in qcom_channel_state_worker()
1331 struct qcom_smd_channel *channel; in qcom_smd_remove() local
1342 list_for_each_entry(channel, &edge->channels, list) { in qcom_smd_remove()
1343 if (!channel->qsdev) in qcom_smd_remove()
1346 qcom_smd_destroy_device(channel); in qcom_smd_remove()