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.
125 * struct n_hdlc - per device instance data structure
129 * @tx_buf_list: list of pending transmit frame buffers
130 * @rx_buf_list: list of received frame buffers
131 * @tx_free_buf_list: list unused transmit frame buffers
132 * @rx_free_buf_list: list unused received frame buffers
145 * HDLC buffer list manipulation functions
157 /* max frame size for memory allocations */
162 struct n_hdlc *n_hdlc = tty->disc_data; in flush_rx_queue()
165 while ((buf = n_hdlc_buf_get(&n_hdlc->rx_buf_list))) in flush_rx_queue()
166 n_hdlc_buf_put(&n_hdlc->rx_free_buf_list, buf); in flush_rx_queue()
171 struct n_hdlc *n_hdlc = tty->disc_data; in flush_tx_queue()
174 while ((buf = n_hdlc_buf_get(&n_hdlc->tx_buf_list))) in flush_tx_queue()
175 n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, buf); in flush_tx_queue()
189 * n_hdlc_tty_close - line discipline close
197 struct n_hdlc *n_hdlc = tty->disc_data; in n_hdlc_tty_close()
199 if (n_hdlc->magic != HDLC_MAGIC) { in n_hdlc_tty_close()
204 clear_bit(TTY_NO_WRITE_SPLIT, &tty->flags); in n_hdlc_tty_close()
206 tty->disc_data = NULL; in n_hdlc_tty_close()
209 wake_up_interruptible(&tty->read_wait); in n_hdlc_tty_close()
210 wake_up_interruptible(&tty->write_wait); in n_hdlc_tty_close()
212 n_hdlc_free_buf_list(&n_hdlc->rx_free_buf_list); in n_hdlc_tty_close()
213 n_hdlc_free_buf_list(&n_hdlc->tx_free_buf_list); in n_hdlc_tty_close()
214 n_hdlc_free_buf_list(&n_hdlc->rx_buf_list); in n_hdlc_tty_close()
215 n_hdlc_free_buf_list(&n_hdlc->tx_buf_list); in n_hdlc_tty_close()
220 * n_hdlc_tty_open - called when line discipline changed to n_hdlc
227 struct n_hdlc *n_hdlc = tty->disc_data; in n_hdlc_tty_open()
229 pr_debug("%s() called (device=%s)\n", __func__, tty->name); in n_hdlc_tty_open()
234 return -EEXIST; in n_hdlc_tty_open()
240 return -ENFILE; in n_hdlc_tty_open()
243 tty->disc_data = n_hdlc; in n_hdlc_tty_open()
244 tty->receive_room = 65536; in n_hdlc_tty_open()
247 set_bit(TTY_NO_WRITE_SPLIT, &tty->flags); in n_hdlc_tty_open()
257 * n_hdlc_send_frames - send frames on pending send buffer list
261 * Send frames on pending send buffer list until the driver does not accept a
262 * frame (busy) this function is called after adding a frame to the send buffer
273 spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock, flags); in n_hdlc_send_frames()
274 if (n_hdlc->tbusy) { in n_hdlc_send_frames()
275 n_hdlc->woke_up = true; in n_hdlc_send_frames()
276 spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags); in n_hdlc_send_frames()
279 n_hdlc->tbusy = true; in n_hdlc_send_frames()
280 n_hdlc->woke_up = false; in n_hdlc_send_frames()
281 spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags); in n_hdlc_send_frames()
283 tbuf = n_hdlc_buf_get(&n_hdlc->tx_buf_list); in n_hdlc_send_frames()
285 pr_debug("sending frame %p, count=%d\n", tbuf, tbuf->count); in n_hdlc_send_frames()
288 set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); in n_hdlc_send_frames()
289 actual = tty->ops->write(tty, tbuf->buf, tbuf->count); in n_hdlc_send_frames()
292 if (actual == -ERESTARTSYS) { in n_hdlc_send_frames()
293 n_hdlc_buf_return(&n_hdlc->tx_buf_list, tbuf); in n_hdlc_send_frames()
296 /* if transmit error, throw frame away by */ in n_hdlc_send_frames()
299 actual = tbuf->count; in n_hdlc_send_frames()
301 if (actual == tbuf->count) { in n_hdlc_send_frames()
302 pr_debug("frame %p completed\n", tbuf); in n_hdlc_send_frames()
304 /* free current transmit buffer */ in n_hdlc_send_frames()
305 n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, tbuf); in n_hdlc_send_frames()
308 wake_up_interruptible(&tty->write_wait); in n_hdlc_send_frames()
310 /* get next pending transmit buffer */ in n_hdlc_send_frames()
311 tbuf = n_hdlc_buf_get(&n_hdlc->tx_buf_list); in n_hdlc_send_frames()
313 pr_debug("frame %p pending\n", tbuf); in n_hdlc_send_frames()
316 * the buffer was not accepted by driver, in n_hdlc_send_frames()
319 n_hdlc_buf_return(&n_hdlc->tx_buf_list, tbuf); in n_hdlc_send_frames()
325 clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); in n_hdlc_send_frames()
327 /* Clear the re-entry flag */ in n_hdlc_send_frames()
328 spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock, flags); in n_hdlc_send_frames()
329 n_hdlc->tbusy = false; in n_hdlc_send_frames()
330 spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags); in n_hdlc_send_frames()
332 if (n_hdlc->woke_up) in n_hdlc_send_frames()
337 * n_hdlc_tty_wakeup - Callback for transmit wakeup
344 struct n_hdlc *n_hdlc = tty->disc_data; in n_hdlc_tty_wakeup()
350 * n_hdlc_tty_receive - Called by tty driver when receive data is available
357 * interpreted as one HDLC frame.
362 register struct n_hdlc *n_hdlc = tty->disc_data; in n_hdlc_tty_receive()
368 if (n_hdlc->magic != HDLC_MAGIC) { in n_hdlc_tty_receive()
378 /* get a free HDLC buffer */ in n_hdlc_tty_receive()
379 buf = n_hdlc_buf_get(&n_hdlc->rx_free_buf_list); in n_hdlc_tty_receive()
383 * buffer unless the maximum count has been reached in n_hdlc_tty_receive()
385 if (n_hdlc->rx_buf_list.count < MAX_RX_BUF_COUNT) in n_hdlc_tty_receive()
395 /* copy received data to HDLC buffer */ in n_hdlc_tty_receive()
396 memcpy(buf->buf, data, count); in n_hdlc_tty_receive()
397 buf->count = count; in n_hdlc_tty_receive()
399 /* add HDLC buffer to list of received frames */ in n_hdlc_tty_receive()
400 n_hdlc_buf_put(&n_hdlc->rx_buf_list, buf); in n_hdlc_tty_receive()
403 wake_up_interruptible(&tty->read_wait); in n_hdlc_tty_receive()
404 if (tty->fasync != NULL) in n_hdlc_tty_receive()
405 kill_fasync(&tty->fasync, SIGIO, POLL_IN); in n_hdlc_tty_receive()
410 * n_hdlc_tty_read - Called to retrieve one frame of data (if available)
413 * @buf: pointer to returned data buffer
414 * @nr: size of returned data buffer
421 struct n_hdlc *n_hdlc = tty->disc_data; in n_hdlc_tty_read()
426 add_wait_queue(&tty->read_wait, &wait); in n_hdlc_tty_read()
429 if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { in n_hdlc_tty_read()
430 ret = -EIO; in n_hdlc_tty_read()
438 rbuf = n_hdlc_buf_get(&n_hdlc->rx_buf_list); in n_hdlc_tty_read()
440 if (rbuf->count > nr) { in n_hdlc_tty_read()
441 /* too large for caller's buffer */ in n_hdlc_tty_read()
442 ret = -EOVERFLOW; in n_hdlc_tty_read()
445 if (copy_to_user(buf, rbuf->buf, rbuf->count)) in n_hdlc_tty_read()
446 ret = -EFAULT; in n_hdlc_tty_read()
448 ret = rbuf->count; in n_hdlc_tty_read()
451 if (n_hdlc->rx_free_buf_list.count > in n_hdlc_tty_read()
455 n_hdlc_buf_put(&n_hdlc->rx_free_buf_list, rbuf); in n_hdlc_tty_read()
461 ret = -EAGAIN; in n_hdlc_tty_read()
468 ret = -EINTR; in n_hdlc_tty_read()
473 remove_wait_queue(&tty->read_wait, &wait); in n_hdlc_tty_read()
481 * n_hdlc_tty_write - write a single frame of data to device
484 * @data: pointer to transmit data (one frame)
485 * @count: size of transmit frame in bytes
492 struct n_hdlc *n_hdlc = tty->disc_data; in n_hdlc_tty_write()
499 if (n_hdlc->magic != HDLC_MAGIC) in n_hdlc_tty_write()
500 return -EIO; in n_hdlc_tty_write()
502 /* verify frame size */ in n_hdlc_tty_write()
509 add_wait_queue(&tty->write_wait, &wait); in n_hdlc_tty_write()
514 tbuf = n_hdlc_buf_get(&n_hdlc->tx_free_buf_list); in n_hdlc_tty_write()
519 error = -EAGAIN; in n_hdlc_tty_write()
525 error = -EINTR; in n_hdlc_tty_write()
531 remove_wait_queue(&tty->write_wait, &wait); in n_hdlc_tty_write()
534 /* Retrieve the user's buffer */ in n_hdlc_tty_write()
535 memcpy(tbuf->buf, data, count); in n_hdlc_tty_write()
538 tbuf->count = error = count; in n_hdlc_tty_write()
539 n_hdlc_buf_put(&n_hdlc->tx_buf_list, tbuf); in n_hdlc_tty_write()
548 * n_hdlc_tty_ioctl - process IOCTL system call for the tty device.
559 struct n_hdlc *n_hdlc = tty->disc_data; in n_hdlc_tty_ioctl()
568 if (n_hdlc->magic != HDLC_MAGIC) in n_hdlc_tty_ioctl()
569 return -EBADF; in n_hdlc_tty_ioctl()
574 /* in next available frame (if any) */ in n_hdlc_tty_ioctl()
575 spin_lock_irqsave(&n_hdlc->rx_buf_list.spinlock, flags); in n_hdlc_tty_ioctl()
576 buf = list_first_entry_or_null(&n_hdlc->rx_buf_list.list, in n_hdlc_tty_ioctl()
579 count = buf->count; in n_hdlc_tty_ioctl()
582 spin_unlock_irqrestore(&n_hdlc->rx_buf_list.spinlock, flags); in n_hdlc_tty_ioctl()
589 /* add size of next output frame in queue */ in n_hdlc_tty_ioctl()
590 spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock, flags); in n_hdlc_tty_ioctl()
591 buf = list_first_entry_or_null(&n_hdlc->tx_buf_list.list, in n_hdlc_tty_ioctl()
594 count += buf->count; in n_hdlc_tty_ioctl()
595 spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags); in n_hdlc_tty_ioctl()
616 * n_hdlc_tty_poll - TTY callback for poll system call
628 struct n_hdlc *n_hdlc = tty->disc_data; in n_hdlc_tty_poll()
631 if (n_hdlc->magic != HDLC_MAGIC) in n_hdlc_tty_poll()
638 poll_wait(filp, &tty->read_wait, wait); in n_hdlc_tty_poll()
639 poll_wait(filp, &tty->write_wait, wait); in n_hdlc_tty_poll()
642 if (!list_empty(&n_hdlc->rx_buf_list.list)) in n_hdlc_tty_poll()
644 if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) in n_hdlc_tty_poll()
649 !list_empty(&n_hdlc->tx_free_buf_list.list)) in n_hdlc_tty_poll()
664 pr_debug("%s(), kmalloc() failed for %s buffer %u\n", in n_hdlc_alloc_buf()
673 * n_hdlc_alloc - allocate an n_hdlc instance data structure
684 spin_lock_init(&n_hdlc->rx_free_buf_list.spinlock); in n_hdlc_alloc()
685 spin_lock_init(&n_hdlc->tx_free_buf_list.spinlock); in n_hdlc_alloc()
686 spin_lock_init(&n_hdlc->rx_buf_list.spinlock); in n_hdlc_alloc()
687 spin_lock_init(&n_hdlc->tx_buf_list.spinlock); in n_hdlc_alloc()
689 INIT_LIST_HEAD(&n_hdlc->rx_free_buf_list.list); in n_hdlc_alloc()
690 INIT_LIST_HEAD(&n_hdlc->tx_free_buf_list.list); in n_hdlc_alloc()
691 INIT_LIST_HEAD(&n_hdlc->rx_buf_list.list); in n_hdlc_alloc()
692 INIT_LIST_HEAD(&n_hdlc->tx_buf_list.list); in n_hdlc_alloc()
694 n_hdlc_alloc_buf(&n_hdlc->rx_free_buf_list, DEFAULT_RX_BUF_COUNT, "rx"); in n_hdlc_alloc()
695 n_hdlc_alloc_buf(&n_hdlc->tx_free_buf_list, DEFAULT_TX_BUF_COUNT, "tx"); in n_hdlc_alloc()
698 n_hdlc->magic = HDLC_MAGIC; in n_hdlc_alloc()
705 * n_hdlc_buf_return - put the HDLC buffer after the head of the specified list
706 * @buf_list: pointer to the buffer list
707 * @buf: pointer to the buffer
714 spin_lock_irqsave(&buf_list->spinlock, flags); in n_hdlc_buf_return()
716 list_add(&buf->list_item, &buf_list->list); in n_hdlc_buf_return()
717 buf_list->count++; in n_hdlc_buf_return()
719 spin_unlock_irqrestore(&buf_list->spinlock, flags); in n_hdlc_buf_return()
723 * n_hdlc_buf_put - add specified HDLC buffer to tail of specified list
724 * @buf_list: pointer to buffer list
725 * @buf: pointer to buffer
732 spin_lock_irqsave(&buf_list->spinlock, flags); in n_hdlc_buf_put()
734 list_add_tail(&buf->list_item, &buf_list->list); in n_hdlc_buf_put()
735 buf_list->count++; in n_hdlc_buf_put()
737 spin_unlock_irqrestore(&buf_list->spinlock, flags); in n_hdlc_buf_put()
741 * n_hdlc_buf_get - remove and return an HDLC buffer from list
742 * @buf_list: pointer to HDLC buffer list
744 * Remove and return an HDLC buffer from the head of the specified HDLC buffer
746 * Returns a pointer to HDLC buffer if available, otherwise %NULL.
753 spin_lock_irqsave(&buf_list->spinlock, flags); in n_hdlc_buf_get()
755 buf = list_first_entry_or_null(&buf_list->list, in n_hdlc_buf_get()
758 list_del(&buf->list_item); in n_hdlc_buf_get()
759 buf_list->count--; in n_hdlc_buf_get()
762 spin_unlock_irqrestore(&buf_list->spinlock, flags); in n_hdlc_buf_get()