[PATCH 22/30] staging: nvec: Allow TX buffers only in the lower 75% of the pool

Julian Andres Klode jak at jak-linux.org
Fri Sep 23 16:38:14 UTC 2011


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 at jak-linux.org>
---
 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




More information about the devel mailing list