diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-06-08 09:55:40 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-06-12 16:19:49 -0400 |
commit | 14be93ddff61eb196382aeaa3ac86f4db844aeb0 (patch) | |
tree | 0cfde7c3f444899508e2d07adb4245d4eb33216b /drivers/char/agp | |
parent | 7e8f6306fe155d6fc3fe99d666be95b4ed24427d (diff) |
drm/i915 + agp/intel-gtt: prep work for direct setup
To be able to directly set up the intel-gtt code from drm/i915 and
avoid setting up the fake-agp driver we need to prepare a few things:
- pass both the bridge and gpu pci_dev to the probe function and add
code to handle the gpu pdev both being present (for drm/i915) and
not present (fake agp).
- add refcounting to the remove function so that unloading drm/i915
doesn't kill the fake agp driver
v2: Fix up the cleanup and refcount, noticed by Jani Nikula.
Reviewed-by: Jani Nikula <jani.nikula@linux.intel.com>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/char/agp')
-rw-r--r-- | drivers/char/agp/intel-agp.c | 5 | ||||
-rw-r--r-- | drivers/char/agp/intel-agp.h | 3 | ||||
-rw-r--r-- | drivers/char/agp/intel-gtt.c | 46 |
3 files changed, 40 insertions, 14 deletions
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 764f70c5e690..c98c5689bb0b 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <asm/smp.h> | 12 | #include <asm/smp.h> |
13 | #include "agp.h" | 13 | #include "agp.h" |
14 | #include "intel-agp.h" | 14 | #include "intel-agp.h" |
15 | #include <drm/intel-gtt.h> | ||
15 | 16 | ||
16 | int intel_agp_enabled; | 17 | int intel_agp_enabled; |
17 | EXPORT_SYMBOL(intel_agp_enabled); | 18 | EXPORT_SYMBOL(intel_agp_enabled); |
@@ -747,7 +748,7 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, | |||
747 | 748 | ||
748 | bridge->capndx = cap_ptr; | 749 | bridge->capndx = cap_ptr; |
749 | 750 | ||
750 | if (intel_gmch_probe(pdev, bridge)) | 751 | if (intel_gmch_probe(pdev, NULL, bridge)) |
751 | goto found_gmch; | 752 | goto found_gmch; |
752 | 753 | ||
753 | for (i = 0; intel_agp_chipsets[i].name != NULL; i++) { | 754 | for (i = 0; intel_agp_chipsets[i].name != NULL; i++) { |
@@ -824,7 +825,7 @@ static void __devexit agp_intel_remove(struct pci_dev *pdev) | |||
824 | 825 | ||
825 | agp_remove_bridge(bridge); | 826 | agp_remove_bridge(bridge); |
826 | 827 | ||
827 | intel_gmch_remove(pdev); | 828 | intel_gmch_remove(); |
828 | 829 | ||
829 | agp_put_bridge(bridge); | 830 | agp_put_bridge(bridge); |
830 | } | 831 | } |
diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h index c0091753a0d1..cf2e764b1760 100644 --- a/drivers/char/agp/intel-agp.h +++ b/drivers/char/agp/intel-agp.h | |||
@@ -250,7 +250,4 @@ | |||
250 | #define PCI_DEVICE_ID_INTEL_HASWELL_SDV 0x0c16 /* SDV */ | 250 | #define PCI_DEVICE_ID_INTEL_HASWELL_SDV 0x0c16 /* SDV */ |
251 | #define PCI_DEVICE_ID_INTEL_HASWELL_E_HB 0x0c04 | 251 | #define PCI_DEVICE_ID_INTEL_HASWELL_E_HB 0x0c04 |
252 | 252 | ||
253 | int intel_gmch_probe(struct pci_dev *pdev, | ||
254 | struct agp_bridge_data *bridge); | ||
255 | void intel_gmch_remove(struct pci_dev *pdev); | ||
256 | #endif | 253 | #endif |
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 5e6c89e1d5eb..cea9f9905c7d 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c | |||
@@ -75,6 +75,7 @@ static struct _intel_private { | |||
75 | struct resource ifp_resource; | 75 | struct resource ifp_resource; |
76 | int resource_valid; | 76 | int resource_valid; |
77 | struct page *scratch_page; | 77 | struct page *scratch_page; |
78 | int refcount; | ||
78 | } intel_private; | 79 | } intel_private; |
79 | 80 | ||
80 | #define INTEL_GTT_GEN intel_private.driver->gen | 81 | #define INTEL_GTT_GEN intel_private.driver->gen |
@@ -1522,14 +1523,32 @@ static int find_gmch(u16 device) | |||
1522 | return 1; | 1523 | return 1; |
1523 | } | 1524 | } |
1524 | 1525 | ||
1525 | int intel_gmch_probe(struct pci_dev *pdev, | 1526 | int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev, |
1526 | struct agp_bridge_data *bridge) | 1527 | struct agp_bridge_data *bridge) |
1527 | { | 1528 | { |
1528 | int i, mask; | 1529 | int i, mask; |
1529 | intel_private.driver = NULL; | 1530 | |
1531 | /* | ||
1532 | * Can be called from the fake agp driver but also directly from | ||
1533 | * drm/i915.ko. Hence we need to check whether everything is set up | ||
1534 | * already. | ||
1535 | */ | ||
1536 | if (intel_private.driver) { | ||
1537 | intel_private.refcount++; | ||
1538 | return 1; | ||
1539 | } | ||
1530 | 1540 | ||
1531 | for (i = 0; intel_gtt_chipsets[i].name != NULL; i++) { | 1541 | for (i = 0; intel_gtt_chipsets[i].name != NULL; i++) { |
1532 | if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) { | 1542 | if (gpu_pdev) { |
1543 | if (gpu_pdev->device == | ||
1544 | intel_gtt_chipsets[i].gmch_chip_id) { | ||
1545 | intel_private.pcidev = pci_dev_get(gpu_pdev); | ||
1546 | intel_private.driver = | ||
1547 | intel_gtt_chipsets[i].gtt_driver; | ||
1548 | |||
1549 | break; | ||
1550 | } | ||
1551 | } else if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) { | ||
1533 | intel_private.driver = | 1552 | intel_private.driver = |
1534 | intel_gtt_chipsets[i].gtt_driver; | 1553 | intel_gtt_chipsets[i].gtt_driver; |
1535 | break; | 1554 | break; |
@@ -1539,15 +1558,17 @@ int intel_gmch_probe(struct pci_dev *pdev, | |||
1539 | if (!intel_private.driver) | 1558 | if (!intel_private.driver) |
1540 | return 0; | 1559 | return 0; |
1541 | 1560 | ||
1561 | intel_private.refcount++; | ||
1562 | |||
1542 | if (bridge) { | 1563 | if (bridge) { |
1543 | bridge->driver = &intel_fake_agp_driver; | 1564 | bridge->driver = &intel_fake_agp_driver; |
1544 | bridge->dev_private_data = &intel_private; | 1565 | bridge->dev_private_data = &intel_private; |
1545 | bridge->dev = pdev; | 1566 | bridge->dev = bridge_pdev; |
1546 | } | 1567 | } |
1547 | 1568 | ||
1548 | intel_private.bridge_dev = pci_dev_get(pdev); | 1569 | intel_private.bridge_dev = pci_dev_get(bridge_pdev); |
1549 | 1570 | ||
1550 | dev_info(&pdev->dev, "Intel %s Chipset\n", intel_gtt_chipsets[i].name); | 1571 | dev_info(&bridge_pdev->dev, "Intel %s Chipset\n", intel_gtt_chipsets[i].name); |
1551 | 1572 | ||
1552 | mask = intel_private.driver->dma_mask_size; | 1573 | mask = intel_private.driver->dma_mask_size; |
1553 | if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask))) | 1574 | if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask))) |
@@ -1557,8 +1578,11 @@ int intel_gmch_probe(struct pci_dev *pdev, | |||
1557 | pci_set_consistent_dma_mask(intel_private.pcidev, | 1578 | pci_set_consistent_dma_mask(intel_private.pcidev, |
1558 | DMA_BIT_MASK(mask)); | 1579 | DMA_BIT_MASK(mask)); |
1559 | 1580 | ||
1560 | if (intel_gtt_init() != 0) | 1581 | if (intel_gtt_init() != 0) { |
1582 | intel_gmch_remove(); | ||
1583 | |||
1561 | return 0; | 1584 | return 0; |
1585 | } | ||
1562 | 1586 | ||
1563 | return 1; | 1587 | return 1; |
1564 | } | 1588 | } |
@@ -1577,12 +1601,16 @@ void intel_gtt_chipset_flush(void) | |||
1577 | } | 1601 | } |
1578 | EXPORT_SYMBOL(intel_gtt_chipset_flush); | 1602 | EXPORT_SYMBOL(intel_gtt_chipset_flush); |
1579 | 1603 | ||
1580 | void intel_gmch_remove(struct pci_dev *pdev) | 1604 | void intel_gmch_remove(void) |
1581 | { | 1605 | { |
1606 | if (--intel_private.refcount) | ||
1607 | return; | ||
1608 | |||
1582 | if (intel_private.pcidev) | 1609 | if (intel_private.pcidev) |
1583 | pci_dev_put(intel_private.pcidev); | 1610 | pci_dev_put(intel_private.pcidev); |
1584 | if (intel_private.bridge_dev) | 1611 | if (intel_private.bridge_dev) |
1585 | pci_dev_put(intel_private.bridge_dev); | 1612 | pci_dev_put(intel_private.bridge_dev); |
1613 | intel_private.driver = NULL; | ||
1586 | } | 1614 | } |
1587 | EXPORT_SYMBOL(intel_gmch_remove); | 1615 | EXPORT_SYMBOL(intel_gmch_remove); |
1588 | 1616 | ||