|
35 | 35 | static int vfio_ap_mdev_reset_queues(struct ap_queue_table *qtable); |
36 | 36 | static struct vfio_ap_queue *vfio_ap_find_queue(int apqn); |
37 | 37 | static const struct vfio_device_ops vfio_ap_matrix_dev_ops; |
38 | | -static int vfio_ap_mdev_reset_queue(struct vfio_ap_queue *q); |
| 38 | +static void vfio_ap_mdev_reset_queue(struct vfio_ap_queue *q); |
39 | 39 |
|
40 | 40 | /** |
41 | 41 | * get_update_locks_for_kvm: Acquire the locks required to dynamically update a |
@@ -1623,19 +1623,21 @@ static int apq_status_check(int apqn, struct ap_queue_status *status) |
1623 | 1623 |
|
1624 | 1624 | #define WAIT_MSG "Waited %dms for reset of queue %02x.%04x (%u, %u, %u)" |
1625 | 1625 |
|
1626 | | -static int apq_reset_check(struct vfio_ap_queue *q) |
| 1626 | +static void apq_reset_check(struct work_struct *reset_work) |
1627 | 1627 | { |
1628 | 1628 | int ret = -EBUSY, elapsed = 0; |
1629 | 1629 | struct ap_queue_status status; |
| 1630 | + struct vfio_ap_queue *q; |
1630 | 1631 |
|
| 1632 | + q = container_of(reset_work, struct vfio_ap_queue, reset_work); |
1631 | 1633 | memcpy(&status, &q->reset_status, sizeof(status)); |
1632 | 1634 | while (true) { |
1633 | 1635 | msleep(AP_RESET_INTERVAL); |
1634 | 1636 | elapsed += AP_RESET_INTERVAL; |
1635 | 1637 | status = ap_tapq(q->apqn, NULL); |
1636 | 1638 | ret = apq_status_check(q->apqn, &status); |
1637 | 1639 | if (ret == -EIO) |
1638 | | - return ret; |
| 1640 | + return; |
1639 | 1641 | if (ret == -EBUSY) { |
1640 | 1642 | pr_notice_ratelimited(WAIT_MSG, elapsed, |
1641 | 1643 | AP_QID_CARD(q->apqn), |
@@ -1663,64 +1665,58 @@ static int apq_reset_check(struct vfio_ap_queue *q) |
1663 | 1665 | break; |
1664 | 1666 | } |
1665 | 1667 | } |
1666 | | - return ret; |
1667 | 1668 | } |
1668 | 1669 |
|
1669 | | -static int vfio_ap_mdev_reset_queue(struct vfio_ap_queue *q) |
| 1670 | +static void vfio_ap_mdev_reset_queue(struct vfio_ap_queue *q) |
1670 | 1671 | { |
1671 | 1672 | struct ap_queue_status status; |
1672 | | - int ret = 0; |
1673 | 1673 |
|
1674 | 1674 | if (!q) |
1675 | | - return 0; |
| 1675 | + return; |
1676 | 1676 | status = ap_zapq(q->apqn, 0); |
1677 | 1677 | memcpy(&q->reset_status, &status, sizeof(status)); |
1678 | 1678 | switch (status.response_code) { |
1679 | 1679 | case AP_RESPONSE_NORMAL: |
1680 | 1680 | case AP_RESPONSE_RESET_IN_PROGRESS: |
1681 | 1681 | case AP_RESPONSE_BUSY: |
1682 | | - /* Let's verify whether the ZAPQ completed successfully */ |
1683 | | - ret = apq_reset_check(q); |
| 1682 | + /* |
| 1683 | + * Let's verify whether the ZAPQ completed successfully on a work queue. |
| 1684 | + */ |
| 1685 | + queue_work(system_long_wq, &q->reset_work); |
1684 | 1686 | break; |
1685 | 1687 | case AP_RESPONSE_DECONFIGURED: |
1686 | 1688 | /* |
1687 | 1689 | * When an AP adapter is deconfigured, the associated |
1688 | 1690 | * queues are reset, so let's set the status response code to 0 |
1689 | | - * so the queue may be passed through (i.e., not filtered) and |
1690 | | - * return a value indicating the reset completed successfully. |
| 1691 | + * so the queue may be passed through (i.e., not filtered). |
1691 | 1692 | */ |
1692 | 1693 | q->reset_status.response_code = 0; |
1693 | | - ret = 0; |
1694 | 1694 | vfio_ap_free_aqic_resources(q); |
1695 | 1695 | break; |
1696 | 1696 | default: |
1697 | 1697 | WARN(true, |
1698 | 1698 | "PQAP/ZAPQ for %02x.%04x failed with invalid rc=%u\n", |
1699 | 1699 | AP_QID_CARD(q->apqn), AP_QID_QUEUE(q->apqn), |
1700 | 1700 | status.response_code); |
1701 | | - return -EIO; |
1702 | 1701 | } |
1703 | | - |
1704 | | - return ret; |
1705 | 1702 | } |
1706 | 1703 |
|
1707 | 1704 | static int vfio_ap_mdev_reset_queues(struct ap_queue_table *qtable) |
1708 | 1705 | { |
1709 | | - int ret, loop_cursor, rc = 0; |
| 1706 | + int ret = 0, loop_cursor; |
1710 | 1707 | struct vfio_ap_queue *q; |
1711 | 1708 |
|
| 1709 | + hash_for_each(qtable->queues, loop_cursor, q, mdev_qnode) |
| 1710 | + vfio_ap_mdev_reset_queue(q); |
| 1711 | + |
1712 | 1712 | hash_for_each(qtable->queues, loop_cursor, q, mdev_qnode) { |
1713 | | - ret = vfio_ap_mdev_reset_queue(q); |
1714 | | - /* |
1715 | | - * Regardless whether a queue turns out to be busy, or |
1716 | | - * is not operational, we need to continue resetting |
1717 | | - * the remaining queues. |
1718 | | - */ |
1719 | | - if (ret) |
1720 | | - rc = ret; |
| 1713 | + flush_work(&q->reset_work); |
| 1714 | + |
| 1715 | + if (q->reset_status.response_code) |
| 1716 | + ret = -EIO; |
1721 | 1717 | } |
1722 | 1718 |
|
1723 | | - return rc; |
| 1719 | + return ret; |
1724 | 1720 | } |
1725 | 1721 |
|
1726 | 1722 | static int vfio_ap_mdev_open_device(struct vfio_device *vdev) |
@@ -2045,6 +2041,7 @@ int vfio_ap_mdev_probe_queue(struct ap_device *apdev) |
2045 | 2041 | q->apqn = to_ap_queue(&apdev->device)->qid; |
2046 | 2042 | q->saved_isc = VFIO_AP_ISC_INVALID; |
2047 | 2043 | memset(&q->reset_status, 0, sizeof(q->reset_status)); |
| 2044 | + INIT_WORK(&q->reset_work, apq_reset_check); |
2048 | 2045 | matrix_mdev = get_update_locks_by_apqn(q->apqn); |
2049 | 2046 |
|
2050 | 2047 | if (matrix_mdev) { |
@@ -2094,6 +2091,7 @@ void vfio_ap_mdev_remove_queue(struct ap_device *apdev) |
2094 | 2091 | } |
2095 | 2092 |
|
2096 | 2093 | vfio_ap_mdev_reset_queue(q); |
| 2094 | + flush_work(&q->reset_work); |
2097 | 2095 | dev_set_drvdata(&apdev->device, NULL); |
2098 | 2096 | kfree(q); |
2099 | 2097 | release_update_locks_for_mdev(matrix_mdev); |
|
0 commit comments