[PATCH 1/1] nvme: add support for dynamic quirk configuration via module parameter

Maurizio Lombardi mlombard at bsdbackstore.eu
Mon Feb 2 09:38:34 PST 2026


Hello Christoph,

On Mon Feb 2, 2026 at 8:17 AM CET, Christoph Hellwig wrote:
>
> Nit: this commit message reads a little odd because line lengths are so
> inconsistent, please use up all 73/75 chracaters consistently.
>
>
>> +			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.

Ok

>
>> +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.

Changed it to used the passed value

>
>> +	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?

That's right, I cleaned it up

>
>> +	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.

Ok

> Given that we're unlikely to add tons of quirk lines, simply reallocing
> the array vs pre-sizing it might also be simpler.

I tried but IMO doesn't make it much 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 ~.

Should all be fixed in V2, please take a look and let me know


Thanks,
Maurizio



More information about the Linux-nvme mailing list