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

ioat: ignore reserved bits for chancnt and xfercap

Don't trust that the reserved bits are always zero, also sanity check
the returned value.

Signed-off-by: Maciej Sosnowski <maciej.sosnowski@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>

+14
+7
drivers/dma/ioat/dma.c
··· 132 132 133 133 INIT_LIST_HEAD(&dma->channels); 134 134 dma->chancnt = readb(device->reg_base + IOAT_CHANCNT_OFFSET); 135 + dma->chancnt &= 0x1f; /* bits [4:0] valid */ 136 + if (dma->chancnt > ARRAY_SIZE(device->idx)) { 137 + dev_warn(dev, "(%d) exceeds max supported channels (%zu)\n", 138 + dma->chancnt, ARRAY_SIZE(device->idx)); 139 + dma->chancnt = ARRAY_SIZE(device->idx); 140 + } 135 141 xfercap_scale = readb(device->reg_base + IOAT_XFERCAP_OFFSET); 142 + xfercap_scale &= 0x1f; /* bits [4:0] valid */ 136 143 xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale)); 137 144 dev_dbg(dev, "%s: xfercap = %d\n", __func__, xfercap); 138 145
+7
drivers/dma/ioat/dma_v2.c
··· 359 359 360 360 INIT_LIST_HEAD(&dma->channels); 361 361 dma->chancnt = readb(device->reg_base + IOAT_CHANCNT_OFFSET); 362 + dma->chancnt &= 0x1f; /* bits [4:0] valid */ 363 + if (dma->chancnt > ARRAY_SIZE(device->idx)) { 364 + dev_warn(dev, "(%d) exceeds max supported channels (%zu)\n", 365 + dma->chancnt, ARRAY_SIZE(device->idx)); 366 + dma->chancnt = ARRAY_SIZE(device->idx); 367 + } 362 368 xfercap_log = readb(device->reg_base + IOAT_XFERCAP_OFFSET); 369 + xfercap_log &= 0x1f; /* bits [4:0] valid */ 363 370 if (xfercap_log == 0) 364 371 return 0; 365 372 dev_dbg(dev, "%s: xfercap = %d\n", __func__, 1 << xfercap_log);