[PATCH v2 1/7] firmware: tegra: Simplify channel management

2018-02-05 Thread Mikko Perttunen
The Tegra194 BPMP only implements 5 channels (4 to BPMP, 1 to CCPLEX),
and they are not placed contiguously in memory. The current channel
management in the BPMP driver does not support this.

Simplify and refactor the channel management such that only one atomic
transmit channel and one receive channel are supported, and channels
are not required to be placed contiguously in memory. The same
configuration also works on T186 so we end up with less code.

Signed-off-by: Mikko Perttunen 
---
 drivers/firmware/tegra/bpmp.c | 142 +++---
 include/soc/tegra/bpmp.h  |   4 +-
 2 files changed, 66 insertions(+), 80 deletions(-)

diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c
index a7f461f2e650..81bc2dce8626 100644
--- a/drivers/firmware/tegra/bpmp.c
+++ b/drivers/firmware/tegra/bpmp.c
@@ -70,57 +70,20 @@ void tegra_bpmp_put(struct tegra_bpmp *bpmp)
 }
 EXPORT_SYMBOL_GPL(tegra_bpmp_put);
 
-static int tegra_bpmp_channel_get_index(struct tegra_bpmp_channel *channel)
-{
-   return channel - channel->bpmp->channels;
-}
-
 static int
 tegra_bpmp_channel_get_thread_index(struct tegra_bpmp_channel *channel)
 {
struct tegra_bpmp *bpmp = channel->bpmp;
-   unsigned int offset, count;
+   unsigned int count;
int index;
 
-   offset = bpmp->soc->channels.thread.offset;
count = bpmp->soc->channels.thread.count;
 
-   index = tegra_bpmp_channel_get_index(channel);
-   if (index < 0)
-   return index;
-
-   if (index < offset || index >= offset + count)
+   index = channel - channel->bpmp->threaded_channels;
+   if (index < 0 || index >= count)
return -EINVAL;
 
-   return index - offset;
-}
-
-static struct tegra_bpmp_channel *
-tegra_bpmp_channel_get_thread(struct tegra_bpmp *bpmp, unsigned int index)
-{
-   unsigned int offset = bpmp->soc->channels.thread.offset;
-   unsigned int count = bpmp->soc->channels.thread.count;
-
-   if (index >= count)
-   return NULL;
-
-   return >channels[offset + index];
-}
-
-static struct tegra_bpmp_channel *
-tegra_bpmp_channel_get_tx(struct tegra_bpmp *bpmp)
-{
-   unsigned int offset = bpmp->soc->channels.cpu_tx.offset;
-
-   return >channels[offset + smp_processor_id()];
-}
-
-static struct tegra_bpmp_channel *
-tegra_bpmp_channel_get_rx(struct tegra_bpmp *bpmp)
-{
-   unsigned int offset = bpmp->soc->channels.cpu_rx.offset;
-
-   return >channels[offset];
+   return index;
 }
 
 static bool tegra_bpmp_message_valid(const struct tegra_bpmp_message *msg)
@@ -271,11 +234,7 @@ tegra_bpmp_write_threaded(struct tegra_bpmp *bpmp, 
unsigned int mrq,
goto unlock;
}
 
-   channel = tegra_bpmp_channel_get_thread(bpmp, index);
-   if (!channel) {
-   err = -EINVAL;
-   goto unlock;
-   }
+   channel = >threaded_channels[index];
 
