[Nouveau] [PATCH v2 6/9] pci: implement PCIe speed change for kepler+
Ben Skeggs
skeggsb at gmail.com
Tue Oct 13 15:59:05 PDT 2015
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
On 10/13/2015 07:44 PM, Karol Herbst wrote:
> v2: rename functions
>
> Signed-off-by: Karol Herbst <nouveau at karolherbst.de> ---
> drm/nouveau/nvkm/subdev/pci/gk104.c | 196
> ++++++++++++++++++++++++++++++++++++ 1 file changed, 196
> insertions(+)
>
> diff --git a/drm/nouveau/nvkm/subdev/pci/gk104.c
> b/drm/nouveau/nvkm/subdev/pci/gk104.c index 458dd31..99b131c
> 100644 --- a/drm/nouveau/nvkm/subdev/pci/gk104.c +++
> b/drm/nouveau/nvkm/subdev/pci/gk104.c @@ -23,6 +23,197 @@ */
> #include "priv.h"
>
> +static u32 +gk104_pci2_rd32(struct nvkm_pci *pci, u16 addr) +{ +
> struct nvkm_device *device = pci->subdev.device; + return
> nvkm_rd32(device, 0x08c000 + addr); +} + +static void
> +gk104_pci2_mask(struct nvkm_pci *pci, u16 addr, u32 mask, u32
> value) +{ + struct nvkm_device *device = pci->subdev.device; +
> nvkm_mask(device, 0x08c000 + addr, mask, value); +} +
Maybe skip these accessors and use nvkm_rd32/nvkm_mask directly, the
code is very specific to this chipset, and we don't need to abstract
away the mmio aperture difference like we do in some of the other code.
I don't have strong opinions on this one though.
> +static int +gk104_pcie_version_supported(struct nvkm_pci *pci) +{
> + return (gk104_pci2_rd32(pci, 0x1c0) & 0x4) == 0x4 ? 2 : 1; +} +
> +static void +gk104_pcie_set_cap_speed(struct nvkm_pci *pci, enum
> nvkm_pcie_speed speed) +{ + switch (speed) { + case
> NVKM_PCIE_SPEED_2_5: + gf100_pcie_set_cap_speed(pci, false); +
> gk104_pci2_mask(pci, 0x1c0, 0x30000, 0x10000); + break; + case
> NVKM_PCIE_SPEED_5_0: + gf100_pcie_set_cap_speed(pci, true); +
> gk104_pci2_mask(pci, 0x1c0, 0x30000, 0x20000); + break; + case
> NVKM_PCIE_SPEED_8_0: + gf100_pcie_set_cap_speed(pci, true); +
> gk104_pci2_mask(pci, 0x1c0, 0x30000, 0x30000); + break; + } +} +
> +static enum nvkm_pcie_speed +gk104_pcie_cap_speed(struct nvkm_pci
> *pci) +{ + int speed = gf100_pcie_cap_speed(pci); + if (speed < 0)
> + return speed; + + if (speed == 0) + return
> NVKM_PCIE_SPEED_2_5; + + if (speed >= 1) { + int speed2 =
> gk104_pci2_rd32(pci, 0x1c0) & 0x30000; + switch (speed2) { + case
> 0x00000: + case 0x10000: + return NVKM_PCIE_SPEED_2_5; + case
> 0x20000: + return NVKM_PCIE_SPEED_5_0; + case 0x30000: +
> return NVKM_PCIE_SPEED_8_0; + } + } + return -EINVAL; +} + +static
> void +gk104_pcie_set_lnkctl_speed(struct nvkm_pci *pci, enum
> nvkm_pcie_speed speed) +{ + u8 reg_v = 0; + switch (speed) { + case
> NVKM_PCIE_SPEED_2_5: + reg_v = 1; + break; + case
> NVKM_PCIE_SPEED_5_0: + reg_v = 2; + break; + case
> NVKM_PCIE_SPEED_8_0: + reg_v = 3; + break; + } +
> nvkm_pci_mask(pci, 0xa8, 0x3, reg_v); +} + +static enum
> nvkm_pcie_speed +gk104_pcie_lnkctl_speed(struct nvkm_pci *pci) +{ +
> u8 reg_v = nvkm_pci_rd32(pci, 0xa8) & 0x3; + switch (reg_v) { +
> case 0: + case 1: + return NVKM_PCIE_SPEED_2_5; + case 2: +
> return NVKM_PCIE_SPEED_5_0; + case 3: + return
> NVKM_PCIE_SPEED_8_0; + } + return -1; +} + +static enum
> nvkm_pcie_speed +gk104_pcie_max_speed(struct nvkm_pci *pci) +{ +
> u32 max_speed = gk104_pci2_rd32(pci, 0x1c0) & 0x300000; + switch
> (max_speed) { + case 0x000000: + return NVKM_PCIE_SPEED_8_0; +
> case 0x100000: + return NVKM_PCIE_SPEED_5_0; + case 0x200000: +
> return NVKM_PCIE_SPEED_2_5; + } + return NVKM_PCIE_SPEED_2_5; +} +
> +static void +gk104_pcie_set_link_speed(struct nvkm_pci *pci, enum
> nvkm_pcie_speed speed) +{ + u32 mask_value; + switch (speed) { +
> default: + case NVKM_PCIE_SPEED_2_5: + mask_value = 0x80000; +
> break; + case NVKM_PCIE_SPEED_5_0: + mask_value = 0x40000; +
> break; + case NVKM_PCIE_SPEED_8_0: + mask_value = 0x00000; +
> break; + } + gk104_pci2_mask(pci, 0x40, 0xc0000, mask_value); +
> gk104_pci2_mask(pci, 0x40, 0x1, 0x1); +} + +static int
> +gk104_pcie_init(struct nvkm_pci * pci) +{ + if
> (!pci_is_pcie(pci->pdev)) + return -ENODEV; + + if
> (gf100_pcie_version(pci) > 1) { + enum nvkm_pcie_speed +
> lnkctl_speed = gk104_pcie_lnkctl_speed(pci), + max_speed =
> gk104_pcie_max_speed(pci), + cap_speed =
> gk104_pcie_cap_speed(pci); + + if (cap_speed != max_speed) { +
> nvkm_debug(&pci->subdev, "adjusting cap speed to max speed\n"); +
> gk104_pcie_set_cap_speed(pci, max_speed); + cap_speed =
> gk104_pcie_cap_speed(pci); + if (cap_speed != max_speed) +
> nvkm_error(&pci->subdev, "couldn't adjust cap speed\n"); + } + +
> if (lnkctl_speed != max_speed) { + nvkm_debug(&pci->subdev, +
> "adjusting link control speed to max speed\n"); +
> gk104_pcie_set_lnkctl_speed(pci, max_speed); + lnkctl_speed =
> gk104_pcie_lnkctl_speed(pci); + if (lnkctl_speed != max_speed) +
> nvkm_error(&pci->subdev, + "couldn't adjust link control
> speed\n"); + } + } + return 0; +} + +static int
> +gk104_pcie_set_link(struct nvkm_pci *pci, enum nvkm_pcie_speed
> req_speed, + u8 req_width) +{ + enum nvkm_pcie_speed +
> lnk_ctl_speed = gk104_pcie_lnkctl_speed(pci), + lnk_cap_speed =
> gk104_pcie_cap_speed(pci); + + if (req_speed > lnk_cap_speed) { +
> req_speed = lnk_cap_speed; + nvkm_warn(&pci->subdev, "dropping
> requested PCIe speed due to low" + " cap speed\n"); + } + + if
> (req_speed > lnk_ctl_speed) { + req_speed = lnk_ctl_speed; +
> nvkm_warn(&pci->subdev, "dropping requested PCIe speed due to low"
> + " control speed\n"); + } + + gk104_pcie_set_link_speed(pci,
> req_speed); + return 0; +} + + static const struct nvkm_pci_func
> gk104_pci_func = { .rd32 = nv40_pci_rd32, @@ -30,10 +221,15 @@
> gk104_pci_func = { .wr32 = nv40_pci_wr32, .msi_rearm =
> nv40_pci_msi_rearm,
>
> + .pcie.init = gk104_pcie_init, + .pcie.set_link =
> gk104_pcie_set_link, + + .pcie.max_speed = gk104_pcie_max_speed,
> .pcie.cur_speed = g84_pcie_cur_speed,
>
> .pcie.set_version = gf100_pcie_set_version, .pcie.version =
> gf100_pcie_version, + .pcie.version_supported =
> gk104_pcie_version_supported, };
>
> int
>
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2
iQIcBAEBCAAGBQJWHYy5AAoJEHYLnGJQkpH7dTEQAKk+oKbt8nZlrrHEAOjarH6w
sLktjZeqLUUUSyK7KXNrpPgzZtvxmuBqPHTcCyjtJ2l/02d1XPT7d6xaRRxPeoXY
RMeqZoUz2t1yJHHuct6KTncTyYuItfO99G2nDbW5lUR6cW9bMBUnrL/FNbfZ+6VN
AJlFim6wiZ8dKsJalNPBS353dChRabSs6XNXlW1U7tOv52aTHRKt5S/PvEVmdyFW
BMMkYuB/8y47TeqjHZo4l3ZfnhPZ0jaJY76CWLOgSkhAx65bMFcu7px5EM0S2gmG
e4ptteJFq5psaeSiLr3kDa3ry4mDRHpwl/yMa4Ej1neTOt1DOl82GqClD/6QwlOw
QOiE41iPgJJYSPDahhmVnUmGEhuSODBtCOX4pMRo1wtjaPgAeP0hUh+sOZJEag/D
LMjnH5MFCtUcmcUSAUQjMlAZrtZw+Fo3eQglzBFd84Zl9JwdK8dNhKtpe8qWUsaB
Hf0bQhXn/5kZLXkhun+Rjucmi7cH6pTu4fDHSe/cHpzPgf06N8pqFQv+D+HzYRYL
7l+MC/gmzBODTx+hpdC75ETwFWBEQug2wuerpCV+nh4KPMbuLVzsBcF8H8xFwa6d
XDCdEQgk9f7KUT8Q2G3oaRBT6jWv8e7bntzu4kGe35aYBxi6pT6EnsbSFesZjxce
q0HaM0kT14JkA/C+NdHZ
=atdH
-----END PGP SIGNATURE-----
More information about the Nouveau
mailing list