1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2023 Advanced Micro Devices, Inc. */
4 #include <linux/vfio.h>
5 #include <linux/vfio_pci_core.h>
11 struct pci_dev
*pds_vfio_to_pci_dev(struct pds_vfio_pci_device
*pds_vfio
)
13 return pds_vfio
->vfio_coredev
.pdev
;
16 struct device
*pds_vfio_to_dev(struct pds_vfio_pci_device
*pds_vfio
)
18 return &pds_vfio_to_pci_dev(pds_vfio
)->dev
;
21 struct pds_vfio_pci_device
*pds_vfio_pci_drvdata(struct pci_dev
*pdev
)
23 struct vfio_pci_core_device
*core_device
= dev_get_drvdata(&pdev
->dev
);
25 return container_of(core_device
, struct pds_vfio_pci_device
,
29 void pds_vfio_state_mutex_unlock(struct pds_vfio_pci_device
*pds_vfio
)
32 mutex_lock(&pds_vfio
->reset_mutex
);
33 if (pds_vfio
->deferred_reset
) {
34 pds_vfio
->deferred_reset
= false;
35 if (pds_vfio
->state
== VFIO_DEVICE_STATE_ERROR
) {
36 pds_vfio_put_restore_file(pds_vfio
);
37 pds_vfio_put_save_file(pds_vfio
);
38 pds_vfio_dirty_disable(pds_vfio
, false);
40 pds_vfio
->state
= pds_vfio
->deferred_reset_state
;
41 pds_vfio
->deferred_reset_state
= VFIO_DEVICE_STATE_RUNNING
;
42 mutex_unlock(&pds_vfio
->reset_mutex
);
45 mutex_unlock(&pds_vfio
->state_mutex
);
46 mutex_unlock(&pds_vfio
->reset_mutex
);
49 void pds_vfio_reset(struct pds_vfio_pci_device
*pds_vfio
)
51 mutex_lock(&pds_vfio
->reset_mutex
);
52 pds_vfio
->deferred_reset
= true;
53 pds_vfio
->deferred_reset_state
= VFIO_DEVICE_STATE_RUNNING
;
54 if (!mutex_trylock(&pds_vfio
->state_mutex
)) {
55 mutex_unlock(&pds_vfio
->reset_mutex
);
58 mutex_unlock(&pds_vfio
->reset_mutex
);
59 pds_vfio_state_mutex_unlock(pds_vfio
);
63 pds_vfio_set_device_state(struct vfio_device
*vdev
,
64 enum vfio_device_mig_state new_state
)
66 struct pds_vfio_pci_device
*pds_vfio
=
67 container_of(vdev
, struct pds_vfio_pci_device
,
69 struct file
*res
= NULL
;
71 mutex_lock(&pds_vfio
->state_mutex
);
73 * only way to transition out of VFIO_DEVICE_STATE_ERROR is via
74 * VFIO_DEVICE_RESET, so prevent the state machine from running since
75 * vfio_mig_get_next_state() will throw a WARN_ON() when transitioning
76 * from VFIO_DEVICE_STATE_ERROR to any other state
78 while (pds_vfio
->state
!= VFIO_DEVICE_STATE_ERROR
&&
79 new_state
!= pds_vfio
->state
) {
80 enum vfio_device_mig_state next_state
;
82 int err
= vfio_mig_get_next_state(vdev
, pds_vfio
->state
,
83 new_state
, &next_state
);
89 res
= pds_vfio_step_device_state_locked(pds_vfio
, next_state
);
93 pds_vfio
->state
= next_state
;
95 if (WARN_ON(res
&& new_state
!= pds_vfio
->state
)) {
96 res
= ERR_PTR(-EINVAL
);
100 pds_vfio_state_mutex_unlock(pds_vfio
);
101 /* still waiting on a deferred_reset */
102 if (pds_vfio
->state
== VFIO_DEVICE_STATE_ERROR
)
108 static int pds_vfio_get_device_state(struct vfio_device
*vdev
,
109 enum vfio_device_mig_state
*current_state
)
111 struct pds_vfio_pci_device
*pds_vfio
=
112 container_of(vdev
, struct pds_vfio_pci_device
,
115 mutex_lock(&pds_vfio
->state_mutex
);
116 *current_state
= pds_vfio
->state
;
117 pds_vfio_state_mutex_unlock(pds_vfio
);
121 static int pds_vfio_get_device_state_size(struct vfio_device
*vdev
,
122 unsigned long *stop_copy_length
)
124 *stop_copy_length
= PDS_LM_DEVICE_STATE_LENGTH
;
128 static const struct vfio_migration_ops pds_vfio_lm_ops
= {
129 .migration_set_state
= pds_vfio_set_device_state
,
130 .migration_get_state
= pds_vfio_get_device_state
,
131 .migration_get_data_size
= pds_vfio_get_device_state_size
134 static const struct vfio_log_ops pds_vfio_log_ops
= {
135 .log_start
= pds_vfio_dma_logging_start
,
136 .log_stop
= pds_vfio_dma_logging_stop
,
137 .log_read_and_clear
= pds_vfio_dma_logging_report
,
140 static int pds_vfio_init_device(struct vfio_device
*vdev
)
142 struct pds_vfio_pci_device
*pds_vfio
=
143 container_of(vdev
, struct pds_vfio_pci_device
,
145 struct pci_dev
*pdev
= to_pci_dev(vdev
->dev
);
146 int err
, vf_id
, pci_id
;
148 vf_id
= pci_iov_vf_id(pdev
);
152 err
= vfio_pci_core_init_dev(vdev
);
156 pds_vfio
->vf_id
= vf_id
;
158 mutex_init(&pds_vfio
->state_mutex
);
159 mutex_init(&pds_vfio
->reset_mutex
);
161 vdev
->migration_flags
= VFIO_MIGRATION_STOP_COPY
| VFIO_MIGRATION_P2P
;
162 vdev
->mig_ops
= &pds_vfio_lm_ops
;
163 vdev
->log_ops
= &pds_vfio_log_ops
;
165 pci_id
= PCI_DEVID(pdev
->bus
->number
, pdev
->devfn
);
167 "%s: PF %#04x VF %#04x vf_id %d domain %d pds_vfio %p\n",
168 __func__
, pci_dev_id(pci_physfn(pdev
)), pci_id
, vf_id
,
169 pci_domain_nr(pdev
->bus
), pds_vfio
);
174 static void pds_vfio_release_device(struct vfio_device
*vdev
)
176 struct pds_vfio_pci_device
*pds_vfio
=
177 container_of(vdev
, struct pds_vfio_pci_device
,
180 mutex_destroy(&pds_vfio
->state_mutex
);
181 mutex_destroy(&pds_vfio
->reset_mutex
);
182 vfio_pci_core_release_dev(vdev
);
185 static int pds_vfio_open_device(struct vfio_device
*vdev
)
187 struct pds_vfio_pci_device
*pds_vfio
=
188 container_of(vdev
, struct pds_vfio_pci_device
,
192 err
= vfio_pci_core_enable(&pds_vfio
->vfio_coredev
);
196 pds_vfio
->state
= VFIO_DEVICE_STATE_RUNNING
;
197 pds_vfio
->deferred_reset_state
= VFIO_DEVICE_STATE_RUNNING
;
199 vfio_pci_core_finish_enable(&pds_vfio
->vfio_coredev
);
204 static void pds_vfio_close_device(struct vfio_device
*vdev
)
206 struct pds_vfio_pci_device
*pds_vfio
=
207 container_of(vdev
, struct pds_vfio_pci_device
,
210 mutex_lock(&pds_vfio
->state_mutex
);
211 pds_vfio_put_restore_file(pds_vfio
);
212 pds_vfio_put_save_file(pds_vfio
);
213 pds_vfio_dirty_disable(pds_vfio
, true);
214 mutex_unlock(&pds_vfio
->state_mutex
);
215 vfio_pci_core_close_device(vdev
);
218 static const struct vfio_device_ops pds_vfio_ops
= {
220 .init
= pds_vfio_init_device
,
221 .release
= pds_vfio_release_device
,
222 .open_device
= pds_vfio_open_device
,
223 .close_device
= pds_vfio_close_device
,
224 .ioctl
= vfio_pci_core_ioctl
,
225 .device_feature
= vfio_pci_core_ioctl_feature
,
226 .read
= vfio_pci_core_read
,
227 .write
= vfio_pci_core_write
,
228 .mmap
= vfio_pci_core_mmap
,
229 .request
= vfio_pci_core_request
,
230 .match
= vfio_pci_core_match
,
231 .bind_iommufd
= vfio_iommufd_physical_bind
,
232 .unbind_iommufd
= vfio_iommufd_physical_unbind
,
233 .attach_ioas
= vfio_iommufd_physical_attach_ioas
,
236 const struct vfio_device_ops
*pds_vfio_ops_info(void)
238 return &pds_vfio_ops
;