Cela se fait au niveau électrique, pas par logiciel. Les deux registres que vous avez énumérés ci-dessus, LNK_CAP et LNK_STA sont ce que vous avez correctement noté comme «Voici ce dont le lien est capable» et «Voici l'état actuel». Il existe également SLT_CAP et SLT_STA, qui peuvent valoir le coup d'œil car elles sont spécifiques à un «emplacement» donné dans la machine.
La spécification PCIe définit une machine d'état LTSSM - Link Training and Status. Au niveau PHY / appareil, c'est ce qui détermine la vitesse maximale prise en charge par les deux appareils, la largeur de liaison maximale prise en charge par les deux appareils, et c'est également là que l'inversion de polarité / l'inversion de voie est gérée (pour nous faciliter la disposition, la spécification permet P / N à échanger, etc.).
Les appareils s'envoient des ensembles de symboles connus et ordonnés et le matériel monte de 2,5 GT / s. Il existe des commandes de changement de vitesse qui peuvent être envoyées les unes aux autres, et c'est ici que les paramètres d'égalisation des canaux sont également définis.
Si vous vous connectez à la mauvaise vitesse, il est possible que le port racine PCIe soit mal configuré ou qu'il y ait un problème d'intégrité du signal forçant une largeur de liaison inférieure. D'après mon expérience, si vous vous connectiez à 5 GT / s au lieu de 8 GT / s, c'est plus un problème SI - la liaison à x4 8 GT / s au lieu de x8 8 GT / s semble être un problème de configuration, ou peut-être en ajoutant une carte à un emplacement qui ne prend pas en charge la largeur x8.
Le registre des capacités complexes racine (décalage 04h) révèlera la largeur maximale prise en charge, ce qui pourrait vous aider dans vos diagnostics. IIRC, -x videra le premier 4K d'espace de configuration, -xx ou -xxx videra l'espace de configuration étendu PCIe. Si vous videz l'intégralité de votre espace de configuration ici / coller, je peux le fouiller pour vous, mais Linux fait un travail décent de décodage de ce que font les registres.