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

nozomi: fix initialization and early flow control access

Due to some flaws in the initialization and flow control
code kernel oopses could be triggered e.g. when accessing
the card too early after insertion.
See e.g. kernel.org bug #10077.
The main part of the fix is a trivial state management
making sure the card is realy ready to use before allowing
any access.

Signed-off-by: Frank Seidel <fseidel@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Frank Seidel and committed by
Greg Kroah-Hartman
661b4e89 ef79df26

+43 -18
+43 -18
drivers/char/nozomi.c
··· 190 190 F32_8 = 8192, /* 3072 bytes downl. + 1024 bytes uplink * 2 -> 8192 */ 191 191 }; 192 192 193 + /* Initialization states a card can be in */ 194 + enum card_state { 195 + NOZOMI_STATE_UKNOWN = 0, 196 + NOZOMI_STATE_ENABLED = 1, /* pci device enabled */ 197 + NOZOMI_STATE_ALLOCATED = 2, /* config setup done */ 198 + NOZOMI_STATE_READY = 3, /* flowcontrols received */ 199 + }; 200 + 193 201 /* Two different toggle channels exist */ 194 202 enum channel_type { 195 203 CH_A = 0, ··· 393 385 spinlock_t spin_mutex; /* secures access to registers and tty */ 394 386 395 387 unsigned int index_start; 388 + enum card_state state; 396 389 u32 open_ttys; 397 390 }; 398 391 ··· 695 686 dc->last_ier = dc->last_ier | CTRL_DL; 696 687 writew(dc->last_ier, dc->reg_ier); 697 688 689 + dc->state = NOZOMI_STATE_ALLOCATED; 698 690 dev_info(&dc->pdev->dev, "Initialization OK!\n"); 699 691 return 1; 700 692 } ··· 954 944 case CTRL_APP2: 955 945 port = PORT_APP2; 956 946 enable_ier = APP2_DL; 947 + if (dc->state == NOZOMI_STATE_ALLOCATED) { 948 + /* 949 + * After card initialization the flow control 950 + * received for APP2 is always the last 951 + */ 952 + dc->state = NOZOMI_STATE_READY; 953 + dev_info(&dc->pdev->dev, "Device READY!\n"); 954 + } 957 955 break; 958 956 default: 959 957 dev_err(&dc->pdev->dev, ··· 1384 1366 1385 1367 dc->pdev = pdev; 1386 1368 1387 - /* Find out what card type it is */ 1388 - nozomi_get_card_type(dc); 1389 - 1390 1369 ret = pci_enable_device(dc->pdev); 1391 1370 if (ret) { 1392 1371 dev_err(&pdev->dev, "Failed to enable PCI Device\n"); 1393 1372 goto err_free; 1394 - } 1395 - 1396 - start = pci_resource_start(dc->pdev, 0); 1397 - if (start == 0) { 1398 - dev_err(&pdev->dev, "No I/O address for card detected\n"); 1399 - ret = -ENODEV; 1400 - goto err_disable_device; 1401 1373 } 1402 1374 1403 1375 ret = pci_request_regions(dc->pdev, NOZOMI_NAME); ··· 1396 1388 (int) /* nozomi_private.io_addr */ 0); 1397 1389 goto err_disable_device; 1398 1390 } 1391 + 1392 + start = pci_resource_start(dc->pdev, 0); 1393 + if (start == 0) { 1394 + dev_err(&pdev->dev, "No I/O address for card detected\n"); 1395 + ret = -ENODEV; 1396 + goto err_rel_regs; 1397 + } 1398 + 1399 + /* Find out what card type it is */ 1400 + nozomi_get_card_type(dc); 1399 1401 1400 1402 dc->base_addr = ioremap(start, dc->card_type); 1401 1403 if (!dc->base_addr) { ··· 1443 1425 dc->index_start = ndev_idx * MAX_PORT; 1444 1426 ndevs[ndev_idx] = dc; 1445 1427 1428 + pci_set_drvdata(pdev, dc); 1429 + 1430 + /* Enable RESET interrupt */ 1431 + dc->last_ier = RESET; 1432 + iowrite16(dc->last_ier, dc->reg_ier); 1433 + 1434 + dc->state = NOZOMI_STATE_ENABLED; 1435 + 1446 1436 for (i = 0; i < MAX_PORT; i++) { 1447 1437 mutex_init(&dc->port[i].tty_sem); 1448 1438 dc->port[i].tty_open_count = 0; ··· 1458 1432 tty_register_device(ntty_driver, dc->index_start + i, 1459 1433 &pdev->dev); 1460 1434 } 1461 - 1462 - /* Enable RESET interrupt. */ 1463 - dc->last_ier = RESET; 1464 - writew(dc->last_ier, dc->reg_ier); 1465 - 1466 - pci_set_drvdata(pdev, dc); 1467 1435 1468 1436 return 0; 1469 1437 ··· 1573 1553 struct nozomi *dc = get_dc_by_tty(tty); 1574 1554 unsigned long flags; 1575 1555 1576 - if (!port || !dc) 1556 + if (!port || !dc || dc->state != NOZOMI_STATE_READY) 1577 1557 return -ENODEV; 1578 1558 1579 1559 if (mutex_lock_interruptible(&port->tty_sem)) ··· 1736 1716 static int ntty_tiocmset(struct tty_struct *tty, struct file *file, 1737 1717 unsigned int set, unsigned int clear) 1738 1718 { 1719 + struct nozomi *dc = get_dc_by_tty(tty); 1720 + unsigned long flags; 1721 + 1722 + spin_lock_irqsave(&dc->spin_mutex, flags); 1739 1723 if (set & TIOCM_RTS) 1740 1724 set_rts(tty, 1); 1741 1725 else if (clear & TIOCM_RTS) ··· 1749 1725 set_dtr(tty, 1); 1750 1726 else if (clear & TIOCM_DTR) 1751 1727 set_dtr(tty, 0); 1728 + spin_unlock_irqrestore(&dc->spin_mutex, flags); 1752 1729 1753 1730 return 0; 1754 1731 } ··· 1787 1762 icount.brk = cnow.brk; 1788 1763 icount.buf_overrun = cnow.buf_overrun; 1789 1764 1790 - return copy_to_user(argp, &icount, sizeof(icount)); 1765 + return copy_to_user(argp, &icount, sizeof(icount)) ? -EFAULT : 0; 1791 1766 } 1792 1767 1793 1768 static int ntty_ioctl(struct tty_struct *tty, struct file *file,