From: Dan Carpenter <dan.carpenter@oracle.com>
To: "Czerwacki, Eial" <eial.czerwacki@sap.com>
Cc: "linux-staging@lists.linux.dev" <linux-staging@lists.linux.dev>,
SAP vSMP Linux Maintainer <linux.vsmp@sap.com>
Subject: Re: [RFC] staging/vSMP: new driver
Date: Thu, 17 Mar 2022 16:56:28 +0300 [thread overview]
Message-ID: <20220317135628.GC3293@kadam> (raw)
In-Reply-To: <PAXPR02MB73109408A4070F19F34AD7D181129@PAXPR02MB7310.eurprd02.prod.outlook.com>
On Thu, Mar 17, 2022 at 01:41:30PM +0000, Czerwacki, Eial wrote:
> >> + printk(KERN_INFO "mapping bar 0: [0x%llx,0x%llx]\n",
> >> + mapped_bars[0].start, mapped_bars[0].start + mapped_bars[0].len);
> >> + cfg_addr = ioremap(mapped_bars[0].start, mapped_bars[0].len);
> >> +
> >> + if (!cfg_addr) {
> >
> >Delete the blank link between the call and the error checking. They are
> >part of the same thing.
> did you meant line?
>
What I mean is that it's like paragraphs.
cfg_addr = ioremap(mapped_bars[0].start, mapped_bars[0].len);
if (!cfg_addr)
return -ENOMEM;
The call and the check go together.
> >
> >> + printk(KERN_ERR
> >> + "failed to map vSMP pci controller at %x:%x.%x, exiting.\n",
> >> + vsmp_bus, vsmp_dev, vsmp_func);
> >> + return -1;
> >> + }
> >> +
> >> + return 0;
> >> +}
> >> +
> >> +/* exported functions */
> >> +
> >> +/**
> >> + * read a value from a specfic register in the vSMP's device config space
> >> + */
> >> +unsigned long vsmp_read_reg_from_cfg(unsigned int reg, enum reg_size_type type)
> >
> >
> >Use u64 when 64 bit types are intended.
> >
> >> +{
> >> + unsigned long ret_val;
> >
> >
> >u64 ret_val;
> sure
>
> >
> >> +
> >> + switch (type) {
> >> + case VSMP_CTL_REG_SIZE_8BIT:
> >> + ret_val = readb(cfg_addr + reg);
> >> + break;
> >> +
> >> + case VSMP_CTL_REG_SIZE_16BIT:
> >> + ret_val = readw(cfg_addr + reg);
> >> + break;
> >> +
> >> + case VSMP_CTL_REG_SIZE_32BIT:
> >> + ret_val = readl(cfg_addr + reg);
> >> + break;
> >> +
> >> + case VSMP_CTL_REG_SIZE_64BIT:
> >> + ret_val = readq(cfg_addr + reg);
> >> + break;
> >> +
> >> + default:
> >> + printk(KERN_ERR "unsupported reg size type %d.\n", type);
> >> + ret_val = (unsigned long)(-1);
> >
> >
> >64 bit types. "ret_val = -1ULL;"
> >
> >
> >> + }
> >> +
> >> + dev_dbg(&vsmp_dev_obj->dev, "%s: read 0x%lx from reg 0x%x of %d bits\n",
> >> + __func__, ret_val, reg, (type + 1) * 8);
> >> + return ret_val;
> >> +}
> >> +EXPORT_SYMBOL_GPL(vsmp_read_reg_from_cfg);
> >> +
> >> +/**
> >> + * write a value to a specfic register in the vSMP's device config space
> >> + */
> >> +void vsmp_write_reg_to_cfg(unsigned int reg, unsigned long value,
> >> + enum reg_size_type type)
> >> +{
> >> + switch (type) {
> >> + case VSMP_CTL_REG_SIZE_8BIT:
> >> + writeb((unsigned char)value, cfg_addr + reg);
> >> + break;
> >> +
> >> + case VSMP_CTL_REG_SIZE_16BIT:
> >> + writew((unsigned short)value, cfg_addr + reg);
> >> + break;
> >> +
> >> + case VSMP_CTL_REG_SIZE_32BIT:
> >> + writel((unsigned int)value, cfg_addr + reg);
> >> + break;
> >> +
> >> + case VSMP_CTL_REG_SIZE_64BIT:
> >> + writeq(value, cfg_addr + reg);
> >> + break;
> >> +
> >> + default:
> >> + printk(KERN_ERR "unsupported reg size type %d.\n", type);
> >> + }
> >> +
> >> + dev_dbg(&vsmp_dev_obj->dev, "%s: wrote 0x%x to reg 0x%x of %u bits\n",
> >> + __func__, reg, reg, (type + 1) * 8);
> >> +}
> >> +EXPORT_SYMBOL_GPL(vsmp_write_reg_to_cfg);
> >> +
> >> +/**
> >> + * reag a buffer from a specific offset in a specific bar, maxed to a predefined len size-wise from the vSMP device
> >> + */
> >> +unsigned int vsmp_read_buff_from_bar(unsigned int bar, unsigned int offset,
> >
> >This is unsigned int but it returns zero or negative error codes.
> >
> >Create a separate function for "halt_on_null". It will be cleaner that
> >way.
> I'll refractor this code properly.
>
> >
> >> + char *out, unsigned int len,
> >> + bool halt_on_null)
> >> +{
> >> + unsigned char __iomem *buff;
> >> +
> >> + BUG_ON(!mapped_bars[bar].start);
> >> + BUG_ON(ARRAY_SIZE(mapped_bars) <= bar);
> >> + BUG_ON((offset + len) > mapped_bars[bar].len);
> >> +
> >> + buff = ioremap(mapped_bars[bar].start + offset, len);
> >> + if (!buff)
> >> + return -ENOMEM;
> >> +
> >> + if (halt_on_null) {
> >> + int i;
> >> + unsigned char c;
> >> +
> >> + for (i = 0; i < len; i++) {
> >> + c = ioread8(&buff[i]);
> >> + if (!c)
> >> + break;
> >> + out[i] = c;
> >
> >Copy the NUL terminator to out[i] before the break.
> >
> should I memset out to zero instead?
Right now you're relying on the caller to set the NUL terminator and
that's ugly. Just do:
for (i = 0; i < len; i++) {
c = ioread8(&buff[i]);
out[i] = c;
if (!c)
break;
>
> >> + }
> >> + } else
> >> + memcpy_fromio(out, buff, len);
> >> +
> >> + iounmap(buff);
> >> +
> >> + return 0;
> >> +}
[ snip ]
> >> +static ssize_t version_read(struct file *filp, struct kobject *kobj,
> >> + struct bin_attribute *bin_attr,
> >> + char *buf, loff_t off, size_t count)
> >> +{
> >> + ssize_t ret_val = vsmp_generic_buff_read(&op, 0,
> >> + vsmp_read_reg32_from_cfg(VSMP_VERSION_REG),
> >> + buf, off, count);
> >
> >Don't put functions which can fail in the declaration block.
> >
> > ret_val = vsmp_generic_buff_read(&op, 0,
> > vsmp_read_reg32_from_cfg(VSMP_VERSION_REG),
> > buf, off, count);
> >
> can you explain what is the reason behind this recommendation?
>
That's just my own preference, not really a rule. I stole that
guideline from someone else. I forget who. But it's a fact that the
declaration block is more bug prone than other code. (Very clean in
static analysis results). Plus it means that you put a blank line
between the call and the check which I do not like (again just my
preference).
> >> +
> >> + if ((ret_val != -ENOMEM) && ((ret_val != -EINVAL)))
> >
> >Don't test for specific error codes.
> >
> > if (ret_val < 0)
> > return ret_val;
> >
> >
> now I understand, there was a patchset which fixes for all the -1 and the specific ret_val testing, I see it
> was misplaced at some point of the work.
> thanks for pointing it out
>
> >> + buf[ret_val++] = '\n';
> >> +
> >> + return ret_val;
> >> +}
> >> +
> >> +struct bin_attribute version_raw_attr = __BIN_ATTR(version, FILE_PREM, version_read, NULL, VERSION_MAX_LEN);
> >> +
> >> +/**
> >> + * retrive str in order to determine the proper length.
> >> + * this is the best way to maintain backwards compatibility with all
> >> + * vSMP versions.
> >> + */
> >> +static int get_version_len(void)
> >> +{
> >> + unsigned reg;
> >> + char *version_str = kzalloc(VERSION_MAX_LEN, GFP_ATOMIC | __GFP_NOWARN);
> >
> >VERSION_MAX_LEN is 524288 bytes. That's too long. Create a small
> >buffer and loop over it until you find the NUL terminator. Why does
> >this need to be ATOMIC, are we holding a lock? Hopefully if we can fix
> >the length the __GFP_NOWARN will be unnecessary.
> I'm not sure it is possible to loopover, I'll take that into consideration.
> in this flow, only one access is possible, so I assume GFP_ATOMIC is not needed
>
This get_version_len() is cray cray... It needs to loop.
> >
> >> +
> >> + if (!version_str)
> >> + return -1;
> >> +
> >> + reg = vsmp_read_reg32_from_cfg(VSMP_VERSION_REG);
> >> + memset(version_str, 0, VERSION_MAX_LEN);
> >> +
> >> + if (vsmp_read_buff_from_bar(0, reg, version_str, VERSION_MAX_LEN, true)) {
> >> + printk(KERN_ERR "failed to read buffer from bar\n");
> >> + return -1;
> >> + }
> >> +
> >> + version_raw_attr.size = strlen(version_str);
> >
> >get_version_len() should return the length instead of setting a global.
> do you mean version_raw_attr.size = get_version_len()?
>
Yes, but with negative error codes.
> >
> >> + kfree(version_str);
> >> +
> >> + return 0;
> >> +}
> >> +
> >> +/**
> >> + * register the version sysfs entry
> >> + */
> >> +int sysfs_register_version_cb(void)
> >> +{
> >> + if (get_version_len()) {
> >> + printk(KERN_ERR "failed to init vSMP version module\n");
> >> + return -1;
> >> + }
> >> +
> >> + if (!vsmp_init_op(&op, version_raw_attr.size, FW_READ)) {
> >
> >This if statement is reversed so this code can never work.
> not sure I follow, can you explain?
>
The vsmp_init_op() function returns zero on success and this code treats
success as failure.
> >
> >> + printk(KERN_ERR "failed to init vSMP version op\n");
> >> + return -1;
> >> + }
> >> +
> >> + return vsmp_register_sysfs_group(&version_raw_attr);
> >> +}
regards,
dan carpenter
next prev parent reply other threads:[~2022-03-17 13:56 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-16 18:13 [RFC] staging/vSMP: new driver Czerwacki, Eial
2022-03-16 18:31 ` Randy Dunlap
2022-03-16 18:57 ` Czerwacki, Eial
2022-03-17 7:23 ` Greg KH
2022-03-17 7:34 ` Czerwacki, Eial
2022-03-17 7:51 ` Greg KH
2022-03-17 8:17 ` Czerwacki, Eial
2022-03-17 8:35 ` Greg KH
2022-03-17 8:52 ` Czerwacki, Eial
2022-03-17 8:59 ` Greg KH
2022-03-17 9:04 ` Czerwacki, Eial
2022-04-20 11:18 ` Czerwacki, Eial
2022-04-20 11:24 ` Greg KH
2022-04-20 11:38 ` Czerwacki, Eial
2022-04-20 11:42 ` Greg KH
2022-04-20 11:57 ` Czerwacki, Eial
2022-04-20 12:17 ` Greg KH
2022-04-20 12:36 ` Czerwacki, Eial
2022-04-20 14:24 ` Greg KH
2022-03-17 7:24 ` Greg KH
2022-03-17 7:38 ` Czerwacki, Eial
2022-03-17 7:52 ` Greg KH
2022-03-17 10:19 ` Dan Carpenter
2022-03-17 10:27 ` Dan Carpenter
2022-03-17 13:41 ` Czerwacki, Eial
2022-03-17 13:56 ` Dan Carpenter [this message]
2022-03-17 14:05 ` Czerwacki, Eial
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220317135628.GC3293@kadam \
--to=dan.carpenter@oracle.com \
--cc=eial.czerwacki@sap.com \
--cc=linux-staging@lists.linux.dev \
--cc=linux.vsmp@sap.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox