Commit bb0590e2 authored by Julian Andres Klode's avatar Julian Andres Klode Committed by Greg Kroah-Hartman

staging: nvec: Allow TX buffers only in the upper 75% of the pool

Allow TX buffers to be allocated only in the upper 75% of the pool
to avoid a completely filled buffer preventing the driver from
processing responses. This also improves performance, as RX
allocations do not require checking buffers allocated for TX
unless there are more than 16 incoming messages -- which is
highly unlikely.

An earlier version used the lower 75% for TX messages, but
that was considered to be not that effective due to the
overlaps of RX and TX buffers mentioned above.
Signed-off-by: default avatarJulian Andres Klode <jak@jak-linux.org>
Acked-by: default avatarMarc Dietrich <marvin24@gmx.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 198dd267
...@@ -62,6 +62,16 @@ ...@@ -62,6 +62,16 @@
#define I2C_SL_ADDR2 0x30 #define I2C_SL_ADDR2 0x30
#define I2C_SL_DELAY_COUNT 0x3c #define I2C_SL_DELAY_COUNT 0x3c
/**
* enum nvec_msg_category - Message categories for nvec_msg_alloc()
* @NVEC_MSG_RX: The message is an incoming message (from EC)
* @NVEC_MSG_TX: The message is an outgoing message (to EC)
*/
enum nvec_msg_category {
NVEC_MSG_RX,
NVEC_MSG_TX,
};
static const unsigned char EC_DISABLE_EVENT_REPORTING[3] = "\x04\x00\x00"; static const unsigned char EC_DISABLE_EVENT_REPORTING[3] = "\x04\x00\x00";
static const unsigned char EC_ENABLE_EVENT_REPORTING[3] = "\x04\x00\x01"; static const unsigned char EC_ENABLE_EVENT_REPORTING[3] = "\x04\x00\x01";
static const unsigned char EC_GET_FIRMWARE_VERSION[2] = "\x07\x15"; static const unsigned char EC_GET_FIRMWARE_VERSION[2] = "\x07\x15";
...@@ -131,23 +141,31 @@ static int nvec_status_notifier(struct notifier_block *nb, ...@@ -131,23 +141,31 @@ static int nvec_status_notifier(struct notifier_block *nb,
/** /**
* nvec_msg_alloc: * nvec_msg_alloc:
* @nvec: A &struct nvec_chip * @nvec: A &struct nvec_chip
* @category: Pool category, see &enum nvec_msg_category
* *
* Allocate a single &struct nvec_msg object from the message pool of * Allocate a single &struct nvec_msg object from the message pool of
* @nvec. The result shall be passed to nvec_msg_free() if no longer * @nvec. The result shall be passed to nvec_msg_free() if no longer
* used. * used.
*
* Outgoing messages are placed in the upper 75% of the pool, keeping the
* lower 25% available for RX buffers only. The reason is to prevent a
* situation where all buffers are full and a message is thus endlessly
* retried because the response could never be processed.
*/ */
static struct nvec_msg *nvec_msg_alloc(struct nvec_chip *nvec) static struct nvec_msg *nvec_msg_alloc(struct nvec_chip *nvec,
enum nvec_msg_category category)
{ {
int i; int i = (category == NVEC_MSG_TX) ? (NVEC_POOL_SIZE / 4) : 0;
for (i = 0; i < NVEC_POOL_SIZE; i++) { for (; i < NVEC_POOL_SIZE; i++) {
if (atomic_xchg(&nvec->msg_pool[i].used, 1) == 0) { if (atomic_xchg(&nvec->msg_pool[i].used, 1) == 0) {
dev_vdbg(nvec->dev, "INFO: Allocate %i\n", i); dev_vdbg(nvec->dev, "INFO: Allocate %i\n", i);
return &nvec->msg_pool[i]; return &nvec->msg_pool[i];
} }
} }
dev_err(nvec->dev, "could not allocate buffer\n"); dev_err(nvec->dev, "could not allocate %s buffer\n",
(category == NVEC_MSG_TX) ? "TX" : "RX");
return NULL; return NULL;
} }
...@@ -230,7 +248,8 @@ int nvec_write_async(struct nvec_chip *nvec, const unsigned char *data, ...@@ -230,7 +248,8 @@ int nvec_write_async(struct nvec_chip *nvec, const unsigned char *data,
struct nvec_msg *msg; struct nvec_msg *msg;
unsigned long flags; unsigned long flags;
msg = nvec_msg_alloc(nvec); msg = nvec_msg_alloc(nvec, NVEC_MSG_TX);
if (msg == NULL) if (msg == NULL)
return -ENOMEM; return -ENOMEM;
...@@ -534,7 +553,7 @@ static irqreturn_t nvec_interrupt(int irq, void *dev) ...@@ -534,7 +553,7 @@ static irqreturn_t nvec_interrupt(int irq, void *dev)
if (status != I2C_SL_IRQ) { if (status != I2C_SL_IRQ) {
nvec_invalid_flags(nvec, status, true); nvec_invalid_flags(nvec, status, true);
} else { } else {
nvec->rx = nvec_msg_alloc(nvec); nvec->rx = nvec_msg_alloc(nvec, NVEC_MSG_RX);
nvec->rx->data[0] = received; nvec->rx->data[0] = received;
nvec->rx->pos = 1; nvec->rx->pos = 1;
nvec->state = 2; nvec->state = 2;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment