Re: [PATCH v3] mailbox: pcc: Support HW-Reduced Communication Subspace type 2

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

 



Hi Ashwin,

On Wed, Jun 8, 2016 at 5:18 AM, Ashwin Chaugule
<ashwin.chaugule@xxxxxxxxxx> wrote:
> + Prashanth (Can you please have a look as well?)
>
> On 31 May 2016 at 15:35, Hoan Tran <hotran@xxxxxxx> wrote:
>> Hi Ashwin,
>
> Hi,
>
> Sorry about the delay. I'm in the middle of switching jobs and
> locations, so its been a bit crazy lately.

It's ok and hope you're doing well.

> I dont have any major
> concerns with this code, although there could be subtle issues with
> this IRQ thing. In this patchset, your intent is to add support for
> PCC subspace type 2. But you're also adding support for tx command
> completion which is not specific to Type 2. We could support that even
> in Type 1. Hence I wanted to separate the two, not just for review,
> but also the async IRQ completion has subtle issues esp. in the case
> of async platform notification, where you could have a PCC client in
> the OS writing to the cmd bit and the platform sending an async
> notification by writing to some bits in the same 8byte address as the
> cmd bit. So we need some mutual exclusivity there, otherwise the OS
> and platform could step on each other. Perhaps Prashanth has better
> insight into this.

I think, this mutual exclusivity could be in another patch.

