All of lore.kernel.org
 help / color / mirror / Atom feed
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


  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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.