|
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