Skip to content

Commit 80c71d7

Browse files
chleroygregkh
authored andcommitted
eeprom: at25: Use DMA safe buffers
commit 5b47b75 upstream. Reading EEPROM fails with following warning: [ 16.357496] ------------[ cut here ]------------ [ 16.357529] fsl_spi b01004c0.spi: rejecting DMA map of vmalloc memory [ 16.357698] WARNING: CPU: 0 PID: 371 at include/linux/dma-mapping.h:326 fsl_spi_cpm_bufs+0x2a0/0x2d8 [ 16.357775] CPU: 0 PID: 371 Comm: od Not tainted 5.16.11-s3k-dev-01743-g19beecbfe9d6-dirty #109 [ 16.357806] NIP: c03fbc9c LR: c03fbc9c CTR: 00000000 [ 16.357825] REGS: e68d9b20 TRAP: 0700 Not tainted (5.16.11-s3k-dev-01743-g19beecbfe9d6-dirty) [ 16.357849] MSR: 00029032 <EE,ME,IR,DR,RI> CR: 24002282 XER: 00000000 [ 16.357931] [ 16.357931] GPR00: c03fbc9c e68d9be0 c26d06a0 00000039 00000001 c0d36364 c0e96428 00000027 [ 16.357931] GPR08: 00000001 00000000 00000023 3fffc000 24002282 100d3dd6 100a2ffc 00000000 [ 16.357931] GPR16: 100cd280 100b0000 00000000 aff54f7e 100d0000 100d0000 00000001 100cf328 [ 16.357931] GPR24: 100cf328 00000000 00000003 e68d9e30 c156b410 e67ab4c0 e68d9d38 c24ab278 [ 16.358253] NIP [c03fbc9c] fsl_spi_cpm_bufs+0x2a0/0x2d8 [ 16.358292] LR [c03fbc9c] fsl_spi_cpm_bufs+0x2a0/0x2d8 [ 16.358325] Call Trace: [ 16.358336] [e68d9be0] [c03fbc9c] fsl_spi_cpm_bufs+0x2a0/0x2d8 (unreliable) [ 16.358388] [e68d9c00] [c03fcb44] fsl_spi_bufs.isra.0+0x94/0x1a0 [ 16.358436] [e68d9c20] [c03fd970] fsl_spi_do_one_msg+0x254/0x3dc [ 16.358483] [e68d9cb0] [c03f7e50] __spi_pump_messages+0x274/0x8a4 [ 16.358529] [e68d9ce0] [c03f9d30] __spi_sync+0x344/0x378 [ 16.358573] [e68d9d20] [c03fb52c] spi_sync+0x34/0x60 [ 16.358616] [e68d9d30] [c03b4dec] at25_ee_read+0x138/0x1a8 [ 16.358667] [e68d9e50] [c04a8fb8] bin_attr_nvmem_read+0x98/0x110 [ 16.358725] [e68d9e60] [c0204b14] kernfs_fop_read_iter+0xc0/0x1fc [ 16.358774] [e68d9e80] [c0168660] vfs_read+0x284/0x410 [ 16.358821] [e68d9f00] [c016925c] ksys_read+0x6c/0x11c [ 16.358863] [e68d9f30] [c00160e0] ret_from_syscall+0x0/0x28 ... [ 16.359608] ---[ end trace a4ce3e34afef0cb5 ]--- [ 16.359638] fsl_spi b01004c0.spi: unable to map tx dma This is due to the AT25 driver using buffers on stack, which is not possible with CONFIG_VMAP_STACK. As mentionned in kernel Documentation (Documentation/spi/spi-summary.rst): - Follow standard kernel rules, and provide DMA-safe buffers in your messages. That way controller drivers using DMA aren't forced to make extra copies unless the hardware requires it (e.g. working around hardware errata that force the use of bounce buffering). Modify the driver to use a buffer located in the at25 device structure which is allocated via kmalloc during probe. Protect writes in this new buffer with the driver's mutex. Fixes: b587b13 ("[PATCH] SPI eeprom driver") Cc: stable <[email protected]> Signed-off-by: Christophe Leroy <[email protected]> Link: https://lore.kernel.org/r/230a9486fc68ea0182df46255e42a51099403642.1648032613.git.christophe.leroy@csgroup.eu Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 7d0010f commit 80c71d7

