spi: remove some spidev oops-on-rmmod paths

Somehow the spidev code forgot to include a critical mechanism: when the
underlying device is removed (e.g. spi_master rmmod), open file
descriptors must be prevented from issuing new I/O requests to that
device. On penalty of the oopsing reported by Sebastian Siewior
<bigeasy@tglx.de> ...

This is a partial fix, adding handshaking between the lower level (SPI
messaging) and the file operations using the spi_dev. (It also fixes an
issue where reads and writes didn't return the number of bytes sent or
received.)

There's still a refcounting issue to be addressed (separately).

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Reported-by: Sebastian Siewior <bigeasy@tglx.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by David Brownell and committed by Linus Torvalds 25d5cb4b 5c02b575

+89 -13
+89 -13
drivers/spi/spidev.c
··· 68 68 69 69 struct spidev_data { 70 70 struct device dev; 71 + spinlock_t spi_lock; 71 72 struct spi_device *spi; 72 73 struct list_head device_entry; 73 74 ··· 86 85 87 86 /*-------------------------------------------------------------------------*/ 88 87 88 + /* 89 + * We can't use the standard synchronous wrappers for file I/O; we 90 + * need to protect against async removal of the underlying spi_device. 91 + */ 92 + static void spidev_complete(void *arg) 93 + { 94 + complete(arg); 95 + } 96 + 97 + static ssize_t 98 + spidev_sync(struct spidev_data *spidev, struct spi_message *message) 99 + { 100 + DECLARE_COMPLETION_ONSTACK(done); 101 + int status; 102 + 103 + message->complete = spidev_complete; 104 + message->context = &done; 105 + 106 + spin_lock_irq(&spidev->spi_lock); 107 + if (spidev->spi == NULL) 108 + status = -ESHUTDOWN; 109 + else 110 + status = spi_async(spidev->spi, message); 111 + spin_unlock_irq(&spidev->spi_lock); 112 + 113 + if (status == 0) { 114 + wait_for_completion(&done); 115 + status = message->status; 116 + if (status == 0) 117 + status = message->actual_length; 118 + } 119 + return status; 120 + } 121 + 122 + static inline ssize_t 123 + spidev_sync_write(struct spidev_data *spidev, size_t len) 124 + { 125 + struct spi_transfer t = { 126 + .tx_buf = spidev->buffer, 127 + .len = len, 128 + }; 129 + struct spi_message m; 130 + 131 + spi_message_init(&m); 132 + spi_message_add_tail(&t, &m); 133 + return spidev_sync(spidev, &m); 134 + } 135 + 136 + static inline ssize_t 137 + spidev_sync_read(struct spidev_data *spidev, size_t len) 138 + { 139 + struct spi_transfer t = { 140 + .rx_buf = spidev->buffer, 141 + .len = len, 142 + }; 143 + struct spi_message m; 144 + 145 + spi_message_init(&m); 146 + spi_message_add_tail(&t, &m); 147 + return spidev_sync(spidev, &m); 148 + } 149 + 150 + /*-------------------------------------------------------------------------*/ 151 + 89 152 /* Read-only message with current device setup */ 90 153 static ssize_t 91 154 spidev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) 92 155 { 93 156 struct spidev_data *spidev; 94 - struct spi_device *spi; 95 157 ssize_t status = 0; 96 158 97 159 /* chipselect only toggles at start or end of operation */ ··· 162 98 return -EMSGSIZE; 163 99 164 100 spidev = filp->private_data; 165 - spi = spidev->spi; 166 101 167 102 mutex_lock(&spidev->buf_lock); 168 - status = spi_read(spi, spidev->buffer, count); 103 + status = spidev_sync_read(spidev, count); 169 104 if (status == 0) { 170 105 unsigned long missing; 171 106 ··· 185 122 size_t count, loff_t *f_pos) 186 123 { 187 124 struct spidev_data *spidev; 188 - struct spi_device *spi; 189 125 ssize_t status = 0; 190 126 unsigned long missing; 191 127 ··· 193 131 return -EMSGSIZE; 194 132 195 133 spidev = filp->private_data; 196 - spi = spidev->spi; 197 134 198 135 mutex_lock(&spidev->buf_lock); 199 136 missing = copy_from_user(spidev->buffer, buf, count); 200 137 if (missing == 0) { 201 - status = spi_write(spi, spidev->buffer, count); 138 + status = spidev_sync_write(spidev, count); 202 139 if (status == 0) 203 140 status = count; 204 141 } else ··· 214 153 struct spi_transfer *k_xfers; 215 154 struct spi_transfer *k_tmp; 216 155 struct spi_ioc_transfer *u_tmp; 217 - struct spi_device *spi = spidev->spi; 218 156 unsigned n, total; 219 157 u8 *buf; 220 158 int status = -EFAULT; ··· 275 215 spi_message_add_tail(k_tmp, &msg); 276 216 } 277 217 278 - status = spi_sync(spi, &msg); 218 + status = spidev_sync(spidev, &msg); 279 219 if (status < 0) 280 220 goto done; 281 221 ··· 329 269 if (err) 330 270 return -EFAULT; 331 271 272 + /* guard against device removal before, or while, 273 + * we issue this ioctl. 274 + */ 332 275 spidev = filp->private_data; 333 - spi = spidev->spi; 276 + spin_lock_irq(&spidev->spi_lock); 277 + spi = spi_dev_get(spidev->spi); 278 + spin_unlock_irq(&spidev->spi_lock); 279 + 280 + if (spi == NULL) 281 + return -ESHUTDOWN; 334 282 335 283 switch (cmd) { 336 284 /* read requests */ ··· 424 356 default: 425 357 /* segmented and/or full-duplex I/O request */ 426 358 if (_IOC_NR(cmd) != _IOC_NR(SPI_IOC_MESSAGE(0)) 427 - || _IOC_DIR(cmd) != _IOC_WRITE) 428 - return -ENOTTY; 359 + || _IOC_DIR(cmd) != _IOC_WRITE) { 360 + retval = -ENOTTY; 361 + break; 362 + } 429 363 430 364 tmp = _IOC_SIZE(cmd); 431 365 if ((tmp % sizeof(struct spi_ioc_transfer)) != 0) { ··· 455 385 kfree(ioc); 456 386 break; 457 387 } 388 + spi_dev_put(spi); 458 389 return retval; 459 390 } 460 391 ··· 559 488 560 489 /* Initialize the driver data */ 561 490 spidev->spi = spi; 491 + spin_lock_init(&spidev->spi_lock); 562 492 mutex_init(&spidev->buf_lock); 563 493 564 494 INIT_LIST_HEAD(&spidev->device_entry); ··· 598 526 { 599 527 struct spidev_data *spidev = dev_get_drvdata(&spi->dev); 600 528 601 - mutex_lock(&device_list_lock); 529 + /* make sure ops on existing fds can abort cleanly */ 530 + spin_lock_irq(&spidev->spi_lock); 531 + spidev->spi = NULL; 532 + spin_unlock_irq(&spidev->spi_lock); 602 533 534 + /* prevent new opens */ 535 + mutex_lock(&device_list_lock); 603 536 list_del(&spidev->device_entry); 604 537 dev_set_drvdata(&spi->dev, NULL); 605 538 clear_bit(MINOR(spidev->dev.devt), minors); 606 539 device_unregister(&spidev->dev); 607 - 608 540 mutex_unlock(&device_list_lock); 609 541 610 542 return 0;