Message ID | 20190318170137.28516.24695.stgit@scvm10.sc.intel.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | [for-next] IB/hfi1: Add debugfs to control expansion ROM write protect | expand |
On Mon, Mar 18, 2019 at 10:01:43AM -0700, Dennis Dalessandro wrote: > From: Josh Collier <josh.d.collier@intel.com> > > 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@intel.com> > Signed-off-by: Josh Collier <josh.d.collier@intel.com> > Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com> > 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
On Mon, Mar 18, 2019 at 10:01:43AM -0700, Dennis Dalessandro wrote: > From: Josh Collier <josh.d.collier@intel.com> > > 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@intel.com> > Signed-off-by: Josh Collier <josh.d.collier@intel.com> > Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com> > 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; > + > +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); And this algorithm is just test and set, no need for a confusing atomic_inc/dec Jason
diff --git a/drivers/infiniband/hw/hfi1/debugfs.c b/drivers/infiniband/hw/hfi1/debugfs.c index 427ba0c..6246707 100644 --- a/drivers/infiniband/hw/hfi1/debugfs.c +++ 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; + +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; + 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); + atomic_dec(&exprom_refcnt); + + return 0; +} + #define DEBUGFS_OPS(nm, readroutine, writeroutine) \ { \ .name = nm, \ @@ -1119,6 +1195,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),