| .. | .. |
|---|
| 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); |
|---|