summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/char/diag/diag_dci.c20
-rw-r--r--drivers/char/diag/diagchar.h3
2 files changed, 22 insertions, 1 deletions
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index e9a6711c9990..cf2e08f65b64 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -1658,10 +1658,13 @@ unsigned char *dci_get_buffer_from_bridge(int token)
{
uint8_t retries = 0, max_retries = 3;
unsigned char *buf = NULL;
+ unsigned long flags;
do {
+ spin_lock_irqsave(&driver->dci_mempool_lock, flags);
buf = diagmem_alloc(driver, DIAG_MDM_BUF_SIZE,
dci_ops_tbl[token].mempool);
+ spin_unlock_irqrestore(&driver->dci_mempool_lock, flags);
if (!buf) {
usleep_range(5000, 5100);
retries++;
@@ -1679,12 +1682,15 @@ int diag_dci_write_bridge(int token, unsigned char *buf, int len)
int diag_dci_write_done_bridge(int index, unsigned char *buf, int len)
{
+ unsigned long flags;
int token = BRIDGE_TO_TOKEN(index);
if (!VALID_DCI_TOKEN(token)) {
pr_err("diag: Invalid DCI token %d in %s\n", token, __func__);
return -EINVAL;
}
+ spin_lock_irqsave(&driver->dci_mempool_lock, flags);
diagmem_free(driver, buf, dci_ops_tbl[token].mempool);
+ spin_unlock_irqrestore(&driver->dci_mempool_lock, flags);
return 0;
}
#endif
@@ -1698,6 +1704,7 @@ static int diag_send_dci_pkt_remote(unsigned char *data, int len, int tag,
int dci_header_size = sizeof(struct diag_dci_header_t);
int ret = DIAG_DCI_NO_ERROR;
uint32_t write_len = 0;
+ unsigned long flags;
if (!data)
return -EIO;
@@ -1731,7 +1738,9 @@ static int diag_send_dci_pkt_remote(unsigned char *data, int len, int tag,
if (ret) {
pr_err("diag: error writing dci pkt to remote proc, token: %d, err: %d\n",
token, ret);
+ spin_lock_irqsave(&driver->dci_mempool_lock, flags);
diagmem_free(driver, buf, dci_ops_tbl[token].mempool);
+ spin_unlock_irqrestore(&driver->dci_mempool_lock, flags);
} else {
ret = DIAG_DCI_NO_ERROR;
}
@@ -1755,6 +1764,7 @@ int diag_dci_send_handshake_pkt(int index)
struct diag_ctrl_dci_handshake_pkt ctrl_pkt;
unsigned char *buf = NULL;
struct diag_dci_header_t dci_header;
+ unsigned long flags;
if (!VALID_DCI_TOKEN(token)) {
pr_err("diag: In %s, invalid DCI token %d\n", __func__, token);
@@ -1794,7 +1804,9 @@ int diag_dci_send_handshake_pkt(int index)
if (err) {
pr_err("diag: error writing ack packet to remote proc, token: %d, err: %d\n",
token, err);
+ spin_lock_irqsave(&driver->dci_mempool_lock, flags);
diagmem_free(driver, buf, dci_ops_tbl[token].mempool);
+ spin_unlock_irqrestore(&driver->dci_mempool_lock, flags);
return err;
}
@@ -2454,6 +2466,7 @@ int diag_send_dci_event_mask_remote(int token)
int i, ret = DIAG_DCI_NO_ERROR, err = DIAG_DCI_NO_ERROR;
unsigned char *event_mask_ptr = NULL;
uint32_t write_len = 0;
+ unsigned long flags;
mutex_lock(&dci_event_mask_mutex);
event_mask_ptr = dci_ops_tbl[token].event_mask_composite;
@@ -2499,7 +2512,9 @@ int diag_send_dci_event_mask_remote(int token)
if (err) {
pr_err("diag: error writing event mask to remote proc, token: %d, err: %d\n",
token, err);
+ spin_lock_irqsave(&driver->dci_mempool_lock, flags);
diagmem_free(driver, buf, dci_ops_tbl[token].mempool);
+ spin_unlock_irqrestore(&driver->dci_mempool_lock, flags);
ret = err;
} else {
ret = DIAG_DCI_NO_ERROR;
@@ -2656,6 +2671,7 @@ int diag_send_dci_log_mask_remote(int token)
int i, ret = DIAG_DCI_NO_ERROR, err = DIAG_DCI_NO_ERROR;
int updated;
uint32_t write_len = 0;
+ unsigned long flags;
mutex_lock(&dci_log_mask_mutex);
log_mask_ptr = dci_ops_tbl[token].log_mask_composite;
@@ -2695,7 +2711,10 @@ int diag_send_dci_log_mask_remote(int token)
if (err) {
pr_err("diag: error writing log mask to remote processor, equip_id: %d, token: %d, err: %d\n",
i, token, err);
+ spin_lock_irqsave(&driver->dci_mempool_lock, flags);
diagmem_free(driver, buf, dci_ops_tbl[token].mempool);
+ spin_unlock_irqrestore(&driver->dci_mempool_lock,
+ flags);
updated = 0;
}
if (updated)
@@ -2840,6 +2859,7 @@ int diag_dci_init(void)
mutex_init(&dci_log_mask_mutex);
mutex_init(&dci_event_mask_mutex);
spin_lock_init(&ws_lock);
+ spin_lock_init(&driver->dci_mempool_lock);
ret = diag_dci_init_ops_tbl();
if (ret)
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index b49d8cb54349..bc7dd020e145 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2018,2020, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -549,6 +549,7 @@ struct diagchar_dev {
struct workqueue_struct *diag_dci_wq;
struct list_head cmd_reg_list;
struct mutex cmd_reg_mutex;
+ spinlock_t dci_mempool_lock;
uint32_t cmd_reg_count;
struct mutex diagfwd_channel_mutex[NUM_PERIPHERALS];
/* Sizes that reflect memory pool sizes */