.. | .. |
---|
24 | 24 | #include <linux/timer.h> |
---|
25 | 25 | #include <linux/kernel_stat.h> |
---|
26 | 26 | #include <linux/sched/signal.h> |
---|
| 27 | +#include <linux/dma-mapping.h> |
---|
27 | 28 | |
---|
28 | 29 | #include <asm/ccwdev.h> |
---|
29 | 30 | #include <asm/cio.h> |
---|
.. | .. |
---|
642 | 643 | return device_add(dev); |
---|
643 | 644 | } |
---|
644 | 645 | |
---|
645 | | -static int match_dev_id(struct device *dev, void *data) |
---|
| 646 | +static int match_dev_id(struct device *dev, const void *data) |
---|
646 | 647 | { |
---|
647 | 648 | struct ccw_device *cdev = to_ccwdev(dev); |
---|
648 | | - struct ccw_dev_id *dev_id = data; |
---|
| 649 | + struct ccw_dev_id *dev_id = (void *)data; |
---|
649 | 650 | |
---|
650 | 651 | return ccw_dev_id_is_equal(&cdev->private->dev_id, dev_id); |
---|
651 | 652 | } |
---|
.. | .. |
---|
687 | 688 | struct ccw_device *cdev; |
---|
688 | 689 | |
---|
689 | 690 | cdev = to_ccwdev(dev); |
---|
| 691 | + cio_gp_dma_free(cdev->private->dma_pool, cdev->private->dma_area, |
---|
| 692 | + sizeof(*cdev->private->dma_area)); |
---|
| 693 | + cio_gp_dma_destroy(cdev->private->dma_pool, &cdev->dev); |
---|
690 | 694 | /* Release reference of parent subchannel. */ |
---|
691 | 695 | put_device(cdev->dev.parent); |
---|
692 | 696 | kfree(cdev->private); |
---|
.. | .. |
---|
696 | 700 | static struct ccw_device * io_subchannel_allocate_dev(struct subchannel *sch) |
---|
697 | 701 | { |
---|
698 | 702 | struct ccw_device *cdev; |
---|
| 703 | + struct gen_pool *dma_pool; |
---|
699 | 704 | |
---|
700 | 705 | cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); |
---|
701 | | - if (cdev) { |
---|
702 | | - cdev->private = kzalloc(sizeof(struct ccw_device_private), |
---|
703 | | - GFP_KERNEL | GFP_DMA); |
---|
704 | | - if (cdev->private) |
---|
705 | | - return cdev; |
---|
706 | | - } |
---|
| 706 | + if (!cdev) |
---|
| 707 | + goto err_cdev; |
---|
| 708 | + cdev->private = kzalloc(sizeof(struct ccw_device_private), |
---|
| 709 | + GFP_KERNEL | GFP_DMA); |
---|
| 710 | + if (!cdev->private) |
---|
| 711 | + goto err_priv; |
---|
| 712 | + cdev->dev.coherent_dma_mask = sch->dev.coherent_dma_mask; |
---|
| 713 | + cdev->dev.dma_mask = sch->dev.dma_mask; |
---|
| 714 | + dma_pool = cio_gp_dma_create(&cdev->dev, 1); |
---|
| 715 | + if (!dma_pool) |
---|
| 716 | + goto err_dma_pool; |
---|
| 717 | + cdev->private->dma_pool = dma_pool; |
---|
| 718 | + cdev->private->dma_area = cio_gp_dma_zalloc(dma_pool, &cdev->dev, |
---|
| 719 | + sizeof(*cdev->private->dma_area)); |
---|
| 720 | + if (!cdev->private->dma_area) |
---|
| 721 | + goto err_dma_area; |
---|
| 722 | + return cdev; |
---|
| 723 | +err_dma_area: |
---|
| 724 | + cio_gp_dma_destroy(dma_pool, &cdev->dev); |
---|
| 725 | +err_dma_pool: |
---|
| 726 | + kfree(cdev->private); |
---|
| 727 | +err_priv: |
---|
707 | 728 | kfree(cdev); |
---|
| 729 | +err_cdev: |
---|
708 | 730 | return ERR_PTR(-ENOMEM); |
---|
709 | 731 | } |
---|
710 | 732 | |
---|
.. | .. |
---|
886 | 908 | wake_up(&ccw_device_init_wq); |
---|
887 | 909 | break; |
---|
888 | 910 | case DEV_STATE_OFFLINE: |
---|
889 | | - /* |
---|
| 911 | + /* |
---|
890 | 912 | * We can't register the device in interrupt context so |
---|
891 | 913 | * we schedule a work item. |
---|
892 | 914 | */ |
---|
.. | .. |
---|
1067 | 1089 | if (!io_priv) |
---|
1068 | 1090 | goto out_schedule; |
---|
1069 | 1091 | |
---|
| 1092 | + io_priv->dma_area = dma_alloc_coherent(&sch->dev, |
---|
| 1093 | + sizeof(*io_priv->dma_area), |
---|
| 1094 | + &io_priv->dma_area_dma, GFP_KERNEL); |
---|
| 1095 | + if (!io_priv->dma_area) { |
---|
| 1096 | + kfree(io_priv); |
---|
| 1097 | + goto out_schedule; |
---|
| 1098 | + } |
---|
| 1099 | + |
---|
1070 | 1100 | set_io_private(sch, io_priv); |
---|
1071 | 1101 | css_schedule_eval(sch->schid); |
---|
1072 | 1102 | return 0; |
---|
.. | .. |
---|
1093 | 1123 | set_io_private(sch, NULL); |
---|
1094 | 1124 | spin_unlock_irq(sch->lock); |
---|
1095 | 1125 | out_free: |
---|
| 1126 | + dma_free_coherent(&sch->dev, sizeof(*io_priv->dma_area), |
---|
| 1127 | + io_priv->dma_area, io_priv->dma_area_dma); |
---|
1096 | 1128 | kfree(io_priv); |
---|
1097 | 1129 | sysfs_remove_group(&sch->dev.kobj, &io_subchannel_attr_group); |
---|
1098 | 1130 | return 0; |
---|
.. | .. |
---|
1235 | 1267 | sch = to_subchannel(cdev->dev.parent); |
---|
1236 | 1268 | if ((sch->schib.pmcw.pam & sch->opm) == sch->vpm) |
---|
1237 | 1269 | break; |
---|
1238 | | - /* fall through */ |
---|
| 1270 | + fallthrough; |
---|
1239 | 1271 | case DEV_STATE_DISCONNECTED: |
---|
1240 | 1272 | CIO_MSG_EVENT(3, "recovery: trigger 0.%x.%04x\n", |
---|
1241 | 1273 | cdev->private->dev_id.ssid, |
---|
.. | .. |
---|
1353 | 1385 | enum io_sch_action { |
---|
1354 | 1386 | IO_SCH_UNREG, |
---|
1355 | 1387 | IO_SCH_ORPH_UNREG, |
---|
| 1388 | + IO_SCH_UNREG_CDEV, |
---|
1356 | 1389 | IO_SCH_ATTACH, |
---|
1357 | 1390 | IO_SCH_UNREG_ATTACH, |
---|
1358 | 1391 | IO_SCH_ORPH_ATTACH, |
---|
.. | .. |
---|
1385 | 1418 | } |
---|
1386 | 1419 | if ((sch->schib.pmcw.pam & sch->opm) == 0) { |
---|
1387 | 1420 | if (ccw_device_notify(cdev, CIO_NO_PATH) != NOTIFY_OK) |
---|
1388 | | - return IO_SCH_UNREG; |
---|
| 1421 | + return IO_SCH_UNREG_CDEV; |
---|
1389 | 1422 | return IO_SCH_DISC; |
---|
1390 | 1423 | } |
---|
1391 | 1424 | if (device_is_disconnected(cdev)) |
---|
.. | .. |
---|
1447 | 1480 | case IO_SCH_ORPH_ATTACH: |
---|
1448 | 1481 | ccw_device_set_disconnected(cdev); |
---|
1449 | 1482 | break; |
---|
| 1483 | + case IO_SCH_UNREG_CDEV: |
---|
1450 | 1484 | case IO_SCH_UNREG_ATTACH: |
---|
1451 | 1485 | case IO_SCH_UNREG: |
---|
1452 | 1486 | if (!cdev) |
---|
.. | .. |
---|
1480 | 1514 | if (rc) |
---|
1481 | 1515 | goto out; |
---|
1482 | 1516 | break; |
---|
| 1517 | + case IO_SCH_UNREG_CDEV: |
---|
1483 | 1518 | case IO_SCH_UNREG_ATTACH: |
---|
1484 | 1519 | spin_lock_irqsave(sch->lock, flags); |
---|
1485 | 1520 | if (cdev->private->flags.resuming) { |
---|
.. | .. |
---|
1598 | 1633 | return ERR_CAST(sch); |
---|
1599 | 1634 | |
---|
1600 | 1635 | io_priv = kzalloc(sizeof(*io_priv), GFP_KERNEL | GFP_DMA); |
---|
1601 | | - if (!io_priv) { |
---|
1602 | | - put_device(&sch->dev); |
---|
1603 | | - return ERR_PTR(-ENOMEM); |
---|
1604 | | - } |
---|
| 1636 | + if (!io_priv) |
---|
| 1637 | + goto err_priv; |
---|
| 1638 | + io_priv->dma_area = dma_alloc_coherent(&sch->dev, |
---|
| 1639 | + sizeof(*io_priv->dma_area), |
---|
| 1640 | + &io_priv->dma_area_dma, GFP_KERNEL); |
---|
| 1641 | + if (!io_priv->dma_area) |
---|
| 1642 | + goto err_dma_area; |
---|
1605 | 1643 | set_io_private(sch, io_priv); |
---|
1606 | 1644 | cdev = io_subchannel_create_ccwdev(sch); |
---|
1607 | 1645 | if (IS_ERR(cdev)) { |
---|
| 1646 | + dma_free_coherent(&sch->dev, sizeof(*io_priv->dma_area), |
---|
| 1647 | + io_priv->dma_area, io_priv->dma_area_dma); |
---|
| 1648 | + set_io_private(sch, NULL); |
---|
1608 | 1649 | put_device(&sch->dev); |
---|
1609 | 1650 | kfree(io_priv); |
---|
1610 | 1651 | return cdev; |
---|
.. | .. |
---|
1612 | 1653 | cdev->drv = drv; |
---|
1613 | 1654 | ccw_device_set_int_class(cdev); |
---|
1614 | 1655 | return cdev; |
---|
| 1656 | + |
---|
| 1657 | +err_dma_area: |
---|
| 1658 | + kfree(io_priv); |
---|
| 1659 | +err_priv: |
---|
| 1660 | + put_device(&sch->dev); |
---|
| 1661 | + return ERR_PTR(-ENOMEM); |
---|
1615 | 1662 | } |
---|
1616 | 1663 | |
---|
1617 | 1664 | void __init ccw_device_destroy_console(struct ccw_device *cdev) |
---|
.. | .. |
---|
1620 | 1667 | struct io_subchannel_private *io_priv = to_io_private(sch); |
---|
1621 | 1668 | |
---|
1622 | 1669 | set_io_private(sch, NULL); |
---|
| 1670 | + dma_free_coherent(&sch->dev, sizeof(*io_priv->dma_area), |
---|
| 1671 | + io_priv->dma_area, io_priv->dma_area_dma); |
---|
1623 | 1672 | put_device(&sch->dev); |
---|
1624 | 1673 | put_device(&cdev->dev); |
---|
1625 | 1674 | kfree(io_priv); |
---|
.. | .. |
---|
1654 | 1703 | EXPORT_SYMBOL_GPL(ccw_device_force_console); |
---|
1655 | 1704 | #endif |
---|
1656 | 1705 | |
---|
1657 | | -/* |
---|
1658 | | - * get ccw_device matching the busid, but only if owned by cdrv |
---|
1659 | | - */ |
---|
1660 | | -static int |
---|
1661 | | -__ccwdev_check_busid(struct device *dev, void *id) |
---|
1662 | | -{ |
---|
1663 | | - char *bus_id; |
---|
1664 | | - |
---|
1665 | | - bus_id = id; |
---|
1666 | | - |
---|
1667 | | - return (strcmp(bus_id, dev_name(dev)) == 0); |
---|
1668 | | -} |
---|
1669 | | - |
---|
1670 | | - |
---|
1671 | 1706 | /** |
---|
1672 | 1707 | * get_ccwdev_by_busid() - obtain device from a bus id |
---|
1673 | 1708 | * @cdrv: driver the device is owned by |
---|
.. | .. |
---|
1684 | 1719 | { |
---|
1685 | 1720 | struct device *dev; |
---|
1686 | 1721 | |
---|
1687 | | - dev = driver_find_device(&cdrv->driver, NULL, (void *)bus_id, |
---|
1688 | | - __ccwdev_check_busid); |
---|
| 1722 | + dev = driver_find_device_by_name(&cdrv->driver, bus_id); |
---|
1689 | 1723 | |
---|
1690 | 1724 | return dev ? to_ccwdev(dev) : NULL; |
---|
1691 | 1725 | } |
---|
.. | .. |
---|
2065 | 2099 | case CDEV_TODO_UNREG_EVAL: |
---|
2066 | 2100 | if (!sch_is_pseudo_sch(sch)) |
---|
2067 | 2101 | css_schedule_eval(sch->schid); |
---|
2068 | | - /* fall-through */ |
---|
| 2102 | + fallthrough; |
---|
2069 | 2103 | case CDEV_TODO_UNREG: |
---|
2070 | 2104 | if (sch_is_pseudo_sch(sch)) |
---|
2071 | 2105 | ccw_device_unregister(cdev); |
---|