|
Lines 98-106
struct vmd_dev {
Link Here
|
| 98 |
struct irq_domain *irq_domain; |
98 |
struct irq_domain *irq_domain; |
| 99 |
struct pci_bus *bus; |
99 |
struct pci_bus *bus; |
| 100 |
u8 busn_start; |
100 |
u8 busn_start; |
| 101 |
|
|
|
| 102 |
struct dma_map_ops dma_ops; |
| 103 |
struct dma_domain dma_domain; |
| 104 |
}; |
101 |
}; |
| 105 |
|
102 |
|
| 106 |
static inline struct vmd_dev *vmd_from_bus(struct pci_bus *bus) |
103 |
static inline struct vmd_dev *vmd_from_bus(struct pci_bus *bus) |
|
Lines 295-445
static struct msi_domain_info vmd_msi_domain_info = {
Link Here
|
| 295 |
.chip = &vmd_msi_controller, |
292 |
.chip = &vmd_msi_controller, |
| 296 |
}; |
293 |
}; |
| 297 |
|
294 |
|
| 298 |
/* |
|
|
| 299 |
* VMD replaces the requester ID with its own. DMA mappings for devices in a |
| 300 |
* VMD domain need to be mapped for the VMD, not the device requiring |
| 301 |
* the mapping. |
| 302 |
*/ |
| 303 |
static struct device *to_vmd_dev(struct device *dev) |
| 304 |
{ |
| 305 |
struct pci_dev *pdev = to_pci_dev(dev); |
| 306 |
struct vmd_dev *vmd = vmd_from_bus(pdev->bus); |
| 307 |
|
| 308 |
return &vmd->dev->dev; |
| 309 |
} |
| 310 |
|
| 311 |
static void *vmd_alloc(struct device *dev, size_t size, dma_addr_t *addr, |
| 312 |
gfp_t flag, unsigned long attrs) |
| 313 |
{ |
| 314 |
return dma_alloc_attrs(to_vmd_dev(dev), size, addr, flag, attrs); |
| 315 |
} |
| 316 |
|
| 317 |
static void vmd_free(struct device *dev, size_t size, void *vaddr, |
| 318 |
dma_addr_t addr, unsigned long attrs) |
| 319 |
{ |
| 320 |
return dma_free_attrs(to_vmd_dev(dev), size, vaddr, addr, attrs); |
| 321 |
} |
| 322 |
|
| 323 |
static int vmd_mmap(struct device *dev, struct vm_area_struct *vma, |
| 324 |
void *cpu_addr, dma_addr_t addr, size_t size, |
| 325 |
unsigned long attrs) |
| 326 |
{ |
| 327 |
return dma_mmap_attrs(to_vmd_dev(dev), vma, cpu_addr, addr, size, |
| 328 |
attrs); |
| 329 |
} |
| 330 |
|
| 331 |
static int vmd_get_sgtable(struct device *dev, struct sg_table *sgt, |
| 332 |
void *cpu_addr, dma_addr_t addr, size_t size, |
| 333 |
unsigned long attrs) |
| 334 |
{ |
| 335 |
return dma_get_sgtable_attrs(to_vmd_dev(dev), sgt, cpu_addr, addr, size, |
| 336 |
attrs); |
| 337 |
} |
| 338 |
|
| 339 |
static dma_addr_t vmd_map_page(struct device *dev, struct page *page, |
| 340 |
unsigned long offset, size_t size, |
| 341 |
enum dma_data_direction dir, |
| 342 |
unsigned long attrs) |
| 343 |
{ |
| 344 |
return dma_map_page_attrs(to_vmd_dev(dev), page, offset, size, dir, |
| 345 |
attrs); |
| 346 |
} |
| 347 |
|
| 348 |
static void vmd_unmap_page(struct device *dev, dma_addr_t addr, size_t size, |
| 349 |
enum dma_data_direction dir, unsigned long attrs) |
| 350 |
{ |
| 351 |
dma_unmap_page_attrs(to_vmd_dev(dev), addr, size, dir, attrs); |
| 352 |
} |
| 353 |
|
| 354 |
static int vmd_map_sg(struct device *dev, struct scatterlist *sg, int nents, |
| 355 |
enum dma_data_direction dir, unsigned long attrs) |
| 356 |
{ |
| 357 |
return dma_map_sg_attrs(to_vmd_dev(dev), sg, nents, dir, attrs); |
| 358 |
} |
| 359 |
|
| 360 |
static void vmd_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, |
| 361 |
enum dma_data_direction dir, unsigned long attrs) |
| 362 |
{ |
| 363 |
dma_unmap_sg_attrs(to_vmd_dev(dev), sg, nents, dir, attrs); |
| 364 |
} |
| 365 |
|
| 366 |
static void vmd_sync_single_for_cpu(struct device *dev, dma_addr_t addr, |
| 367 |
size_t size, enum dma_data_direction dir) |
| 368 |
{ |
| 369 |
dma_sync_single_for_cpu(to_vmd_dev(dev), addr, size, dir); |
| 370 |
} |
| 371 |
|
| 372 |
static void vmd_sync_single_for_device(struct device *dev, dma_addr_t addr, |
| 373 |
size_t size, enum dma_data_direction dir) |
| 374 |
{ |
| 375 |
dma_sync_single_for_device(to_vmd_dev(dev), addr, size, dir); |
| 376 |
} |
| 377 |
|
| 378 |
static void vmd_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, |
| 379 |
int nents, enum dma_data_direction dir) |
| 380 |
{ |
| 381 |
dma_sync_sg_for_cpu(to_vmd_dev(dev), sg, nents, dir); |
| 382 |
} |
| 383 |
|
| 384 |
static void vmd_sync_sg_for_device(struct device *dev, struct scatterlist *sg, |
| 385 |
int nents, enum dma_data_direction dir) |
| 386 |
{ |
| 387 |
dma_sync_sg_for_device(to_vmd_dev(dev), sg, nents, dir); |
| 388 |
} |
| 389 |
|
| 390 |
static int vmd_dma_supported(struct device *dev, u64 mask) |
| 391 |
{ |
| 392 |
return dma_supported(to_vmd_dev(dev), mask); |
| 393 |
} |
| 394 |
|
| 395 |
static u64 vmd_get_required_mask(struct device *dev) |
| 396 |
{ |
| 397 |
return dma_get_required_mask(to_vmd_dev(dev)); |
| 398 |
} |
| 399 |
|
| 400 |
static void vmd_teardown_dma_ops(struct vmd_dev *vmd) |
| 401 |
{ |
| 402 |
struct dma_domain *domain = &vmd->dma_domain; |
| 403 |
|
| 404 |
if (get_dma_ops(&vmd->dev->dev)) |
| 405 |
del_dma_domain(domain); |
| 406 |
} |
| 407 |
|
| 408 |
#define ASSIGN_VMD_DMA_OPS(source, dest, fn) \ |
| 409 |
do { \ |
| 410 |
if (source->fn) \ |
| 411 |
dest->fn = vmd_##fn; \ |
| 412 |
} while (0) |
| 413 |
|
| 414 |
static void vmd_setup_dma_ops(struct vmd_dev *vmd) |
| 415 |
{ |
| 416 |
const struct dma_map_ops *source = get_dma_ops(&vmd->dev->dev); |
| 417 |
struct dma_map_ops *dest = &vmd->dma_ops; |
| 418 |
struct dma_domain *domain = &vmd->dma_domain; |
| 419 |
|
| 420 |
domain->domain_nr = vmd->sysdata.domain; |
| 421 |
domain->dma_ops = dest; |
| 422 |
|
| 423 |
if (!source) |
| 424 |
return; |
| 425 |
ASSIGN_VMD_DMA_OPS(source, dest, alloc); |
| 426 |
ASSIGN_VMD_DMA_OPS(source, dest, free); |
| 427 |
ASSIGN_VMD_DMA_OPS(source, dest, mmap); |
| 428 |
ASSIGN_VMD_DMA_OPS(source, dest, get_sgtable); |
| 429 |
ASSIGN_VMD_DMA_OPS(source, dest, map_page); |
| 430 |
ASSIGN_VMD_DMA_OPS(source, dest, unmap_page); |
| 431 |
ASSIGN_VMD_DMA_OPS(source, dest, map_sg); |
| 432 |
ASSIGN_VMD_DMA_OPS(source, dest, unmap_sg); |
| 433 |
ASSIGN_VMD_DMA_OPS(source, dest, sync_single_for_cpu); |
| 434 |
ASSIGN_VMD_DMA_OPS(source, dest, sync_single_for_device); |
| 435 |
ASSIGN_VMD_DMA_OPS(source, dest, sync_sg_for_cpu); |
| 436 |
ASSIGN_VMD_DMA_OPS(source, dest, sync_sg_for_device); |
| 437 |
ASSIGN_VMD_DMA_OPS(source, dest, dma_supported); |
| 438 |
ASSIGN_VMD_DMA_OPS(source, dest, get_required_mask); |
| 439 |
add_dma_domain(domain); |
| 440 |
} |
| 441 |
#undef ASSIGN_VMD_DMA_OPS |
| 442 |
|
| 443 |
static char __iomem *vmd_cfg_addr(struct vmd_dev *vmd, struct pci_bus *bus, |
295 |
static char __iomem *vmd_cfg_addr(struct vmd_dev *vmd, struct pci_bus *bus, |
| 444 |
unsigned int devfn, int reg, int len) |
296 |
unsigned int devfn, int reg, int len) |
| 445 |
{ |
297 |
{ |
|
Lines 713-719
static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
Link Here
|
| 713 |
} |
565 |
} |
| 714 |
|
566 |
|
| 715 |
vmd_attach_resources(vmd); |
567 |
vmd_attach_resources(vmd); |
| 716 |
vmd_setup_dma_ops(vmd); |
|
|
| 717 |
dev_set_msi_domain(&vmd->bus->dev, vmd->irq_domain); |
568 |
dev_set_msi_domain(&vmd->bus->dev, vmd->irq_domain); |
| 718 |
|
569 |
|
| 719 |
pci_scan_child_bus(vmd->bus); |
570 |
pci_scan_child_bus(vmd->bus); |
|
Lines 829-835
static void vmd_remove(struct pci_dev *dev)
Link Here
|
| 829 |
pci_stop_root_bus(vmd->bus); |
680 |
pci_stop_root_bus(vmd->bus); |
| 830 |
pci_remove_root_bus(vmd->bus); |
681 |
pci_remove_root_bus(vmd->bus); |
| 831 |
vmd_cleanup_srcu(vmd); |
682 |
vmd_cleanup_srcu(vmd); |
| 832 |
vmd_teardown_dma_ops(vmd); |
|
|
| 833 |
vmd_detach_resources(vmd); |
683 |
vmd_detach_resources(vmd); |
| 834 |
irq_domain_remove(vmd->irq_domain); |
684 |
irq_domain_remove(vmd->irq_domain); |
| 835 |
irq_domain_free_fwnode(fn); |
685 |
irq_domain_free_fwnode(fn); |
| 836 |
- |
|
|