>
>>
>> On Tue, May 31, 2016 at 12:05 PM, Ashwin Chaugule
>> <ashwin.chaugule@xxxxxxxxxx> wrote:
>>> On 19 May 2016 at 20:32, Hoan Tran <hotran@xxxxxxx> wrote:
>>>> ACPI 6.1 has a PCC HW-Reduced Communication Subspace type 2 intended for
>>>> use on HW-Reduce ACPI Platform, which requires read-modify-write sequence
>>>> to acknowledge doorbell interrupt. This patch provides the implementation
>>>> for the Communication Subspace Type 2.
>>>>
>>>> v3
>>>>  * Remove 2 global structures
>>>>  * Correct parsing subspace type 1 and subspace type 2
>>>>
>>>> v2
>>>>  * Remove changes inside "actbl3.h". This file is taken care by ACPICA.
>>>>  * Parse both subspace type 1 and subspace type 2
>>>>  * Remove unnecessary variable initialization
>>>>  * ISR returns IRQ_NONE in case of error
>>>>
>>>> v1
>>>>  * Initial
>>>>
>>>> Signed-off-by: Hoan Tran <hotran@xxxxxxx>
>>>> ---
>>>>  drivers/mailbox/pcc.c | 316 ++++++++++++++++++++++++++++++++++++++------------
>>>>  1 file changed, 245 insertions(+), 71 deletions(-)
>>>>
>>>> diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c
>>>> index 043828d..c98bd94 100644
>>>> --- a/drivers/mailbox/pcc.c
>>>> +++ b/drivers/mailbox/pcc.c
>>>> @@ -59,6 +59,7 @@
>>>>  #include <linux/delay.h>
>>>>  #include <linux/io.h>
>>>>  #include <linux/init.h>
>>>> +#include <linux/interrupt.h>
>>>>  #include <linux/list.h>
>>>>  #include <linux/platform_device.h>
>>>>  #include <linux/mailbox_controller.h>
>>>> @@ -68,11 +69,16 @@
>>>>  #include "mailbox.h"
>>>>
>>>>  #define MAX_PCC_SUBSPACES      256
>>>> +#define MBOX_IRQ_NAME          "pcc-mbox"
>>>>
>>>>  static struct mbox_chan *pcc_mbox_channels;
>>>>
>>>>  /* Array of cached virtual address for doorbell registers */
>>>>  static void __iomem **pcc_doorbell_vaddr;
>>>> +/* Array of cached virtual address for doorbell ack registers */
>>>> +static void __iomem **pcc_doorbell_ack_vaddr;
>>>> +/* Array of doorbell interrupts */
>>>> +static int *pcc_doorbell_irq;
>>>>
>>>>  static struct mbox_controller pcc_mbox_ctrl = {};
>>>>  /**
>>>> @@ -91,6 +97,132 @@ static struct mbox_chan *get_pcc_channel(int id)
>>>>         return &pcc_mbox_channels[id];
>>>>  }
>>>>
>>>> +/*
>>>> + * PCC can be used with perf critical drivers such as CPPC
>>>> + * So it makes sense to locally cache the virtual address and
>>>> + * use it to read/write to PCC registers such as doorbell register
>>>> + *
>>>> + * The below read_register and write_registers are used to read and
>>>> + * write from perf critical registers such as PCC doorbell register
>>>> + */
>>>> +static int read_register(void __iomem *vaddr, u64 *val, unsigned int bit_width)
>>>> +{
>>>> +       int ret_val = 0;
>>>> +
>>>> +       switch (bit_width) {
>>>> +       case 8:
>>>> +               *val = readb(vaddr);
>>>> +               break;
>>>> +       case 16:
>>>> +               *val = readw(vaddr);
>>>> +               break;
>>>> +       case 32:
>>>> +               *val = readl(vaddr);
>>>> +               break;
>>>> +       case 64:
>>>> +               *val = readq(vaddr);
>>>> +               break;
>>>> +       default:
>>>> +               pr_debug("Error: Cannot read register of %u bit width",
>>>> +                       bit_width);
>>>> +               ret_val = -EFAULT;
>>>> +               break;
>>>> +       }
>>>> +       return ret_val;
>>>> +}
>>>> +
>>>> +static int write_register(void __iomem *vaddr, u64 val, unsigned int bit_width)
>>>> +{
>>>> +       int ret_val = 0;
>>>> +
>>>> +       switch (bit_width) {
>>>> +       case 8:
>>>> +               writeb(val, vaddr);
>>>> +               break;
>>>> +       case 16:
>>>> +               writew(val, vaddr);
>>>> +               break;
>>>> +       case 32:
>>>> +               writel(val, vaddr);
>>>> +               break;
>>>> +       case 64:
>>>> +               writeq(val, vaddr);
>>>> +               break;
>>>> +       default:
>>>> +               pr_debug("Error: Cannot write register of %u bit width",
>>>> +                       bit_width);
>>>> +               ret_val = -EFAULT;
>>>> +               break;
>>>> +       }
>>>> +       return ret_val;
>>>> +}
>>>> +
>>>
>>> Isn't this just reordering of function locations? I don't mean to be
>>> nitpicky, but your cosmetic changes in this file make it harder to
>>> review the meat of the patch.
>>
>> Yes, it is. As I would like to call these functions but actually, they
>> are declared quite late.
>> Do you have a any suggestion? Thanks
>>
>
> No this is fine. I missed the place where you needed to call these.
>
>>>
>>>> +/**
>>>> + * pcc_map_interrupt - Map a PCC subspace GSI to a linux IRQ number
>>>> + * @interrupt: GSI number.
>>>> + * @flags: interrupt flags
>>>> + *
>>>> + * Returns: a valid linux IRQ number on success
>>>> + *             0 or -EINVAL on failure
>>>> + */
>>>> +static int pcc_map_interrupt(u32 interrupt, u32 flags)
>>>> +{
>>>> +       int trigger, polarity;
>>>> +
>>>> +       if (!interrupt)
>>>> +               return 0;
>>>> +
>>>> +       trigger = (flags & ACPI_PCCT_INTERRUPT_MODE) ? ACPI_EDGE_SENSITIVE
>>>> +                       : ACPI_LEVEL_SENSITIVE;
>>>> +
>>>> +       polarity = (flags & ACPI_PCCT_INTERRUPT_POLARITY) ? ACPI_ACTIVE_LOW
>>>> +                       : ACPI_ACTIVE_HIGH;
>>>> +
>>>> +       return acpi_register_gsi(NULL, interrupt, trigger, polarity);
>>>> +}
>>>> +
>>>> +/**
>>>> + * pcc_mbox_irq - PCC mailbox interrupt handler
>>>> + */
>>>> +static irqreturn_t pcc_mbox_irq(int irq, void *p)
>>>> +{
>>>> +       struct acpi_generic_address *doorbell_ack;
>>>> +       struct acpi_pcct_hw_reduced *pcct_ss;
>>>> +       struct mbox_chan *chan = p;
>>>> +       u64 doorbell_ack_preserve;
>>>> +       u64 doorbell_ack_write;
>>>> +       u64 doorbell_ack_val;
>>>> +       int ret;
>>>> +
>>>> +       pcct_ss = chan->con_priv;
>>>> +
>>>> +       mbox_chan_received_data(chan, NULL);
>>>
>>> Does this really do anything? IIUC, your mbox controller rings
>>> doorbell, platform sets cmd_completion and sends an IRQ to the OS.
>>> This is the function where you field it to ACK the doorbell. But
>>> you're not really consuming any new data sent by the platform, right?
>>> i.e. this IRQ use case is not the same as the async notification from
>>> platform as described in the ACPIv5+ spec. Or did I misunderstand the
>>> bigger picture?
>>>
>>
>> The purpose of this function call is
>> 1./ Notify the completion of a command to OSPM.
>> For example, instead of using polling with udelay, CPPC could use this
>> call to complete a "completion".
>> I'm preparing to post a version to support it for CPPC.
>>
>
> I see. This is the part I was missing. Seems like you could call the
> mbox_chan_received_data() only after you add support for this.
>
>> 2./ Notify OSPM about a notification message sent by Platform
>
> This will require adding some sort of rx_callback to field the notification.
>
>>>
>>> [...]
>>>
>>>> +
>>>> +/**
>>>>   * acpi_pcc_probe - Parse the ACPI tree for the PCCT.
>>>>   *
>>>>   * Return: 0 for Success, else errno.
>>>> @@ -316,7 +449,9 @@ static int __init acpi_pcc_probe(void)
>>>>         acpi_size pcct_tbl_header_size;
>>>>         struct acpi_table_header *pcct_tbl;
>>>>         struct acpi_subtable_header *pcct_entry;
>>>> -       int count, i;
>>>> +       struct acpi_table_pcct *acpi_pcct_tbl;
>>>> +       int count, i, rc;
>>>> +       int sum = 0;
>>>>         acpi_status status = AE_OK;
>>>>
>>>>         /* Search for PCCT */
>>>> @@ -333,37 +468,66 @@ static int __init acpi_pcc_probe(void)
>>>>                         sizeof(struct acpi_table_pcct),
>>>>                         ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE,
>>>>                         parse_pcc_subspace, MAX_PCC_SUBSPACES);
>>>> +       sum += (count > 0)? count: 0;
>>>> +
>>>> +       count = acpi_table_parse_entries(ACPI_SIG_PCCT,
>>>> +                       sizeof(struct acpi_table_pcct),
>>>> +                       ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE_TYPE2,
>>>> +                       parse_pcc_subspace, MAX_PCC_SUBSPACES);
>>>> +       sum += (count > 0)? count: 0;
>>>>
>>>> -       if (count <= 0) {
>>>> +       if (sum == 0 || sum >= MAX_PCC_SUBSPACES) {
>>>>                 pr_err("Error parsing PCC subspaces from PCCT\n");
>>>>                 return -EINVAL;
>>>>         }
>>>>
>>>>         pcc_mbox_channels = kzalloc(sizeof(struct mbox_chan) *
>>>> -                       count, GFP_KERNEL);
>>>> -
>>>> +                       sum, GFP_KERNEL);
>>>>         if (!pcc_mbox_channels) {
>>>>                 pr_err("Could not allocate space for PCC mbox channels\n");
>>>>                 return -ENOMEM;
>>>>         }
>>>>
>>>> -       pcc_doorbell_vaddr = kcalloc(count, sizeof(void *), GFP_KERNEL);
>>>> +       pcc_doorbell_vaddr = kcalloc(sum, sizeof(void *), GFP_KERNEL);
>>>>         if (!pcc_doorbell_vaddr) {
>>>> -               kfree(pcc_mbox_channels);
>>>> -               return -ENOMEM;
>>>> +               rc = -ENOMEM;
>>>> +               goto err_free_mbox;
>>>> +       }
>>>> +
>>>> +       pcc_doorbell_ack_vaddr = kcalloc(sum, sizeof(void *), GFP_KERNEL);
>>>> +       if (!pcc_doorbell_ack_vaddr) {
>>>> +               rc = -ENOMEM;
>>>> +               goto err_free_db_vaddr;
>>>> +       }
>>>> +
>>>> +       pcc_doorbell_irq = kcalloc(sum, sizeof(int), GFP_KERNEL);
>>>> +       if (!pcc_doorbell_irq) {
>>>> +               rc = -ENOMEM;
>>>> +               goto err_free_db_ack_vaddr;
>>>>         }
>>>>
>>>>         /* Point to the first PCC subspace entry */
>>>>         pcct_entry = (struct acpi_subtable_header *) (
>>>>                 (unsigned long) pcct_tbl + sizeof(struct acpi_table_pcct));
>>>>
>>>> -       for (i = 0; i < count; i++) {
>>>> +       acpi_pcct_tbl = (struct acpi_table_pcct *) pcct_tbl;
>>>> +       if (acpi_pcct_tbl->flags & ACPI_PCCT_DOORBELL)
>>>> +               pcc_mbox_ctrl.txdone_irq = true;
>>>> +
>>>
>>> This flag is still bothering me. Can't you have a system where one
>>> client requires polling on the command completion bit and another can
>>> send a command completion IRQ? Seems to me that you need a channel
>>> specific flag to indicate this. Besides, this global flag seems to be
>>> used for async platform notifications. i.e. when the OS sets the
>>> Generate doorbell irq bit in the Command field (Section 14.2.1 in ACPI
>>> v6.1).
>>
>> I thought this bit is the global configuration for PCC.
>> We still can support the polling mode if this flag is ON. Just don't
>> set "Generate Doorbell Interrupt" bit inside Command Field.
>>
>
> From the spec point of view it would seem so, but does the mbox
> controller code allow for that?  i.e. let individual PCC channels
> decide whether to use txdone irq or poll? Seems like
> pcc_mbox_ctrl.txdone_irq is a global setting for all mbox channels.

I think for PCC, it's depend on the PCC client not mbox controller.
Client can decide to send a command in polling or interrupt mode by
configuring "Generate Doorbell Interrupt" bit.
For the txdone_irq flag, it is a global setting for all mbox channels.
If txdone_irq is enabled, the client has to use mbox_chan_txdone()
function to notify the framework that the last command has completed.

Thanks and Regards
Hoan

>
> I apologize again, going forward my replies could be further delayed.
> In process of relocating to a new job and role to a different city
> which is several time zones away. :)
>
> Thanks,
> Ashwin.
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux