Lines Matching +full:channel +full:-
1 // SPDX-License-Identifier: GPL-2.0-only
66 * struct hsc_channel - hsi_char internal channel data
67 * @ch: channel number
68 * @flags: Keeps state of the channel (open/close, reading, writing)
92 * struct hsc_client_data - hsi_char internal client data
116 static void hsc_add_tail(struct hsc_channel *channel, struct hsi_msg *msg, in hsc_add_tail() argument
121 spin_lock_irqsave(&channel->lock, flags); in hsc_add_tail()
122 list_add_tail(&msg->link, queue); in hsc_add_tail()
123 spin_unlock_irqrestore(&channel->lock, flags); in hsc_add_tail()
126 static struct hsi_msg *hsc_get_first_msg(struct hsc_channel *channel, in hsc_get_first_msg() argument
132 spin_lock_irqsave(&channel->lock, flags); in hsc_get_first_msg()
138 list_del(&msg->link); in hsc_get_first_msg()
140 spin_unlock_irqrestore(&channel->lock, flags); in hsc_get_first_msg()
147 kfree(sg_virt(msg->sgt.sgl)); in hsc_msg_free()
156 list_del(&msg->link); in hsc_free_list()
161 static void hsc_reset_list(struct hsc_channel *channel, struct list_head *l) in hsc_reset_list() argument
166 spin_lock_irqsave(&channel->lock, flags); in hsc_reset_list()
168 spin_unlock_irqrestore(&channel->lock, flags); in hsc_reset_list()
186 sg_init_one(msg->sgt.sgl, buf, alloc_size); in hsc_msg_alloc()
195 static inline int hsc_msgs_alloc(struct hsc_channel *channel) in hsc_msgs_alloc() argument
204 msg->channel = channel->ch; in hsc_msgs_alloc()
205 list_add_tail(&msg->link, &channel->free_msgs_list); in hsc_msgs_alloc()
210 hsc_free_list(&channel->free_msgs_list); in hsc_msgs_alloc()
212 return -ENOMEM; in hsc_msgs_alloc()
217 return msg->sgt.sgl->length; in hsc_msg_len_get()
222 msg->sgt.sgl->length = len; in hsc_msg_len_set()
227 struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl); in hsc_rx_completed()
228 struct hsc_channel *channel = cl_data->channels + msg->channel; in hsc_rx_completed() local
230 if (test_bit(HSC_CH_READ, &channel->flags)) { in hsc_rx_completed()
231 hsc_add_tail(channel, msg, &channel->rx_msgs_queue); in hsc_rx_completed()
232 wake_up(&channel->rx_wait); in hsc_rx_completed()
234 hsc_add_tail(channel, msg, &channel->free_msgs_list); in hsc_rx_completed()
240 msg->status = HSI_STATUS_ERROR; in hsc_rx_msg_destructor()
247 struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl); in hsc_tx_completed()
248 struct hsc_channel *channel = cl_data->channels + msg->channel; in hsc_tx_completed() local
250 if (test_bit(HSC_CH_WRITE, &channel->flags)) { in hsc_tx_completed()
251 hsc_add_tail(channel, msg, &channel->tx_msgs_queue); in hsc_tx_completed()
252 wake_up(&channel->tx_wait); in hsc_tx_completed()
254 hsc_add_tail(channel, msg, &channel->free_msgs_list); in hsc_tx_completed()
260 msg->status = HSI_STATUS_ERROR; in hsc_tx_msg_destructor()
267 struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl); in hsc_break_req_destructor()
270 clear_bit(HSC_RXBREAK, &cl_data->flags); in hsc_break_req_destructor()
275 struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl); in hsc_break_received()
276 struct hsc_channel *channel = cl_data->channels; in hsc_break_received() local
280 for (i = 0; i < HSC_DEVS; i++, channel++) { in hsc_break_received()
283 if (!test_bit(HSC_CH_READ, &channel->flags)) in hsc_break_received()
285 msg2 = hsc_get_first_msg(channel, &channel->free_msgs_list); in hsc_break_received()
288 clear_bit(HSC_CH_READ, &channel->flags); in hsc_break_received()
290 msg2->status = HSI_STATUS_COMPLETED; in hsc_break_received()
291 hsc_add_tail(channel, msg2, &channel->rx_msgs_queue); in hsc_break_received()
292 wake_up(&channel->rx_wait); in hsc_break_received()
294 hsi_flush(msg->cl); in hsc_break_received()
295 ret = hsi_async_read(msg->cl, msg); in hsc_break_received()
306 if (test_and_set_bit(HSC_RXBREAK, &cl_data->flags)) in hsc_break_request()
307 return -EBUSY; in hsc_break_request()
311 clear_bit(HSC_RXBREAK, &cl_data->flags); in hsc_break_request()
312 return -ENOMEM; in hsc_break_request()
314 msg->break_frame = 1; in hsc_break_request()
315 msg->complete = hsc_break_received; in hsc_break_request()
316 msg->destructor = hsc_break_req_destructor; in hsc_break_request()
331 return -ENOMEM; in hsc_break_send()
332 msg->break_frame = 1; in hsc_break_send()
333 msg->complete = hsi_free_msg; in hsc_break_send()
334 msg->destructor = hsi_free_msg; in hsc_break_send()
347 if ((rxc->mode != HSI_MODE_STREAM) && (rxc->mode != HSI_MODE_FRAME)) in hsc_rx_set()
348 return -EINVAL; in hsc_rx_set()
349 if ((rxc->channels == 0) || (rxc->channels > HSC_DEVS)) in hsc_rx_set()
350 return -EINVAL; in hsc_rx_set()
351 if (rxc->channels & (rxc->channels - 1)) in hsc_rx_set()
352 return -EINVAL; in hsc_rx_set()
353 if ((rxc->flow != HSI_FLOW_SYNC) && (rxc->flow != HSI_FLOW_PIPE)) in hsc_rx_set()
354 return -EINVAL; in hsc_rx_set()
355 tmp = cl->rx_cfg; in hsc_rx_set()
356 cl->rx_cfg.mode = rxc->mode; in hsc_rx_set()
357 cl->rx_cfg.num_hw_channels = rxc->channels; in hsc_rx_set()
358 cl->rx_cfg.flow = rxc->flow; in hsc_rx_set()
361 cl->rx_cfg = tmp; in hsc_rx_set()
364 if (rxc->mode == HSI_MODE_FRAME) in hsc_rx_set()
372 rxc->mode = cl->rx_cfg.mode; in hsc_rx_get()
373 rxc->channels = cl->rx_cfg.num_hw_channels; in hsc_rx_get()
374 rxc->flow = cl->rx_cfg.flow; in hsc_rx_get()
382 if ((txc->mode != HSI_MODE_STREAM) && (txc->mode != HSI_MODE_FRAME)) in hsc_tx_set()
383 return -EINVAL; in hsc_tx_set()
384 if ((txc->channels == 0) || (txc->channels > HSC_DEVS)) in hsc_tx_set()
385 return -EINVAL; in hsc_tx_set()
386 if (txc->channels & (txc->channels - 1)) in hsc_tx_set()
387 return -EINVAL; in hsc_tx_set()
388 if ((txc->arb_mode != HSI_ARB_RR) && (txc->arb_mode != HSI_ARB_PRIO)) in hsc_tx_set()
389 return -EINVAL; in hsc_tx_set()
390 tmp = cl->tx_cfg; in hsc_tx_set()
391 cl->tx_cfg.mode = txc->mode; in hsc_tx_set()
392 cl->tx_cfg.num_hw_channels = txc->channels; in hsc_tx_set()
393 cl->tx_cfg.speed = txc->speed; in hsc_tx_set()
394 cl->tx_cfg.arb_mode = txc->arb_mode; in hsc_tx_set()
397 cl->tx_cfg = tmp; in hsc_tx_set()
406 txc->mode = cl->tx_cfg.mode; in hsc_tx_get()
407 txc->channels = cl->tx_cfg.num_hw_channels; in hsc_tx_get()
408 txc->speed = cl->tx_cfg.speed; in hsc_tx_get()
409 txc->arb_mode = cl->tx_cfg.arb_mode; in hsc_tx_get()
415 struct hsc_channel *channel = file->private_data; in hsc_read() local
422 return -EINVAL; in hsc_read()
425 if (channel->ch >= channel->cl->rx_cfg.num_hw_channels) in hsc_read()
426 return -ECHRNG; in hsc_read()
427 if (test_and_set_bit(HSC_CH_READ, &channel->flags)) in hsc_read()
428 return -EBUSY; in hsc_read()
429 msg = hsc_get_first_msg(channel, &channel->free_msgs_list); in hsc_read()
431 ret = -ENOSPC; in hsc_read()
435 msg->complete = hsc_rx_completed; in hsc_read()
436 msg->destructor = hsc_rx_msg_destructor; in hsc_read()
437 ret = hsi_async_read(channel->cl, msg); in hsc_read()
439 hsc_add_tail(channel, msg, &channel->free_msgs_list); in hsc_read()
443 ret = wait_event_interruptible(channel->rx_wait, in hsc_read()
444 !list_empty(&channel->rx_msgs_queue)); in hsc_read()
446 clear_bit(HSC_CH_READ, &channel->flags); in hsc_read()
447 hsi_flush(channel->cl); in hsc_read()
448 return -EINTR; in hsc_read()
451 msg = hsc_get_first_msg(channel, &channel->rx_msgs_queue); in hsc_read()
453 if (msg->status != HSI_STATUS_ERROR) { in hsc_read()
455 sg_virt(msg->sgt.sgl), hsc_msg_len_get(msg)); in hsc_read()
457 ret = -EFAULT; in hsc_read()
461 ret = -EIO; in hsc_read()
463 hsc_add_tail(channel, msg, &channel->free_msgs_list); in hsc_read()
466 clear_bit(HSC_CH_READ, &channel->flags); in hsc_read()
474 struct hsc_channel *channel = file->private_data; in hsc_write() local
479 return -EINVAL; in hsc_write()
482 if (channel->ch >= channel->cl->tx_cfg.num_hw_channels) in hsc_write()
483 return -ECHRNG; in hsc_write()
484 if (test_and_set_bit(HSC_CH_WRITE, &channel->flags)) in hsc_write()
485 return -EBUSY; in hsc_write()
486 msg = hsc_get_first_msg(channel, &channel->free_msgs_list); in hsc_write()
488 clear_bit(HSC_CH_WRITE, &channel->flags); in hsc_write()
489 return -ENOSPC; in hsc_write()
491 if (copy_from_user(sg_virt(msg->sgt.sgl), (void __user *)buf, len)) { in hsc_write()
492 ret = -EFAULT; in hsc_write()
496 msg->complete = hsc_tx_completed; in hsc_write()
497 msg->destructor = hsc_tx_msg_destructor; in hsc_write()
498 ret = hsi_async_write(channel->cl, msg); in hsc_write()
502 ret = wait_event_interruptible(channel->tx_wait, in hsc_write()
503 !list_empty(&channel->tx_msgs_queue)); in hsc_write()
505 clear_bit(HSC_CH_WRITE, &channel->flags); in hsc_write()
506 hsi_flush(channel->cl); in hsc_write()
507 return -EINTR; in hsc_write()
510 msg = hsc_get_first_msg(channel, &channel->tx_msgs_queue); in hsc_write()
512 if (msg->status == HSI_STATUS_ERROR) in hsc_write()
513 ret = -EIO; in hsc_write()
517 hsc_add_tail(channel, msg, &channel->free_msgs_list); in hsc_write()
520 clear_bit(HSC_CH_WRITE, &channel->flags); in hsc_write()
527 struct hsc_channel *channel = file->private_data; in hsc_ioctl() local
535 hsi_flush(channel->cl); in hsc_ioctl()
539 return -EFAULT; in hsc_ioctl()
541 if (test_and_set_bit(HSC_CH_WLINE, &channel->flags)) in hsc_ioctl()
542 return -EINVAL; in hsc_ioctl()
543 ret = hsi_start_tx(channel->cl); in hsc_ioctl()
545 if (!test_and_clear_bit(HSC_CH_WLINE, &channel->flags)) in hsc_ioctl()
546 return -EINVAL; in hsc_ioctl()
547 ret = hsi_stop_tx(channel->cl); in hsc_ioctl()
549 ret = -EINVAL; in hsc_ioctl()
553 return hsc_break_send(channel->cl); in hsc_ioctl()
556 return -EFAULT; in hsc_ioctl()
557 return hsc_rx_set(channel->cl, &rxc); in hsc_ioctl()
559 hsc_rx_get(channel->cl, &rxc); in hsc_ioctl()
561 return -EFAULT; in hsc_ioctl()
565 return -EFAULT; in hsc_ioctl()
566 return hsc_tx_set(channel->cl, &txc); in hsc_ioctl()
568 hsc_tx_get(channel->cl, &txc); in hsc_ioctl()
570 return -EFAULT; in hsc_ioctl()
573 return -ENOIOCTLCMD; in hsc_ioctl()
581 BUG_ON(cl_data->usecnt == 0); in __hsc_port_release()
583 if (--cl_data->usecnt == 0) { in __hsc_port_release()
584 hsi_flush(cl_data->cl); in __hsc_port_release()
585 hsi_release_port(cl_data->cl); in __hsc_port_release()
592 struct hsc_channel *channel; in hsc_open() local
597 cl_data = container_of(inode->i_cdev, struct hsc_client_data, cdev); in hsc_open()
598 mutex_lock(&cl_data->lock); in hsc_open()
599 channel = cl_data->channels + (iminor(inode) & HSC_CH_MASK); in hsc_open()
601 if (test_and_set_bit(HSC_CH_OPEN, &channel->flags)) { in hsc_open()
602 ret = -EBUSY; in hsc_open()
609 if (cl_data->usecnt == 0) { in hsc_open()
610 ret = hsi_claim_port(cl_data->cl, 0); in hsc_open()
613 hsi_setup(cl_data->cl); in hsc_open()
615 cl_data->usecnt++; in hsc_open()
617 ret = hsc_msgs_alloc(channel); in hsc_open()
623 file->private_data = channel; in hsc_open()
624 mutex_unlock(&cl_data->lock); in hsc_open()
628 mutex_unlock(&cl_data->lock); in hsc_open()
635 struct hsc_channel *channel = file->private_data; in hsc_release() local
636 struct hsc_client_data *cl_data = channel->cl_data; in hsc_release()
638 mutex_lock(&cl_data->lock); in hsc_release()
639 file->private_data = NULL; in hsc_release()
640 if (test_and_clear_bit(HSC_CH_WLINE, &channel->flags)) in hsc_release()
641 hsi_stop_tx(channel->cl); in hsc_release()
643 hsc_reset_list(channel, &channel->rx_msgs_queue); in hsc_release()
644 hsc_reset_list(channel, &channel->tx_msgs_queue); in hsc_release()
645 hsc_reset_list(channel, &channel->free_msgs_list); in hsc_release()
646 clear_bit(HSC_CH_READ, &channel->flags); in hsc_release()
647 clear_bit(HSC_CH_WRITE, &channel->flags); in hsc_release()
648 clear_bit(HSC_CH_OPEN, &channel->flags); in hsc_release()
649 wake_up(&channel->rx_wait); in hsc_release()
650 wake_up(&channel->tx_wait); in hsc_release()
651 mutex_unlock(&cl_data->lock); in hsc_release()
665 static void hsc_channel_init(struct hsc_channel *channel) in hsc_channel_init() argument
667 init_waitqueue_head(&channel->rx_wait); in hsc_channel_init()
668 init_waitqueue_head(&channel->tx_wait); in hsc_channel_init()
669 spin_lock_init(&channel->lock); in hsc_channel_init()
670 INIT_LIST_HEAD(&channel->free_msgs_list); in hsc_channel_init()
671 INIT_LIST_HEAD(&channel->rx_msgs_queue); in hsc_channel_init()
672 INIT_LIST_HEAD(&channel->tx_msgs_queue); in hsc_channel_init()
679 struct hsc_channel *channel; in hsc_probe() local
688 return -ENOMEM; in hsc_probe()
705 mutex_init(&cl_data->lock); in hsc_probe()
707 cdev_init(&cl_data->cdev, &hsc_fops); in hsc_probe()
708 cl_data->cdev.owner = THIS_MODULE; in hsc_probe()
709 cl_data->cl = cl; in hsc_probe()
710 for (i = 0, channel = cl_data->channels; i < HSC_DEVS; i++, channel++) { in hsc_probe()
711 hsc_channel_init(channel); in hsc_probe()
712 channel->ch = i; in hsc_probe()
713 channel->cl = cl; in hsc_probe()
714 channel->cl_data = cl_data; in hsc_probe()
717 /* 1 hsi client -> N char devices (one for each channel) */ in hsc_probe()
718 ret = cdev_add(&cl_data->cdev, hsc_dev, HSC_DEVS); in hsc_probe()
737 dev_t hsc_dev = cl_data->cdev.dev; in hsc_remove()
739 cdev_del(&cl_data->cdev); in hsc_remove()
761 (max_data_size & (max_data_size - 1))) { in hsc_init()
763 return -EINVAL; in hsc_init()