748 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2 3#include <linux/virtio_pci_modern.h>4#include <linux/module.h>5#include <linux/pci.h>6#include <linux/delay.h>7 8/*9 * vp_modern_map_capability - map a part of virtio pci capability10 * @mdev: the modern virtio-pci device11 * @off: offset of the capability12 * @minlen: minimal length of the capability13 * @align: align requirement14 * @start: start from the capability15 * @size: map size16 * @len: the length that is actually mapped17 * @pa: physical address of the capability18 *19 * Returns the io address of for the part of the capability20 */21static void __iomem *22vp_modern_map_capability(struct virtio_pci_modern_device *mdev, int off,23 size_t minlen, u32 align, u32 start, u32 size,24 size_t *len, resource_size_t *pa)25{26 struct pci_dev *dev = mdev->pci_dev;27 u8 bar;28 u32 offset, length;29 void __iomem *p;30 31 pci_read_config_byte(dev, off + offsetof(struct virtio_pci_cap,32 bar),33 &bar);34 pci_read_config_dword(dev, off + offsetof(struct virtio_pci_cap, offset),35 &offset);36 pci_read_config_dword(dev, off + offsetof(struct virtio_pci_cap, length),37 &length);38 39 /* Check if the BAR may have changed since we requested the region. */40 if (bar >= PCI_STD_NUM_BARS || !(mdev->modern_bars & (1 << bar))) {41 dev_err(&dev->dev,42 "virtio_pci: bar unexpectedly changed to %u\n", bar);43 return NULL;44 }45 46 if (length <= start) {47 dev_err(&dev->dev,48 "virtio_pci: bad capability len %u (>%u expected)\n",49 length, start);50 return NULL;51 }52 53 if (length - start < minlen) {54 dev_err(&dev->dev,55 "virtio_pci: bad capability len %u (>=%zu expected)\n",56 length, minlen);57 return NULL;58 }59 60 length -= start;61 62 if (start + offset < offset) {63 dev_err(&dev->dev,64 "virtio_pci: map wrap-around %u+%u\n",65 start, offset);66 return NULL;67 }68 69 offset += start;70 71 if (offset & (align - 1)) {72 dev_err(&dev->dev,73 "virtio_pci: offset %u not aligned to %u\n",74 offset, align);75 return NULL;76 }77 78 if (length > size)79 length = size;80 81 if (len)82 *len = length;83 84 if (minlen + offset < minlen ||85 minlen + offset > pci_resource_len(dev, bar)) {86 dev_err(&dev->dev,87 "virtio_pci: map virtio %zu@%u "88 "out of range on bar %i length %lu\n",89 minlen, offset,90 bar, (unsigned long)pci_resource_len(dev, bar));91 return NULL;92 }93 94 p = pci_iomap_range(dev, bar, offset, length);95 if (!p)96 dev_err(&dev->dev,97 "virtio_pci: unable to map virtio %u@%u on bar %i\n",98 length, offset, bar);99 else if (pa)100 *pa = pci_resource_start(dev, bar) + offset;101 102 return p;103}104 105/**106 * virtio_pci_find_capability - walk capabilities to find device info.107 * @dev: the pci device108 * @cfg_type: the VIRTIO_PCI_CAP_* value we seek109 * @ioresource_types: IORESOURCE_MEM and/or IORESOURCE_IO.110 * @bars: the bitmask of BARs111 *112 * Returns offset of the capability, or 0.113 */114static inline int virtio_pci_find_capability(struct pci_dev *dev, u8 cfg_type,115 u32 ioresource_types, int *bars)116{117 int pos;118 119 for (pos = pci_find_capability(dev, PCI_CAP_ID_VNDR);120 pos > 0;121 pos = pci_find_next_capability(dev, pos, PCI_CAP_ID_VNDR)) {122 u8 type, bar;123 pci_read_config_byte(dev, pos + offsetof(struct virtio_pci_cap,124 cfg_type),125 &type);126 pci_read_config_byte(dev, pos + offsetof(struct virtio_pci_cap,127 bar),128 &bar);129 130 /* Ignore structures with reserved BAR values */131 if (bar >= PCI_STD_NUM_BARS)132 continue;133 134 if (type == cfg_type) {135 if (pci_resource_len(dev, bar) &&136 pci_resource_flags(dev, bar) & ioresource_types) {137 *bars |= (1 << bar);138 return pos;139 }140 }141 }142 return 0;143}144 145/* This is part of the ABI. Don't screw with it. */146static inline void check_offsets(void)147{148 /* Note: disk space was harmed in compilation of this function. */149 BUILD_BUG_ON(VIRTIO_PCI_CAP_VNDR !=150 offsetof(struct virtio_pci_cap, cap_vndr));151 BUILD_BUG_ON(VIRTIO_PCI_CAP_NEXT !=152 offsetof(struct virtio_pci_cap, cap_next));153 BUILD_BUG_ON(VIRTIO_PCI_CAP_LEN !=154 offsetof(struct virtio_pci_cap, cap_len));155 BUILD_BUG_ON(VIRTIO_PCI_CAP_CFG_TYPE !=156 offsetof(struct virtio_pci_cap, cfg_type));157 BUILD_BUG_ON(VIRTIO_PCI_CAP_BAR !=158 offsetof(struct virtio_pci_cap, bar));159 BUILD_BUG_ON(VIRTIO_PCI_CAP_OFFSET !=160 offsetof(struct virtio_pci_cap, offset));161 BUILD_BUG_ON(VIRTIO_PCI_CAP_LENGTH !=162 offsetof(struct virtio_pci_cap, length));163 BUILD_BUG_ON(VIRTIO_PCI_NOTIFY_CAP_MULT !=164 offsetof(struct virtio_pci_notify_cap,165 notify_off_multiplier));166 BUILD_BUG_ON(VIRTIO_PCI_COMMON_DFSELECT !=167 offsetof(struct virtio_pci_common_cfg,168 device_feature_select));169 BUILD_BUG_ON(VIRTIO_PCI_COMMON_DF !=170 offsetof(struct virtio_pci_common_cfg, device_feature));171 BUILD_BUG_ON(VIRTIO_PCI_COMMON_GFSELECT !=172 offsetof(struct virtio_pci_common_cfg,173 guest_feature_select));174 BUILD_BUG_ON(VIRTIO_PCI_COMMON_GF !=175 offsetof(struct virtio_pci_common_cfg, guest_feature));176 BUILD_BUG_ON(VIRTIO_PCI_COMMON_MSIX !=177 offsetof(struct virtio_pci_common_cfg, msix_config));178 BUILD_BUG_ON(VIRTIO_PCI_COMMON_NUMQ !=179 offsetof(struct virtio_pci_common_cfg, num_queues));180 BUILD_BUG_ON(VIRTIO_PCI_COMMON_STATUS !=181 offsetof(struct virtio_pci_common_cfg, device_status));182 BUILD_BUG_ON(VIRTIO_PCI_COMMON_CFGGENERATION !=183 offsetof(struct virtio_pci_common_cfg, config_generation));184 BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_SELECT !=185 offsetof(struct virtio_pci_common_cfg, queue_select));186 BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_SIZE !=187 offsetof(struct virtio_pci_common_cfg, queue_size));188 BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_MSIX !=189 offsetof(struct virtio_pci_common_cfg, queue_msix_vector));190 BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_ENABLE !=191 offsetof(struct virtio_pci_common_cfg, queue_enable));192 BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_NOFF !=193 offsetof(struct virtio_pci_common_cfg, queue_notify_off));194 BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_DESCLO !=195 offsetof(struct virtio_pci_common_cfg, queue_desc_lo));196 BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_DESCHI !=197 offsetof(struct virtio_pci_common_cfg, queue_desc_hi));198 BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_AVAILLO !=199 offsetof(struct virtio_pci_common_cfg, queue_avail_lo));200 BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_AVAILHI !=201 offsetof(struct virtio_pci_common_cfg, queue_avail_hi));202 BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_USEDLO !=203 offsetof(struct virtio_pci_common_cfg, queue_used_lo));204 BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_USEDHI !=205 offsetof(struct virtio_pci_common_cfg, queue_used_hi));206 BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_NDATA !=207 offsetof(struct virtio_pci_modern_common_cfg, queue_notify_data));208 BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_RESET !=209 offsetof(struct virtio_pci_modern_common_cfg, queue_reset));210 BUILD_BUG_ON(VIRTIO_PCI_COMMON_ADM_Q_IDX !=211 offsetof(struct virtio_pci_modern_common_cfg, admin_queue_index));212 BUILD_BUG_ON(VIRTIO_PCI_COMMON_ADM_Q_NUM !=213 offsetof(struct virtio_pci_modern_common_cfg, admin_queue_num));214}215 216/*217 * vp_modern_probe: probe the modern virtio pci device, note that the218 * caller is required to enable PCI device before calling this function.219 * @mdev: the modern virtio-pci device220 *221 * Return 0 on succeed otherwise fail222 */223int vp_modern_probe(struct virtio_pci_modern_device *mdev)224{225 struct pci_dev *pci_dev = mdev->pci_dev;226 int err, common, isr, notify, device;227 u32 notify_length;228 u32 notify_offset;229 int devid;230 231 check_offsets();232 233 if (mdev->device_id_check) {234 devid = mdev->device_id_check(pci_dev);235 if (devid < 0)236 return devid;237 mdev->id.device = devid;238 } else {239 /* We only own devices >= 0x1000 and <= 0x107f: leave the rest. */240 if (pci_dev->device < 0x1000 || pci_dev->device > 0x107f)241 return -ENODEV;242 243 if (pci_dev->device < 0x1040) {244 /* Transitional devices: use the PCI subsystem device id as245 * virtio device id, same as legacy driver always did.246 */247 mdev->id.device = pci_dev->subsystem_device;248 } else {249 /* Modern devices: simply use PCI device id, but start from 0x1040. */250 mdev->id.device = pci_dev->device - 0x1040;251 }252 }253 mdev->id.vendor = pci_dev->subsystem_vendor;254 255 /* check for a common config: if not, use legacy mode (bar 0). */256 common = virtio_pci_find_capability(pci_dev, VIRTIO_PCI_CAP_COMMON_CFG,257 IORESOURCE_IO | IORESOURCE_MEM,258 &mdev->modern_bars);259 if (!common) {260 dev_info(&pci_dev->dev,261 "virtio_pci: leaving for legacy driver\n");262 return -ENODEV;263 }264 265 /* If common is there, these should be too... */266 isr = virtio_pci_find_capability(pci_dev, VIRTIO_PCI_CAP_ISR_CFG,267 IORESOURCE_IO | IORESOURCE_MEM,268 &mdev->modern_bars);269 notify = virtio_pci_find_capability(pci_dev, VIRTIO_PCI_CAP_NOTIFY_CFG,270 IORESOURCE_IO | IORESOURCE_MEM,271 &mdev->modern_bars);272 if (!isr || !notify) {273 dev_err(&pci_dev->dev,274 "virtio_pci: missing capabilities %i/%i/%i\n",275 common, isr, notify);276 return -EINVAL;277 }278 279 err = dma_set_mask_and_coherent(&pci_dev->dev,280 mdev->dma_mask ? : DMA_BIT_MASK(64));281 if (err)282 err = dma_set_mask_and_coherent(&pci_dev->dev,283 DMA_BIT_MASK(32));284 if (err)285 dev_warn(&pci_dev->dev, "Failed to enable 64-bit or 32-bit DMA. Trying to continue, but this might not work.\n");286 287 /* Device capability is only mandatory for devices that have288 * device-specific configuration.289 */290 device = virtio_pci_find_capability(pci_dev, VIRTIO_PCI_CAP_DEVICE_CFG,291 IORESOURCE_IO | IORESOURCE_MEM,292 &mdev->modern_bars);293 294 err = pci_request_selected_regions(pci_dev, mdev->modern_bars,295 "virtio-pci-modern");296 if (err)297 return err;298 299 err = -EINVAL;300 mdev->common = vp_modern_map_capability(mdev, common,301 sizeof(struct virtio_pci_common_cfg), 4, 0,302 offsetofend(struct virtio_pci_modern_common_cfg,303 admin_queue_num),304 &mdev->common_len, NULL);305 if (!mdev->common)306 goto err_map_common;307 mdev->isr = vp_modern_map_capability(mdev, isr, sizeof(u8), 1,308 0, 1,309 NULL, NULL);310 if (!mdev->isr)311 goto err_map_isr;312 313 /* Read notify_off_multiplier from config space. */314 pci_read_config_dword(pci_dev,315 notify + offsetof(struct virtio_pci_notify_cap,316 notify_off_multiplier),317 &mdev->notify_offset_multiplier);318 /* Read notify length and offset from config space. */319 pci_read_config_dword(pci_dev,320 notify + offsetof(struct virtio_pci_notify_cap,321 cap.length),322 ¬ify_length);323 324 pci_read_config_dword(pci_dev,325 notify + offsetof(struct virtio_pci_notify_cap,326 cap.offset),327 ¬ify_offset);328 329 /* We don't know how many VQs we'll map, ahead of the time.330 * If notify length is small, map it all now.331 * Otherwise, map each VQ individually later.332 */333 if ((u64)notify_length + (notify_offset % PAGE_SIZE) <= PAGE_SIZE) {334 mdev->notify_base = vp_modern_map_capability(mdev, notify,335 2, 2,336 0, notify_length,337 &mdev->notify_len,338 &mdev->notify_pa);339 if (!mdev->notify_base)340 goto err_map_notify;341 } else {342 mdev->notify_map_cap = notify;343 }344 345 /* Again, we don't know how much we should map, but PAGE_SIZE346 * is more than enough for all existing devices.347 */348 if (device) {349 mdev->device = vp_modern_map_capability(mdev, device, 0, 4,350 0, PAGE_SIZE,351 &mdev->device_len,352 NULL);353 if (!mdev->device)354 goto err_map_device;355 }356 357 return 0;358 359err_map_device:360 if (mdev->notify_base)361 pci_iounmap(pci_dev, mdev->notify_base);362err_map_notify:363 pci_iounmap(pci_dev, mdev->isr);364err_map_isr:365 pci_iounmap(pci_dev, mdev->common);366err_map_common:367 pci_release_selected_regions(pci_dev, mdev->modern_bars);368 return err;369}370EXPORT_SYMBOL_GPL(vp_modern_probe);371 372/*373 * vp_modern_remove: remove and cleanup the modern virtio pci device374 * @mdev: the modern virtio-pci device375 */376void vp_modern_remove(struct virtio_pci_modern_device *mdev)377{378 struct pci_dev *pci_dev = mdev->pci_dev;379 380 if (mdev->device)381 pci_iounmap(pci_dev, mdev->device);382 if (mdev->notify_base)383 pci_iounmap(pci_dev, mdev->notify_base);384 pci_iounmap(pci_dev, mdev->isr);385 pci_iounmap(pci_dev, mdev->common);386 pci_release_selected_regions(pci_dev, mdev->modern_bars);387}388EXPORT_SYMBOL_GPL(vp_modern_remove);389 390/*391 * vp_modern_get_features - get features from device392 * @mdev: the modern virtio-pci device393 *394 * Returns the features read from the device395 */396u64 vp_modern_get_features(struct virtio_pci_modern_device *mdev)397{398 struct virtio_pci_common_cfg __iomem *cfg = mdev->common;399 400 u64 features;401 402 vp_iowrite32(0, &cfg->device_feature_select);403 features = vp_ioread32(&cfg->device_feature);404 vp_iowrite32(1, &cfg->device_feature_select);405 features |= ((u64)vp_ioread32(&cfg->device_feature) << 32);406 407 return features;408}409EXPORT_SYMBOL_GPL(vp_modern_get_features);410 411/*412 * vp_modern_get_driver_features - get driver features from device413 * @mdev: the modern virtio-pci device414 *415 * Returns the driver features read from the device416 */417u64 vp_modern_get_driver_features(struct virtio_pci_modern_device *mdev)418{419 struct virtio_pci_common_cfg __iomem *cfg = mdev->common;420 421 u64 features;422 423 vp_iowrite32(0, &cfg->guest_feature_select);424 features = vp_ioread32(&cfg->guest_feature);425 vp_iowrite32(1, &cfg->guest_feature_select);426 features |= ((u64)vp_ioread32(&cfg->guest_feature) << 32);427 428 return features;429}430EXPORT_SYMBOL_GPL(vp_modern_get_driver_features);431 432/*433 * vp_modern_set_features - set features to device434 * @mdev: the modern virtio-pci device435 * @features: the features set to device436 */437void vp_modern_set_features(struct virtio_pci_modern_device *mdev,438 u64 features)439{440 struct virtio_pci_common_cfg __iomem *cfg = mdev->common;441 442 vp_iowrite32(0, &cfg->guest_feature_select);443 vp_iowrite32((u32)features, &cfg->guest_feature);444 vp_iowrite32(1, &cfg->guest_feature_select);445 vp_iowrite32(features >> 32, &cfg->guest_feature);446}447EXPORT_SYMBOL_GPL(vp_modern_set_features);448 449/*450 * vp_modern_generation - get the device genreation451 * @mdev: the modern virtio-pci device452 *453 * Returns the genreation read from device454 */455u32 vp_modern_generation(struct virtio_pci_modern_device *mdev)456{457 struct virtio_pci_common_cfg __iomem *cfg = mdev->common;458 459 return vp_ioread8(&cfg->config_generation);460}461EXPORT_SYMBOL_GPL(vp_modern_generation);462 463/*464 * vp_modern_get_status - get the device status465 * @mdev: the modern virtio-pci device466 *467 * Returns the status read from device468 */469u8 vp_modern_get_status(struct virtio_pci_modern_device *mdev)470{471 struct virtio_pci_common_cfg __iomem *cfg = mdev->common;472 473 return vp_ioread8(&cfg->device_status);474}475EXPORT_SYMBOL_GPL(vp_modern_get_status);476 477/*478 * vp_modern_set_status - set status to device479 * @mdev: the modern virtio-pci device480 * @status: the status set to device481 */482void vp_modern_set_status(struct virtio_pci_modern_device *mdev,483 u8 status)484{485 struct virtio_pci_common_cfg __iomem *cfg = mdev->common;486 487 /*488 * Per memory-barriers.txt, wmb() is not needed to guarantee489 * that the cache coherent memory writes have completed490 * before writing to the MMIO region.491 */492 vp_iowrite8(status, &cfg->device_status);493}494EXPORT_SYMBOL_GPL(vp_modern_set_status);495 496/*497 * vp_modern_get_queue_reset - get the queue reset status498 * @mdev: the modern virtio-pci device499 * @index: queue index500 */501int vp_modern_get_queue_reset(struct virtio_pci_modern_device *mdev, u16 index)502{503 struct virtio_pci_modern_common_cfg __iomem *cfg;504 505 cfg = (struct virtio_pci_modern_common_cfg __iomem *)mdev->common;506 507 vp_iowrite16(index, &cfg->cfg.queue_select);508 return vp_ioread16(&cfg->queue_reset);509}510EXPORT_SYMBOL_GPL(vp_modern_get_queue_reset);511 512/*513 * vp_modern_set_queue_reset - reset the queue514 * @mdev: the modern virtio-pci device515 * @index: queue index516 */517void vp_modern_set_queue_reset(struct virtio_pci_modern_device *mdev, u16 index)518{519 struct virtio_pci_modern_common_cfg __iomem *cfg;520 521 cfg = (struct virtio_pci_modern_common_cfg __iomem *)mdev->common;522 523 vp_iowrite16(index, &cfg->cfg.queue_select);524 vp_iowrite16(1, &cfg->queue_reset);525 526 while (vp_ioread16(&cfg->queue_reset))527 msleep(1);528 529 while (vp_ioread16(&cfg->cfg.queue_enable))530 msleep(1);531}532EXPORT_SYMBOL_GPL(vp_modern_set_queue_reset);533 534/*535 * vp_modern_queue_vector - set the MSIX vector for a specific virtqueue536 * @mdev: the modern virtio-pci device537 * @index: queue index538 * @vector: the config vector539 *540 * Returns the config vector read from the device541 */542u16 vp_modern_queue_vector(struct virtio_pci_modern_device *mdev,543 u16 index, u16 vector)544{545 struct virtio_pci_common_cfg __iomem *cfg = mdev->common;546 547 vp_iowrite16(index, &cfg->queue_select);548 vp_iowrite16(vector, &cfg->queue_msix_vector);549 /* Flush the write out to device */550 return vp_ioread16(&cfg->queue_msix_vector);551}552EXPORT_SYMBOL_GPL(vp_modern_queue_vector);553 554/*555 * vp_modern_config_vector - set the vector for config interrupt556 * @mdev: the modern virtio-pci device557 * @vector: the config vector558 *559 * Returns the config vector read from the device560 */561u16 vp_modern_config_vector(struct virtio_pci_modern_device *mdev,562 u16 vector)563{564 struct virtio_pci_common_cfg __iomem *cfg = mdev->common;565 566 /* Setup the vector used for configuration events */567 vp_iowrite16(vector, &cfg->msix_config);568 /* Verify we had enough resources to assign the vector */569 /* Will also flush the write out to device */570 return vp_ioread16(&cfg->msix_config);571}572EXPORT_SYMBOL_GPL(vp_modern_config_vector);573 574/*575 * vp_modern_queue_address - set the virtqueue address576 * @mdev: the modern virtio-pci device577 * @index: the queue index578 * @desc_addr: address of the descriptor area579 * @driver_addr: address of the driver area580 * @device_addr: address of the device area581 */582void vp_modern_queue_address(struct virtio_pci_modern_device *mdev,583 u16 index, u64 desc_addr, u64 driver_addr,584 u64 device_addr)585{586 struct virtio_pci_common_cfg __iomem *cfg = mdev->common;587 588 vp_iowrite16(index, &cfg->queue_select);589 590 vp_iowrite64_twopart(desc_addr, &cfg->queue_desc_lo,591 &cfg->queue_desc_hi);592 vp_iowrite64_twopart(driver_addr, &cfg->queue_avail_lo,593 &cfg->queue_avail_hi);594 vp_iowrite64_twopart(device_addr, &cfg->queue_used_lo,595 &cfg->queue_used_hi);596}597EXPORT_SYMBOL_GPL(vp_modern_queue_address);598 599/*600 * vp_modern_set_queue_enable - enable a virtqueue601 * @mdev: the modern virtio-pci device602 * @index: the queue index603 * @enable: whether the virtqueue is enable or not604 */605void vp_modern_set_queue_enable(struct virtio_pci_modern_device *mdev,606 u16 index, bool enable)607{608 vp_iowrite16(index, &mdev->common->queue_select);609 vp_iowrite16(enable, &mdev->common->queue_enable);610}611EXPORT_SYMBOL_GPL(vp_modern_set_queue_enable);612 613/*614 * vp_modern_get_queue_enable - enable a virtqueue615 * @mdev: the modern virtio-pci device616 * @index: the queue index617 *618 * Returns whether a virtqueue is enabled or not619 */620bool vp_modern_get_queue_enable(struct virtio_pci_modern_device *mdev,621 u16 index)622{623 vp_iowrite16(index, &mdev->common->queue_select);624 625 return vp_ioread16(&mdev->common->queue_enable);626}627EXPORT_SYMBOL_GPL(vp_modern_get_queue_enable);628 629/*630 * vp_modern_set_queue_size - set size for a virtqueue631 * @mdev: the modern virtio-pci device632 * @index: the queue index633 * @size: the size of the virtqueue634 */635void vp_modern_set_queue_size(struct virtio_pci_modern_device *mdev,636 u16 index, u16 size)637{638 vp_iowrite16(index, &mdev->common->queue_select);639 vp_iowrite16(size, &mdev->common->queue_size);640 641}642EXPORT_SYMBOL_GPL(vp_modern_set_queue_size);643 644/*645 * vp_modern_get_queue_size - get size for a virtqueue646 * @mdev: the modern virtio-pci device647 * @index: the queue index648 *649 * Returns the size of the virtqueue650 */651u16 vp_modern_get_queue_size(struct virtio_pci_modern_device *mdev,652 u16 index)653{654 vp_iowrite16(index, &mdev->common->queue_select);655 656 return vp_ioread16(&mdev->common->queue_size);657 658}659EXPORT_SYMBOL_GPL(vp_modern_get_queue_size);660 661/*662 * vp_modern_get_num_queues - get the number of virtqueues663 * @mdev: the modern virtio-pci device664 *665 * Returns the number of virtqueues666 */667u16 vp_modern_get_num_queues(struct virtio_pci_modern_device *mdev)668{669 return vp_ioread16(&mdev->common->num_queues);670}671EXPORT_SYMBOL_GPL(vp_modern_get_num_queues);672 673/*674 * vp_modern_get_queue_notify_off - get notification offset for a virtqueue675 * @mdev: the modern virtio-pci device676 * @index: the queue index677 *678 * Returns the notification offset for a virtqueue679 */680static u16 vp_modern_get_queue_notify_off(struct virtio_pci_modern_device *mdev,681 u16 index)682{683 vp_iowrite16(index, &mdev->common->queue_select);684 685 return vp_ioread16(&mdev->common->queue_notify_off);686}687 688/*689 * vp_modern_map_vq_notify - map notification area for a690 * specific virtqueue691 * @mdev: the modern virtio-pci device692 * @index: the queue index693 * @pa: the pointer to the physical address of the nofity area694 *695 * Returns the address of the notification area696 */697void __iomem *vp_modern_map_vq_notify(struct virtio_pci_modern_device *mdev,698 u16 index, resource_size_t *pa)699{700 u16 off = vp_modern_get_queue_notify_off(mdev, index);701 702 if (mdev->notify_base) {703 /* offset should not wrap */704 if ((u64)off * mdev->notify_offset_multiplier + 2705 > mdev->notify_len) {706 dev_warn(&mdev->pci_dev->dev,707 "bad notification offset %u (x %u) "708 "for queue %u > %zd",709 off, mdev->notify_offset_multiplier,710 index, mdev->notify_len);711 return NULL;712 }713 if (pa)714 *pa = mdev->notify_pa +715 off * mdev->notify_offset_multiplier;716 return mdev->notify_base + off * mdev->notify_offset_multiplier;717 } else {718 return vp_modern_map_capability(mdev,719 mdev->notify_map_cap, 2, 2,720 off * mdev->notify_offset_multiplier, 2,721 NULL, pa);722 }723}724EXPORT_SYMBOL_GPL(vp_modern_map_vq_notify);725 726u16 vp_modern_avq_num(struct virtio_pci_modern_device *mdev)727{728 struct virtio_pci_modern_common_cfg __iomem *cfg;729 730 cfg = (struct virtio_pci_modern_common_cfg __iomem *)mdev->common;731 return vp_ioread16(&cfg->admin_queue_num);732}733EXPORT_SYMBOL_GPL(vp_modern_avq_num);734 735u16 vp_modern_avq_index(struct virtio_pci_modern_device *mdev)736{737 struct virtio_pci_modern_common_cfg __iomem *cfg;738 739 cfg = (struct virtio_pci_modern_common_cfg __iomem *)mdev->common;740 return vp_ioread16(&cfg->admin_queue_index);741}742EXPORT_SYMBOL_GPL(vp_modern_avq_index);743 744MODULE_VERSION("0.1");745MODULE_DESCRIPTION("Modern Virtio PCI Device");746MODULE_AUTHOR("Jason Wang <jasowang@redhat.com>");747MODULE_LICENSE("GPL");748