[PATCH linux dev-4.7 4/4] drivers/fsi: Set IRQ masks along hub path

Christopher Bostic cbostic at linux.vnet.ibm.com
Tue Apr 11 06:39:44 AEST 2017



On 4/10/17 3:32 PM, Eddie James wrote:
>
>
> On 04/07/2017 08:52 AM, Christopher Bostic wrote:
>> Enable/disable client engine IRQ masks including those along
>> the hub path to a particular engine. This includes slave
>> MMODE i-poll, Si1M, SRSIM, and hub master MSIEP.
>>
>> Signed-off-by: Christopher Bostic <cbostic at linux.vnet.ibm.com>
>> ---
>>   drivers/fsi/fsi-core.c   | 142 
>> ++++++++++++++++++++++++++++++++++++++++++++---
>>   drivers/fsi/fsi-master.h |   4 ++
>>   2 files changed, 139 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c
>> index 72f3a35..5ee6bc1 100644
>> --- a/drivers/fsi/fsi-core.c
>> +++ b/drivers/fsi/fsi-core.c
>> @@ -1086,17 +1086,140 @@ void fsi_driver_unregister(struct fsi_driver 
>> *fsi_drv)
>>   }
>>   EXPORT_SYMBOL_GPL(fsi_driver_unregister);
>>
>> +static uint32_t link_to_srsim_mask(int link)
>> +{
>> +    return ((0x80000000 >> 6) >> FSI_SRSIX_BITS_PER_LINK*link);
>> +}
>> +
>> +static uint32_t link_to_msiep_mask(int link)
>> +{
>> +    return (0xf0000000 >> (FSI_MSIEP_BITS_PER_LINK*link));
>> +}
>> +
>> +static int set_si1m(struct fsi_slave *slave, uint32_t mask, int on)
>> +{
>> +    int rc;
>> +    uint32_t si1m;
>> +
>> +    rc = fsi_slave_read(slave, FSI_SLAVE_BASE + FSI_SI1M, &si1m,
>> +            sizeof(si1m));
>> +    if (rc) {
>> +        dev_dbg(&slave->dev, "Failed to read SI1M\n");
>> +        return rc;
>> +    }
>> +
>> +    if (on)
>> +        si1m |= mask;
>> +    else
>> +        si1m &= ~mask;
>> +
>> +    return fsi_slave_write(slave, FSI_SLAVE_BASE + FSI_SI1M, &si1m,
>> +            sizeof(si1m));
>> +}
>> +
>> +static int set_upstream_irq_masks(struct fsi_master *master,
>> +                struct fsi_slave *slave, int on)
>> +{
>> +    struct fsi_slave *upstream_slave;
>> +    struct fsi_master *upstream_master;
>> +    uint32_t mask, si1m;
>> +    int rc;
>> +
>> +    if (!master->idx)
>> +        return 0;
>> +
>> +    upstream_slave = to_fsi_slave(slave->master->dev->parent);
>> +    if (!upstream_slave) {
>> +        dev_dbg(&slave->dev, "No upstream slave found\n");
>> +        return -ENODEV;
>> +    }
>> +
>> +    rc = fsi_slave_read(upstream_slave, FSI_SLAVE_BASE + FSI_SRSIM0, 
>> &si1m,
>> +            sizeof(si1m));
>> +    if (rc) {
>> +        dev_dbg(&slave->dev, "Failed to read SRSIM0\n");
>> +        return rc;
>> +    }
>> +
>> +    mask = link_to_srsim_mask(slave->link);
>> +    if (on)
>> +        si1m |= mask;
>> +    else
>> +        si1m &= ~mask;
>> +    rc = fsi_slave_write(upstream_slave, FSI_SLAVE_BASE + 
>> FSI_SRSIM0, &si1m,
>> +            sizeof(si1m));
>> +    if (rc) {
>> +        dev_dbg(&slave->dev, "Failed to write SRSIM0\n");
>> +        return rc;
>> +    }
>> +
>> +    upstream_master = upstream_slave->master;
>> +    if (!upstream_master) {
>> +        dev_dbg(&upstream_slave->dev, "Cannot find master\n");
>> +        return -ENODEV;
>> +    }
>> +
>> +    rc = upstream_master->read(upstream_master, 0, 0,
>> +                FSI_HUB_CONTROL + FSI_MSIEP0, &si1m,
>> +                sizeof(si1m));
>> +    if (rc) {
>> +        dev_dbg(&upstream_slave->dev,
>> +            "Could not read master's MSIEP\n");
>> +        return rc;
>> +    }
>> +
>> +    /* TODO: merge this into above on/off check */
>> +    mask = link_to_msiep_mask(slave->link);
>> +    if (on) {
>> +        upstream_master->ipoll |= FSI_SI1_HUB_SRC;
>> +        si1m |= mask;
>> +    } else {
>> +        upstream_master->ipoll &= ~FSI_SI1_HUB_SRC;
>> +        si1m &= ~mask;
>> +    }
>> +
>> +    rc = upstream_master->write(upstream_master, 0, 0,
>> +                FSI_HUB_CONTROL + FSI_MSIEP0, &si1m,
>> +                sizeof(si1m));
>> +    if (rc) {
>> +        dev_dbg(&upstream_slave->dev,
>> +            "Failed to write to master's MSIEP\n");
>> +        return rc;
>> +    }
>> +    si1m = 0xd0040410;
>> +    rc = upstream_master->write(upstream_master, 0, 0,
>> +                FSI_HUB_CONTROL + FSI_MMODE, &si1m,
>> +                sizeof(si1m));
>> +    if (rc) {
>> +        dev_dbg(&upstream_slave->dev,
>> +            "Failed to set hub I POLL\n");
>> +    }
>> +
>> +    si1m = FSI_SI1_HUB_SRC;
>> +    rc = upstream_master->write(upstream_master, 0, 0,
>> +                FSI_SLAVE_BASE + FSI_SI1M, &si1m,
>> +                sizeof(si1m));
>> +    if (rc) {
>> +        dev_dbg(&upstream_slave->dev,
>> +            "Failed to set hub mask in SI1M\n");
>> +    }
>> +
>> +    return set_si1m(upstream_slave, FSI_SI1_HUB_SRC, on);
>> +}
>> +
>>   int fsi_enable_irq(struct fsi_device *dev)
>>   {
>>       int rc;
>>       u32 si1m;
>>       u32 bit = 0x80000000 >> dev->si1s_bit;
>>       struct fsi_master *master = dev->slave->master;
>> +    struct fsi_slave *slave = dev->slave;
>> +    int link = slave->link;
>>
>>       if (!dev->irq_handler)
>>           return -EINVAL;
>>
>> -    rc = master->read(master, 0, 0, FSI_SLAVE_BASE + FSI_SI1M, &si1m,
>> +    rc = master->read(master, link, 0, FSI_SLAVE_BASE + FSI_SI1M, 
>> &si1m,
>>               sizeof(u32));
>>       if (rc) {
>>           dev_err(master->dev, "couldn't read si1m:%d\n", rc);
>> @@ -1104,7 +1227,7 @@ int fsi_enable_irq(struct fsi_device *dev)
>>       }
>>
>>       si1m |= bit;
>> -    rc = master->write(master, 0, 0, FSI_SLAVE_BASE + FSI_SI1M, &si1m,
>> +    rc = master->write(master, link, 0, FSI_SLAVE_BASE + FSI_SI1M, 
>> &si1m,
>>               sizeof(u32));
>>       if (rc) {
>>           dev_err(master->dev, "couldn't write si1m:%d\n", rc);
>> @@ -1112,7 +1235,7 @@ int fsi_enable_irq(struct fsi_device *dev)
>>       }
>>
>>       master->ipoll |= bit;
>> -    return 0;
>> +    return set_upstream_irq_masks(master, slave, 1);
>>   }
>>   EXPORT_SYMBOL_GPL(fsi_enable_irq);
>>
>> @@ -1122,23 +1245,28 @@ void fsi_disable_irq(struct fsi_device *dev)
>>       u32 si1m;
>>       u32 bits = ~(0x80000000 >> dev->si1s_bit);
>>       struct fsi_master *master = dev->slave->master;
>> +    struct fsi_slave *slave = dev->slave;
>> +    int link = dev->slave->link;
>>
>> -    master->ipoll &= bits;
>> +    master->ipoll &= ~bits;
>
> Does this work? Looks like a double bit inversion. Maybe I'm missing 
> something but appears to be enabling rather than disabling the si1s bit.

Hi Eddie,
Yeah, I missed the inverting of bits when the variable is declared above.
>
>>
>> -    rc = master->read(master, 0, 0, FSI_SLAVE_BASE + FSI_SI1M, &si1m,
>> +    rc = master->read(master, link, 0, FSI_SLAVE_BASE + FSI_SI1M, 
>> &si1m,
>>               sizeof(u32));
>>       if (rc) {
>>           dev_err(master->dev, "couldn't read si1m:%d\n", rc);
>>           return;
>>       }
>>
>> -    si1m &= bits;
>> -    rc = master->write(master, 0, 0, FSI_SLAVE_BASE + FSI_SI1M, &si1m,
>> +    si1m &= ~bits;
>
> Same question here.
I'll remove the invert in variable declaration and will take care of it.

Thanks,
Chris
>
> Other than that patch set looks good.
>
> Thanks,
> Eddie
>
>> +    rc = master->write(master, link, 0, FSI_SLAVE_BASE + FSI_SI1M, 
>> &si1m,
>>               sizeof(u32));
>>       if (rc) {
>>           dev_err(master->dev, "couldn't write si1m:%d\n", rc);
>>           return;
>>       }
>> +
>> +    if (!master->ipoll)
>> +        set_upstream_irq_masks(master, slave, 0);
>>   }
>>
>>   struct bus_type fsi_bus_type = {
>> diff --git a/drivers/fsi/fsi-master.h b/drivers/fsi/fsi-master.h
>> index 54723a7..7c9c3fa 100644
>> --- a/drivers/fsi/fsi-master.h
>> +++ b/drivers/fsi/fsi-master.h
>> @@ -27,6 +27,7 @@
>>   #define FSI_MLEVP0        0x18        /* R: plug detect */
>>   #define FSI_MSENP0        0x18        /* S: Set enable */
>>   #define FSI_MCENP0        0x20        /* C: Clear enable */
>> +#define FSI_MSIEP0        0x30        /* R/W: Slave IRQ enable */
>>   #define FSI_MAEB        0x70        /* R: Error address */
>>   #define FSI_MVER        0x74        /* R: master version/type */
>>   #define FSI_MRESP0        0xd0        /* W: Port reset */
>> @@ -47,6 +48,9 @@
>>   #define FSI_MMODE_CRS1SHFT    8        /* Clk rate selection 1 
>> shift */
>>   #define FSI_MMODE_CRS1MASK    0x3ff        /* Clk rate selection 1 
>> mask */
>>
>> +/* MSIEP: Slave interrupt enable */
>> +#define FSI_MSIEP_BITS_PER_LINK    4
>> +
>>   /* MRESB: Reset brindge */
>>   #define FSI_MRESB_RST_GEN    0x80000000    /* General reset */
>>   #define FSI_MRESB_RST_ERR    0x40000000    /* Error Reset */
>



More information about the openbmc mailing list