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