Skip to content

Commit 5b47b75

Browse files
chleroygregkh
authored andcommitted
eeprom: at25: Use DMA safe buffers
Reading EEPROM fails with following warning: [ 16.357496] ------------[ cut here ]------------ [ 16.357529] fsl_spi b01004c.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] [e68d9f3] [c00160e0] ret_from_syscall+0x0/0x28 ... [ 16.359608] ---[ end trace a4ce3e34afef0cb5 ]--- [ 16.359638] fsl_spi b01004c.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 ef38de9 commit 5b47b75

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
@@ -31,6 +31,8 @@
3131
*/
3232

3333
#define FM25_SN_LEN 8 /* serial number length */
34+
#define EE_MAXADDRLEN 3 /* 24 bit addresses, up to 2 MBytes */
35+
3436
struct at25_data {
3537
struct spi_eeprom chip;
3638
struct spi_device *spi;
@@ -39,6 +41,7 @@ struct at25_data {
3941
struct nvmem_config nvmem_config;
4042
struct nvmem_device *nvmem;
4143
u8 sernum[FM25_SN_LEN];
44+
u8 command[EE_MAXADDRLEN + 1];
4245
};
4346

4447
#define AT25_WREN 0x06 /* latch the write enable */
@@ -61,8 +64,6 @@ struct at25_data {
6164

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

64-
#define EE_MAXADDRLEN 3 /* 24 bit addresses, up to 2 MBytes */
65-
6667
/*
6768
* Specs often allow 5ms for a page write, sometimes 20ms;
6869
* it's important to recover from write timeouts.
@@ -78,7 +79,6 @@ static int at25_ee_read(void *priv, unsigned int offset,
7879
{
7980
struct at25_data *at25 = priv;
8081
char *buf = val;
81-
u8 command[EE_MAXADDRLEN + 1];
8282
u8 *cp;
8383
ssize_t status;
8484
struct spi_transfer t[2];
@@ -92,12 +92,15 @@ static int at25_ee_read(void *priv, unsigned int offset,
9292
if (unlikely(!count))
9393
return -EINVAL;
9494

95-
cp = command;
95+
cp = at25->command;
9696

9797
instr = AT25_READ;
9898
if (at25->chip.flags & EE_INSTR_BIT3_IS_ADDR)
9999
if (offset >= BIT(at25->addrlen * 8))
100100
instr |= AT25_INSTR_BIT3;
101+
102+
mutex_lock(&at25->lock);
103+
101104
*cp++ = instr;
102105

103106
/* 8/16/24-bit address is written MSB first */
@@ -116,16 +119,14 @@ static int at25_ee_read(void *priv, unsigned int offset,
116119
spi_message_init(&m);
117120
memset(t, 0, sizeof(t));
118121

119-
t[0].tx_buf = command;
122+
t[0].tx_buf = at25->command;
120123
t[0].len = at25->addrlen + 1;
121124
spi_message_add_tail(&t[0], &m);
122125

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

127-
mutex_lock(&at25->lock);
128-
129130
/*
130131
* Read it all at once.
131132
*
@@ -152,7 +153,7 @@ static int fm25_aux_read(struct at25_data *at25, u8 *buf, uint8_t command,
152153
spi_message_init(&m);
153154
memset(t, 0, sizeof(t));
154155

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

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

163164
mutex_lock(&at25->lock);
164165

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

0 commit comments

Comments
 (0)