Message ID | 20191215042455.51001-9-samuel@sholland.org (mailing list archive) |
---|---|
State | Not Applicable, archived |
Headers | show |
Series | Allwinner sun6i message box support | expand |
On Sat, Dec 14, 2019 at 10:24:55PM -0600, Samuel Holland wrote: > Some mailbox controllers have only unidirectional channels, so we need a > pair of them for each SCPI channel. If a mbox-names property is present, > look for "rx" and "tx" mbox channels; otherwise, the existing behavior > is preserved, and a single mbox channel is used for each SCPI channel. > I need to look at the bindings again, but I think you must update it. > Note that since the mailbox framework only supports a single phandle > with each name (mbox_request_channel_byname always returns the first > one), this new mode only supports a single SCPI channel. > > Signed-off-by: Samuel Holland <samuel@sholland.org> > --- > drivers/firmware/arm_scpi.c | 58 +++++++++++++++++++++++++++++-------- > 1 file changed, 46 insertions(+), 12 deletions(-) > > diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c > index a80c331c3a6e..36ff9dd8d0fa 100644 > --- a/drivers/firmware/arm_scpi.c > +++ b/drivers/firmware/arm_scpi.c > @@ -231,7 +231,8 @@ struct scpi_xfer { > > struct scpi_chan { > struct mbox_client cl; > - struct mbox_chan *chan; > + struct mbox_chan *rx_chan; > + struct mbox_chan *tx_chan; > void __iomem *tx_payload; > void __iomem *rx_payload; > struct list_head rx_pending; > @@ -505,7 +506,7 @@ static int scpi_send_message(u8 idx, void *tx_buf, unsigned int tx_len, > msg->rx_len = rx_len; > reinit_completion(&msg->done); > > - ret = mbox_send_message(scpi_chan->chan, msg); > + ret = mbox_send_message(scpi_chan->tx_chan, msg); > if (ret < 0 || !rx_buf) > goto out; > > @@ -854,8 +855,13 @@ static void scpi_free_channels(void *data) > struct scpi_drvinfo *info = data; > int i; > > - for (i = 0; i < info->num_chans; i++) > - mbox_free_channel(info->channels[i].chan); > + for (i = 0; i < info->num_chans; i++) { > + struct scpi_chan *pchan = &info->channels[i]; > + > + if (pchan->tx_chan != pchan->rx_chan) > + mbox_free_channel(pchan->tx_chan); > + mbox_free_channel(pchan->rx_chan); I think mbox_free_channel handles !chan->cl, so just do unconditionally. > + } > } > > static int scpi_remove(struct platform_device *pdev) > @@ -903,6 +909,7 @@ static int scpi_probe(struct platform_device *pdev) > struct resource res; > struct device *dev = &pdev->dev; > struct device_node *np = dev->of_node; > + bool use_mbox_names = false; > > scpi_info = devm_kzalloc(dev, sizeof(*scpi_info), GFP_KERNEL); > if (!scpi_info) > @@ -916,6 +923,14 @@ static int scpi_probe(struct platform_device *pdev) > dev_err(dev, "no mboxes property in '%pOF'\n", np); > return -ENODEV; > } > + if (of_get_property(dev->of_node, "mbox-names", NULL)) { So, for this platform, this is required and must fail if it is not found. But instead your check here is optional and may end up populating 2 scpi channels instead of one. I would suggest to make it required and fail for it based on some compatible, otherwise you are not checking correctly. Something like: if (of_match_device(blah_blah_of_match, &pdev->dev)) { use_mbox_names = true; count = 1; } > + use_mbox_names = true; > + if (count != 2) { > + dev_err(dev, "need exactly 2 mboxes with mbox-names\n"); > + return -ENODEV; > + } > + count /= 2; > + } Ah, OK then you must update the binding as it's different usage of mailbox. General query, not related to this patch: If you are in process of implementing the firmware, I suggest to move to SCMI protocol than this one if not too late. This specification is deprecated and no longer updated while SCMI is actively developed and maintained. However it has slightly different notion of tx and rx and the way the specification commands which messages are synchronous and which can be async/delayed. -- Regards, Sudeep
diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c index a80c331c3a6e..36ff9dd8d0fa 100644 --- a/drivers/firmware/arm_scpi.c +++ b/drivers/firmware/arm_scpi.c @@ -231,7 +231,8 @@ struct scpi_xfer { struct scpi_chan { struct mbox_client cl; - struct mbox_chan *chan; + struct mbox_chan *rx_chan; + struct mbox_chan *tx_chan; void __iomem *tx_payload; void __iomem *rx_payload; struct list_head rx_pending; @@ -505,7 +506,7 @@ static int scpi_send_message(u8 idx, void *tx_buf, unsigned int tx_len, msg->rx_len = rx_len; reinit_completion(&msg->done); - ret = mbox_send_message(scpi_chan->chan, msg); + ret = mbox_send_message(scpi_chan->tx_chan, msg); if (ret < 0 || !rx_buf) goto out; @@ -854,8 +855,13 @@ static void scpi_free_channels(void *data) struct scpi_drvinfo *info = data; int i; - for (i = 0; i < info->num_chans; i++) - mbox_free_channel(info->channels[i].chan); + for (i = 0; i < info->num_chans; i++) { + struct scpi_chan *pchan = &info->channels[i]; + + if (pchan->tx_chan != pchan->rx_chan) + mbox_free_channel(pchan->tx_chan); + mbox_free_channel(pchan->rx_chan); + } } static int scpi_remove(struct platform_device *pdev) @@ -903,6 +909,7 @@ static int scpi_probe(struct platform_device *pdev) struct resource res; struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; + bool use_mbox_names = false; scpi_info = devm_kzalloc(dev, sizeof(*scpi_info), GFP_KERNEL); if (!scpi_info) @@ -916,6 +923,14 @@ static int scpi_probe(struct platform_device *pdev) dev_err(dev, "no mboxes property in '%pOF'\n", np); return -ENODEV; } + if (of_get_property(dev->of_node, "mbox-names", NULL)) { + use_mbox_names = true; + if (count != 2) { + dev_err(dev, "need exactly 2 mboxes with mbox-names\n"); + return -ENODEV; + } + count /= 2; + } scpi_info->channels = devm_kcalloc(dev, count, sizeof(struct scpi_chan), GFP_KERNEL); @@ -961,15 +976,34 @@ static int scpi_probe(struct platform_device *pdev) mutex_init(&pchan->xfers_lock); ret = scpi_alloc_xfer_list(dev, pchan); - if (!ret) { - pchan->chan = mbox_request_channel(cl, idx); - if (!IS_ERR(pchan->chan)) - continue; - ret = PTR_ERR(pchan->chan); - if (ret != -EPROBE_DEFER) - dev_err(dev, "failed to get channel%d err %d\n", - idx, ret); + if (ret) + return ret; + + if (use_mbox_names) { + pchan->rx_chan = mbox_request_channel_byname(cl, "rx"); + if (IS_ERR(pchan->rx_chan)) { + ret = PTR_ERR(pchan->rx_chan); + goto fail; + } + pchan->tx_chan = mbox_request_channel_byname(cl, "tx"); + if (IS_ERR(pchan->rx_chan)) { + ret = PTR_ERR(pchan->tx_chan); + goto fail; + } + } else { + pchan->rx_chan = mbox_request_channel(cl, idx); + if (IS_ERR(pchan->rx_chan)) { + ret = PTR_ERR(pchan->rx_chan); + goto fail; + } + pchan->tx_chan = pchan->rx_chan; } + continue; + +fail: + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to get channel%d err %d\n", + idx, ret); return ret; }
Some mailbox controllers have only unidirectional channels, so we need a pair of them for each SCPI channel. If a mbox-names property is present, look for "rx" and "tx" mbox channels; otherwise, the existing behavior is preserved, and a single mbox channel is used for each SCPI channel. Note that since the mailbox framework only supports a single phandle with each name (mbox_request_channel_byname always returns the first one), this new mode only supports a single SCPI channel. Signed-off-by: Samuel Holland <samuel@sholland.org> --- drivers/firmware/arm_scpi.c | 58 +++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 12 deletions(-)