[v7,07/20] mailbox: Allow direct registration to a channel
Commit Message
Support virtual mailbox controllers and clients which are not platform
devices or come from the devicetree by allowing them to match client to
channel via some other mechanism.
Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
---
drivers/mailbox/mailbox.c | 96 ++++++++++++++++++++++++----------
drivers/mailbox/omap-mailbox.c | 18 ++-----
drivers/mailbox/pcc.c | 17 ++----
include/linux/mailbox_client.h | 1 +
4 files changed, 76 insertions(+), 56 deletions(-)
Comments
Hi Elliot,
I love your patch! Perhaps something to improve:
[auto build test WARNING on 094226ad94f471a9f19e8f8e7140a09c2625abaa]
url: https://github.com/intel-lab-lkp/linux/commits/Elliot-Berman/Drivers-for-gunyah-hypervisor/20221121-220942
base: 094226ad94f471a9f19e8f8e7140a09c2625abaa
patch link: https://lore.kernel.org/r/20221121140009.2353512-8-quic_eberman%40quicinc.com
patch subject: [PATCH v7 07/20] mailbox: Allow direct registration to a channel
config: x86_64-allyesconfig
compiler: gcc-11 (Debian 11.3.0-8) 11.3.0
reproduce (this is a W=1 build):
# https://github.com/intel-lab-lkp/linux/commit/5b7d4244a3896cfa8c098f01bee924c3ea869884
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Elliot-Berman/Drivers-for-gunyah-hypervisor/20221121-220942
git checkout 5b7d4244a3896cfa8c098f01bee924c3ea869884
# save the config file
mkdir build_dir && cp config build_dir/.config
make W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash drivers/mailbox/
If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
All warnings (new ones prefixed by >>):
drivers/mailbox/pcc.c: In function 'pcc_mbox_request_channel':
>> drivers/mailbox/pcc.c:286:23: warning: unused variable 'flags' [-Wunused-variable]
286 | unsigned long flags;
| ^~~~~
vim +/flags +286 drivers/mailbox/pcc.c
aca314efb177274 hotran 2016-08-15 267
86c22f8c9a3b71d Ashwin Chaugule 2014-11-12 268 /**
86c22f8c9a3b71d Ashwin Chaugule 2014-11-12 269 * pcc_mbox_request_channel - PCC clients call this function to
86c22f8c9a3b71d Ashwin Chaugule 2014-11-12 270 * request a pointer to their PCC subspace, from which they
86c22f8c9a3b71d Ashwin Chaugule 2014-11-12 271 * can get the details of communicating with the remote.
86c22f8c9a3b71d Ashwin Chaugule 2014-11-12 272 * @cl: Pointer to Mailbox client, so we know where to bind the
86c22f8c9a3b71d Ashwin Chaugule 2014-11-12 273 * Channel.
86c22f8c9a3b71d Ashwin Chaugule 2014-11-12 274 * @subspace_id: The PCC Subspace index as parsed in the PCC client
86c22f8c9a3b71d Ashwin Chaugule 2014-11-12 275 * ACPI package. This is used to lookup the array of PCC
86c22f8c9a3b71d Ashwin Chaugule 2014-11-12 276 * subspaces as parsed by the PCC Mailbox controller.
86c22f8c9a3b71d Ashwin Chaugule 2014-11-12 277 *
7b6da7fe7bba1cd Sudeep Holla 2021-09-17 278 * Return: Pointer to the PCC Mailbox Channel if successful or ERR_PTR.
86c22f8c9a3b71d Ashwin Chaugule 2014-11-12 279 */
7b6da7fe7bba1cd Sudeep Holla 2021-09-17 280 struct pcc_mbox_chan *
7b6da7fe7bba1cd Sudeep Holla 2021-09-17 281 pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id)
86c22f8c9a3b71d Ashwin Chaugule 2014-11-12 282 {
80b2bdde002c521 Sudeep Holla 2021-09-17 283 struct pcc_chan_info *pchan;
86c22f8c9a3b71d Ashwin Chaugule 2014-11-12 284 struct mbox_chan *chan;
ce028702ddbc697 Sudeep Holla 2021-09-17 285 struct device *dev;
86c22f8c9a3b71d Ashwin Chaugule 2014-11-12 @286 unsigned long flags;
5b7d4244a3896cf Elliot Berman 2022-11-21 287 int rc;
86c22f8c9a3b71d Ashwin Chaugule 2014-11-12 288
ce028702ddbc697 Sudeep Holla 2021-09-17 289 if (subspace_id < 0 || subspace_id >= pcc_chan_count)
7b6da7fe7bba1cd Sudeep Holla 2021-09-17 290 return ERR_PTR(-ENOENT);
86c22f8c9a3b71d Ashwin Chaugule 2014-11-12 291
7b6da7fe7bba1cd Sudeep Holla 2021-09-17 292 pchan = chan_info + subspace_id;
7b6da7fe7bba1cd Sudeep Holla 2021-09-17 293 chan = pchan->chan.mchan;
d311a28a5853857 Sudip Mukherjee 2015-09-16 294 if (IS_ERR(chan) || chan->cl) {
960c4056aadcf61 Sudeep Holla 2021-12-09 295 pr_err("Channel not found for idx: %d\n", subspace_id);
86c22f8c9a3b71d Ashwin Chaugule 2014-11-12 296 return ERR_PTR(-EBUSY);
86c22f8c9a3b71d Ashwin Chaugule 2014-11-12 297 }
ce028702ddbc697 Sudeep Holla 2021-09-17 298 dev = chan->mbox->dev;
86c22f8c9a3b71d Ashwin Chaugule 2014-11-12 299
5b7d4244a3896cf Elliot Berman 2022-11-21 300 rc = mbox_bind_client(chan, cl);
5b7d4244a3896cf Elliot Berman 2022-11-21 301 if (rc)
5b7d4244a3896cf Elliot Berman 2022-11-21 302 return ERR_PTR(rc);
6ca595a70bc46e1 Hoan Tran 2016-11-14 303
f92ae90e52bb09d Sudeep Holla 2021-09-17 304 if (pchan->plat_irq > 0) {
f92ae90e52bb09d Sudeep Holla 2021-09-17 305 rc = devm_request_irq(dev, pchan->plat_irq, pcc_mbox_irq, 0,
80b2bdde002c521 Sudeep Holla 2021-09-17 306 MBOX_IRQ_NAME, chan);
aca314efb177274 hotran 2016-08-15 307 if (unlikely(rc)) {
aca314efb177274 hotran 2016-08-15 308 dev_err(dev, "failed to register PCC interrupt %d\n",
f92ae90e52bb09d Sudeep Holla 2021-09-17 309 pchan->plat_irq);
7b6da7fe7bba1cd Sudeep Holla 2021-09-17 310 pcc_mbox_free_channel(&pchan->chan);
7b6da7fe7bba1cd Sudeep Holla 2021-09-17 311 return ERR_PTR(rc);
aca314efb177274 hotran 2016-08-15 312 }
aca314efb177274 hotran 2016-08-15 313 }
aca314efb177274 hotran 2016-08-15 314
7b6da7fe7bba1cd Sudeep Holla 2021-09-17 315 return &pchan->chan;
86c22f8c9a3b71d Ashwin Chaugule 2014-11-12 316 }
86c22f8c9a3b71d Ashwin Chaugule 2014-11-12 317 EXPORT_SYMBOL_GPL(pcc_mbox_request_channel);
86c22f8c9a3b71d Ashwin Chaugule 2014-11-12 318
@@ -317,6 +317,71 @@ int mbox_flush(struct mbox_chan *chan, unsigned long timeout)
}
EXPORT_SYMBOL_GPL(mbox_flush);
+static int __mbox_bind_client(struct mbox_chan *chan, struct mbox_client *cl)
+{
+ struct device *dev = cl->dev;
+ unsigned long flags;
+ int ret;
+
+ if (chan->cl || !try_module_get(chan->mbox->dev->driver->owner)) {
+ dev_dbg(dev, "%s: mailbox not free\n", __func__);
+ return -EBUSY;
+ }
+
+ spin_lock_irqsave(&chan->lock, flags);
+ chan->msg_free = 0;
+ chan->msg_count = 0;
+ chan->active_req = NULL;
+ chan->cl = cl;
+ init_completion(&chan->tx_complete);
+
+ if (chan->txdone_method == TXDONE_BY_POLL && cl->knows_txdone)
+ chan->txdone_method = TXDONE_BY_ACK;
+
+ spin_unlock_irqrestore(&chan->lock, flags);
+
+ if (chan->mbox->ops->startup) {
+ ret = chan->mbox->ops->startup(chan);
+
+ if (ret) {
+ dev_err(dev, "Unable to startup the chan (%d)\n", ret);
+ mbox_free_channel(chan);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * mbox_bind_client - Request a mailbox channel.
+ * @chan: The mailbox channel to bind the client to.
+ * @cl: Identity of the client requesting the channel.
+ *
+ * The Client specifies its requirements and capabilities while asking for
+ * a mailbox channel. It can't be called from atomic context.
+ * The channel is exclusively allocated and can't be used by another
+ * client before the owner calls mbox_free_channel.
+ * After assignment, any packet received on this channel will be
+ * handed over to the client via the 'rx_callback'.
+ * The framework holds reference to the client, so the mbox_client
+ * structure shouldn't be modified until the mbox_free_channel returns.
+ *
+ * Return: 0 if the channel was assigned to the client successfully.
+ * <0 for request failure.
+ */
+int mbox_bind_client(struct mbox_chan *chan, struct mbox_client *cl)
+{
+ int ret;
+
+ mutex_lock(&con_mutex);
+ ret = __mbox_bind_client(chan, cl);
+ mutex_unlock(&con_mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(mbox_bind_client);
+
/**
* mbox_request_channel - Request a mailbox channel.
* @cl: Identity of the client requesting the channel.
@@ -340,7 +405,6 @@ struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index)
struct mbox_controller *mbox;
struct of_phandle_args spec;
struct mbox_chan *chan;
- unsigned long flags;
int ret;
if (!dev || !dev->of_node) {
@@ -372,33 +436,9 @@ struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index)
return chan;
}
- if (chan->cl || !try_module_get(mbox->dev->driver->owner)) {
- dev_dbg(dev, "%s: mailbox not free\n", __func__);
- mutex_unlock(&con_mutex);
- return ERR_PTR(-EBUSY);
- }
-
- spin_lock_irqsave(&chan->lock, flags);
- chan->msg_free = 0;
- chan->msg_count = 0;
- chan->active_req = NULL;
- chan->cl = cl;
- init_completion(&chan->tx_complete);
-
- if (chan->txdone_method == TXDONE_BY_POLL && cl->knows_txdone)
- chan->txdone_method = TXDONE_BY_ACK;
-
- spin_unlock_irqrestore(&chan->lock, flags);
-
- if (chan->mbox->ops->startup) {
- ret = chan->mbox->ops->startup(chan);
-
- if (ret) {
- dev_err(dev, "Unable to startup the chan (%d)\n", ret);
- mbox_free_channel(chan);
- chan = ERR_PTR(ret);
- }
- }
+ ret = __mbox_bind_client(chan, cl);
+ if (ret)
+ chan = ERR_PTR(ret);
mutex_unlock(&con_mutex);
return chan;
@@ -441,21 +441,9 @@ struct mbox_chan *omap_mbox_request_channel(struct mbox_client *cl,
if (!mbox || !mbox->chan)
return ERR_PTR(-ENOENT);
- chan = mbox->chan;
- spin_lock_irqsave(&chan->lock, flags);
- chan->msg_free = 0;
- chan->msg_count = 0;
- chan->active_req = NULL;
- chan->cl = cl;
- init_completion(&chan->tx_complete);
- spin_unlock_irqrestore(&chan->lock, flags);
-
- ret = chan->mbox->ops->startup(chan);
- if (ret) {
- pr_err("Unable to startup the chan (%d)\n", ret);
- mbox_free_channel(chan);
- chan = ERR_PTR(ret);
- }
+ ret = mbox_bind_client(mbox->chan, cl);
+ if (ret)
+ return ERR_PTR(ret);
return chan;
}
@@ -284,6 +284,7 @@ pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id)
struct mbox_chan *chan;
struct device *dev;
unsigned long flags;
+ int rc;
if (subspace_id < 0 || subspace_id >= pcc_chan_count)
return ERR_PTR(-ENOENT);
@@ -296,21 +297,11 @@ pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id)
}
dev = chan->mbox->dev;
- spin_lock_irqsave(&chan->lock, flags);
- chan->msg_free = 0;
- chan->msg_count = 0;
- chan->active_req = NULL;
- chan->cl = cl;
- init_completion(&chan->tx_complete);
-
- if (chan->txdone_method == TXDONE_BY_POLL && cl->knows_txdone)
- chan->txdone_method = TXDONE_BY_ACK;
-
- spin_unlock_irqrestore(&chan->lock, flags);
+ rc = mbox_bind_client(chan, cl);
+ if (rc)
+ return ERR_PTR(rc);
if (pchan->plat_irq > 0) {
- int rc;
-
rc = devm_request_irq(dev, pchan->plat_irq, pcc_mbox_irq, 0,
MBOX_IRQ_NAME, chan);
if (unlikely(rc)) {
@@ -37,6 +37,7 @@ struct mbox_client {
void (*tx_done)(struct mbox_client *cl, void *mssg, int r);
};
+int mbox_bind_client(struct mbox_chan *chan, struct mbox_client *cl);
struct mbox_chan *mbox_request_channel_byname(struct mbox_client *cl,
const char *name);
struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index);