Lines Matching +full:frame +full:- +full:buffer

1 // SPDX-License-Identifier: GPL-1.0+
16 * tty device drivers that support bit-synchronous HDLC communications.
18 * All HDLC data is frame oriented which means:
20 * 1. tty write calls represent one complete transmit frame of data
21 * The device driver should accept the complete frame or none of
22 * the frame (busy) in the write method. Each write call should have
23 * a byte count in the range of 2-65535 bytes (2 is min HDLC frame
26 * CCITT CRC32, 4 crc bytes are required, so the maximum size frame
28 * CRC16, the maximum application frame size would be 65533.
32 * one received frame. The device driver should bypass
33 * the tty flip buffer and call the line discipline receive
41 * 3. tty read calls returns an entire frame of data or nothing.
49 * otherwise the count of the next available frame is returned.
50 * (instead of the sum of all received frame counts).
54 * this line discipline (or another line discipline that is frame
64 * and frame orientation of HDLC communications.
126 * struct n_hdlc - per device instance data structure
130 * @tx_buf_list: list of pending transmit frame buffers
131 * @rx_buf_list: list of received frame buffers
132 * @tx_free_buf_list: list unused transmit frame buffers
133 * @rx_free_buf_list: list unused received frame buffers
146 * HDLC buffer list manipulation functions
158 /* max frame size for memory allocations */
163 struct n_hdlc *n_hdlc = tty->disc_data; in flush_rx_queue()
166 while ((buf = n_hdlc_buf_get(&n_hdlc->rx_buf_list))) in flush_rx_queue()
167 n_hdlc_buf_put(&n_hdlc->rx_free_buf_list, buf); in flush_rx_queue()
172 struct n_hdlc *n_hdlc = tty->disc_data; in flush_tx_queue()
175 while ((buf = n_hdlc_buf_get(&n_hdlc->tx_buf_list))) in flush_tx_queue()
176 n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, buf); in flush_tx_queue()
190 * n_hdlc_tty_close - line discipline close
198 struct n_hdlc *n_hdlc = tty->disc_data; in n_hdlc_tty_close()
200 if (n_hdlc->magic != HDLC_MAGIC) { in n_hdlc_tty_close()
205 clear_bit(TTY_NO_WRITE_SPLIT, &tty->flags); in n_hdlc_tty_close()
207 tty->disc_data = NULL; in n_hdlc_tty_close()
210 wake_up_interruptible(&tty->read_wait); in n_hdlc_tty_close()
211 wake_up_interruptible(&tty->write_wait); in n_hdlc_tty_close()
213 n_hdlc_free_buf_list(&n_hdlc->rx_free_buf_list); in n_hdlc_tty_close()
214 n_hdlc_free_buf_list(&n_hdlc->tx_free_buf_list); in n_hdlc_tty_close()
215 n_hdlc_free_buf_list(&n_hdlc->rx_buf_list); in n_hdlc_tty_close()
216 n_hdlc_free_buf_list(&n_hdlc->tx_buf_list); in n_hdlc_tty_close()
221 * n_hdlc_tty_open - called when line discipline changed to n_hdlc
228 struct n_hdlc *n_hdlc = tty->disc_data; in n_hdlc_tty_open()
230 pr_debug("%s() called (device=%s)\n", __func__, tty->name); in n_hdlc_tty_open()
235 return -EEXIST; in n_hdlc_tty_open()
241 return -ENFILE; in n_hdlc_tty_open()
244 tty->disc_data = n_hdlc; in n_hdlc_tty_open()
245 tty->receive_room = 65536; in n_hdlc_tty_open()
248 set_bit(TTY_NO_WRITE_SPLIT, &tty->flags); in n_hdlc_tty_open()
258 * n_hdlc_send_frames - send frames on pending send buffer list
262 * Send frames on pending send buffer list until the driver does not accept a
263 * frame (busy) this function is called after adding a frame to the send buffer
274 spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock, flags); in n_hdlc_send_frames()
275 if (n_hdlc->tbusy) { in n_hdlc_send_frames()
276 n_hdlc->woke_up = true; in n_hdlc_send_frames()
277 spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags); in n_hdlc_send_frames()
280 n_hdlc->tbusy = true; in n_hdlc_send_frames()
281 n_hdlc->woke_up = false; in n_hdlc_send_frames()
282 spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags); in n_hdlc_send_frames()
284 tbuf = n_hdlc_buf_get(&n_hdlc->tx_buf_list); in n_hdlc_send_frames()
286 pr_debug("sending frame %p, count=%d\n", tbuf, tbuf->count); in n_hdlc_send_frames()
289 set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); in n_hdlc_send_frames()
290 actual = tty->ops->write(tty, tbuf->buf, tbuf->count); in n_hdlc_send_frames()
293 if (actual == -ERESTARTSYS) { in n_hdlc_send_frames()
294 n_hdlc_buf_return(&n_hdlc->tx_buf_list, tbuf); in n_hdlc_send_frames()
297 /* if transmit error, throw frame away by */ in n_hdlc_send_frames()
300 actual = tbuf->count; in n_hdlc_send_frames()
302 if (actual == tbuf->count) { in n_hdlc_send_frames()
303 pr_debug("frame %p completed\n", tbuf); in n_hdlc_send_frames()
305 /* free current transmit buffer */ in n_hdlc_send_frames()
306 n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, tbuf); in n_hdlc_send_frames()
309 wake_up_interruptible(&tty->write_wait); in n_hdlc_send_frames()
311 /* get next pending transmit buffer */ in n_hdlc_send_frames()
312 tbuf = n_hdlc_buf_get(&n_hdlc->tx_buf_list); in n_hdlc_send_frames()
314 pr_debug("frame %p pending\n", tbuf); in n_hdlc_send_frames()
317 * the buffer was not accepted by driver, in n_hdlc_send_frames()
320 n_hdlc_buf_return(&n_hdlc->tx_buf_list, tbuf); in n_hdlc_send_frames()
326 clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); in n_hdlc_send_frames()
328 /* Clear the re-entry flag */ in n_hdlc_send_frames()
329 spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock, flags); in n_hdlc_send_frames()
330 n_hdlc->tbusy = false; in n_hdlc_send_frames()
331 spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags); in n_hdlc_send_frames()
333 if (n_hdlc->woke_up) in n_hdlc_send_frames()
338 * n_hdlc_tty_wakeup - Callback for transmit wakeup
345 struct n_hdlc *n_hdlc = tty->disc_data; in n_hdlc_tty_wakeup()
351 * n_hdlc_tty_receive - Called by tty driver when receive data is available
358 * interpreted as one HDLC frame.
363 register struct n_hdlc *n_hdlc = tty->disc_data; in n_hdlc_tty_receive()
369 if (n_hdlc->magic != HDLC_MAGIC) { in n_hdlc_tty_receive()
379 /* get a free HDLC buffer */ in n_hdlc_tty_receive()
380 buf = n_hdlc_buf_get(&n_hdlc->rx_free_buf_list); in n_hdlc_tty_receive()
384 * buffer unless the maximum count has been reached in n_hdlc_tty_receive()
386 if (n_hdlc->rx_buf_list.count < MAX_RX_BUF_COUNT) in n_hdlc_tty_receive()
396 /* copy received data to HDLC buffer */ in n_hdlc_tty_receive()
397 memcpy(buf->buf, data, count); in n_hdlc_tty_receive()
398 buf->count = count; in n_hdlc_tty_receive()
400 /* add HDLC buffer to list of received frames */ in n_hdlc_tty_receive()
401 n_hdlc_buf_put(&n_hdlc->rx_buf_list, buf); in n_hdlc_tty_receive()
404 wake_up_interruptible(&tty->read_wait); in n_hdlc_tty_receive()
405 if (tty->fasync != NULL) in n_hdlc_tty_receive()
406 kill_fasync(&tty->fasync, SIGIO, POLL_IN); in n_hdlc_tty_receive()
411 * n_hdlc_tty_read - Called to retrieve one frame of data (if available)
414 * @kbuf: pointer to returned data buffer
415 * @nr: size of returned data buffer
417 * @offset: offset into the data buffer
425 struct n_hdlc *n_hdlc = tty->disc_data; in n_hdlc_tty_read()
435 add_wait_queue(&tty->read_wait, &wait); in n_hdlc_tty_read()
438 if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { in n_hdlc_tty_read()
439 ret = -EIO; in n_hdlc_tty_read()
447 rbuf = n_hdlc_buf_get(&n_hdlc->rx_buf_list); in n_hdlc_tty_read()
453 ret = -EAGAIN; in n_hdlc_tty_read()
460 ret = -EINTR; in n_hdlc_tty_read()
465 remove_wait_queue(&tty->read_wait, &wait); in n_hdlc_tty_read()
474 if (offset >= rbuf->count) in n_hdlc_tty_read()
478 ret = -EOVERFLOW; in n_hdlc_tty_read()
483 ret = rbuf->count - offset; in n_hdlc_tty_read()
486 memcpy(kbuf, rbuf->buf+offset, ret); in n_hdlc_tty_read()
490 if (offset < rbuf->count) in n_hdlc_tty_read()
496 if (n_hdlc->rx_free_buf_list.count > DEFAULT_RX_BUF_COUNT) in n_hdlc_tty_read()
499 n_hdlc_buf_put(&n_hdlc->rx_free_buf_list, rbuf); in n_hdlc_tty_read()
506 * n_hdlc_tty_write - write a single frame of data to device
509 * @data: pointer to transmit data (one frame)
510 * @count: size of transmit frame in bytes
517 struct n_hdlc *n_hdlc = tty->disc_data; in n_hdlc_tty_write()
524 if (n_hdlc->magic != HDLC_MAGIC) in n_hdlc_tty_write()
525 return -EIO; in n_hdlc_tty_write()
527 /* verify frame size */ in n_hdlc_tty_write()
534 add_wait_queue(&tty->write_wait, &wait); in n_hdlc_tty_write()
539 tbuf = n_hdlc_buf_get(&n_hdlc->tx_free_buf_list); in n_hdlc_tty_write()
544 error = -EAGAIN; in n_hdlc_tty_write()
550 error = -EINTR; in n_hdlc_tty_write()
556 remove_wait_queue(&tty->write_wait, &wait); in n_hdlc_tty_write()
559 /* Retrieve the user's buffer */ in n_hdlc_tty_write()
560 memcpy(tbuf->buf, data, count); in n_hdlc_tty_write()
563 tbuf->count = error = count; in n_hdlc_tty_write()
564 n_hdlc_buf_put(&n_hdlc->tx_buf_list, tbuf); in n_hdlc_tty_write()
573 * n_hdlc_tty_ioctl - process IOCTL system call for the tty device.
584 struct n_hdlc *n_hdlc = tty->disc_data; in n_hdlc_tty_ioctl()
593 if (n_hdlc->magic != HDLC_MAGIC) in n_hdlc_tty_ioctl()
594 return -EBADF; in n_hdlc_tty_ioctl()
599 /* in next available frame (if any) */ in n_hdlc_tty_ioctl()
600 spin_lock_irqsave(&n_hdlc->rx_buf_list.spinlock, flags); in n_hdlc_tty_ioctl()
601 buf = list_first_entry_or_null(&n_hdlc->rx_buf_list.list, in n_hdlc_tty_ioctl()
604 count = buf->count; in n_hdlc_tty_ioctl()
607 spin_unlock_irqrestore(&n_hdlc->rx_buf_list.spinlock, flags); in n_hdlc_tty_ioctl()
614 /* add size of next output frame in queue */ in n_hdlc_tty_ioctl()
615 spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock, flags); in n_hdlc_tty_ioctl()
616 buf = list_first_entry_or_null(&n_hdlc->tx_buf_list.list, in n_hdlc_tty_ioctl()
619 count += buf->count; in n_hdlc_tty_ioctl()
620 spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags); in n_hdlc_tty_ioctl()
641 * n_hdlc_tty_poll - TTY callback for poll system call
653 struct n_hdlc *n_hdlc = tty->disc_data; in n_hdlc_tty_poll()
656 if (n_hdlc->magic != HDLC_MAGIC) in n_hdlc_tty_poll()
663 poll_wait(filp, &tty->read_wait, wait); in n_hdlc_tty_poll()
664 poll_wait(filp, &tty->write_wait, wait); in n_hdlc_tty_poll()
667 if (!list_empty(&n_hdlc->rx_buf_list.list)) in n_hdlc_tty_poll()
669 if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) in n_hdlc_tty_poll()
674 !list_empty(&n_hdlc->tx_free_buf_list.list)) in n_hdlc_tty_poll()
689 pr_debug("%s(), kmalloc() failed for %s buffer %u\n", in n_hdlc_alloc_buf()
698 * n_hdlc_alloc - allocate an n_hdlc instance data structure
709 spin_lock_init(&n_hdlc->rx_free_buf_list.spinlock); in n_hdlc_alloc()
710 spin_lock_init(&n_hdlc->tx_free_buf_list.spinlock); in n_hdlc_alloc()
711 spin_lock_init(&n_hdlc->rx_buf_list.spinlock); in n_hdlc_alloc()
712 spin_lock_init(&n_hdlc->tx_buf_list.spinlock); in n_hdlc_alloc()
714 INIT_LIST_HEAD(&n_hdlc->rx_free_buf_list.list); in n_hdlc_alloc()
715 INIT_LIST_HEAD(&n_hdlc->tx_free_buf_list.list); in n_hdlc_alloc()
716 INIT_LIST_HEAD(&n_hdlc->rx_buf_list.list); in n_hdlc_alloc()
717 INIT_LIST_HEAD(&n_hdlc->tx_buf_list.list); in n_hdlc_alloc()
719 n_hdlc_alloc_buf(&n_hdlc->rx_free_buf_list, DEFAULT_RX_BUF_COUNT, "rx"); in n_hdlc_alloc()
720 n_hdlc_alloc_buf(&n_hdlc->tx_free_buf_list, DEFAULT_TX_BUF_COUNT, "tx"); in n_hdlc_alloc()
723 n_hdlc->magic = HDLC_MAGIC; in n_hdlc_alloc()
730 * n_hdlc_buf_return - put the HDLC buffer after the head of the specified list
731 * @buf_list: pointer to the buffer list
732 * @buf: pointer to the buffer
739 spin_lock_irqsave(&buf_list->spinlock, flags); in n_hdlc_buf_return()
741 list_add(&buf->list_item, &buf_list->list); in n_hdlc_buf_return()
742 buf_list->count++; in n_hdlc_buf_return()
744 spin_unlock_irqrestore(&buf_list->spinlock, flags); in n_hdlc_buf_return()
748 * n_hdlc_buf_put - add specified HDLC buffer to tail of specified list
749 * @buf_list: pointer to buffer list
750 * @buf: pointer to buffer
757 spin_lock_irqsave(&buf_list->spinlock, flags); in n_hdlc_buf_put()
759 list_add_tail(&buf->list_item, &buf_list->list); in n_hdlc_buf_put()
760 buf_list->count++; in n_hdlc_buf_put()
762 spin_unlock_irqrestore(&buf_list->spinlock, flags); in n_hdlc_buf_put()
766 * n_hdlc_buf_get - remove and return an HDLC buffer from list
767 * @buf_list: pointer to HDLC buffer list
769 * Remove and return an HDLC buffer from the head of the specified HDLC buffer
771 * Returns a pointer to HDLC buffer if available, otherwise %NULL.
778 spin_lock_irqsave(&buf_list->spinlock, flags); in n_hdlc_buf_get()
780 buf = list_first_entry_or_null(&buf_list->list, in n_hdlc_buf_get()
783 list_del(&buf->list_item); in n_hdlc_buf_get()
784 buf_list->count--; in n_hdlc_buf_get()
787 spin_unlock_irqrestore(&buf_list->spinlock, flags); in n_hdlc_buf_get()