0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #include "priv.h"
0025
0026 static char *nvkm_pcie_speeds[] = {
0027 "2.5GT/s",
0028 "5.0GT/s",
0029 "8.0GT/s",
0030 };
0031
0032 static enum nvkm_pcie_speed
0033 nvkm_pcie_speed(enum pci_bus_speed speed)
0034 {
0035 switch (speed) {
0036 case PCIE_SPEED_2_5GT:
0037 return NVKM_PCIE_SPEED_2_5;
0038 case PCIE_SPEED_5_0GT:
0039 return NVKM_PCIE_SPEED_5_0;
0040 case PCIE_SPEED_8_0GT:
0041 return NVKM_PCIE_SPEED_8_0;
0042 default:
0043
0044 if (speed == 0x17)
0045 return NVKM_PCIE_SPEED_8_0;
0046 return -1;
0047 }
0048 }
0049
0050 static int
0051 nvkm_pcie_get_version(struct nvkm_pci *pci)
0052 {
0053 if (!pci->func->pcie.version)
0054 return -ENOSYS;
0055
0056 return pci->func->pcie.version(pci);
0057 }
0058
0059 static int
0060 nvkm_pcie_get_max_version(struct nvkm_pci *pci)
0061 {
0062 if (!pci->func->pcie.version_supported)
0063 return -ENOSYS;
0064
0065 return pci->func->pcie.version_supported(pci);
0066 }
0067
0068 static int
0069 nvkm_pcie_set_version(struct nvkm_pci *pci, int version)
0070 {
0071 if (!pci->func->pcie.set_version)
0072 return -ENOSYS;
0073
0074 nvkm_trace(&pci->subdev, "set to version %i\n", version);
0075 pci->func->pcie.set_version(pci, version);
0076 return nvkm_pcie_get_version(pci);
0077 }
0078
0079 int
0080 nvkm_pcie_oneinit(struct nvkm_pci *pci)
0081 {
0082 if (pci->func->pcie.max_speed)
0083 nvkm_debug(&pci->subdev, "pcie max speed: %s\n",
0084 nvkm_pcie_speeds[pci->func->pcie.max_speed(pci)]);
0085 return 0;
0086 }
0087
0088 int
0089 nvkm_pcie_init(struct nvkm_pci *pci)
0090 {
0091 struct nvkm_subdev *subdev = &pci->subdev;
0092 int ret;
0093
0094
0095 ret = nvkm_pcie_get_version(pci);
0096 if (ret > 0) {
0097 int max_version = nvkm_pcie_get_max_version(pci);
0098 if (max_version > 0 && max_version > ret)
0099 ret = nvkm_pcie_set_version(pci, max_version);
0100
0101 if (ret < max_version)
0102 nvkm_error(subdev, "couldn't raise version: %i\n", ret);
0103 }
0104
0105 if (pci->func->pcie.init)
0106 pci->func->pcie.init(pci);
0107
0108 if (pci->pcie.speed != -1)
0109 nvkm_pcie_set_link(pci, pci->pcie.speed, pci->pcie.width);
0110
0111 return 0;
0112 }
0113
0114 int
0115 nvkm_pcie_set_link(struct nvkm_pci *pci, enum nvkm_pcie_speed speed, u8 width)
0116 {
0117 struct nvkm_subdev *subdev = &pci->subdev;
0118 enum nvkm_pcie_speed cur_speed, max_speed;
0119 struct pci_bus *pbus;
0120 int ret;
0121
0122 if (!pci || !pci_is_pcie(pci->pdev))
0123 return 0;
0124 pbus = pci->pdev->bus;
0125
0126 if (!pci->func->pcie.set_link)
0127 return -ENOSYS;
0128
0129 nvkm_trace(subdev, "requested %s\n", nvkm_pcie_speeds[speed]);
0130
0131 if (pci->func->pcie.version(pci) < 2) {
0132 nvkm_error(subdev, "setting link failed due to low version\n");
0133 return -ENODEV;
0134 }
0135
0136 cur_speed = pci->func->pcie.cur_speed(pci);
0137 max_speed = min(nvkm_pcie_speed(pbus->max_bus_speed),
0138 pci->func->pcie.max_speed(pci));
0139
0140 nvkm_trace(subdev, "current speed: %s\n", nvkm_pcie_speeds[cur_speed]);
0141
0142 if (speed > max_speed) {
0143 nvkm_debug(subdev, "%s not supported by bus or card, dropping"
0144 "requested speed to %s", nvkm_pcie_speeds[speed],
0145 nvkm_pcie_speeds[max_speed]);
0146 speed = max_speed;
0147 }
0148
0149 pci->pcie.speed = speed;
0150 pci->pcie.width = width;
0151
0152 if (speed == cur_speed) {
0153 nvkm_debug(subdev, "requested matches current speed\n");
0154 return speed;
0155 }
0156
0157 nvkm_debug(subdev, "set link to %s x%i\n",
0158 nvkm_pcie_speeds[speed], width);
0159
0160 ret = pci->func->pcie.set_link(pci, speed, width);
0161 if (ret < 0)
0162 nvkm_error(subdev, "setting link failed: %i\n", ret);
0163
0164 return ret;
0165 }