Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mtd: cfi_cmdset_0001: Support the absence of protection registers

The flash controller implemented by the Arm Base platform behaves like
the Intel StrataFlash J3 device, but omits several features. In
particular it doesn't implement a protection register, so "Number of
Protection register fields" in the Primary Vendor-Specific Extended
Query, is 0.

The Intel StrataFlash J3 datasheet only lists 1 as a valid value for
NumProtectionFields. It describes the field as:

"Number of Protection register fields in JEDEC ID space.
“00h,” indicates that 256 protection bytes are available"

While a value of 0 may arguably not be architecturally valid, the
driver's current behavior is certainly wrong: if NumProtectionFields is
0, read_pri_intelext() adds a negative value to the unsigned extra_size,
and ends up in an infinite loop.

Fix it by ignoring a NumProtectionFields of 0.

Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
Tested-by: Sudeep Holla <sudeep.holla@arm.com>
Tested-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com>

authored by

Jean-Philippe Brucker and committed by
Vignesh Raghavendra
b359ed51 ae83d0b4

+8 -5
+8 -5
drivers/mtd/chips/cfi_cmdset_0001.c
··· 420 420 extra_size = 0; 421 421 422 422 /* Protection Register info */ 423 - extra_size += (extp->NumProtectionFields - 1) * 424 - sizeof(struct cfi_intelext_otpinfo); 423 + if (extp->NumProtectionFields) 424 + extra_size += (extp->NumProtectionFields - 1) * 425 + sizeof(struct cfi_intelext_otpinfo); 425 426 } 426 427 427 428 if (extp->MinorVersion >= '1') { ··· 696 695 */ 697 696 if (extp && extp->MajorVersion == '1' && extp->MinorVersion >= '3' 698 697 && extp->FeatureSupport & (1 << 9)) { 698 + int offs = 0; 699 699 struct cfi_private *newcfi; 700 700 struct flchip *chip; 701 701 struct flchip_shared *shared; 702 - int offs, numregions, numparts, partshift, numvirtchips, i, j; 702 + int numregions, numparts, partshift, numvirtchips, i, j; 703 703 704 704 /* Protection Register info */ 705 - offs = (extp->NumProtectionFields - 1) * 706 - sizeof(struct cfi_intelext_otpinfo); 705 + if (extp->NumProtectionFields) 706 + offs = (extp->NumProtectionFields - 1) * 707 + sizeof(struct cfi_intelext_otpinfo); 707 708 708 709 /* Burst Read info */ 709 710 offs += extp->extra[offs+1]+2;