summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArun Murthy <arun.murthy@stericsson.com>2011-09-08 16:56:48 +0530
committerMathieu J. Poirier <mathieu.poirier@linaro.org>2011-11-10 11:12:18 -0700
commit42813f3a235a525cae87ad5dbfe313aaed2d416e (patch)
tree88c852d59d1e6daa6d62c268aca2bb0d830a2c63
parentd627724af2455ddd0c8e0c9e9014beb39c5fa99e (diff)
mbox: optimize tx path and fix bug in rx path
During tx, in the work function check for if any messages are pending to be transmitted, if so, re-transmit. If in rx path work function is queued twice then the work is executed only once so the other message will be lost. Hence check if work has been queued and if so read the next message. ST-Ericsson Linux next: NA ST-Ericsson ID: 357703 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I7f3a18947e36cae30da8ca391d10ed5d3ac0eb03 Signed-off-by: Arun Murthy <arun.murthy@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/31742 Reviewed-by: Bibek BASU <bibek.basu@stericsson.com> Tested-by: Bibek BASU <bibek.basu@stericsson.com>
-rw-r--r--drivers/misc/mbox.c6
-rw-r--r--drivers/misc/mbox_channels-db5500.c36
2 files changed, 36 insertions, 6 deletions
diff --git a/drivers/misc/mbox.c b/drivers/misc/mbox.c
index b2810718822..5f5a457b277 100644
--- a/drivers/misc/mbox.c
+++ b/drivers/misc/mbox.c
@@ -348,6 +348,7 @@ static irqreturn_t mbox_irq(int irq, void *arg)
if (nbr_occup == 0)
goto exit;
+redo:
if (mbox->cb == NULL) {
dev_dbg(&(mbox->pdev->dev), "No receive callback registered, "
"leaving %d incoming messages in fifo!\n", nbr_occup);
@@ -363,6 +364,11 @@ static irqreturn_t mbox_irq(int irq, void *arg)
mbox_value);
mbox->cb(mbox_value, mbox->client_data);
+ nbr_occup = readl(mbox->virtbase_local + MBOX_FIFO_STATUS) & 0x7;
+
+ if (nbr_occup > 0)
+ goto redo;
+
exit:
dev_dbg(&(mbox->pdev->dev), "Exit mbox IRQ. ri = %d, wi = %d\n",
mbox->read_index, mbox->write_index);
diff --git a/drivers/misc/mbox_channels-db5500.c b/drivers/misc/mbox_channels-db5500.c
index a0b72d4d97a..43a4d57caaf 100644
--- a/drivers/misc/mbox_channels-db5500.c
+++ b/drivers/misc/mbox_channels-db5500.c
@@ -121,7 +121,7 @@ struct rx_pending_elem {
void *priv;
};
-struct rx_pending_elem rx_pending[NUM_DSP_BUFFER + 1];
+struct rx_pending_elem rx_pending[NUM_DSP_BUFFER];
/* This structure holds list of pending elements for mbox tx channel */
struct tx_channel {
@@ -154,6 +154,7 @@ struct rx_channel {
* @lock: holds lock for channel
*/
struct channel_status {
+ atomic_t rcv_counter;
struct list_head list;
u16 channel;
int state;
@@ -362,6 +363,9 @@ void mbox_handle_receive_msg(struct work_struct *work)
struct channel_status,
receive_msg);
+ if (!atomic_read(&rx_chan->rcv_counter))
+ return;
+rcv_msg:
/* Call client's callback and reset state */
if (rx_chan->cb) {
static int rx_pending_count;
@@ -375,6 +379,8 @@ void mbox_handle_receive_msg(struct work_struct *work)
dev_err(&channels.pdev->dev,
"%s no callback provided\n", __func__);
}
+ if (atomic_dec_and_test(&rx_chan->rcv_counter) > 0)
+ goto rcv_msg;
}
@@ -413,12 +419,14 @@ static bool handle_receive_msg(u32 mbox_msg, struct channel_status *rx_chan)
if (rx_chan) {
/* Store received data in RX channel buffer */
rx_chan->rx.buffer[rx_chan->rx.index++] = mbox_msg;
+
/* Check if it's last data of PDU */
if (rx_chan->rx.index == rx_chan->rx.length) {
for (i = 0; i < MAILBOX_NR_OF_DATAWORDS; i++) {
rx_pending[rx_pending_count].buffer[i] =
rx_chan->rx.buffer[i];
}
+
rx_pending[rx_pending_count].length =
rx_chan->rx.length;
rx_pending[rx_pending_count].priv = rx_chan->priv;
@@ -429,10 +437,12 @@ static bool handle_receive_msg(u32 mbox_msg, struct channel_status *rx_chan)
rx_pending_count++;
if (rx_pending_count == NUM_DSP_BUFFER)
rx_pending_count = 0;
+ atomic_inc(&rx_chan->rcv_counter);
queue_work(rx_chan->receive_wq,
&rx_chan->receive_msg);
}
dev_dbg(&channels.pdev->dev, "%s OK\n", __func__);
+
return true;
}
return false;
@@ -529,6 +539,9 @@ static void mbox_cb(u32 mbox_msg, void *priv)
struct channel_status *rx_chan = NULL;
bool is_Payload = 0;
+ dev_dbg(&channels.pdev->dev, "%s type %d\t, mbox_msg %x\n",
+ __func__, type, mbox_msg);
+
/* Get RX channels list for given mbox unit */
rx_list = get_rx_list(mbox_id);
if (rx_list == NULL) {
@@ -606,6 +619,7 @@ int mbox_channel_register(u16 channel, mbox_channel_cb_t *cb, void *priv)
int res = 0;
struct mbox_unit_status *mbox_unit;
+ dev_dbg(&channels.pdev->dev, " %s channel = %d\n", __func__, channel);
/* Check for callback fcn */
if (cb == NULL) {
dev_err(&channels.pdev->dev,
@@ -655,6 +669,7 @@ int mbox_channel_register(u16 channel, mbox_channel_cb_t *cb, void *priv)
goto exit;
}
+ atomic_set(&rx_chan->rcv_counter, 0);
/* Fill out newly allocated element and add it to rx list */
rx_chan->channel = channel;
rx_chan->cb = cb;
@@ -780,22 +795,26 @@ int mbox_channel_send(struct mbox_channel_msg *msg)
struct channel_status *tx_chan = NULL;
struct pending_elem *pending;
struct mbox_unit_status *mbox_unit;
+ int res = 0;
if (msg->length > MAILBOX_NR_OF_DATAWORDS || msg->length == 0) {
dev_err(&channels.pdev->dev, "data length incorrect\n");
- return -EINVAL;
+ res = -EINVAL;
+ goto exit;
}
if (!check_channel(msg->channel, MBOX_TX)) {
dev_err(&channels.pdev->dev, "wrong channel number %d\n",
msg->channel);
- return -EINVAL;
+ res = -EINVAL;
+ goto exit;
}
tx_list = get_tx_list(get_mbox_id(msg->channel));
if (tx_list == NULL) {
dev_err(&channels.pdev->dev, "given mbox id is not valid\n");
- return -EINVAL;
+ res = -EINVAL;
+ goto exit;
}
mbox_unit = container_of(tx_list, struct mbox_unit_status, tx_chans);
@@ -814,7 +833,8 @@ int mbox_channel_send(struct mbox_channel_msg *msg)
if (pending == NULL) {
dev_err(&channels.pdev->dev,
"couldn't allocate memory for pending\n");
- return -ENOMEM;
+ res = -ENOMEM;
+ goto exit;
}
pending->data = msg->data;
pending->length = msg->length;
@@ -836,7 +856,8 @@ int mbox_channel_send(struct mbox_channel_msg *msg)
dev_err(&channels.pdev->dev,
"couldn't allocate memory for \
tx_chan\n");
- return -ENOMEM;
+ res = -ENOMEM;
+ goto exit;
}
tx_chan->channel = msg->channel;
tx_chan->cb = msg->cb;
@@ -856,6 +877,9 @@ int mbox_channel_send(struct mbox_channel_msg *msg)
mutex_unlock(&tx_chan->lock);
}
return 0;
+
+exit:
+ return res;
}
EXPORT_SYMBOL(mbox_channel_send);