blob: 579e960a08fab59ae5d0475df094688f8d832cd8 [file] [log] [blame]
From 55124901b0e4b05999669830cf6e0b240f8cb2fd Mon Sep 17 00:00:00 2001
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Date: Thu, 24 Jan 2019 13:35:36 +0100
Subject: [PATCH 06/15] tty: n_r3964: for tx_blocks, use a real kernel list
The tx blocks have a hand-rolled linked list structure, use a "normal"
kernel list structure instead, making the code smaller and easier to
understand and verify that it really does what we think it should be
doing.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/tty/n_r3964.c | 85 +++++++++++++++-----------------------------------
1 file changed, 26 insertions(+), 59 deletions(-)
--- a/drivers/tty/n_r3964.c
+++ b/drivers/tty/n_r3964.c
@@ -140,7 +140,7 @@ struct rx_block_header {
struct tx_block_header {
unsigned int length; /* length in chars without header */
unsigned char *data;
- struct tx_block_header *next;
+ struct list_head node;
struct r3964_client_info *owner;
};
@@ -171,8 +171,7 @@ struct r3964_info {
struct rx_block_header *rx_first;
struct rx_block_header *rx_last;
- struct tx_block_header *tx_first;
- struct tx_block_header *tx_last;
+ struct list_head tx_blocks;
unsigned int tx_position;
unsigned int rx_position;
unsigned char last_rx;
@@ -316,42 +315,25 @@ static void add_tx_queue(struct r3964_in
unsigned long flags;
spin_lock_irqsave(&pInfo->lock, flags);
-
- pHeader->next = NULL;
-
- if (pInfo->tx_last == NULL) {
- pInfo->tx_first = pInfo->tx_last = pHeader;
- } else {
- pInfo->tx_last->next = pHeader;
- pInfo->tx_last = pHeader;
- }
-
+ list_add_tail(&pHeader->node, &pInfo->tx_blocks);
spin_unlock_irqrestore(&pInfo->lock, flags);
-
- TRACE_Q("add_tx_queue %p, length %d, tx_first = %p",
- pHeader, pHeader->length, pInfo->tx_first);
}
static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code)
{
struct tx_block_header *pHeader;
unsigned long flags;
-#ifdef DEBUG_QUEUE
- struct tx_block_header *pDump;
-#endif
- pHeader = pInfo->tx_first;
-
- if (pHeader == NULL)
+ spin_lock_irqsave(&pInfo->lock, flags);
+ if (list_empty(&pInfo->tx_blocks)) {
+ spin_unlock_irqrestore(&pInfo->lock, flags);
return;
+ }
-#ifdef DEBUG_QUEUE
- printk("r3964: remove_from_tx_queue: %p, length %u - ",
- pHeader, pHeader->length);
- for (pDump = pHeader; pDump; pDump = pDump->next)
- printk("%p ", pDump);
- printk("\n");
-#endif
+ pHeader = list_first_entry(&pInfo->tx_blocks, struct tx_block_header,
+ node);
+ list_del(&pHeader->node);
+ spin_unlock_irqrestore(&pInfo->lock, flags);
if (pHeader->owner) {
if (error_code) {
@@ -364,20 +346,7 @@ static void remove_from_tx_queue(struct
wake_up_interruptible(&pInfo->tty->read_wait);
}
- spin_lock_irqsave(&pInfo->lock, flags);
-
- pInfo->tx_first = pHeader->next;
- if (pInfo->tx_first == NULL) {
- pInfo->tx_last = NULL;
- }
-
- spin_unlock_irqrestore(&pInfo->lock, flags);
-
kfree(pHeader);
- TRACE_M("remove_from_tx_queue - kfree %p", pHeader);
-
- TRACE_Q("remove_from_tx_queue: tx_first = %p, tx_last = %p",
- pInfo->tx_first, pInfo->tx_last);
}
static void add_rx_queue(struct r3964_info *pInfo,
@@ -476,7 +445,7 @@ static void trigger_transmit(struct r396
spin_lock_irqsave(&pInfo->lock, flags);
- if ((pInfo->state == R3964_IDLE) && (pInfo->tx_first != NULL)) {
+ if ((pInfo->state == R3964_IDLE) && (!list_empty(&pInfo->tx_blocks))) {
pInfo->state = R3964_TX_REQUEST;
pInfo->nRetry = 0;
pInfo->flags &= ~R3964_ERROR;
@@ -522,17 +491,19 @@ static void retry_transmit(struct r3964_
static void transmit_block(struct r3964_info *pInfo)
{
struct tty_struct *tty = pInfo->tty;
- struct tx_block_header *pBlock = pInfo->tx_first;
- int room = 0;
+ struct tx_block_header *pBlock;
+ int room;
- if (tty == NULL || pBlock == NULL) {
+ if (!tty)
return;
- }
- room = tty_write_room(tty);
+ if (list_empty(&pInfo->tx_blocks))
+ return;
- TRACE_PS("transmit_block %p, room %d, length %d",
- pBlock, room, pBlock->length);
+ pBlock = list_first_entry(&pInfo->tx_blocks, struct tx_block_header,
+ node);
+
+ room = tty_write_room(tty);
while (pInfo->tx_position < pBlock->length) {
if (room < 2)
@@ -1077,7 +1048,7 @@ static int r3964_open(struct tty_struct
pInfo->tty = tty;
pInfo->priority = R3964_MASTER;
pInfo->rx_first = pInfo->rx_last = NULL;
- pInfo->tx_first = pInfo->tx_last = NULL;
+ INIT_LIST_HEAD(&pInfo->tx_blocks);
pInfo->rx_position = 0;
pInfo->tx_position = 0;
pInfo->last_rx = 0;
@@ -1100,7 +1071,7 @@ static void r3964_close(struct tty_struc
struct r3964_info *pInfo = tty->disc_data;
struct r3964_client_info *pClient, *pNext;
struct r3964_message *pMsg;
- struct tx_block_header *pHeader, *pNextHeader;
+ struct tx_block_header *pHeader, *tmp;
unsigned long flags;
TRACE_L("close");
@@ -1129,15 +1100,11 @@ static void r3964_close(struct tty_struc
}
/* Remove jobs from tx_queue: */
spin_lock_irqsave(&pInfo->lock, flags);
- pHeader = pInfo->tx_first;
- pInfo->tx_first = pInfo->tx_last = NULL;
- spin_unlock_irqrestore(&pInfo->lock, flags);
-
- while (pHeader) {
- pNextHeader = pHeader->next;
+ list_for_each_entry_safe(pHeader, tmp, &pInfo->tx_blocks, node) {
+ list_del(&pHeader->node);
kfree(pHeader);
- pHeader = pNextHeader;
}
+ spin_unlock_irqrestore(&pInfo->lock, flags);
/* Free buffers: */
kfree(pInfo->rx_buf);