From: Christoph Hellwig <hch@lst.de>
To: Maurizio Lombardi <mlombard@redhat.com>
Cc: kbusch@kernel.org, hch@lst.de, linux-nvme@lists.infradead.org,
dwagner@suse.de, hare@suse.de, jmeneghi@redhat.com,
emilne@redhat.com, mlombard@bsdbackstore.eu
Subject: Re: [PATCH 1/1] nvme: add support for dynamic quirk configuration via module parameter
Date: Mon, 2 Feb 2026 08:17:03 +0100 [thread overview]
Message-ID: <20260202071703.GA991@lst.de> (raw)
In-Reply-To: <20260128103318.76842-2-mlombard@redhat.com>
On Wed, Jan 28, 2026 at 11:33:18AM +0100, Maurizio Lombardi wrote:
> Introduce support for enabling or disabling specific NVMe quirks at
> module load time through the `quirks` module parameter.
> This mechanism allows users to apply known quirks dynamically
> based on the device's PCI vendor and device IDs,
> without requiring to add hardcoded entries in the driver
> and recompiling the kernel.
Nit: this commit message reads a little odd because line lengths are so
inconsistent, please use up all 73/75 chracaters consistently.
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
I thought those file only used to document always built-in paramters
using __setup and not module parameters, but grabbing random ones that
look modular disproves that.
> + list of quirk names separated by commas. A quirk name can
> + be prefixed by '^', meaning that the specified quirk must
Overly long lines.
> +static int quirks_param_set(const char *value, const struct kernel_param *kp);
Can we get away without a forware declaration here?
> +static struct quirk_entry *quirk_list;
> +static unsigned int quirk_count;
Please use nvme_pci_ prefixes for global variables and functions.
> +static int quirks_param_set(const char *value, const struct kernel_param *kp)
> +{
> + char *val, *outer_ptr, *inner_ptr, *field;
> + char *q_name;
> + u16 vid, did;
> + u32 *flags;
> + size_t i = 0, q_len, field_len;
> + int err, b;
> +
> + val = kstrdup(value, GFP_KERNEL);
> + if (!val)
> + return -ENOMEM;
> +
> + err = param_set_copystring(val, kp);
> + if (err)
> + goto exit;
All other callers of param_set_copystring except for usbhid set
it to the passsed in value and not a copy. Given that this
function has no documentation I'm not sure what is right, but
this smells a bit fishy.
> + kfree(quirk_list);
> + quirk_list = NULL;
How can quirk_list be non-NULL here given that we don't allow
runtime-changes to the paramter?
> + if (!*val) {
> + quirk_count = 0;
> + goto exit;
> + }
> + for (quirk_count = 1, i = 0; val[i]; i++)
> + if (val[i] == '-')
> + quirk_count++;
initializing the quirk_count in the loop looks odd, compare to:
quirk_count = 1;
for (i = 0; val[i]; i++)
if (val[i] == '-')
quirk_count++;
> +
> + quirk_list = kcalloc(quirk_count, sizeof(struct quirk_entry),
> + GFP_KERNEL);
> + if (!quirk_list) {
> + quirk_count = 0;
> + err = -ENOMEM;
> + goto exit;
> + }
Instead of zeroing the global variable on error, please only set it
from a local one on success to make the code more robust.
> + i = 0;
> + outer_ptr = val;
> + while ((field = strsep(&outer_ptr, "-"))) {
> + inner_ptr = field;
> +
> + /* Each entry consists of VID:DID:quirk_names */
> + field = strsep(&inner_ptr, ":");
This juggling between field and innter_ptr looks odd. I'd scan directly
into innter_ptr and keep field declarated locally in the loop. Same
for any other variable not used globally. Also splitting out the
loop bodies into well named helpers would help readability a lot here.
> + field_len = strlen(field);
> + for (b = 0; ; ++b) {
> + q_name = nvme_quirk_name(BIT(b));
Urrg. Please avoid use of BIT in general, but especially here where
you're actually doing arithmetics amd just declare constants.
Given that we're unlikely to add tons of quirk lines, simply reallocing
the array vs pre-sizing it might also be simpler.
> +static struct quirk_entry *detect_dynamic_quirks(struct pci_dev *pdev)
> +{
> + int i;
> +
> + for (i = 0; i < quirk_count; ++i) {
The nvme driver like most of the kernel uses post-increments in for
loops. (We already had at least one more instance above).
> + if (pdev->vendor == quirk_list[i].vendor_id &&
> + pdev->device == quirk_list[i].dev_id) {
> + return &quirk_list[i];
> + }
> + }
No need for either braces, and at least the inner ones are counter to
the usual kernel style.
> + qentry = detect_dynamic_quirks(pdev);
> + if (qentry) {
> + quirks |= qentry->enabled_quirks;
> + quirks &= ~(qentry->disabled_quirks);
No need for the braces after the ~.
next prev parent reply other threads:[~2026-02-02 7:17 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-28 10:33 [PATCH 0/1] Enable/Disable NVMe quirks via module parameter Maurizio Lombardi
2026-01-28 10:33 ` [PATCH 1/1] nvme: add support for dynamic quirk configuration " Maurizio Lombardi
2026-02-02 7:17 ` Christoph Hellwig [this message]
2026-02-02 17:38 ` Maurizio Lombardi
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=20260202071703.GA991@lst.de \
--to=hch@lst.de \
--cc=dwagner@suse.de \
--cc=emilne@redhat.com \
--cc=hare@suse.de \
--cc=jmeneghi@redhat.com \
--cc=kbusch@kernel.org \
--cc=linux-nvme@lists.infradead.org \
--cc=mlombard@bsdbackstore.eu \
--cc=mlombard@redhat.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