aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/nvec
diff options
context:
space:
mode:
authorJulian Andres Klode <jak@jak-linux.org>2011-09-27 19:00:59 +0200
committerGreg Kroah-Hartman <gregkh@suse.de>2011-09-29 17:41:36 -0700
commitbb0590e2723eed53b524d61cf011d53fc7280949 (patch)
treed34c8a10090ead1242c71882df26191639be2555 /drivers/staging/nvec
parentstaging: nvec: Export nvec_msg_free() to clients (diff)
downloadlinux-dev-bb0590e2723eed53b524d61cf011d53fc7280949.tar.xz
linux-dev-bb0590e2723eed53b524d61cf011d53fc7280949.zip
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: Julian Andres Klode <jak@jak-linux.org> Acked-by: Marc Dietrich <marvin24@gmx.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/nvec')
-rw-r--r--drivers/staging/nvec/nvec.c31
1 files changed, 25 insertions, 6 deletions
diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c
index 488d7dd78a2f..c05adcd7fbfd 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";
@@ -131,23 +141,31 @@ 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 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) {
dev_vdbg(nvec->dev, "INFO: Allocate %i\n", 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;
}
@@ -230,7 +248,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;
@@ -534,7 +553,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;