if (!tegra_bpmp_master_free(channel)) {
err = -EBUSY;
@@ -328,12 +287,18 @@ int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp,
if (!tegra_bpmp_message_valid(msg))
return -EINVAL;
 
-   channel = tegra_bpmp_channel_get_tx(bpmp);
+   channel = bpmp->tx_channel;
+
+   spin_lock(>atomic_tx_lock);
 
err = tegra_bpmp_channel_write(channel, msg->mrq, MSG_ACK,
   msg->tx.data, msg->tx.size);
-   if (err < 0)
+   if (err < 0) {
+   spin_unlock(>atomic_tx_lock);
return err;
+   }
+
+   spin_unlock(>atomic_tx_lock);
 
err = mbox_send_message(bpmp->mbox.channel, NULL);
if (err < 0)
@@ -607,7 +572,7 @@ static void tegra_bpmp_handle_rx(struct mbox_client 
*client, void *data)
unsigned int i, count;
unsigned long *busy;
 
-   channel = tegra_bpmp_channel_get_rx(bpmp);
+   channel = bpmp->rx_channel;
count = bpmp->soc->channels.thread.count;
busy = bpmp->threaded.busy;
 
@@ -619,9 +584,7 @@ static void tegra_bpmp_handle_rx(struct mbox_client 
*client, void *data)
for_each_set_bit(i, busy, count) {
struct tegra_bpmp_channel *channel;
 
-   channel = tegra_bpmp_channel_get_thread(bpmp, i);
-   if (!channel)
-   continue;
+   channel = >threaded_channels[i];
 
if (tegra_bpmp_master_acked(channel)) {
tegra_bpmp_channel_signal(channel);
@@ -698,7 +661,6 @@ static void tegra_bpmp_channel_cleanup(struct 
tegra_bpmp_channel *channel)
 
 static int tegra_bpmp_probe(struct platform_device *pdev)
 {
-   struct tegra_bpmp_channel *channel;
struct tegra_bpmp *bpmp;
unsigned int i;
char tag[32];
@@ -758,24 +720,45 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
goto free_rx;
}
 
-   bpmp->num_channels = 

[PATCH v2 1/7] firmware: tegra: Simplify channel management

2018-02-05 Thread Mikko Perttunen
The Tegra194 BPMP only implements 5 channels (4 to BPMP, 1 to CCPLEX),
and they are not placed contiguously in memory. The current channel
management in the BPMP driver does not support this.

Simplify and refactor the channel management such that only one atomic
transmit channel and one receive channel are supported, and channels
are not required to be placed contiguously in memory. The same
configuration also works on T186 so we end up with less code.

Signed-off-by: Mikko Perttunen 
---
 drivers/firmware/tegra/bpmp.c | 142 +++---
 include/soc/tegra/bpmp.h  |   4 +-
 2 files changed, 66 insertions(+), 80 deletions(-)

diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c
index a7f461f2e650..81bc2dce8626 100644
--- a/drivers/firmware/tegra/bpmp.c
+++ b/drivers/firmware/tegra/bpmp.c
@@ -70,57 +70,20 @@ void tegra_bpmp_put(struct tegra_bpmp *bpmp)
 }
 EXPORT_SYMBOL_GPL(tegra_bpmp_put);
 
-static int tegra_bpmp_channel_get_index(struct tegra_bpmp_channel *channel)
-{
-   return channel - channel->bpmp->channels;
-}
-
 static int
 tegra_bpmp_channel_get_thread_index(struct tegra_bpmp_channel *channel)
 {
struct tegra_bpmp *bpmp = channel->bpmp;
-   unsigned int offset, count;
+   unsigned int count;
int index;
 
-   offset = bpmp->soc->channels.thread.offset;
count = bpmp->soc->channels.thread.count;
 
-   index = tegra_bpmp_channel_get_index(channel);
-   if (index < 0)
-   return index;
-
-   if (index < offset || index >= offset + count)
+   index = channel - channel->bpmp->threaded_channels;
+   if (index < 0 || index >= count)
return -EINVAL;
 
-   return index - offset;
-}
-
-static struct tegra_bpmp_channel *
-tegra_bpmp_channel_get_thread(struct tegra_bpmp *bpmp, unsigned int index)
-{
-   unsigned int offset = bpmp->soc->channels.thread.offset;
-   unsigned int count = bpmp->soc->channels.thread.count;
-
-   if (index >= count)
-   return NULL;
-
-   return >channels[offset + index];
-}
-
-static struct tegra_bpmp_channel *
-tegra_bpmp_channel_get_tx(struct tegra_bpmp *bpmp)
-{
-   unsigned int offset = bpmp->soc->channels.cpu_tx.offset;
-
-   return >channels[offset + smp_processor_id()];
-}
-
-static struct tegra_bpmp_channel *
-tegra_bpmp_channel_get_rx(struct tegra_bpmp *bpmp)
-{
-   unsigned int offset = bpmp->soc->channels.cpu_rx.offset;
-
-   return >channels[offset];
+   return index;
 }
 
 static bool tegra_bpmp_message_valid(const struct tegra_bpmp_message *msg)
@@ -271,11 +234,7 @@ tegra_bpmp_write_threaded(struct tegra_bpmp *bpmp, 
unsigned int mrq,
goto unlock;
}
 
-   channel = tegra_bpmp_channel_get_thread(bpmp, index);
-   if (!channel) {
-   err = -EINVAL;
-   goto unlock;
-   }
+   channel = >threaded_channels[index];
 
if (!tegra_bpmp_master_free(channel)) {
err = -EBUSY;
@@ -328,12 +287,18 @@ int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp,
if (!tegra_bpmp_message_valid(msg))
return -EINVAL;
 
-   channel = tegra_bpmp_channel_get_tx(bpmp);
+   channel = bpmp->tx_channel;
+
+   spin_lock(>atomic_tx_lock);
 
err = tegra_bpmp_channel_write(channel, msg->mrq, MSG_ACK,
   msg->tx.data, msg->tx.size);
-   if (err < 0)
+   if (err < 0) {
+   spin_unlock(>atomic_tx_lock);
return err;
+   }
+
+   spin_unlock(>atomic_tx_lock);
 
err = mbox_send_message(bpmp->mbox.channel, NULL);
if (err < 0)
@@ -607,7 +572,7 @@ static void tegra_bpmp_handle_rx(struct mbox_client 
*client, void *data)
unsigned int i, count;
unsigned long *busy;
 
-   channel = tegra_bpmp_channel_get_rx(bpmp);
+   channel = bpmp->rx_channel;
count = bpmp->soc->channels.thread.count;
busy = bpmp->threaded.busy;
 
@@ -619,9 +584,7 @@ static void tegra_bpmp_handle_rx(struct mbox_client 
*client, void *data)
for_each_set_bit(i, busy, count) {
struct tegra_bpmp_channel *channel;
 
-   channel = tegra_bpmp_channel_get_thread(bpmp, i);
-   if (!channel)
-   continue;
+   channel = >threaded_channels[i];
 
if (tegra_bpmp_master_acked(channel)) {
tegra_bpmp_channel_signal(channel);
@@ -698,7 +661,6 @@ static void tegra_bpmp_channel_cleanup(struct 
tegra_bpmp_channel *channel)
 
 static int tegra_bpmp_probe(struct platform_device *pdev)
 {
-   struct tegra_bpmp_channel *channel;
struct tegra_bpmp *bpmp;
unsigned int i;
char tag[32];
@@ -758,24 +720,45 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
goto free_rx;
}
 
-   bpmp->num_channels = bpmp->soc->channels.cpu_tx.count +
-