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; | |
38eb4a29 MT |
122 | u16 num; |
123 | int err; | |
124 | ||
125 | /* Select the queue we're interested in */ | |
126 | iowrite16(index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL); | |
127 | ||
128 | /* Check if queue is either not available or already active. */ | |
129 | num = ioread16(vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NUM); | |
130 | if (!num || ioread32(vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN)) | |
131 | return ERR_PTR(-ENOENT); | |
132 | ||
38eb4a29 MT |
133 | info->msix_vector = msix_vec; |
134 | ||
7a5589b2 AL |
135 | /* create the vring */ |
136 | vq = vring_create_virtqueue(index, num, | |
137 | VIRTIO_PCI_VRING_ALIGN, &vp_dev->vdev, | |
138 | true, false, vp_notify, callback, name); | |
139 | if (!vq) | |
38eb4a29 MT |
140 | return ERR_PTR(-ENOMEM); |
141 | ||
142 | /* activate the queue */ | |
7a5589b2 | 143 | iowrite32(virtqueue_get_desc_addr(vq) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT, |
38eb4a29 MT |
144 | vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); |
145 | ||
38eb4a29 MT |
146 | vq->priv = (void __force *)vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY; |
147 | ||
148 | if (msix_vec != VIRTIO_MSI_NO_VECTOR) { | |
149 | iowrite16(msix_vec, vp_dev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR); | |
150 | msix_vec = ioread16(vp_dev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR); | |
151 | if (msix_vec == VIRTIO_MSI_NO_VECTOR) { | |
152 | err = -EBUSY; | |
7a5589b2 | 153 | goto out_deactivate; |
38eb4a29 MT |
154 | } |
155 | } | |
156 | ||
157 | return vq; | |
158 | ||
7a5589b2 | 159 | out_deactivate: |
38eb4a29 | 160 | iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); |
7a5589b2 | 161 | vring_del_virtqueue(vq); |
38eb4a29 MT |
162 | return ERR_PTR(err); |
163 | } | |
164 | ||
165 | static void del_vq(struct virtio_pci_vq_info *info) | |
166 | { | |
167 | struct virtqueue *vq = info->vq; | |
168 | struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); | |
38eb4a29 MT |
169 | |
170 | iowrite16(vq->index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL); | |
171 | ||
172 | if (vp_dev->msix_enabled) { | |
173 | iowrite16(VIRTIO_MSI_NO_VECTOR, | |
174 | vp_dev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR); | |
175 | /* Flush the write out to device */ | |
176 | ioread8(vp_dev->ioaddr + VIRTIO_PCI_ISR); | |
177 | } | |
178 | ||
38eb4a29 MT |
179 | /* Select and deactivate the queue */ |
180 | iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); | |
181 | ||
7a5589b2 | 182 | vring_del_virtqueue(vq); |
38eb4a29 MT |
183 | } |
184 | ||
185 | static const struct virtio_config_ops virtio_pci_config_ops = { | |
186 | .get = vp_get, | |
187 | .set = vp_set, | |
188 | .get_status = vp_get_status, | |
189 | .set_status = vp_set_status, | |
190 | .reset = vp_reset, | |
191 | .find_vqs = vp_find_vqs, | |
192 | .del_vqs = vp_del_vqs, | |
193 | .get_features = vp_get_features, | |
194 | .finalize_features = vp_finalize_features, | |
195 | .bus_name = vp_bus_name, | |
196 | .set_vq_affinity = vp_set_vq_affinity, | |
197 | }; | |
198 | ||
199 | /* the PCI probing function */ | |
ff31d2e2 | 200 | int virtio_pci_legacy_probe(struct virtio_pci_device *vp_dev) |
38eb4a29 | 201 | { |
ff31d2e2 | 202 | struct pci_dev *pci_dev = vp_dev->pci_dev; |
59a5b0f7 | 203 | int rc; |
38eb4a29 MT |
204 | |
205 | /* We only own devices >= 0x1000 and <= 0x103f: leave the rest. */ | |
206 | if (pci_dev->device < 0x1000 || pci_dev->device > 0x103f) | |
207 | return -ENODEV; | |
208 | ||
209 | if (pci_dev->revision != VIRTIO_PCI_ABI_VERSION) { | |
210 | printk(KERN_ERR "virtio_pci: expected ABI version %d, got %d\n", | |
211 | VIRTIO_PCI_ABI_VERSION, pci_dev->revision); | |
212 | return -ENODEV; | |
213 | } | |
214 | ||
7a5589b2 AL |
215 | rc = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(64)); |
216 | if (rc) | |
217 | rc = dma_set_mask_and_coherent(&pci_dev->dev, | |
218 | DMA_BIT_MASK(32)); | |
219 | if (rc) | |
220 | dev_warn(&pci_dev->dev, "Failed to enable 64-bit or 32-bit DMA. Trying to continue, but this might not work.\n"); | |
221 | ||
59a5b0f7 GH |
222 | rc = pci_request_region(pci_dev, 0, "virtio-pci-legacy"); |
223 | if (rc) | |
224 | return rc; | |
225 | ||
226 | rc = -ENOMEM; | |
38eb4a29 | 227 | vp_dev->ioaddr = pci_iomap(pci_dev, 0, 0); |
ff31d2e2 | 228 | if (!vp_dev->ioaddr) |
59a5b0f7 | 229 | goto err_iomap; |
38eb4a29 MT |
230 | |
231 | vp_dev->isr = vp_dev->ioaddr + VIRTIO_PCI_ISR; | |
232 | ||
38eb4a29 MT |
233 | /* we use the subsystem vendor/device id as the virtio vendor/device |
234 | * id. this allows us to use the same PCI vendor/device id for all | |
235 | * virtio devices and to identify the particular virtio driver by | |
236 | * the subsystem ids */ | |
237 | vp_dev->vdev.id.vendor = pci_dev->subsystem_vendor; | |
238 | vp_dev->vdev.id.device = pci_dev->subsystem_device; | |
239 | ||
ff31d2e2 MT |
240 | vp_dev->vdev.config = &virtio_pci_config_ops; |
241 | ||
38eb4a29 MT |
242 | vp_dev->config_vector = vp_config_vector; |
243 | vp_dev->setup_vq = setup_vq; | |
244 | vp_dev->del_vq = del_vq; | |
245 | ||
38eb4a29 | 246 | return 0; |
59a5b0f7 GH |
247 | |
248 | err_iomap: | |
249 | pci_release_region(pci_dev, 0); | |
250 | return rc; | |
38eb4a29 MT |
251 | } |
252 | ||
ff31d2e2 | 253 | void virtio_pci_legacy_remove(struct virtio_pci_device *vp_dev) |
38eb4a29 | 254 | { |
ff31d2e2 | 255 | struct pci_dev *pci_dev = vp_dev->pci_dev; |
38eb4a29 | 256 | |
38eb4a29 | 257 | pci_iounmap(pci_dev, vp_dev->ioaddr); |
59a5b0f7 | 258 | pci_release_region(pci_dev, 0); |
38eb4a29 | 259 | } |