On Mon, Mar 18, 2019 at 10:01:43AM -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. > > 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> > drivers/infiniband/hw/hfi1/debugfs.c | 79 ++++++++++++++++++++++++++++++++++ > 1 files changed, 79 insertions(+), 0 deletions(-) > > diff --git a/drivers/infiniband/hw/hfi1/debugfs.c b/drivers/infiniband/hw/hfi1/debugfs.c > index 427ba0c..6246707 100644 > +++ b/drivers/infiniband/hw/hfi1/debugfs.c > @@ -1080,6 +1080,82 @@ 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 int exprom_wp_disabled; should be bool > + > +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 = 1; > + dd_dev_info(dd, "Disable Expansion ROM Write Protection\n"); > + } else { > + exprom_wp_disabled = 0; > + 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 atomic_t exprom_refcnt = ATOMIC_INIT(0); > + > +static int exprom_wp_debugfs_open(struct inode *in, struct file *fp) > +{ > + int ret; > + > + ret = atomic_fetch_inc(&exprom_refcnt); > + if (ret) { > + atomic_dec(&exprom_refcnt); > + return -EBUSY; > + } > + exprom_wp_disabled = 0; seems weird to set this here Jason