diff options
| author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-05-15 10:20:16 +0200 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-05-15 10:20:16 +0200 |
| commit | 2c3266e8829eb5a611a08cddca97f79c05ed28db (patch) | |
| tree | b7aaa09c1ee1f738acd83b9a46ae2d135f89b22c /0008-tty-n_r3964-don-t-hand-roll-a-reference-count.patch | |
| parent | cf6fd4d72fe78061c68af7a241387ec2d26dc161 (diff) | |
| download | patches-2c3266e8829eb5a611a08cddca97f79c05ed28db.tar.gz | |
tty patches added
Diffstat (limited to '0008-tty-n_r3964-don-t-hand-roll-a-reference-count.patch')
| -rw-r--r-- | 0008-tty-n_r3964-don-t-hand-roll-a-reference-count.patch | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/0008-tty-n_r3964-don-t-hand-roll-a-reference-count.patch b/0008-tty-n_r3964-don-t-hand-roll-a-reference-count.patch new file mode 100644 index 00000000000000..0fd59803294b63 --- /dev/null +++ b/0008-tty-n_r3964-don-t-hand-roll-a-reference-count.patch @@ -0,0 +1,160 @@ +From 6e885d94ba582aec3e689d94b3b2deb3570a5e06 Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Date: Thu, 24 Jan 2019 16:44:28 +0100 +Subject: [PATCH 08/15] tty: n_r3964: don't hand-roll a reference count + +rx_block_header had a "locks" variable that was trying to be a reference +count on the header. When it would drop to zero, the memory would be +freed. Convert this to be a kref instead to handle the housekeeping for +doing reference counting properly. + +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + drivers/tty/n_r3964.c | 61 ++++++++++++++++++++----------------------- + 1 file changed, 28 insertions(+), 33 deletions(-) + +diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c +index 8275fb905aeb..a79c8d485030 100644 +--- a/drivers/tty/n_r3964.c ++++ b/drivers/tty/n_r3964.c +@@ -26,6 +26,7 @@ + #include <linux/param.h> + #include <linux/poll.h> + #include <linux/init.h> ++#include <linux/kref.h> + #include <linux/uaccess.h> + #include <uapi/linux/n_r3964.h> + +@@ -131,8 +132,9 @@ struct rx_block_header { + unsigned int length; /* length in chars without header */ + unsigned char *data; /* usually data is located immediately + * behind this struct */ +- unsigned int locks; /* only used in rx_buffer */ + struct list_head node; ++ struct kref kref; ++ struct r3964_info *info; + }; + + /* Header of received block in tx_buf: */ +@@ -200,8 +202,7 @@ static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg, + int error_code, struct rx_block_header *pBlock); + static struct r3964_message *remove_msg(struct r3964_info *pInfo, + struct r3964_client_info *pClient); +-static void remove_client_block(struct r3964_info *pInfo, +- struct r3964_client_info *pClient); ++static void remove_client_block(struct r3964_client_info *pClient); + + static int r3964_open(struct tty_struct *tty); + static void r3964_close(struct tty_struct *tty); +@@ -357,28 +358,28 @@ static void add_rx_queue(struct r3964_info *pInfo, + spin_unlock_irqrestore(&pInfo->lock, flags); + } + +-static void remove_from_rx_queue(struct r3964_info *pInfo, +- struct rx_block_header *pHeader) ++static void remove_from_rx_queue(struct kref *kref) + { +- struct rx_block_header *pFind, *tmp; ++ struct rx_block_header *header, *find; ++ struct r3964_info *info; + unsigned long flags; + +- if (pHeader == NULL) +- return; ++ header = container_of(kref, struct rx_block_header, kref); ++ info = header->info; + +- spin_lock_irqsave(&pInfo->lock, flags); +- list_for_each_entry_safe(pFind, tmp, &pInfo->rx_blocks, node) { +- if (pFind == pHeader) { ++ spin_lock_irqsave(&info->lock, flags); ++ list_for_each_entry(find, &info->rx_blocks, node) { ++ if (find == header) { + /* Got it. */ +- list_del(&pFind->node); +- pInfo->blocks_in_rx_queue--; ++ list_del(&find->node); ++ info->blocks_in_rx_queue--; + goto exit; + } + } + exit: +- spin_unlock_irqrestore(&pInfo->lock, flags); ++ spin_unlock_irqrestore(&info->lock, flags); + +- kfree(pHeader); ++ kfree(header); + } + + static void put_char(struct r3964_info *pInfo, unsigned char ch) +@@ -540,7 +541,8 @@ static void on_receive_block(struct r3964_info *pInfo) + + pBlock->length = length; + pBlock->data = ((unsigned char *)pBlock) + sizeof(*pBlock); +- pBlock->locks = 0; ++ pBlock->info = pInfo; ++ kref_init(&pBlock->kref); + INIT_LIST_HEAD(&pBlock->node); + + memcpy(pBlock->data, pInfo->rx_buf, length); +@@ -855,7 +857,7 @@ static int read_telegram(struct r3964_info *pInfo, struct pid *pid, + if (copy_to_user(buf, block->data, block->length)) + return -EFAULT; + +- remove_client_block(pInfo, pClient); ++ remove_client_block(pClient); + return block->length; + } + +@@ -894,9 +896,9 @@ static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg, + + pClient->msg_count++; + +- if (pBlock != NULL) { +- pBlock->locks++; +- } ++ if (pBlock != NULL) ++ kref_get(&pBlock->kref); ++ + spin_unlock_irqrestore(&pClient->lock, flags); + } else { + if ((pClient->last_msg->msg_id == R3964_MSG_ACK) +@@ -935,7 +937,7 @@ static struct r3964_message *remove_msg(struct r3964_info *pInfo, + + pClient->msg_count--; + if (pMsg->block) { +- remove_client_block(pInfo, pClient); ++ remove_client_block(pClient); + pClient->next_block_to_read = pMsg->block; + } + spin_unlock_irqrestore(&pClient->lock, flags); +@@ -943,21 +945,14 @@ static struct r3964_message *remove_msg(struct r3964_info *pInfo, + return pMsg; + } + +-static void remove_client_block(struct r3964_info *pInfo, +- struct r3964_client_info *pClient) ++static void remove_client_block(struct r3964_client_info *client) + { + struct rx_block_header *block; + +- TRACE_PS("remove_client_block PID %d", pid_nr(pClient->pid)); +- +- block = pClient->next_block_to_read; +- if (block) { +- block->locks--; +- if (block->locks == 0) { +- remove_from_rx_queue(pInfo, block); +- } +- } +- pClient->next_block_to_read = NULL; ++ block = client->next_block_to_read; ++ if (block) ++ kref_put(&block->kref, remove_from_rx_queue); ++ client->next_block_to_read = NULL; + } + + /************************************************************* +-- +2.21.0 + |
