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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'staging-6.18-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging

Pull staging driver fixes from Greg KH:
"Here are some staging driver fixes that missed 6.17-final due to my
travel schedule. They fix a number of reported issues in the axis-fifo
driver, one of which was just independently discovered by someone else
today so someone is looking at this code.

All of these fixes have been in linux-next for many weeks with no
reported issues"

* tag 'staging-6.18-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging:
staging: axis-fifo: flush RX FIFO on read errors
staging: axis-fifo: fix TX handling on copy_from_user() failure
staging: axis-fifo: fix maximum TX packet length check

+31 -37
+31 -37
drivers/staging/axis-fifo/axis-fifo.c
··· 43 43 #define DRIVER_NAME "axis_fifo" 44 44 45 45 #define READ_BUF_SIZE 128U /* read buffer length in words */ 46 - #define WRITE_BUF_SIZE 128U /* write buffer length in words */ 47 46 48 47 #define AXIS_FIFO_DEBUG_REG_NAME_MAX_LEN 4 49 48 ··· 230 231 } 231 232 232 233 bytes_available = ioread32(fifo->base_addr + XLLF_RLR_OFFSET); 234 + words_available = bytes_available / sizeof(u32); 233 235 if (!bytes_available) { 234 236 dev_err(fifo->dt_device, "received a packet of length 0\n"); 235 237 ret = -EIO; ··· 241 241 dev_err(fifo->dt_device, "user read buffer too small (available bytes=%zu user buffer bytes=%zu)\n", 242 242 bytes_available, len); 243 243 ret = -EINVAL; 244 - goto end_unlock; 244 + goto err_flush_rx; 245 245 } 246 246 247 247 if (bytes_available % sizeof(u32)) { ··· 250 250 */ 251 251 dev_err(fifo->dt_device, "received a packet that isn't word-aligned\n"); 252 252 ret = -EIO; 253 - goto end_unlock; 253 + goto err_flush_rx; 254 254 } 255 - 256 - words_available = bytes_available / sizeof(u32); 257 255 258 256 /* read data into an intermediate buffer, copying the contents 259 257 * to userspace when the buffer is full ··· 264 266 tmp_buf[i] = ioread32(fifo->base_addr + 265 267 XLLF_RDFD_OFFSET); 266 268 } 269 + words_available -= copy; 267 270 268 271 if (copy_to_user(buf + copied * sizeof(u32), tmp_buf, 269 272 copy * sizeof(u32))) { 270 273 ret = -EFAULT; 271 - goto end_unlock; 274 + goto err_flush_rx; 272 275 } 273 276 274 277 copied += copy; 275 - words_available -= copy; 276 278 } 279 + mutex_unlock(&fifo->read_lock); 277 280 278 - ret = bytes_available; 281 + return bytes_available; 282 + 283 + err_flush_rx: 284 + while (words_available--) 285 + ioread32(fifo->base_addr + XLLF_RDFD_OFFSET); 279 286 280 287 end_unlock: 281 288 mutex_unlock(&fifo->read_lock); ··· 308 305 { 309 306 struct axis_fifo *fifo = (struct axis_fifo *)f->private_data; 310 307 unsigned int words_to_write; 311 - unsigned int copied; 312 - unsigned int copy; 313 - unsigned int i; 308 + u32 *txbuf; 314 309 int ret; 315 - u32 tmp_buf[WRITE_BUF_SIZE]; 316 310 317 311 if (len % sizeof(u32)) { 318 312 dev_err(fifo->dt_device, ··· 325 325 return -EINVAL; 326 326 } 327 327 328 - if (words_to_write > fifo->tx_fifo_depth) { 329 - dev_err(fifo->dt_device, "tried to write more words [%u] than slots in the fifo buffer [%u]\n", 330 - words_to_write, fifo->tx_fifo_depth); 328 + /* 329 + * In 'Store-and-Forward' mode, the maximum packet that can be 330 + * transmitted is limited by the size of the FIFO, which is 331 + * (C_TX_FIFO_DEPTH–4)*(data interface width/8) bytes. 332 + * 333 + * Do not attempt to send a packet larger than 'tx_fifo_depth - 4', 334 + * otherwise a 'Transmit Packet Overrun Error' interrupt will be 335 + * raised, which requires a reset of the TX circuit to recover. 336 + */ 337 + if (words_to_write > (fifo->tx_fifo_depth - 4)) 331 338 return -EINVAL; 332 - } 333 339 334 340 if (fifo->write_flags & O_NONBLOCK) { 335 341 /* ··· 374 368 } 375 369 } 376 370 377 - /* write data from an intermediate buffer into the fifo IP, refilling 378 - * the buffer with userspace data as needed 379 - */ 380 - copied = 0; 381 - while (words_to_write > 0) { 382 - copy = min(words_to_write, WRITE_BUF_SIZE); 383 - 384 - if (copy_from_user(tmp_buf, buf + copied * sizeof(u32), 385 - copy * sizeof(u32))) { 386 - ret = -EFAULT; 387 - goto end_unlock; 388 - } 389 - 390 - for (i = 0; i < copy; i++) 391 - iowrite32(tmp_buf[i], fifo->base_addr + 392 - XLLF_TDFD_OFFSET); 393 - 394 - copied += copy; 395 - words_to_write -= copy; 371 + txbuf = vmemdup_user(buf, len); 372 + if (IS_ERR(txbuf)) { 373 + ret = PTR_ERR(txbuf); 374 + goto end_unlock; 396 375 } 397 376 398 - ret = copied * sizeof(u32); 377 + for (int i = 0; i < words_to_write; ++i) 378 + iowrite32(txbuf[i], fifo->base_addr + XLLF_TDFD_OFFSET); 399 379 400 380 /* write packet size to fifo */ 401 - iowrite32(ret, fifo->base_addr + XLLF_TLR_OFFSET); 381 + iowrite32(len, fifo->base_addr + XLLF_TLR_OFFSET); 402 382 383 + ret = len; 384 + kvfree(txbuf); 403 385 end_unlock: 404 386 mutex_unlock(&fifo->write_lock); 405 387