Message ID | 20170410212651.65499-5-cbostic@linux.vnet.ibm.com |
---|---|
State | Rejected, archived |
Headers | show |
On 04/10/2017 04:26 PM, 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@linux.vnet.ibm.com> > --- > v2 - fsi_disable_irq remove double inversion of bit mask. > --- > drivers/fsi/fsi-core.c | 138 +++++++++++++++++++++++++++++++++++++++++++++-- > drivers/fsi/fsi-master.h | 4 ++ > 2 files changed, 137 insertions(+), 5 deletions(-) > > diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c > index 72f3a35..9f55d69 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,10 +1245,12 @@ 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; > > - 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); > @@ -1133,12 +1258,15 @@ void fsi_disable_irq(struct fsi_device *dev) > } > > si1m &= bits; > - 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); > 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 */ Thanks for making that fix. All looks good. Acked-by: Eddie James <eajames@linux.vnet.ibm.com>
diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c index 72f3a35..9f55d69 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,10 +1245,12 @@ 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; - 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); @@ -1133,12 +1258,15 @@ void fsi_disable_irq(struct fsi_device *dev) } si1m &= bits; - 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); 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 */
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@linux.vnet.ibm.com> --- v2 - fsi_disable_irq remove double inversion of bit mask. --- drivers/fsi/fsi-core.c | 138 +++++++++++++++++++++++++++++++++++++++++++++-- drivers/fsi/fsi-master.h | 4 ++ 2 files changed, 137 insertions(+), 5 deletions(-)