On Tue, Feb 26, 2019 at 11:23:49AM +0000, Sverdlin, Alexander (Nokia - DE/Ulm) wrote: > It was observed that reads crossing 4K address boundary are failing. > > This limitation is mentioned in Intel documents: > > Intel(R) 9 Series Chipset Family Platform Controller Hub (PCH) Datasheet: > > "5.26.3 Flash Access > Program Register Access: > * Program Register Accesses are not allowed to cross a 4 KB boundary..." > > Enhanced Serial Peripheral Interface (eSPI) > Interface Base Specification (for Client and Server Platforms): > > "5.1.4 Address > For other memory transactions, the address may start or end at any byte > boundary. However, the address and payload length combination must not > cross the naturally aligned address boundary of the corresponding Maximum > Payload Size. It must not cross a 4 KB address boundary." > > Avoid this by splitting an operation crossing the boundary into two > operations. > > Cc: stable@xxxxxxxxxxxxxxx > Reported-by: Romain Porte <romain.porte@xxxxxxxxx> > Tested-by: Pascal Fabreges <pascal.fabreges@xxxxxxxxx> > Signed-off-by: Alexander Sverdlin <alexander.sverdlin@xxxxxxxxx> > --- > drivers/mtd/spi-nor/intel-spi.c | 8 ++++++++ > 1 file changed, 8 insertions(+) > > diff --git a/drivers/mtd/spi-nor/intel-spi.c b/drivers/mtd/spi-nor/intel-spi.c > index af0a220..b83ea79 100644 > --- a/drivers/mtd/spi-nor/intel-spi.c > +++ b/drivers/mtd/spi-nor/intel-spi.c > @@ -632,6 +632,10 @@ static ssize_t intel_spi_read(struct spi_nor *nor, loff_t from, size_t len, > while (len > 0) { > block_size = min_t(size_t, len, INTEL_SPI_FIFO_SZ); > > + /* Read cannot cross 4K boundary */ > + if ((from ^ (from + block_size - 1)) & ~(SZ_4K - 1LL)) Don't we have existing macros in kernel.h that can be used here and below? > + block_size -= (from + block_size) & (SZ_4K - 1); > + > writel(from, ispi->base + FADDR); > > val = readl(ispi->base + HSFSTS_CTL); > @@ -685,6 +689,10 @@ static ssize_t intel_spi_write(struct spi_nor *nor, loff_t to, size_t len, > while (len > 0) { > block_size = min_t(size_t, len, INTEL_SPI_FIFO_SZ); > > + /* Write cannot cross 4K boundary */ > + if ((to ^ (to + block_size - 1)) & ~(SZ_4K - 1LL)) > + block_size -= (to + block_size) & (SZ_4K - 1); > + > writel(to, ispi->base + FADDR); > > val = readl(ispi->base + HSFSTS_CTL); > -- > 2.4.6