This v5 of the patch series is based on v4 sent by Lucas Kannebley Tavares with a few changes:
1. Fix a compilation warning on the code from the first patch, where it was missing a declaration of struct pci_host_bridge, used on the definition of the function pointer pcibios_root_bridge_prepare() in arch/powerpc/include/asm/machdep.h. 2. Incorporate some changes proposed by Tony Breeds in pseries_root_bridge_prepare().
The following description of the changes was extrated from v4:
This patch series does: 1. max_bus_speed is used to set the device to gen2 speeds 2. on power there's no longer a conflict between the pseries call and other architectures, because the overwrite is done via a ppc_md hook 3. radeon is using bus->max_bus_speed instead of drm_pcie_get_speed_cap_mask for gen2 capability detection
The first patch consists of some architecture changes, such as adding a hook on powerpc for pci_root_bridge_prepare, so that pseries will initialize it to a function, while all other architectures get a NULL pointer. So that whenever pci_create_root_bus is called, we'll get max_bus_speed properly setup from OpenFirmware.
The second patch consists of simple radeon changes not to call drm_get_pcie_speed_cap_mask anymore. I assume that on x86 machines, the max_bus_speed property will be properly set already.
Kleber Sacilotto de Souza (2): ppc64: perform proper max_bus_speed detection radeon: use max_bus_speed to activate gen2 speeds
arch/powerpc/include/asm/machdep.h | 3 ++ arch/powerpc/kernel/pci-common.c | 8 ++++ arch/powerpc/platforms/pseries/pci.c | 53 ++++++++++++++++++++++++++++++ arch/powerpc/platforms/pseries/pseries.h | 4 ++ arch/powerpc/platforms/pseries/setup.c | 2 + drivers/gpu/drm/radeon/evergreen.c | 10 ++---- drivers/gpu/drm/radeon/r600.c | 9 +---- drivers/gpu/drm/radeon/rv770.c | 9 +---- 8 files changed, 77 insertions(+), 21 deletions(-)
On pseries machines the detection for max_bus_speed should be done through an OpenFirmware property. This patch adds a function to perform this detection and a hook to perform dynamic adding of the function only for pseries. This is done by overwriting the weak pcibios_root_bridge_prepare function which is called by pci_create_root_bus().
From: Lucas Kannebley Tavares lucaskt@linux.vnet.ibm.com Signed-off-by: Kleber Sacilotto de Souza klebers@linux.vnet.ibm.com --- arch/powerpc/include/asm/machdep.h | 3 ++ arch/powerpc/kernel/pci-common.c | 8 ++++ arch/powerpc/platforms/pseries/pci.c | 53 ++++++++++++++++++++++++++++++ arch/powerpc/platforms/pseries/pseries.h | 4 ++ arch/powerpc/platforms/pseries/setup.c | 2 + 5 files changed, 70 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index 3f3f691..92386fc 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h @@ -29,6 +29,7 @@ struct rtc_time; struct file; struct pci_controller; struct kimage; +struct pci_host_bridge;
struct machdep_calls { char *name; @@ -108,6 +109,8 @@ struct machdep_calls { void (*pcibios_fixup)(void); int (*pci_probe_mode)(struct pci_bus *); void (*pci_irq_fixup)(struct pci_dev *dev); + int (*pcibios_root_bridge_prepare)(struct pci_host_bridge + *bridge);
/* To setup PHBs when using automatic OF platform driver for PCI */ int (*pci_setup_phb)(struct pci_controller *host); diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index f325dc9..d5811d8 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -845,6 +845,14 @@ int pci_proc_domain(struct pci_bus *bus) return 1; }
+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) +{ + if (ppc_md.pcibios_root_bridge_prepare) + return ppc_md.pcibios_root_bridge_prepare(bridge); + + return 0; +} + /* This header fixup will do the resource fixup for all devices as they are * probed, but not for bridge ranges */ diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c index 0b580f4..5f93856 100644 --- a/arch/powerpc/platforms/pseries/pci.c +++ b/arch/powerpc/platforms/pseries/pci.c @@ -108,3 +108,56 @@ static void fixup_winbond_82c105(struct pci_dev* dev) } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, fixup_winbond_82c105); + +int pseries_root_bridge_prepare(struct pci_host_bridge *bridge) +{ + struct device_node *dn, *pdn; + struct pci_bus *bus; + const uint32_t *pcie_link_speed_stats; + + bus = bridge->bus; + + dn = pcibios_get_phb_of_node(bus); + if (!dn) + return 0; + + for (pdn = dn; pdn != NULL; pdn = of_get_next_parent(pdn)) { + pcie_link_speed_stats = (const uint32_t *) of_get_property(pdn, + "ibm,pcie-link-speed-stats", NULL); + if (pcie_link_speed_stats) + break; + } + + of_node_put(pdn); + + if (!pcie_link_speed_stats) { + pr_err("no ibm,pcie-link-speed-stats property\n"); + return 0; + } + + switch (pcie_link_speed_stats[0]) { + case 0x01: + bus->max_bus_speed = PCIE_SPEED_2_5GT; + break; + case 0x02: + bus->max_bus_speed = PCIE_SPEED_5_0GT; + break; + default: + bus->max_bus_speed = PCI_SPEED_UNKNOWN; + break; + } + + switch (pcie_link_speed_stats[1]) { + case 0x01: + bus->cur_bus_speed = PCIE_SPEED_2_5GT; + break; + case 0x02: + bus->cur_bus_speed = PCIE_SPEED_5_0GT; + break; + default: + bus->cur_bus_speed = PCI_SPEED_UNKNOWN; + break; + } + + return 0; +} diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h index 8af71e4..c2a3a25 100644 --- a/arch/powerpc/platforms/pseries/pseries.h +++ b/arch/powerpc/platforms/pseries/pseries.h @@ -63,4 +63,8 @@ extern int dlpar_detach_node(struct device_node *); /* Snooze Delay, pseries_idle */ DECLARE_PER_CPU(long, smt_snooze_delay);
+/* PCI root bridge prepare function override for pseries */ +struct pci_host_bridge; +int pseries_root_bridge_prepare(struct pci_host_bridge *bridge); + #endif /* _PSERIES_PSERIES_H */ diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index ac932a9..c11c823 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -466,6 +466,8 @@ static void __init pSeries_setup_arch(void) else ppc_md.enable_pmcs = power4_enable_pmcs;
+ ppc_md.pcibios_root_bridge_prepare = pseries_root_bridge_prepare; + if (firmware_has_feature(FW_FEATURE_SET_MODE)) { long rc; if ((rc = pSeries_enable_reloc_on_exc()) != H_SUCCESS) {
radeon currently uses a drm function to get the speed capabilities for the bus, drm_pcie_get_speed_cap_mask. However, this is a non-standard method of performing this detection and this patch changes it to use the max_bus_speed attribute.
From: Lucas Kannebley Tavares lucaskt@linux.vnet.ibm.com Signed-off-by: Kleber Sacilotto de Souza klebers@linux.vnet.ibm.com --- drivers/gpu/drm/radeon/evergreen.c | 10 +++------- drivers/gpu/drm/radeon/r600.c | 9 ++------- drivers/gpu/drm/radeon/rv770.c | 9 ++------- 3 files changed, 7 insertions(+), 21 deletions(-)
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 105bafb..3966696 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -4992,8 +4992,7 @@ void evergreen_fini(struct radeon_device *rdev)
void evergreen_pcie_gen2_enable(struct radeon_device *rdev) { - u32 link_width_cntl, speed_cntl, mask; - int ret; + u32 link_width_cntl, speed_cntl;
if (radeon_pcie_gen2 == 0) return; @@ -5008,11 +5007,8 @@ void evergreen_pcie_gen2_enable(struct radeon_device *rdev) if (ASIC_IS_X2(rdev)) return;
- ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask); - if (ret != 0) - return; - - if (!(mask & DRM_PCIE_SPEED_50)) + if ((rdev->pdev->bus->max_bus_speed != PCIE_SPEED_5_0GT) && + (rdev->pdev->bus->max_bus_speed != PCIE_SPEED_8_0GT)) return;
speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL); diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 1a08008..b45e648 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -4631,8 +4631,6 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev) { u32 link_width_cntl, lanes, speed_cntl, training_cntl, tmp; u16 link_cntl2; - u32 mask; - int ret;
if (radeon_pcie_gen2 == 0) return; @@ -4651,11 +4649,8 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev) if (rdev->family <= CHIP_R600) return;
- ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask); - if (ret != 0) - return; - - if (!(mask & DRM_PCIE_SPEED_50)) + if ((rdev->pdev->bus->max_bus_speed != PCIE_SPEED_5_0GT) && + (rdev->pdev->bus->max_bus_speed != PCIE_SPEED_8_0GT)) return;
speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL); diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 83f612a..a6af4aa 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -2113,8 +2113,6 @@ static void rv770_pcie_gen2_enable(struct radeon_device *rdev) { u32 link_width_cntl, lanes, speed_cntl, tmp; u16 link_cntl2; - u32 mask; - int ret;
if (radeon_pcie_gen2 == 0) return; @@ -2129,11 +2127,8 @@ static void rv770_pcie_gen2_enable(struct radeon_device *rdev) if (ASIC_IS_X2(rdev)) return;
- ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask); - if (ret != 0) - return; - - if (!(mask & DRM_PCIE_SPEED_50)) + if ((rdev->pdev->bus->max_bus_speed != PCIE_SPEED_5_0GT) && + (rdev->pdev->bus->max_bus_speed != PCIE_SPEED_8_0GT)) return;
DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n");
On Fri, 2013-05-03 at 19:43 -0300, Kleber Sacilotto de Souza wrote:
So I'm ok with the approach now and I might even put the powerpc patch in for 3.10 since arguably we are fixing a nasty bug (uninitialized max_bus_speed).
David, what's your feeling about the radeon change ? It would be nice if that could go in soon for various distro targets :-) On the other hand I'm not going to be pushy if you are not comfortable with it.
Cheers, Ben.
On Fri, May 3, 2013 at 7:01 PM, Benjamin Herrenschmidt benh@kernel.crashing.org wrote:
FWIW, the radeon change looks fine to me.
Alex
n Mon, May 6, 2013 at 10:32 AM, Alex Deucher alexdeucher@gmail.com wrote:
As said previously, looks fine to me too.
Cheers, Jerome
On 05/06/2013 11:32 AM, Alex Deucher wrote:
Hi David,
Are you planning to accept the radeon patch? If yes, can we still expect it to make it for 3.10?
As Ben mentioned, we have some distro targets to make and it would be nice to have an outlook of the upstream acceptance to start the conversations with those distros.
Thanks!
On Wed, May 15, 2013 at 8:35 AM, Kleber Sacilotto de Souza klebers@linux.vnet.ibm.com wrote:
Is the rest of this series already upstream? I don't see a problem pulling it in if the rest of the patches are in Dave's tree. Dave, do you want to grab this, or do you wan me to pull it in through my tree?
Alex
dri-devel@lists.freedesktop.org