On Thu, Apr 11, 2019 at 07:07:42AM -0700, Dennis Dalessandro wrote: > From: Josh Collier <josh.d.collier@xxxxxxxxx> > > Some kernels now enable CONFIG_IO_STRICT_DEVMEM > which prevents multiple handles to PCI resource0. In order > to continue to support expansion ROM updates while the > driver is loaded, the driver must now provide an interface > to control the expansion ROM write protection. From this description, it seems like that CONFIG_IO_STRICT_DEVMEM was added to prevent this type of access, doesn't it? > > This patch adds an exprom_wp debugfs interface that > allows the hfi1_eprom user tool to disable the expansion ROM > write protection by opening the file and writing a '1'. > The write protection is released when writing a '0' or > automatically re-enabled when the handle is closed. > The current implementation will only allow one handle > to be opened at a time across all hfi1 devices. > > Reviewed-by: Dennis Dalessandro <dennis.dalessandro@xxxxxxxxx> > Signed-off-by: Josh Collier <josh.d.collier@xxxxxxxxx> > Signed-off-by: Dennis Dalessandro <dennis.dalessandro@xxxxxxxxx> > > --- > Changes since v1: > Use bool instead of int for disabled flag > Simplify open routine with test/set vs atomic_inc/dec. > --- > drivers/infiniband/hw/hfi1/debugfs.c | 74 ++++++++++++++++++++++++++++++++++ > 1 files changed, 74 insertions(+), 0 deletions(-) > > diff --git a/drivers/infiniband/hw/hfi1/debugfs.c b/drivers/infiniband/hw/hfi1/debugfs.c > index 057bb82..15efb4a 100644 > --- a/drivers/infiniband/hw/hfi1/debugfs.c > +++ b/drivers/infiniband/hw/hfi1/debugfs.c > @@ -1080,6 +1080,77 @@ static int qsfp2_debugfs_release(struct inode *in, struct file *fp) > return __qsfp_debugfs_release(in, fp, 1); > } > > +#define EXPROM_WRITE_ENABLE BIT_ULL(14) > + > +static bool exprom_wp_disabled; > + > +static int exprom_wp_set(struct hfi1_devdata *dd, bool disable) > +{ > + u64 gpio_val = 0; > + > + if (disable) { > + gpio_val = EXPROM_WRITE_ENABLE; > + exprom_wp_disabled = true; > + dd_dev_info(dd, "Disable Expansion ROM Write Protection\n"); > + } else { > + exprom_wp_disabled = false; > + dd_dev_info(dd, "Enable Expansion ROM Write Protection\n"); > + } > + > + write_csr(dd, ASIC_GPIO_OUT, gpio_val); > + write_csr(dd, ASIC_GPIO_OE, gpio_val); > + > + return 0; > +} > + > +static ssize_t exprom_wp_debugfs_read(struct file *file, char __user *buf, > + size_t count, loff_t *ppos) > +{ > + return 0; > +} > + > +static ssize_t exprom_wp_debugfs_write(struct file *file, > + const char __user *buf, size_t count, > + loff_t *ppos) > +{ > + struct hfi1_pportdata *ppd = private2ppd(file); > + char cdata; > + > + if (count != 1) > + return -EINVAL; > + if (get_user(cdata, buf)) > + return -EFAULT; > + if (cdata == '0') > + exprom_wp_set(ppd->dd, false); > + else if (cdata == '1') > + exprom_wp_set(ppd->dd, true); > + else > + return -EINVAL; > + > + return 1; > +} > + > +static unsigned long exprom_in_use; > + > +static int exprom_wp_debugfs_open(struct inode *in, struct file *fp) > +{ > + if (test_and_set_bit(0, &exprom_in_use)) > + return -EBUSY; > + > + return 0; > +} > + > +static int exprom_wp_debugfs_release(struct inode *in, struct file *fp) > +{ > + struct hfi1_pportdata *ppd = private2ppd(fp); > + > + if (exprom_wp_disabled) > + exprom_wp_set(ppd->dd, false); > + clear_bit(0, &exprom_in_use); > + > + return 0; > +} > + > #define DEBUGFS_OPS(nm, readroutine, writeroutine) \ > { \ > .name = nm, \ > @@ -1119,6 +1190,9 @@ static int qsfp2_debugfs_release(struct inode *in, struct file *fp) > qsfp1_debugfs_open, qsfp1_debugfs_release), > DEBUGFS_XOPS("qsfp2", qsfp2_debugfs_read, qsfp2_debugfs_write, > qsfp2_debugfs_open, qsfp2_debugfs_release), > + DEBUGFS_XOPS("exprom_wp", exprom_wp_debugfs_read, > + exprom_wp_debugfs_write, exprom_wp_debugfs_open, > + exprom_wp_debugfs_release), > DEBUGFS_OPS("asic_flags", asic_flags_read, asic_flags_write), > DEBUGFS_OPS("dc8051_memory", dc8051_memory_read, NULL), > DEBUGFS_OPS("lcb", debugfs_lcb_read, debugfs_lcb_write), >
Attachment:
signature.asc
Description: PGP signature