Commit | Line | Data |
---|---|---|
38eb4a29 | 1 | /* |
a90fdce9 | 2 | * Virtio PCI driver - legacy device support |
38eb4a29 MT |
3 | * |
4 | * This module allows virtio devices to be used over a virtual PCI device. | |
5 | * This can be used with QEMU based VMMs like KVM or Xen. | |
6 | * | |
7 | * Copyright IBM Corp. 2007 | |
a90fdce9 | 8 | * Copyright Red Hat, Inc. 2014 |
38eb4a29 MT |
9 | * |
10 | * Authors: | |
11 | * Anthony Liguori <aliguori@us.ibm.com> | |
a90fdce9 MT |
12 | * Rusty Russell <rusty@rustcorp.com.au> |
13 | * Michael S. Tsirkin <mst@redhat.com> | |
38eb4a29 MT |
14 | * |
15 | * This work is licensed under the terms of the GNU GPL, version 2 or later. | |
16 | * See the COPYING file in the top-level directory. | |
17 | * | |
18 | */ | |
19 | ||
5f4c9760 | 20 | #include "virtio_pci_common.h" |
38eb4a29 | 21 | |
38eb4a29 MT |
22 | /* virtio config->get_features() implementation */ |
23 | static u64 vp_get_features(struct virtio_device *vdev) | |
24 | { | |
25 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); | |
26 | ||
27 | /* When someone needs more than 32 feature bits, we'll need to | |
28 | * steal a bit to indicate that the rest are somewhere else. */ | |
29 | return ioread32(vp_dev->ioaddr + VIRTIO_PCI_HOST_FEATURES); | |
30 | } | |
31 | ||
32 | /* virtio config->finalize_features() implementation */ | |
33 | static int vp_finalize_features(struct virtio_device *vdev) | |
34 | { | |
35 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); | |
36 | ||
37 | /* Give virtio_ring a chance to accept features. */ | |
38 | vring_transport_features(vdev); | |
39 | ||
40 | /* Make sure we don't have any features > 32 bits! */ | |
41 | BUG_ON((u32)vdev->features != vdev->features); | |
42 | ||
43 | /* We only support 32 feature bits. */ | |
44 | iowrite32(vdev->features, vp_dev->ioaddr + VIRTIO_PCI_GUEST_FEATURES); | |
45 | ||
46 | return 0; | |
47 | } | |
48 | ||
49 | /* virtio config->get() implementation */ | |
50 | static void vp_get(struct virtio_device *vdev, unsigned offset, | |
51 | void *buf, unsigned len) | |
52 | { | |
53 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); | |
54 | void __iomem *ioaddr = vp_dev->ioaddr + | |
55 | VIRTIO_PCI_CONFIG(vp_dev) + offset; | |
56 | u8 *ptr = buf; | |
57 | int i; | |
58 | ||
59 | for (i = 0; i < len; i++) | |
60 | ptr[i] = ioread8(ioaddr + i); | |
61 | } | |
62 | ||
63 | /* the config->set() implementation. it's symmetric to the config->get() | |
64 | * implementation */ | |
65 | static void vp_set(struct virtio_device *vdev, unsigned offset, | |
66 | const void *buf, unsigned len) | |
67 | { | |
68 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); | |
69 | void __iomem *ioaddr = vp_dev->ioaddr + | |
70 | VIRTIO_PCI_CONFIG(vp_dev) + offset; | |
71 | const u8 *ptr = buf; | |
72 | int i; | |
73 | ||
74 | for (i = 0; i < len; i++) | |
75 | iowrite8(ptr[i], ioaddr + i); | |
76 | } | |
77 | ||
78 | /* config->{get,set}_status() implementations */ | |
79 | static u8 vp_get_status(struct virtio_device *vdev) | |
80 | { | |
81 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); | |
82 | return ioread8(vp_dev->ioaddr + VIRTIO_PCI_STATUS); | |
83 | } | |
84 | ||
85 | static void vp_set_status(struct virtio_device *vdev, u8 status) | |
86 | { | |
87 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); | |
88 | /* We should never be setting status to 0. */ | |
89 | BUG_ON(status == 0); | |
90 | iowrite8(status, vp_dev->ioaddr + VIRTIO_PCI_STATUS); | |
91 | } | |
92 | ||
93 | static void vp_reset(struct virtio_device *vdev) | |
94 | { | |
95 | struct virtio_pci_device *vp_dev = to_vp_device(vdev); | |
96 | /* 0 status means a reset. */ | |
97 | iowrite8(0, vp_dev->ioaddr + VIRTIO_PCI_STATUS); | |
98 | /* Flush out the status write, and flush in device writes, | |
99 | * including MSi-X interrupts, if any. */ | |
100 | ioread8(vp_dev->ioaddr + VIRTIO_PCI_STATUS); | |
101 | /* Flush pending VQ/configuration callbacks. */ | |
102 | vp_synchronize_vectors(vdev); | |
103 | } | |
104 | ||
105 | static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector) | |
106 | { | |
107 | /* Setup the vector used for configuration events */ | |
108 | iowrite16(vector, vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR); | |
109 | /* Verify we had enough resources to assign the vector */ | |
110 | /* Will also flush the write out to device */ | |
111 | return ioread16(vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR); | |
112 | } | |
113 | ||
114 | static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev, | |
115 | struct virtio_pci_vq_info *info, | |
116 | unsigned index, | |
117 | void (*callback)(struct virtqueue *vq), | |
118 | const char *name, | |
119 | u16 msix_vec) | |
120 | { | |
121 | struct virtqueue *vq; | |
122 | unsigned long size; | |
123 | u16 num; | |
124 | int err; | |
125 | ||
126 | /* Select the queue we're interested in */ | |
127 | iowrite16(index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL); | |
128 | ||
129 | /* Check if queue is either not available or already active. */ | |
130 | num = ioread16(vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NUM); | |
131 | if (!num || ioread32(vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN)) | |
132 | return ERR_PTR(-ENOENT); | |
133 | ||
134 | info->num = num; | |
135 | info->msix_vector = msix_vec; | |
136 | ||
137 | size = PAGE_ALIGN(vring_size(num, VIRTIO_PCI_VRING_ALIGN)); | |
138 | info->queue = alloc_pages_exact(size, GFP_KERNEL|__GFP_ZERO); | |
139 | if (info->queue == NULL) | |
140 | return ERR_PTR(-ENOMEM); | |
141 | ||
142 | /* activate the queue */ | |
143 | iowrite32(virt_to_phys(info->queue) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT, | |
144 | vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); | |
145 | ||
146 | /* create the vring */ | |
147 | vq = vring_new_virtqueue(index, info->num, | |
148 | VIRTIO_PCI_VRING_ALIGN, &vp_dev->vdev, | |
149 | true, info->queue, vp_notify, callback, name); | |
150 | if (!vq) { | |
151 | err = -ENOMEM; | |
152 | goto out_activate_queue; | |
153 | } | |
154 | ||
155 | vq->priv = (void __force *)vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY; | |
156 | ||
157 | if (msix_vec != VIRTIO_MSI_NO_VECTOR) { | |
158 | iowrite16(msix_vec, vp_dev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR); | |
159 | msix_vec = ioread16(vp_dev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR); | |
160 | if (msix_vec == VIRTIO_MSI_NO_VECTOR) { | |
161 | err = -EBUSY; | |
162 | goto out_assign; | |
163 | } | |
164 | } | |
165 | ||
166 | return vq; | |
167 | ||
168 | out_assign: | |
169 | vring_del_virtqueue(vq); | |
170 | out_activate_queue: | |
171 | iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); | |
172 | free_pages_exact(info->queue, size); | |
173 | return ERR_PTR(err); | |
174 | } | |
175 | ||
176 | static void del_vq(struct virtio_pci_vq_info *info) | |
177 | { | |
178 | struct virtqueue *vq = info->vq; | |
179 | struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); | |
180 | unsigned long size; | |
181 | ||
182 | iowrite16(vq->index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL); | |
183 | ||
184 | if (vp_dev->msix_enabled) { | |
185 | iowrite16(VIRTIO_MSI_NO_VECTOR, | |
186 | vp_dev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR); | |
187 | /* Flush the write out to device */ | |
188 | ioread8(vp_dev->ioaddr + VIRTIO_PCI_ISR); | |
189 | } | |
190 | ||
191 | vring_del_virtqueue(vq); | |
192 | ||
193 | /* Select and deactivate the queue */ | |
194 | iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); | |
195 | ||
196 | size = PAGE_ALIGN(vring_size(info->num, VIRTIO_PCI_VRING_ALIGN)); | |
197 | free_pages_exact(info->queue, size); | |
198 | } | |
199 | ||
200 | static const struct virtio_config_ops virtio_pci_config_ops = { | |
201 | .get = vp_get, | |
202 | .set = vp_set, | |
203 | .get_status = vp_get_status, | |
204 | .set_status = vp_set_status, | |
205 | .reset = vp_reset, | |
206 | .find_vqs = vp_find_vqs, | |
207 | .del_vqs = vp_del_vqs, | |
208 | .get_features = vp_get_features, | |
209 | .finalize_features = vp_finalize_features, | |
210 | .bus_name = vp_bus_name, | |
211 | .set_vq_affinity = vp_set_vq_affinity, | |
212 | }; | |
213 | ||
214 | /* the PCI probing function */ | |
ff31d2e2 | 215 | int virtio_pci_legacy_probe(struct virtio_pci_device *vp_dev) |
38eb4a29 | 216 | { |
ff31d2e2 | 217 | struct pci_dev *pci_dev = vp_dev->pci_dev; |
59a5b0f7 | 218 | int rc; |
38eb4a29 MT |
219 | |
220 | /* We only own devices >= 0x1000 and <= 0x103f: leave the rest. */ | |
221 | if (pci_dev->device < 0x1000 || pci_dev->device > 0x103f) | |
222 | return -ENODEV; | |
223 | ||
224 | if (pci_dev->revision != VIRTIO_PCI_ABI_VERSION) { | |
225 | printk(KERN_ERR "virtio_pci: expected ABI version %d, got %d\n", | |
226 | VIRTIO_PCI_ABI_VERSION, pci_dev->revision); | |
227 | return -ENODEV; | |
228 | } | |
229 | ||
59a5b0f7 GH |
230 | rc = pci_request_region(pci_dev, 0, "virtio-pci-legacy"); |
231 | if (rc) | |
232 | return rc; | |
233 | ||
234 | rc = -ENOMEM; | |
38eb4a29 | 235 | vp_dev->ioaddr = pci_iomap(pci_dev, 0, 0); |
ff31d2e2 | 236 | if (!vp_dev->ioaddr) |
59a5b0f7 | 237 | goto err_iomap; |
38eb4a29 MT |
238 | |
239 | vp_dev->isr = vp_dev->ioaddr + VIRTIO_PCI_ISR; | |
240 | ||
38eb4a29 MT |
241 | /* we use the subsystem vendor/device id as the virtio vendor/device |
242 | * id. this allows us to use the same PCI vendor/device id for all | |
243 | * virtio devices and to identify the particular virtio driver by | |
244 | * the subsystem ids */ | |
245 | vp_dev->vdev.id.vendor = pci_dev->subsystem_vendor; | |
246 | vp_dev->vdev.id.device = pci_dev->subsystem_device; | |
247 | ||
ff31d2e2 MT |
248 | vp_dev->vdev.config = &virtio_pci_config_ops; |
249 | ||
38eb4a29 MT |
250 | vp_dev->config_vector = vp_config_vector; |
251 | vp_dev->setup_vq = setup_vq; | |
252 | vp_dev->del_vq = del_vq; | |
253 | ||
38eb4a29 | 254 | return 0; |
59a5b0f7 GH |
255 | |
256 | err_iomap: | |
257 | pci_release_region(pci_dev, 0); | |
258 | return rc; | |
38eb4a29 MT |
259 | } |
260 | ||
ff31d2e2 | 261 | void virtio_pci_legacy_remove(struct virtio_pci_device *vp_dev) |
38eb4a29 | 262 | { |
ff31d2e2 | 263 | struct pci_dev *pci_dev = vp_dev->pci_dev; |
38eb4a29 | 264 | |
38eb4a29 | 265 | pci_iounmap(pci_dev, vp_dev->ioaddr); |
59a5b0f7 | 266 | pci_release_region(pci_dev, 0); |
38eb4a29 | 267 | } |