Allow TX buffers to be allocated only in the lower 75% of the pool to avoid a completely filled buffer preventing the driver from processing responses. Signed-off-by: Julian Andres Klode <jak@xxxxxxxxxxxxx> --- drivers/staging/nvec/nvec.c | 32 +++++++++++++++++++++++++++----- 1 files changed, 27 insertions(+), 5 deletions(-) diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c index 34b9c11..13934d9 100644 --- a/drivers/staging/nvec/nvec.c +++ b/drivers/staging/nvec/nvec.c @@ -62,6 +62,16 @@ #define I2C_SL_ADDR2 0x30 #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_ENABLE_EVENT_REPORTING[3] = "\x04\x00\x01"; static const unsigned char EC_GET_FIRMWARE_VERSION[2] = "\x07\x15"; @@ -135,21 +145,32 @@ static int nvec_status_notifier(struct notifier_block *nb, /** * nvec_msg_alloc: * @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 * @nvec. The result shall be passed to nvec_msg_free() if no longer * used. + * + * Outgoing messages are placed in the lower 75% of the pool, keeping the + * upper 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) { size_t i; - for (i = 0; i < NVEC_POOL_SIZE; i++) + size_t max = NVEC_POOL_SIZE; + if (category == NVEC_MSG_TX) + max = 3 * max / 4; + for (i = 0; i < max ; i++) if (atomic_xchg(&nvec->msg_pool[i].used, 1) == 0) { dev_vdbg(nvec->dev, "INFO: Alloc %u\n", (uint) 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; } @@ -231,7 +252,8 @@ int nvec_write_async(struct nvec_chip *nvec, const unsigned char *data, struct nvec_msg *msg; unsigned long flags; - msg = nvec_msg_alloc(nvec); + msg = nvec_msg_alloc(nvec, NVEC_MSG_TX); + if (msg == NULL) return -ENOMEM; @@ -535,7 +557,7 @@ static irqreturn_t nvec_interrupt(int irq, void *dev) if (status != I2C_SL_IRQ) { nvec_invalid_flags(nvec, status, true); } else { - nvec->rx = nvec_msg_alloc(nvec); + nvec->rx = nvec_msg_alloc(nvec, NVEC_MSG_RX); nvec->rx->data[0] = received; nvec->rx->pos = 1; nvec->state = 2; -- 1.7.5.4 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/devel