xref: /linux/drivers/vfio/pci/ism/main.c (revision f0bf3eac92b2be5f34b944cb82f1c23db642c7f5)
1*bf4197beSJulian Ruess // SPDX-License-Identifier: GPL-2.0
2*bf4197beSJulian Ruess /*
3*bf4197beSJulian Ruess  * vfio-ISM driver for s390
4*bf4197beSJulian Ruess  *
5*bf4197beSJulian Ruess  * Copyright IBM Corp.
6*bf4197beSJulian Ruess  */
7*bf4197beSJulian Ruess 
8*bf4197beSJulian Ruess #include <linux/slab.h>
9*bf4197beSJulian Ruess #include "../vfio_pci_priv.h"
10*bf4197beSJulian Ruess 
11*bf4197beSJulian Ruess #define ISM_VFIO_PCI_OFFSET_SHIFT   48
12*bf4197beSJulian Ruess #define ISM_VFIO_PCI_OFFSET_TO_INDEX(off) ((off) >> ISM_VFIO_PCI_OFFSET_SHIFT)
13*bf4197beSJulian Ruess #define ISM_VFIO_PCI_INDEX_TO_OFFSET(index) ((u64)(index) << ISM_VFIO_PCI_OFFSET_SHIFT)
14*bf4197beSJulian Ruess #define ISM_VFIO_PCI_OFFSET_MASK (((u64)(1) << ISM_VFIO_PCI_OFFSET_SHIFT) - 1)
15*bf4197beSJulian Ruess 
16*bf4197beSJulian Ruess /*
17*bf4197beSJulian Ruess  * Use __zpci_load() to bypass automatic use of
18*bf4197beSJulian Ruess  * PCI MIO instructions which are not supported on ISM devices
19*bf4197beSJulian Ruess  */
20*bf4197beSJulian Ruess #define ISM_READ(size)                                                        \
21*bf4197beSJulian Ruess 	static int ism_read##size(struct zpci_dev *zdev, int bar,             \
22*bf4197beSJulian Ruess 				  size_t *filled, char __user *buf,           \
23*bf4197beSJulian Ruess 				  loff_t off)                                 \
24*bf4197beSJulian Ruess 	{                                                                     \
25*bf4197beSJulian Ruess 		u64 req, tmp;                                                 \
26*bf4197beSJulian Ruess 		u##size val;                                                  \
27*bf4197beSJulian Ruess 		int ret;                                                      \
28*bf4197beSJulian Ruess 									      \
29*bf4197beSJulian Ruess 		req = ZPCI_CREATE_REQ(READ_ONCE(zdev->fh), bar, sizeof(val)); \
30*bf4197beSJulian Ruess 		ret = __zpci_load(&tmp, req, off);                            \
31*bf4197beSJulian Ruess 		if (ret)                                                      \
32*bf4197beSJulian Ruess 			return ret;                                           \
33*bf4197beSJulian Ruess 		val = (u##size)tmp;                                           \
34*bf4197beSJulian Ruess 		if (copy_to_user(buf, &val, sizeof(val)))                     \
35*bf4197beSJulian Ruess 			return -EFAULT;                                       \
36*bf4197beSJulian Ruess 		*filled = sizeof(val);                                        \
37*bf4197beSJulian Ruess 		return 0;						      \
38*bf4197beSJulian Ruess 	}
39*bf4197beSJulian Ruess 
40*bf4197beSJulian Ruess ISM_READ(64);
41*bf4197beSJulian Ruess ISM_READ(32);
42*bf4197beSJulian Ruess ISM_READ(16);
43*bf4197beSJulian Ruess ISM_READ(8);
44*bf4197beSJulian Ruess 
45*bf4197beSJulian Ruess struct ism_vfio_pci_core_device {
46*bf4197beSJulian Ruess 	struct vfio_pci_core_device core_device;
47*bf4197beSJulian Ruess 	struct kmem_cache *store_block_cache;
48*bf4197beSJulian Ruess };
49*bf4197beSJulian Ruess 
50*bf4197beSJulian Ruess static int ism_vfio_pci_open_device(struct vfio_device *core_vdev)
51*bf4197beSJulian Ruess {
52*bf4197beSJulian Ruess 	struct ism_vfio_pci_core_device *ivpcd;
53*bf4197beSJulian Ruess 	struct vfio_pci_core_device *vdev;
54*bf4197beSJulian Ruess 	int ret;
55*bf4197beSJulian Ruess 
56*bf4197beSJulian Ruess 	ivpcd = container_of(core_vdev, struct ism_vfio_pci_core_device,
57*bf4197beSJulian Ruess 			     core_device.vdev);
58*bf4197beSJulian Ruess 	vdev = &ivpcd->core_device;
59*bf4197beSJulian Ruess 
60*bf4197beSJulian Ruess 	ret = vfio_pci_core_enable(vdev);
61*bf4197beSJulian Ruess 	if (ret)
62*bf4197beSJulian Ruess 		return ret;
63*bf4197beSJulian Ruess 
64*bf4197beSJulian Ruess 	vfio_pci_core_finish_enable(vdev);
65*bf4197beSJulian Ruess 	return 0;
66*bf4197beSJulian Ruess }
67*bf4197beSJulian Ruess 
68*bf4197beSJulian Ruess /*
69*bf4197beSJulian Ruess  * ism_vfio_pci_do_io_r()
70*bf4197beSJulian Ruess  *
71*bf4197beSJulian Ruess  * On s390, kernel primitives such as ioread() and iowrite() are switched over
72*bf4197beSJulian Ruess  * from function-handle-based PCI load/stores instructions to PCI memory-I/O (MIO)
73*bf4197beSJulian Ruess  * loads/stores when these are available and not explicitly disabled. Since these
74*bf4197beSJulian Ruess  * instructions cannot be used with ISM devices, ensure that classic
75*bf4197beSJulian Ruess  * function-handle-based PCI instructions are used instead.
76*bf4197beSJulian Ruess  */
77*bf4197beSJulian Ruess static ssize_t ism_vfio_pci_do_io_r(struct vfio_pci_core_device *vdev,
78*bf4197beSJulian Ruess 				    char __user *buf, loff_t off, size_t count,
79*bf4197beSJulian Ruess 				    int bar)
80*bf4197beSJulian Ruess {
81*bf4197beSJulian Ruess 	struct zpci_dev *zdev = to_zpci(vdev->pdev);
82*bf4197beSJulian Ruess 	ssize_t done = 0;
83*bf4197beSJulian Ruess 	int ret;
84*bf4197beSJulian Ruess 
85*bf4197beSJulian Ruess 	while (count) {
86*bf4197beSJulian Ruess 		size_t filled;
87*bf4197beSJulian Ruess 
88*bf4197beSJulian Ruess 		if (count >= 8 && IS_ALIGNED(off, 8)) {
89*bf4197beSJulian Ruess 			ret = ism_read64(zdev, bar, &filled, buf, off);
90*bf4197beSJulian Ruess 			if (ret)
91*bf4197beSJulian Ruess 				return ret;
92*bf4197beSJulian Ruess 		} else if (count >= 4 && IS_ALIGNED(off, 4)) {
93*bf4197beSJulian Ruess 			ret = ism_read32(zdev, bar, &filled, buf, off);
94*bf4197beSJulian Ruess 			if (ret)
95*bf4197beSJulian Ruess 				return ret;
96*bf4197beSJulian Ruess 		} else if (count >= 2 && IS_ALIGNED(off, 2)) {
97*bf4197beSJulian Ruess 			ret = ism_read16(zdev, bar, &filled, buf, off);
98*bf4197beSJulian Ruess 			if (ret)
99*bf4197beSJulian Ruess 				return ret;
100*bf4197beSJulian Ruess 		} else {
101*bf4197beSJulian Ruess 			ret = ism_read8(zdev, bar, &filled, buf, off);
102*bf4197beSJulian Ruess 			if (ret)
103*bf4197beSJulian Ruess 				return ret;
104*bf4197beSJulian Ruess 		}
105*bf4197beSJulian Ruess 
106*bf4197beSJulian Ruess 		count -= filled;
107*bf4197beSJulian Ruess 		done += filled;
108*bf4197beSJulian Ruess 		off += filled;
109*bf4197beSJulian Ruess 		buf += filled;
110*bf4197beSJulian Ruess 	}
111*bf4197beSJulian Ruess 
112*bf4197beSJulian Ruess 	return done;
113*bf4197beSJulian Ruess }
114*bf4197beSJulian Ruess 
115*bf4197beSJulian Ruess /*
116*bf4197beSJulian Ruess  * ism_vfio_pci_do_io_w()
117*bf4197beSJulian Ruess  *
118*bf4197beSJulian Ruess  * Ensure that the PCI store block (PCISTB) instruction is used as required by the
119*bf4197beSJulian Ruess  * ISM device. The ISM device also uses a 256 TiB BAR 0 for write operations,
120*bf4197beSJulian Ruess  * which requires a 48bit region address space (ISM_VFIO_PCI_OFFSET_SHIFT).
121*bf4197beSJulian Ruess  */
122*bf4197beSJulian Ruess static ssize_t ism_vfio_pci_do_io_w(struct vfio_pci_core_device *vdev,
123*bf4197beSJulian Ruess 				    char __user *buf, loff_t off, size_t count,
124*bf4197beSJulian Ruess 				    int bar)
125*bf4197beSJulian Ruess {
126*bf4197beSJulian Ruess 	struct zpci_dev *zdev = to_zpci(vdev->pdev);
127*bf4197beSJulian Ruess 	struct ism_vfio_pci_core_device *ivpcd;
128*bf4197beSJulian Ruess 	ssize_t ret;
129*bf4197beSJulian Ruess 	void *data;
130*bf4197beSJulian Ruess 	u64 req;
131*bf4197beSJulian Ruess 
132*bf4197beSJulian Ruess 	if (count > zdev->maxstbl)
133*bf4197beSJulian Ruess 		return -EINVAL;
134*bf4197beSJulian Ruess 	if (((off % PAGE_SIZE) + count) > PAGE_SIZE)
135*bf4197beSJulian Ruess 		return -EINVAL;
136*bf4197beSJulian Ruess 
137*bf4197beSJulian Ruess 	ivpcd = container_of(vdev, struct ism_vfio_pci_core_device,
138*bf4197beSJulian Ruess 			     core_device);
139*bf4197beSJulian Ruess 	data = kmem_cache_alloc(ivpcd->store_block_cache, GFP_KERNEL);
140*bf4197beSJulian Ruess 	if (!data)
141*bf4197beSJulian Ruess 		return -ENOMEM;
142*bf4197beSJulian Ruess 
143*bf4197beSJulian Ruess 	if (copy_from_user(data, buf, count)) {
144*bf4197beSJulian Ruess 		ret = -EFAULT;
145*bf4197beSJulian Ruess 		goto out_free;
146*bf4197beSJulian Ruess 	}
147*bf4197beSJulian Ruess 
148*bf4197beSJulian Ruess 	req = ZPCI_CREATE_REQ(READ_ONCE(zdev->fh), bar, count);
149*bf4197beSJulian Ruess 	ret = __zpci_store_block(data, req, off);
150*bf4197beSJulian Ruess 	if (ret)
151*bf4197beSJulian Ruess 		goto out_free;
152*bf4197beSJulian Ruess 
153*bf4197beSJulian Ruess 	ret = count;
154*bf4197beSJulian Ruess 
155*bf4197beSJulian Ruess out_free:
156*bf4197beSJulian Ruess 	kmem_cache_free(ivpcd->store_block_cache, data);
157*bf4197beSJulian Ruess 	return ret;
158*bf4197beSJulian Ruess }
159*bf4197beSJulian Ruess 
160*bf4197beSJulian Ruess static ssize_t ism_vfio_pci_bar_rw(struct vfio_pci_core_device *vdev,
161*bf4197beSJulian Ruess 				   char __user *buf, size_t count, loff_t *ppos,
162*bf4197beSJulian Ruess 				   bool iswrite)
163*bf4197beSJulian Ruess {
164*bf4197beSJulian Ruess 	int bar = ISM_VFIO_PCI_OFFSET_TO_INDEX(*ppos);
165*bf4197beSJulian Ruess 	loff_t pos = *ppos & ISM_VFIO_PCI_OFFSET_MASK;
166*bf4197beSJulian Ruess 	resource_size_t end;
167*bf4197beSJulian Ruess 	ssize_t done = 0;
168*bf4197beSJulian Ruess 
169*bf4197beSJulian Ruess 	if (pci_resource_start(vdev->pdev, bar))
170*bf4197beSJulian Ruess 		end = pci_resource_len(vdev->pdev, bar);
171*bf4197beSJulian Ruess 	else
172*bf4197beSJulian Ruess 		return -EINVAL;
173*bf4197beSJulian Ruess 
174*bf4197beSJulian Ruess 	if (pos >= end)
175*bf4197beSJulian Ruess 		return -EINVAL;
176*bf4197beSJulian Ruess 
177*bf4197beSJulian Ruess 	count = min(count, (size_t)(end - pos));
178*bf4197beSJulian Ruess 
179*bf4197beSJulian Ruess 	if (iswrite)
180*bf4197beSJulian Ruess 		done = ism_vfio_pci_do_io_w(vdev, buf, pos, count, bar);
181*bf4197beSJulian Ruess 	else
182*bf4197beSJulian Ruess 		done = ism_vfio_pci_do_io_r(vdev, buf, pos, count, bar);
183*bf4197beSJulian Ruess 
184*bf4197beSJulian Ruess 	if (done >= 0)
185*bf4197beSJulian Ruess 		*ppos += done;
186*bf4197beSJulian Ruess 
187*bf4197beSJulian Ruess 	return done;
188*bf4197beSJulian Ruess }
189*bf4197beSJulian Ruess 
190*bf4197beSJulian Ruess static ssize_t ism_vfio_pci_config_rw(struct vfio_pci_core_device *vdev,
191*bf4197beSJulian Ruess 				      char __user *buf, size_t count,
192*bf4197beSJulian Ruess 				      loff_t *ppos, bool iswrite)
193*bf4197beSJulian Ruess {
194*bf4197beSJulian Ruess 	loff_t pos = *ppos;
195*bf4197beSJulian Ruess 	size_t done = 0;
196*bf4197beSJulian Ruess 	int ret = 0;
197*bf4197beSJulian Ruess 
198*bf4197beSJulian Ruess 	pos &= ISM_VFIO_PCI_OFFSET_MASK;
199*bf4197beSJulian Ruess 
200*bf4197beSJulian Ruess 	while (count) {
201*bf4197beSJulian Ruess 		/*
202*bf4197beSJulian Ruess 		 * zPCI must not use MIO instructions for config space access,
203*bf4197beSJulian Ruess 		 * so we can use common code path here.
204*bf4197beSJulian Ruess 		 */
205*bf4197beSJulian Ruess 		ret = vfio_pci_config_rw_single(vdev, buf, count, &pos, iswrite);
206*bf4197beSJulian Ruess 		if (ret < 0)
207*bf4197beSJulian Ruess 			return ret;
208*bf4197beSJulian Ruess 
209*bf4197beSJulian Ruess 		count -= ret;
210*bf4197beSJulian Ruess 		done += ret;
211*bf4197beSJulian Ruess 		buf += ret;
212*bf4197beSJulian Ruess 		pos += ret;
213*bf4197beSJulian Ruess 	}
214*bf4197beSJulian Ruess 
215*bf4197beSJulian Ruess 	*ppos += done;
216*bf4197beSJulian Ruess 
217*bf4197beSJulian Ruess 	return done;
218*bf4197beSJulian Ruess }
219*bf4197beSJulian Ruess 
220*bf4197beSJulian Ruess static ssize_t ism_vfio_pci_rw(struct vfio_device *core_vdev, char __user *buf,
221*bf4197beSJulian Ruess 			       size_t count, loff_t *ppos, bool iswrite)
222*bf4197beSJulian Ruess {
223*bf4197beSJulian Ruess 	unsigned int index = ISM_VFIO_PCI_OFFSET_TO_INDEX(*ppos);
224*bf4197beSJulian Ruess 	struct vfio_pci_core_device *vdev;
225*bf4197beSJulian Ruess 	int ret;
226*bf4197beSJulian Ruess 
227*bf4197beSJulian Ruess 	vdev = container_of(core_vdev, struct vfio_pci_core_device, vdev);
228*bf4197beSJulian Ruess 
229*bf4197beSJulian Ruess 	if (!count)
230*bf4197beSJulian Ruess 		return 0;
231*bf4197beSJulian Ruess 
232*bf4197beSJulian Ruess 	switch (index) {
233*bf4197beSJulian Ruess 	case VFIO_PCI_CONFIG_REGION_INDEX:
234*bf4197beSJulian Ruess 		ret = ism_vfio_pci_config_rw(vdev, buf, count, ppos, iswrite);
235*bf4197beSJulian Ruess 		break;
236*bf4197beSJulian Ruess 
237*bf4197beSJulian Ruess 	case VFIO_PCI_BAR0_REGION_INDEX ... VFIO_PCI_BAR5_REGION_INDEX:
238*bf4197beSJulian Ruess 		ret = ism_vfio_pci_bar_rw(vdev, buf, count, ppos, iswrite);
239*bf4197beSJulian Ruess 		break;
240*bf4197beSJulian Ruess 
241*bf4197beSJulian Ruess 	default:
242*bf4197beSJulian Ruess 		return -EINVAL;
243*bf4197beSJulian Ruess 	}
244*bf4197beSJulian Ruess 
245*bf4197beSJulian Ruess 	return ret;
246*bf4197beSJulian Ruess }
247*bf4197beSJulian Ruess 
248*bf4197beSJulian Ruess static ssize_t ism_vfio_pci_read(struct vfio_device *core_vdev,
249*bf4197beSJulian Ruess 				 char __user *buf, size_t count, loff_t *ppos)
250*bf4197beSJulian Ruess {
251*bf4197beSJulian Ruess 	return ism_vfio_pci_rw(core_vdev, buf, count, ppos, false);
252*bf4197beSJulian Ruess }
253*bf4197beSJulian Ruess 
254*bf4197beSJulian Ruess static ssize_t ism_vfio_pci_write(struct vfio_device *core_vdev,
255*bf4197beSJulian Ruess 				  const char __user *buf, size_t count,
256*bf4197beSJulian Ruess 				  loff_t *ppos)
257*bf4197beSJulian Ruess {
258*bf4197beSJulian Ruess 	return ism_vfio_pci_rw(core_vdev, (char __user *)buf, count, ppos,
259*bf4197beSJulian Ruess 			       true);
260*bf4197beSJulian Ruess }
261*bf4197beSJulian Ruess 
262*bf4197beSJulian Ruess static int ism_vfio_pci_ioctl_get_region_info(struct vfio_device *core_vdev,
263*bf4197beSJulian Ruess 					      struct vfio_region_info *info,
264*bf4197beSJulian Ruess 					      struct vfio_info_cap *caps)
265*bf4197beSJulian Ruess {
266*bf4197beSJulian Ruess 	struct vfio_pci_core_device *vdev =
267*bf4197beSJulian Ruess 		container_of(core_vdev, struct vfio_pci_core_device, vdev);
268*bf4197beSJulian Ruess 	struct pci_dev *pdev = vdev->pdev;
269*bf4197beSJulian Ruess 
270*bf4197beSJulian Ruess 	switch (info->index) {
271*bf4197beSJulian Ruess 	case VFIO_PCI_CONFIG_REGION_INDEX:
272*bf4197beSJulian Ruess 		info->offset = ISM_VFIO_PCI_INDEX_TO_OFFSET(info->index);
273*bf4197beSJulian Ruess 		info->size = pdev->cfg_size;
274*bf4197beSJulian Ruess 		info->flags = VFIO_REGION_INFO_FLAG_READ |
275*bf4197beSJulian Ruess 			      VFIO_REGION_INFO_FLAG_WRITE;
276*bf4197beSJulian Ruess 		break;
277*bf4197beSJulian Ruess 	case VFIO_PCI_BAR0_REGION_INDEX ... VFIO_PCI_BAR5_REGION_INDEX:
278*bf4197beSJulian Ruess 		info->offset = ISM_VFIO_PCI_INDEX_TO_OFFSET(info->index);
279*bf4197beSJulian Ruess 		info->size = pci_resource_len(pdev, info->index);
280*bf4197beSJulian Ruess 		if (!info->size) {
281*bf4197beSJulian Ruess 			info->flags = 0;
282*bf4197beSJulian Ruess 			break;
283*bf4197beSJulian Ruess 		}
284*bf4197beSJulian Ruess 		info->flags = VFIO_REGION_INFO_FLAG_READ |
285*bf4197beSJulian Ruess 			      VFIO_REGION_INFO_FLAG_WRITE;
286*bf4197beSJulian Ruess 		break;
287*bf4197beSJulian Ruess 	default:
288*bf4197beSJulian Ruess 		info->offset = 0;
289*bf4197beSJulian Ruess 		info->size = 0;
290*bf4197beSJulian Ruess 		info->flags = 0;
291*bf4197beSJulian Ruess 		return -EINVAL;
292*bf4197beSJulian Ruess 	}
293*bf4197beSJulian Ruess 	return 0;
294*bf4197beSJulian Ruess }
295*bf4197beSJulian Ruess 
296*bf4197beSJulian Ruess static int ism_vfio_pci_init_dev(struct vfio_device *core_vdev)
297*bf4197beSJulian Ruess {
298*bf4197beSJulian Ruess 	struct zpci_dev *zdev = to_zpci(to_pci_dev(core_vdev->dev));
299*bf4197beSJulian Ruess 	struct ism_vfio_pci_core_device *ivpcd;
300*bf4197beSJulian Ruess 	char cache_name[20];
301*bf4197beSJulian Ruess 	int ret;
302*bf4197beSJulian Ruess 
303*bf4197beSJulian Ruess 	ivpcd = container_of(core_vdev, struct ism_vfio_pci_core_device,
304*bf4197beSJulian Ruess 			     core_device.vdev);
305*bf4197beSJulian Ruess 
306*bf4197beSJulian Ruess 	snprintf(cache_name, sizeof(cache_name), "ism_sb_fid_%08x", zdev->fid);
307*bf4197beSJulian Ruess 
308*bf4197beSJulian Ruess 	ivpcd->store_block_cache =
309*bf4197beSJulian Ruess 		kmem_cache_create(cache_name, zdev->maxstbl,
310*bf4197beSJulian Ruess 				  (&(struct kmem_cache_args){
311*bf4197beSJulian Ruess 					  .align = PAGE_SIZE,
312*bf4197beSJulian Ruess 					  .useroffset = 0,
313*bf4197beSJulian Ruess 					  .usersize = zdev->maxstbl,
314*bf4197beSJulian Ruess 				  }),
315*bf4197beSJulian Ruess 				  (SLAB_RECLAIM_ACCOUNT | SLAB_ACCOUNT));
316*bf4197beSJulian Ruess 	if (!ivpcd->store_block_cache)
317*bf4197beSJulian Ruess 		return -ENOMEM;
318*bf4197beSJulian Ruess 
319*bf4197beSJulian Ruess 	ret = vfio_pci_core_init_dev(core_vdev);
320*bf4197beSJulian Ruess 	if (ret)
321*bf4197beSJulian Ruess 		kmem_cache_destroy(ivpcd->store_block_cache);
322*bf4197beSJulian Ruess 
323*bf4197beSJulian Ruess 	return ret;
324*bf4197beSJulian Ruess }
325*bf4197beSJulian Ruess 
326*bf4197beSJulian Ruess static void ism_vfio_pci_release_dev(struct vfio_device *core_vdev)
327*bf4197beSJulian Ruess {
328*bf4197beSJulian Ruess 	struct ism_vfio_pci_core_device *ivpcd = container_of(
329*bf4197beSJulian Ruess 		core_vdev, struct ism_vfio_pci_core_device, core_device.vdev);
330*bf4197beSJulian Ruess 
331*bf4197beSJulian Ruess 	kmem_cache_destroy(ivpcd->store_block_cache);
332*bf4197beSJulian Ruess 	vfio_pci_core_release_dev(core_vdev);
333*bf4197beSJulian Ruess }
334*bf4197beSJulian Ruess 
335*bf4197beSJulian Ruess static const struct vfio_device_ops ism_pci_ops = {
336*bf4197beSJulian Ruess 	.name = "ism-vfio-pci",
337*bf4197beSJulian Ruess 	.init = ism_vfio_pci_init_dev,
338*bf4197beSJulian Ruess 	.release = ism_vfio_pci_release_dev,
339*bf4197beSJulian Ruess 	.open_device = ism_vfio_pci_open_device,
340*bf4197beSJulian Ruess 	.close_device = vfio_pci_core_close_device,
341*bf4197beSJulian Ruess 	.ioctl = vfio_pci_core_ioctl,
342*bf4197beSJulian Ruess 	.get_region_info_caps = ism_vfio_pci_ioctl_get_region_info,
343*bf4197beSJulian Ruess 	.device_feature = vfio_pci_core_ioctl_feature,
344*bf4197beSJulian Ruess 	.read = ism_vfio_pci_read,
345*bf4197beSJulian Ruess 	.write = ism_vfio_pci_write,
346*bf4197beSJulian Ruess 	.request = vfio_pci_core_request,
347*bf4197beSJulian Ruess 	.match = vfio_pci_core_match,
348*bf4197beSJulian Ruess 	.match_token_uuid = vfio_pci_core_match_token_uuid,
349*bf4197beSJulian Ruess 	.bind_iommufd = vfio_iommufd_physical_bind,
350*bf4197beSJulian Ruess 	.unbind_iommufd = vfio_iommufd_physical_unbind,
351*bf4197beSJulian Ruess 	.attach_ioas = vfio_iommufd_physical_attach_ioas,
352*bf4197beSJulian Ruess 	.detach_ioas = vfio_iommufd_physical_detach_ioas,
353*bf4197beSJulian Ruess };
354*bf4197beSJulian Ruess 
355*bf4197beSJulian Ruess static int ism_vfio_pci_probe(struct pci_dev *pdev,
356*bf4197beSJulian Ruess 			      const struct pci_device_id *id)
357*bf4197beSJulian Ruess {
358*bf4197beSJulian Ruess 	struct ism_vfio_pci_core_device *ivpcd;
359*bf4197beSJulian Ruess 	int ret;
360*bf4197beSJulian Ruess 
361*bf4197beSJulian Ruess 	ivpcd = vfio_alloc_device(ism_vfio_pci_core_device, core_device.vdev,
362*bf4197beSJulian Ruess 				  &pdev->dev, &ism_pci_ops);
363*bf4197beSJulian Ruess 	if (IS_ERR(ivpcd))
364*bf4197beSJulian Ruess 		return PTR_ERR(ivpcd);
365*bf4197beSJulian Ruess 
366*bf4197beSJulian Ruess 	dev_set_drvdata(&pdev->dev, &ivpcd->core_device);
367*bf4197beSJulian Ruess 
368*bf4197beSJulian Ruess 	ret = vfio_pci_core_register_device(&ivpcd->core_device);
369*bf4197beSJulian Ruess 	if (ret)
370*bf4197beSJulian Ruess 		vfio_put_device(&ivpcd->core_device.vdev);
371*bf4197beSJulian Ruess 
372*bf4197beSJulian Ruess 	return ret;
373*bf4197beSJulian Ruess }
374*bf4197beSJulian Ruess 
375*bf4197beSJulian Ruess static void ism_vfio_pci_remove(struct pci_dev *pdev)
376*bf4197beSJulian Ruess {
377*bf4197beSJulian Ruess 	struct vfio_pci_core_device *core_device;
378*bf4197beSJulian Ruess 	struct ism_vfio_pci_core_device *ivpcd;
379*bf4197beSJulian Ruess 
380*bf4197beSJulian Ruess 	core_device = dev_get_drvdata(&pdev->dev);
381*bf4197beSJulian Ruess 	ivpcd = container_of(core_device, struct ism_vfio_pci_core_device,
382*bf4197beSJulian Ruess 			     core_device);
383*bf4197beSJulian Ruess 
384*bf4197beSJulian Ruess 	vfio_pci_core_unregister_device(&ivpcd->core_device);
385*bf4197beSJulian Ruess 	vfio_put_device(&ivpcd->core_device.vdev);
386*bf4197beSJulian Ruess }
387*bf4197beSJulian Ruess 
388*bf4197beSJulian Ruess static const struct pci_device_id ism_device_table[] = {
389*bf4197beSJulian Ruess 	{ PCI_DRIVER_OVERRIDE_DEVICE_VFIO(PCI_VENDOR_ID_IBM,
390*bf4197beSJulian Ruess 					  PCI_DEVICE_ID_IBM_ISM) },
391*bf4197beSJulian Ruess 	{}
392*bf4197beSJulian Ruess };
393*bf4197beSJulian Ruess MODULE_DEVICE_TABLE(pci, ism_device_table);
394*bf4197beSJulian Ruess 
395*bf4197beSJulian Ruess static struct pci_driver ism_vfio_pci_driver = {
396*bf4197beSJulian Ruess 	.name = KBUILD_MODNAME,
397*bf4197beSJulian Ruess 	.id_table = ism_device_table,
398*bf4197beSJulian Ruess 	.probe = ism_vfio_pci_probe,
399*bf4197beSJulian Ruess 	.remove = ism_vfio_pci_remove,
400*bf4197beSJulian Ruess 	.err_handler = &vfio_pci_core_err_handlers,
401*bf4197beSJulian Ruess 	.driver_managed_dma = true,
402*bf4197beSJulian Ruess };
403*bf4197beSJulian Ruess 
404*bf4197beSJulian Ruess module_pci_driver(ism_vfio_pci_driver);
405*bf4197beSJulian Ruess 
406*bf4197beSJulian Ruess MODULE_LICENSE("GPL");
407*bf4197beSJulian Ruess MODULE_DESCRIPTION("vfio-pci variant driver for the IBM Internal Shared Memory (ISM) device");
408*bf4197beSJulian Ruess MODULE_AUTHOR("IBM Corporation");
409