File tree

1 file changed

+11
-8
lines changed

1 file changed

+11
-8
lines changed

drivers/misc/eeprom/at25.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
*/
3131

3232
#define FM25_SN_LEN 8 /* serial number length */
33+
#define EE_MAXADDRLEN 3 /* 24 bit addresses, up to 2 MBytes */
34+
3335
struct at25_data {
3436
struct spi_device *spi;
3537
struct mutex lock;
@@ -38,6 +40,7 @@ struct at25_data {
3840
struct nvmem_config nvmem_config;
3941
struct nvmem_device *nvmem;
4042
u8 sernum[FM25_SN_LEN];
43+
u8 command[EE_MAXADDRLEN + 1];
4144
};
4245

4346
#define AT25_WREN 0x06 /* latch the write enable */
@@ -60,8 +63,6 @@ struct at25_data {
6063

6164
#define FM25_ID_LEN 9 /* ID length */
6265

63-
#define EE_MAXADDRLEN 3 /* 24 bit addresses, up to 2 MBytes */
64-
6566
/* Specs often allow 5 msec for a page write, sometimes 20 msec;
6667
* it's important to recover from write timeouts.
6768
*/
@@ -76,7 +77,6 @@ static int at25_ee_read(void *priv, unsigned int offset,
7677
{
7778
struct at25_data *at25 = priv;
7879
char *buf = val;
79-
u8 command[EE_MAXADDRLEN + 1];
8080
u8 *cp;
8181
ssize_t status;
8282
struct spi_transfer t[2];
@@ -90,12 +90,15 @@ static int at25_ee_read(void *priv, unsigned int offset,
9090
if (unlikely(!count))
9191
return -EINVAL;
9292

93-
cp = command;
93+
cp = at25->command;
9494

9595
instr = AT25_READ;
9696
if (at25->chip.flags & EE_INSTR_BIT3_IS_ADDR)
9797
if (offset >= (1U << (at25->addrlen * 8)))
9898
instr |= AT25_INSTR_BIT3;
99+
100+
mutex_lock(&at25->lock);
101+
99102
*cp++ = instr;
100103

101104
/* 8/16/24-bit address is written MSB first */
@@ -114,16 +117,14 @@ static int at25_ee_read(void *priv, unsigned int offset,
114117
spi_message_init(&m);
115118
memset(t, 0, sizeof(t));
116119

117-
t[0].tx_buf = command;
120+
t[0].tx_buf = at25->command;
118121
t[0].len = at25->addrlen + 1;
119122
spi_message_add_tail(&t[0], &m);
120123

121124
t[1].rx_buf = buf;
122125
t[1].len = count;
123126
spi_message_add_tail(&t[1], &m);
124127

125-
mutex_lock(&at25->lock);
126-
127128
/* Read it all at once.
128129
*
129130
* REVISIT that's potentially a problem with large chips, if
@@ -151,7 +152,7 @@ static int fm25_aux_read(struct at25_data *at25, u8 *buf, uint8_t command,
151152
spi_message_init(&m);
152153
memset(t, 0, sizeof(t));
153154

154-
t[0].tx_buf = &command;
155+
t[0].tx_buf = at25->command;
155156
t[0].len = 1;
156157
spi_message_add_tail(&t[0], &m);
157158

@@ -161,6 +162,8 @@ static int fm25_aux_read(struct at25_data *at25, u8 *buf, uint8_t command,
161162

162163
mutex_lock(&at25->lock);
163164

165+
at25->command[0] = command;
166+
164167
status = spi_sync(at25->spi, &m);
165168
dev_dbg(&at25->spi->dev, "read %d aux bytes --> %d\n", len, status);
166169

0 commit comments

Comments
 (0)