root/drivers/gpu/drm/nouveau/nvkm/subdev/pci/pcie.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nvkm_pcie_speed
  2. nvkm_pcie_get_version
  3. nvkm_pcie_get_max_version
  4. nvkm_pcie_set_version
  5. nvkm_pcie_oneinit
  6. nvkm_pcie_init
  7. nvkm_pcie_set_link

   1 /*
   2  * Copyright 2015 Karol Herbst <nouveau@karolherbst.de>
   3  *
   4  * Permission is hereby granted, free of charge, to any person obtaining a
   5  * copy of this software and associated documentation files (the "Software"),
   6  * to deal in the Software without restriction, including without limitation
   7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8  * and/or sell copies of the Software, and to permit persons to whom the
   9  * Software is furnished to do so, subject to the following conditions:
  10  *
  11  * The above copyright notice and this permission notice shall be included in
  12  * all copies or substantial portions of the Software.
  13  *
  14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20  * OTHER DEALINGS IN THE SOFTWARE.
  21  *
  22  * Authors: Karol Herbst <git@karolherbst.de>
  23  */
  24 #include "priv.h"
  25 
  26 static char *nvkm_pcie_speeds[] = {
  27         "2.5GT/s",
  28         "5.0GT/s",
  29         "8.0GT/s",
  30 };
  31 
  32 static enum nvkm_pcie_speed
  33 nvkm_pcie_speed(enum pci_bus_speed speed)
  34 {
  35         switch (speed) {
  36         case PCIE_SPEED_2_5GT:
  37                 return NVKM_PCIE_SPEED_2_5;
  38         case PCIE_SPEED_5_0GT:
  39                 return NVKM_PCIE_SPEED_5_0;
  40         case PCIE_SPEED_8_0GT:
  41                 return NVKM_PCIE_SPEED_8_0;
  42         default:
  43                 /* XXX 0x16 is 8_0, assume 0x17 will be 16_0 for now */
  44                 if (speed == 0x17)
  45                         return NVKM_PCIE_SPEED_8_0;
  46                 return -1;
  47         }
  48 }
  49 
  50 static int
  51 nvkm_pcie_get_version(struct nvkm_pci *pci)
  52 {
  53         if (!pci->func->pcie.version)
  54                 return -ENOSYS;
  55 
  56         return pci->func->pcie.version(pci);
  57 }
  58 
  59 static int
  60 nvkm_pcie_get_max_version(struct nvkm_pci *pci)
  61 {
  62         if (!pci->func->pcie.version_supported)
  63                 return -ENOSYS;
  64 
  65         return pci->func->pcie.version_supported(pci);
  66 }
  67 
  68 static int
  69 nvkm_pcie_set_version(struct nvkm_pci *pci, int version)
  70 {
  71         if (!pci->func->pcie.set_version)
  72                 return -ENOSYS;
  73 
  74         nvkm_trace(&pci->subdev, "set to version %i\n", version);
  75         pci->func->pcie.set_version(pci, version);
  76         return nvkm_pcie_get_version(pci);
  77 }
  78 
  79 int
  80 nvkm_pcie_oneinit(struct nvkm_pci *pci)
  81 {
  82         if (pci->func->pcie.max_speed)
  83                 nvkm_debug(&pci->subdev, "pcie max speed: %s\n",
  84                            nvkm_pcie_speeds[pci->func->pcie.max_speed(pci)]);
  85         return 0;
  86 }
  87 
  88 int
  89 nvkm_pcie_init(struct nvkm_pci *pci)
  90 {
  91         struct nvkm_subdev *subdev = &pci->subdev;
  92         int ret;
  93 
  94         /* raise pcie version first */
  95         ret = nvkm_pcie_get_version(pci);
  96         if (ret > 0) {
  97                 int max_version = nvkm_pcie_get_max_version(pci);
  98                 if (max_version > 0 && max_version > ret)
  99                         ret = nvkm_pcie_set_version(pci, max_version);
 100 
 101                 if (ret < max_version)
 102                         nvkm_error(subdev, "couldn't raise version: %i\n", ret);
 103         }
 104 
 105         if (pci->func->pcie.init)
 106                 pci->func->pcie.init(pci);
 107 
 108         if (pci->pcie.speed != -1)
 109                 nvkm_pcie_set_link(pci, pci->pcie.speed, pci->pcie.width);
 110 
 111         return 0;
 112 }
 113 
 114 int
 115 nvkm_pcie_set_link(struct nvkm_pci *pci, enum nvkm_pcie_speed speed, u8 width)
 116 {
 117         struct nvkm_subdev *subdev = &pci->subdev;
 118         enum nvkm_pcie_speed cur_speed, max_speed;
 119         struct pci_bus *pbus;
 120         int ret;
 121 
 122         if (!pci || !pci_is_pcie(pci->pdev))
 123                 return 0;
 124         pbus = pci->pdev->bus;
 125 
 126         if (!pci->func->pcie.set_link)
 127                 return -ENOSYS;
 128 
 129         nvkm_trace(subdev, "requested %s\n", nvkm_pcie_speeds[speed]);
 130 
 131         if (pci->func->pcie.version(pci) < 2) {
 132                 nvkm_error(subdev, "setting link failed due to low version\n");
 133                 return -ENODEV;
 134         }
 135 
 136         cur_speed = pci->func->pcie.cur_speed(pci);
 137         max_speed = min(nvkm_pcie_speed(pbus->max_bus_speed),
 138                         pci->func->pcie.max_speed(pci));
 139 
 140         nvkm_trace(subdev, "current speed: %s\n", nvkm_pcie_speeds[cur_speed]);
 141 
 142         if (speed > max_speed) {
 143                 nvkm_debug(subdev, "%s not supported by bus or card, dropping"
 144                            "requested speed to %s", nvkm_pcie_speeds[speed],
 145                            nvkm_pcie_speeds[max_speed]);
 146                 speed = max_speed;
 147         }
 148 
 149         pci->pcie.speed = speed;
 150         pci->pcie.width = width;
 151 
 152         if (speed == cur_speed) {
 153                 nvkm_debug(subdev, "requested matches current speed\n");
 154                 return speed;
 155         }
 156 
 157         nvkm_debug(subdev, "set link to %s x%i\n",
 158                    nvkm_pcie_speeds[speed], width);
 159 
 160         ret = pci->func->pcie.set_link(pci, speed, width);
 161         if (ret < 0)
 162                 nvkm_error(subdev, "setting link failed: %i\n", ret);
 163 
 164         return ret;
 165 }

/* [<][>][^][v][top][bottom][index][help] */