[PATCH v2 21/30] staging: nvec: Allow TX buffers only in the upper 75% of the pool

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxxx>
Acked-by: Marc Dietrich <marvin24@xxxxxx>
---
 drivers/staging/nvec/nvec.c |   31 +++++++++++++++++++++++++------
 1 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c
index 488d7dd..c05adcd 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;
-- 
1.7.5.4

_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/devel


[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux