Déconnexions USB en passthrough sur Proxmox : alimentation, autosuspend et correctifs de stabilité

Cet article vous a aidé ?

Le passthrough USB sur Proxmox fonctionne très bien jusqu’au moment où il cesse de fonctionner. Une minute votre coordinateur Zigbee ronronne, votre UPS rapporte correctement, ou votre SSD externe sert les sauvegardes. La minute suivante : le périphérique disparaît, les logs VM se remplissent de reconnections répétées, et vos automatismes commencent à faire n’importe quoi.

Cela n’est généralement pas « un bug de Proxmox ». C’est l’alimentation, la gestion d’énergie à l’exécution, les resets du contrôleur, des hubs instables, ou un petit désalignement entre la façon dont vous avez passé le périphérique et ce que Linux attend sous charge. La bonne nouvelle : vous pouvez rendre l’USB ennuyeux à nouveau. La meilleure nouvelle : vous pouvez prouver quelle couche échoue avant de changer quoi que ce soit.

Mode de diagnostic rapide

Quand le passthrough USB lâche en production, vous n’avez pas le loisir de danser autour du problème. Vous avez besoin d’une séquence serrée qui sépare : panne du périphérique, problèmes d’alimentation, gestion d’énergie du noyau, comportement de reset du contrôleur, et plomberie de virtualisation.

Première étape : déterminer où se produit la déconnexion

  • Seulement l’hôte ? Les logs du noyau hôte montrent des déconnexions et une ré-énumération. La VM/conteneur voit juste « périphérique disparu ». Réparez d’abord l’alimentation/PM/contrôleur côté hôte.
  • Seulement l’invité ? L’hôte voit l’USB stable, mais le pilote invité reset. Concentrez-vous sur le noyau invité, le choix d’émulation USB QEMU, et la façon dont vous avez passé le périphérique.
  • Physique uniquement ? LED du périphérique clignote/réinitialise, clics du hub, ou d’autres périphériques sur le même hub tombent aussi. Réparez l’alimentation, le câble, le hub ou le port.

Deuxième étape : capturer les preuves pendant que ça se passe

  • Exécutez dmesg -Tw sur l’hôte Proxmox pendant une chute.
  • Vérifiez les logs de l’invité au même horodatage.
  • Corrélez si le bus reset (usb X-Y: reset) ou si le périphérique se déconnecte (disconnect).

Troisième étape : classifier le mode de défaillance

  • Sous-tension / brownout : déconnexions sous charge ; le hub ou le port montre des événements d’alimentation ; plusieurs périphériques peuvent tomber ensemble.
  • Autosuspend : chute après une période d’inactivité ; intervalle récurrent ; se réveille au trafic puis oscille.
  • Quirks de reset xHCI : « xHCI host controller not responding » ou fréquents « reset SuperSpeed Gen 1 USB device ».
  • Mauvaise approche de passthrough : le passthrough du périphérique vers QEMU fonctionne jusqu’à ce que le périphérique se ré-énumère avec un chemin différent ; il faut passer par bus/port ou contrôleur.

Quatrième étape : appliquer le plus petit correctif efficace

  • Changez le câble/port/hub et assurez-vous d’un hub alimenté si besoin.
  • Désactivez l’autosuspend pour ce périphérique (pas globalement, sauf en dernier recours).
  • Si c’est un problème chronique de reset xHCI : passez tout le contrôleur USB via PCIe (IOMMU), ou appliquez des quirks noyau conservateurs.

Comment le passthrough USB échoue réellement (et pourquoi ce n’est pas aléatoire)

L’USB est trompeusement simple au niveau humain : branchez, ça marche. Sous le capot c’est une négociation entre périphérique, hub, contrôleur hôte, pilotes noyau et politiques d’alimentation. Ajoutez la virtualisation et vous avez maintenant deux noyaux et un hyperviseur impliqués dans cette négociation.

La plupart des déconnexions USB « aléatoires » suivent quelques schémas prévisibles :

  • Instabilité d’énumération : le périphérique se déconnecte et revient avec une nouvelle adresse. Si votre passthrough était lié à un identifiant fragile, l’invité le perd.
  • Gestion d’énergie à l’exécution : Linux essaie d’économiser de l’énergie en suspendant le périphérique. Certains périphériques interprètent cela comme « temps de paniquer ».
  • Intégrité du signal : câbles marginaux, rallonges non blindées et hubs surchargés créent des erreurs CRC et des resets, surtout aux débits USB 3.x.
  • Comportement de reset du contrôleur : les contrôleurs xHCI peuvent entrer en tempête de reset dans certaines conditions, et la logique de récupération du noyau n’est pas toujours bienveillante pour les sessions long-running.
  • Temporisation et buffering virtualisés : les pilotes invités se comportent parfois différemment lorsque le transport USB est émulé ou médiatisé par QEMU au lieu d’être natif.

Il y a aussi une vérité dure : beaucoup de dongles populaires (sticks Zigbee, Z-Wave, RTL-SDR) ont été conçus pour des PC de loisir, pas pour des serveurs toujours allumés derrière un hub bruyant sur une étagère de rack. Vous pouvez néanmoins les rendre fiables. Il faut juste les traiter comme des dépendances de production, pas comme des accessoires mignons.

Idée paraphrasée de Werner Vogels (CTO d’Amazon) : on construit la fiabilité en supposant que les choses vont échouer et en concevant pour que ces échecs ne deviennent pas des incidents.

Une blague, puisque nous allons lire des logs un moment : USB signifie « Unexpected Sudden Bye-bye ». Ce n’est pas officiel, mais ça colle aux tickets.

Faits intéressants et contexte historique (utile, pas du trivia)

  1. Autosuspend USB existe dans Linux depuis des années, et il est devenu plus agressif à mesure que les ordinateurs portables ont imposé des valeurs par défaut pour économiser l’énergie. Les serveurs héritent de ces valeurs par défaut sauf si vous les surchargez.
  2. xHCI a remplacé EHCI/OHCI/UHCI avec l’arrivée de l’USB 3.x, consolidant la complexité dans un seul modèle de contrôleur. Super pour les fonctionnalités ; parfois épicé pour la stabilité.
  3. Les adresses des périphériques USB ne sont pas des identifiants stables. Elles sont attribuées lors de l’énumération et peuvent changer après un reset. Si votre configuration se base sur une adresse changeante, elle échouera tôt ou tard.
  4. Certains ports « USB 3 » partagent des hubs internes sur les cartes mères, ce qui signifie que deux ports physiques peuvent être un seul hub logique. Un reset peut emporter les deux.
  5. Le passthrough USB pour VM a commencé historiquement par des contrôleurs émulés (UHCI/OHCI/EHCI dans QEMU). Les configurations modernes préfèrent le passthrough de périphérique hôte ou le passthrough de contrôleur entier pour la fiabilité.
  6. USB selective suspend sous Windows et autosuspend sous Linux résolvent des problèmes similaires avec des réglages différents. Beaucoup de périphériques sont testés contre les valeurs par défaut Windows et pas contre des charges de serveur Linux.
  7. USB 3.x utilise des paires SuperSpeed supplémentaires en plus des fils USB 2.0. Un câble qui « marche bien » en USB 2.0 peut échouer de façon spectaculaire en USB 3.x.
  8. Le passthrough PCIe d’un contrôleur USB corrige souvent la flakiness en supprimant la couche d’émulation et en donnant au client le contrôle natif — au prix de la flexibilité.

Tâches pratiques : commandes, sorties et la décision que vous prenez

Ce sont des tâches réelles que vous pouvez exécuter sur un hôte Proxmox. Chaque tâche inclut : commande, ce que vous regardez, et quelle décision prendre ensuite. Exécutez-les en fonctionnement normal et pendant une défaillance si possible.

Tâche 1 : Surveiller les événements noyau de l’hôte en direct

cr0x@server:~$ sudo dmesg -Tw
[Thu Dec 26 11:18:02 2025] usb 2-2: USB disconnect, device number 7
[Thu Dec 26 11:18:03 2025] usb 2-2: new full-speed USB device number 8 using xhci_hcd
[Thu Dec 26 11:18:03 2025] usb 2-2: New USB device found, idVendor=10c4, idProduct=ea60, bcdDevice= 1.00
[Thu Dec 26 11:18:03 2025] usb 2-2: Product: CP2102N USB to UART Bridge Controller

Ce que ça signifie : L’hôte a perdu le périphérique et l’a ré-énumé. Ce n’est pas « seulement l’invité ».

Décision : Concentrez-vous sur la gestion d’alimentation/PM/câblage/contrôleur côté hôte. Les réglages de l’invité seuls ne résoudront pas des déconnexions physiques.

Tâche 2 : Confirmer ce que Proxmox pense être attaché (VID:PID et chemin)

cr0x@server:~$ lsusb
Bus 002 Device 008: ID 10c4:ea60 Silicon Labs CP210x UART Bridge
Bus 002 Device 002: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 002: ID 1d6b:0002 Linux Foundation 2.0 root hub

Ce que ça signifie : Vous avez un device CP210x sur le Bus 002. Le numéro de périphérique peut changer. Le vendor/product est stable.

Décision : Privilégiez le passthrough par vendor/product et port physique (chemin bus/port) plutôt que par numéro de périphérique.

Tâche 3 : Obtenir une topologie physique stable (trouver la chaîne de ports)

cr0x@server:~$ lsusb -t
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/8p, 5000M
    |__ Port 2: Dev 8, If 0, Class=Vendor Specific Class, Driver=cp210x, 12M
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/14p, 480M

Ce que ça signifie : Le périphérique est sur Bus 02, Port 2 du root hub. Cette relation physique est l’ancre que vous souhaitez.

Décision : Si vous pouvez le garder sur le même port/chaîne de hub, vous pouvez écrire des règles udev déterministes et des configs Proxmox fiables.

Tâche 4 : Inspecter l’état de contrôle d’alimentation USB pour le périphérique

cr0x@server:~$ DEVPATH=$(udevadm info -q path -n /dev/ttyUSB0); echo "$DEVPATH"
/devices/pci0000:00/0000:00:14.0/usb2/2-2/2-2:1.0
cr0x@server:~$ cat /sys$DEVPATH/power/control
auto

Ce que ça signifie : Le runtime PM est activé (auto). Le noyau peut autosuspendre cette interface.

Décision : Si vous observez des déconnexions après des périodes d’inactivité, mettez ceci sur on via une règle udev (spécifique au périphérique) ou désactivez l’autosuspend.

Tâche 5 : Vérifier le délai d’autosuspend pour l’interface

cr0x@server:~$ cat /sys$DEVPATH/power/autosuspend_delay_ms
2000

Ce que ça signifie : Le système est prêt à autosuspendre après 2 secondes d’inactivité. Beaucoup de dongles détestent ça.

Décision : Pour les adaptateurs série, coordinators, HID d’UPS et SDR : désactivez l’autosuspend pour ce périphérique.

Tâche 6 : Vérifier le contrôleur USB et son pilote (xHCI, etc.)

cr0x@server:~$ lspci -nnk | grep -A3 -i usb
00:14.0 USB controller [0c03]: Intel Corporation Device [8086:a36d] (rev 10)
	Subsystem: Intel Corporation Device [8086:7270]
	Kernel driver in use: xhci_hcd
	Kernel modules: xhci_pci

Ce que ça signifie : Votre contrôleur USB est un xHCI Intel sur 00:14.0.

Décision : Si vous choisissez plus tard le passthrough PCI d’un contrôleur, c’est le périphérique que vous isoleriez et passeriez (si son groupe IOMMU est sane).

Tâche 7 : Vérifier l’activation IOMMU (nécessaire pour le passthrough PCIe)

cr0x@server:~$ dmesg | grep -E "DMAR|IOMMU" | head
[    0.812345] DMAR: IOMMU enabled
[    0.812678] DMAR: Host address width 39
[    0.813210] DMAR: DRHD base: 0x000000fed91000 flags: 0x0

Ce que ça signifie : VT-d/IOMMU est activé et le noyau le voit.

Décision : Vous pouvez envisager de passer tout un contrôleur USB si son groupe IOMMU est isolable.

Tâche 8 : Déterminer le groupe IOMMU du contrôleur USB

cr0x@server:~$ for d in /sys/kernel/iommu_groups/*/devices/*; do
  if [[ "$d" == *"0000:00:14.0"* ]]; then echo "USB controller is in: ${d%/*}"; fi
done
USB controller is in: /sys/kernel/iommu_groups/5/devices

Ce que ça signifie : Le contrôleur est dans le groupe 5. Confirmez que le groupe 5 n’inclut pas des périphériques que vous ne pouvez pas céder à une VM (comme SATA ou NIC).

Décision : Si le groupe inclut des périphériques critiques, ne passez pas ce contrôleur ; utilisez plutôt une carte USB PCIe séparée.

Tâche 9 : Lister tout dans le même groupe IOMMU

cr0x@server:~$ ls -1 /sys/kernel/iommu_groups/5/devices
0000:00:14.0
0000:00:14.2

Ce que ça signifie : Il y a un autre périphérique (00:14.2) dans le groupe. Identifiez-le avant tout passthrough.

Décision : Si c’est quelque chose comme Intel PCH thermal ou MEI, vous pouvez encore décider ; si c’est stockage/NIC, arrêtez.

Tâche 10 : Inspecter la config VM Proxmox pour un mapping USB fragile

cr0x@server:~$ sudo cat /etc/pve/qemu-server/101.conf
agent: 1
boot: order=scsi0;net0
cores: 4
memory: 4096
net0: virtio=DE:AD:BE:EF:00:01,bridge=vmbr0
scsi0: local-lvm:vm-101-disk-0,iothread=1,size=32G
usb0: host=10c4:ea60

Ce que ça signifie : Cette VM passe par VID:PID, ce qui est généralement bien. Mais si vous avez plusieurs dongles identiques, elle peut quand même choisir le mauvais.

Décision : Si vous avez plusieurs périphériques correspondants, passez-les par bus/port (ou utilisez udev pour créer des symlinks stables et liez par serial/chemin).

Tâche 11 : Confirmer si le périphérique expose un numéro de série que vous pouvez lier

cr0x@server:~$ sudo udevadm info -a -n /dev/ttyUSB0 | grep -E "serial|idVendor|idProduct" | head -n 10
    ATTRS{idVendor}=="10c4"
    ATTRS{idProduct}=="ea60"
    ATTRS{serial}=="01A2B3C4"

Ce que ça signifie : Parfait : un serial stable est exposé. C’est de l’or pour des règles et une affectation stable.

Décision : Écrivez des règles udev pour définir power/control et créer des symlinks stables basés sur le serial.

Tâche 12 : Vérifier si usbcore autosuspend est activé globalement via la ligne de commande du noyau

cr0x@server:~$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-6.8.12-4-pve root=/dev/mapper/pve-root ro quiet intel_iommu=on

Ce que ça signifie : Aucun réglage usbcore.autosuspend explicite. Les valeurs par défaut s’appliquent (souvent autosuspend activé).

Décision : Préférez des corrections spécifiques au périphérique, mais si vous déboguez, vous pouvez temporairement définir usbcore.autosuspend=-1 pour tester l’hypothèse.

Tâche 13 : Valider si le runtime PM suspend réellement le périphérique

cr0x@server:~$ cat /sys$DEVPATH/power/runtime_status
suspended

Ce que ça signifie : L’interface est suspendue en ce moment. Si votre service attend une présence constante, c’est un signal d’alerte.

Décision : Désactivez l’autosuspend pour le périphérique et observez si les déconnexions cessent.

Tâche 14 : Chercher des schémas « contrôleur xHCI non répondant »

cr0x@server:~$ journalctl -k -b | grep -i -E "xhci|host controller|not responding|reset" | tail -n 12
Dec 26 10:55:14 server kernel: xhci_hcd 0000:00:14.0: xHCI host controller not responding, assume dead
Dec 26 10:55:14 server kernel: xhci_hcd 0000:00:14.0: HC died; cleaning up
Dec 26 10:55:15 server kernel: usb 2-2: USB disconnect, device number 7
Dec 26 10:55:17 server kernel: xhci_hcd 0000:00:14.0: xHCI Host Controller
Dec 26 10:55:17 server kernel: xhci_hcd 0000:00:14.0: new USB bus registered, assigned bus number 2

Ce que ça signifie : C’est un reset côté contrôleur. Tout ce qui est sous ce contrôleur tombera, pas seulement votre dongle.

Décision : Ne perdez pas de temps sur des ajustements par périphérique. Ajoutez un contrôleur USB dédié (carte PCIe) ou passez un contrôleur dédié à la VM.

Alimentation et intégrité du signal : la cause racine peu glamour

Si vous voulez un passthrough USB stable, partez du principe que votre installation est sous-alimentée ou électriquement sale. Cette hypothèse est souvent correcte, et elle est moins coûteuse que de chasser des bugs fantômes.

Méthodes courantes liées à l’alimentation

  • « Déconnexion sous charge » : le SSD externe tombe quand la sauvegarde démarre ; le dongle SDR tombe quand l’échantillonnage augmente ; le stick Zigbee tombe quand la radio émet davantage.
  • « Plusieurs périphériques tombent ensemble » : indique un reset de hub ou de contrôleur, ou une chute de rail d’alimentation partagé.
  • « Marche sur un desktop, échoue sur un serveur » : les ports desktop ont souvent une topologie de hub différente et parfois un câblage frontal meilleur que l’adaptateur d’en-tête interne que vous avez utilisé dans le serveur.

Que faire (point de vue tranché)

Utilisez un hub alimenté pour les dongles de faible qualité et tout câblage long. Oui, même si le périphérique « devrait » consommer peu. Beaucoup de dongles passent en moyenne, mais déclenchent des pics à des moments irritants. Le régulateur et la capacité de réserve du hub font souvent la différence.

Évitez les câbles USB 3 bas de gamme. L’intégrité du signal USB 3 est moins tolérante. Si vous avez besoin d’un long câble, utilisez un câble de haute qualité ou restez en USB 2 quand c’est possible.

Préférez les ports I/O arrière directement sur la carte mère. Les en-têtes frontaux et câbles internes sont une taxe sur la fiabilité.

Comment prouver que c’est l’alimentation

  • Les déconnexions se corrèlent avec l’activité du périphérique, pas avec le temps.
  • Passer sur un hub alimenté ou un autre port réduit ou élimine les chutes.
  • Vous voyez des messages « over-current » ou de type « power surge » (moins communs, mais très révélateurs).

Deuxième blague (et la dernière) : un hub alimenté est essentiellement une lettre d’excuses à la physique avec un bloc d’alimentation attaché.

Autosuspend et runtime PM : le tueur silencieux de périphériques

La gestion d’énergie à l’exécution de Linux est une bonne idée avec une mauvaise habitude : elle suppose que les périphériques implémentent correctement la spécification. Beaucoup le font. Certains absolument pas. Pour les adaptateurs série USB, les coordinateurs radio et les périphériques de type HID qui font semblant d’être simples, l’autosuspend peut provoquer des oscillations ou des « périphérique disparu » qui ressemblent à une panne matérielle.

Trois approches, du meilleur au pire

1) Désactiver l’autosuspend par périphérique via udev (préféré)

Trouvez des attributs identifiants (vendor/product, serial ou interface) et forcez power/control=on pour ce périphérique. Cela garde le runtime PM activé pour le reste.

cr0x@server:~$ sudo tee /etc/udev/rules.d/99-usb-no-autosuspend.rules > /dev/null <<'EOF'
ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="10c4", ATTR{idProduct}=="ea60", TEST=="power/control", ATTR{power/control}="on"
EOF
cr0x@server:~$ sudo udevadm control --reload-rules
cr0x@server:~$ sudo udevadm trigger

Ce que ça signifie : Les nouveaux périphériques correspondant au VID:PID auront le runtime PM forcé sur on.

Décision : Si votre périphérique tombe après inactivité, c’est généralement la première correction durable.

2) Désactiver l’autosuspend globalement (utile pour tester, à éviter en permanence)

Mettre usbcore.autosuspend=-1 désactive l’autosuspend globalement. Utile pour prouver la causalité rapidement, surtout en incident. Mais c’est une méthode brute.

cr0x@server:~$ sudo sed -i 's/^GRUB_CMDLINE_LINUX_DEFAULT="/GRUB_CMDLINE_LINUX_DEFAULT="usbcore.autosuspend=-1 /' /etc/default/grub
cr0x@server:~$ sudo update-grub
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-6.8.12-4-pve
done

Ce que ça signifie : Au prochain boot l’autosuspend USB sera désactivé globalement.

Décision : Si la stabilité s’améliore immédiatement, revenez et implémentez plutôt des règles udev par périphérique au lieu de laisser ça en permanence.

3) Traffic keep-alive (parfois nécessaire, souvent moche)

Certain·e·s exécutent des lectures/écritures périodiques ou du polling pour garder les périphériques éveillés. C’est un contournement quand le firmware du périphérique est fragile. C’est aussi comme ça qu’un cron devient « infrastructure critique ».

Décision : Utilisez des keep-alives uniquement après avoir prouvé que l’autosuspend est le déclencheur et que les contrôles power via udev ne suffisent pas.

xHCI resets, quirks et corrections côté contrôleur

Si vos logs montrent que le contrôleur xHCI meurt et revient, vous n’avez plus affaire à « un dongle capricieux ». Vous traitez le contrôleur hôte ou son interaction avec le firmware, la gestion d’alimentation PCIe, ou une mauvaise combinaison de périphériques sur le bus.

Reconnaître les resets du contrôleur

Ces schémas comptent :

  • xHCI host controller not responding, assume dead
  • HC died; cleaning up
  • Réassignation des numéros de bus après le reset
  • Déconnexions simultanées de plusieurs périphériques USB

Hiérarchie des corrections (faites-les dans cet ordre)

1) Sanity du firmware/BIOS

  • Mettez à jour le BIOS/UEFI de la carte mère. Les bugs de stabilité USB sont déprimant fréquents dans le firmware.
  • Désactivez « ErP » ou les fonctions de mise en veille profonde qui interfèrent avec les rails USB, si applicable.
  • Envisagez de désactiver PCIe ASPM pour des serveurs qui n’en ont pas besoin. ASPM peut interagir mal avec certains contrôleurs.

2) Ajouter un contrôleur USB PCIe dédié (ma solution de référence)

Une carte USB PCIe à 20–50 $ avec un chipset raisonnable peut isoler vos périphériques problématiques du contrôleur intégré PCH. Vous pouvez ensuite passer ce contrôleur en passthrough ou le garder sur l’hôte avec des réglages d’alimentation adaptés.

Décision : Si les resets de contrôleur tuent la disponibilité, achetez de l’isolation. C’est moins cher que votre temps.

3) Passer tout le contrôleur (PCI passthrough)

Pour les périphériques qui détestent le passthrough médiatisé, donner au VM le contrôle direct du contrôleur USB règle souvent le problème. La VM voit le matériel natif ; les resets et ré-énumérations restent dans l’invité.

Compromis : vous perdez l’accès hôte à ces ports, et vous devez gérer correctement les groupes IOMMU. Aussi : la migration à chaud devient plus difficile ou impossible selon votre configuration.

4) Paramètres noyau et quirks (chirurgique, mais sachez ce que vous faites)

Parfois vous pouvez contourner la fragilité avec des paramètres noyau affectant xHCI ou le comportement du core USB. C’est là que vous gardez un contrôle strict des changements car vous touchez l’hôte.

Décision : Si un contrôleur dédié fixe le problème, n’essayez pas d’être trop malin avec des quirks. Si vous devez en appliquer, documentez la raison et les motifs observés dans les logs.

Choisir le bon mode de passthrough (périphérique vs port vs contrôleur)

La plupart des douleurs de passthrough USB sur Proxmox sont auto-infligées en choisissant la mauvaise granularité. Le bon choix dépend de la façon dont le périphérique se comporte quand il se déconnecte et se ré-énumère.

Option A : Passer un périphérique USB (VID:PID)

Bien pour : périphériques uniques avec identité stable, où la ré-énumération ne perturbe pas le mappage.

Mauvais pour : plusieurs périphériques identiques, ou périphériques qui changent d’ID selon le mode (bootloader vs runtime).

Mode de défaillance : le mauvais périphérique est attaché après un reboot, ou le périphérique disparaît et revient avec un ID différent et ne se rattache jamais.

Option B : Passer par chemin bus/port

Cela est plus déterministe si le périphérique reste physiquement sur le même port. C’est aussi moins flexible si vous bougez les câbles.

Bien pour : labos et serveurs où le dongle fait « partie de la machine », pas un accessoire mobile.

Option C : Passer tout le contrôleur (PCI)

Bien pour : périphériques nécessitant un accès bas-niveau, périphériques qui se ré-énumèrent de façon chaotique, et configurations où l’invité doit posséder la pile USB de bout en bout (les VMs Home Assistant sont courantes ici).

Mauvais pour : hôtes où vous avez besoin de ces ports pour d’autres fonctions hôtes, ou lorsque le groupement IOMMU empêche une isolation sûre.

VM vs LXC : ce qui change, ce qui reste

Proxmox propose deux principaux consommateurs d’USB : les VMs QEMU et les conteneurs LXC. Les réalités matérielles ne changent pas : l’alimentation reste l’alimentation, le contrôleur hôte est le contrôleur hôte, et le noyau hôte est toujours impliqué sauf si vous passez un contrôleur PCIe.

VM QEMU

  • Vous pouvez attacher des périphériques USB à la VM via passthrough hôte.
  • Si l’hôte perd le périphérique, la VM le perdra aussi.
  • Passer tout le contrôleur via PCIe donne à l’invité une énumération native et souvent la meilleure stabilité.

Conteneurs LXC

  • LXC partage le noyau hôte. Vous n’émulez pas la pile USB ; vous donnez accès aux nœuds de périphérique.
  • L’autosuspend et le runtime PM sont des comportements de l’hôte. Corrigez-les sur l’hôte.
  • Les permissions et règles cgroup pour les devices comptent : une « déconnexion » peut en réalité être un « nœud de périphérique changé et le conteneur ne peut plus l’ouvrir ».

Règle de décision : Si vous avez besoin qu’un périphérique USB capricieux soit stable, une VM avec passthrough de contrôleur USB PCIe est souvent l’architecture la plus propre. LXC est excellent, mais ce n’est pas une frontière d’isolation USB.

Erreurs courantes : symptôme → cause → correctif

1) Le périphérique tombe exactement après quelques secondes/minutes d’inactivité

Symptôme : Fonctionne en usage actif ; tombe quand il est au repos ; se reconnecte quand le trafic reprend ; parfois l’application invitée ne se remet jamais.

Cause racine : USB autosuspend/runtime PM qui suspend un périphérique qui ne sait pas reprendre proprement.

Fix : règle udev : définir power/control=on pour ce VID:PID ou serial ; optionnellement tester avec usbcore.autosuspend=-1.

2) Plusieurs périphériques USB disparaissent simultanément

Symptôme : Stick Zigbee, câble UPS et clavier tombent en même temps. Les numéros de bus se réinitialisent.

Cause racine : reset du contrôleur xHCI ou chute du rail d’alimentation affectant un hub/contrôleur partagé.

Fix : déplacer le périphérique critique vers un contrôleur dédié ; ajouter une carte USB PCIe ; mettre à jour le BIOS ; éviter les hubs surchargés.

3) Disque USB externe tombe pendant des sauvegardes

Symptôme : erreurs I/O dans l’invité ou l’hôte, suivies d’une ré-énumération ; ZFS ou job de backup échoue.

Cause racine : problèmes d’alimentation/câble ; quirks UAS ; firmware d’enclosure ; brownout du hub.

Fix : hub alimenté ou port direct ; câble plus court ; envisager de désactiver UAS pour l’enclosure (spécifique au périphérique) ; préférer SATA/NVMe pour les cibles de sauvegarde sérieuses.

4) Le passthrough fonctionne jusqu’au mode update du firmware

Symptôme : Vous flashez un dongle ; il disparaît ; il revient avec un autre USB ID ; la VM ne le capture plus.

Cause racine : le bootloader s’énumère avec un VID:PID différent et votre mapping est trop étroit.

Fix : passer temporairement par chemin de port ; ou passer le contrôleur ; ou inclure les deux IDs si vous les connaissez.

5) Deux dongles identiques échangent leur place après reboot

Symptôme : La VM obtient « le mauvais stick » et tout casse de manière subtile.

Cause racine : mapping par VID:PID sans serial unique ; l’ordre d’énumération change.

Fix : attacher par serial via udev ; ou utiliser le mapping physique par port ; étiquetez les câbles comme un adulte.

6) Le conteneur LXC perd le périphérique après reconnexion

Symptôme : Le conteneur avait /dev/ttyUSB0, puis après reconnexion il devient /dev/ttyUSB1 ; l’application échoue.

Cause racine : le nœud de périphérique change ; les permissions/cgroup du conteneur n’incluent pas le nouveau nœud.

Fix : créez un symlink stable dans /dev/serial/by-id ou /dev/serial/by-path ; bind-montez le chemin stable dans le conteneur ; assurez-vous que les permissions cgroup le permettent.

7) Le « fix » était de désactiver l’autosuspend globalement et maintenant d’autres USB se comportent étrangement

Symptôme : La consommation électrique augmente ; certains périphériques se comportent différemment ; les fonctions power laptop deviennent hors sujet, mais vous êtes sur un serveur de toute façon.

Cause racine : coup de marteau global pour un problème spécifique.

Fix : revenez sur le réglage global ; implémentez une règle udev pour le périphérique concerné ; confirmez que runtime_status reste actif pour ce seul périphérique.

Listes de contrôle / plan pas à pas

Plan de durcissement pas à pas (compatible production)

  1. Capturer les preuves : enregistrez la sortie hôte de dmesg -Tw pendant au moins une déconnexion ; sauvegardez les lignes pertinentes de journalctl -k.
  2. Confirmer la topologie : exécutez lsusb -t ; notez la chaîne bus/port. Si vous ne pouvez pas décrire où c’est branché, vous ne pouvez pas le rendre stable.
  3. Baseliner l’alimentation : déplacez le périphérique vers un port arrière de la carte mère ; retirez les câbles d’extension ; testez avec un hub alimenté si c’est un dongle.
  4. Désactiver l’autosuspend par périphérique : implémentez une règle udev pour le VID:PID (et serial si disponible). Rebranchez et vérifiez que power/control montre on.
  5. Vérifier la stabilité à l’inactivité : laissez-le inactif plus longtemps que la fenêtre de défaillance précédente ; confirmez l’absence de déconnexions dans journalctl -k.
  6. Stresser le périphérique : générez du trafic réaliste (activité radio, I/O disque, polling UPS). Surveillez les resets.
  7. Si des resets de contrôleur apparaissent : stoppez. Ajoutez un contrôleur USB PCIe dédié ou isolez via passthrough PCI.
  8. Choisir la granularité de passthrough : passthrough par périphérique si unique et stable ; par port/path si fixé physiquement ; par contrôleur si le périphérique est capricieux.
  9. Verrouiller l’identité : utilisez des symlinks stables dans /dev/serial/by-id ou by-path ; évitez les numéros fragiles comme /dev/ttyUSB0.
  10. Documentez : notez quel port, quelle règle et quelle ligne de config VM. Le futur vous sera reconnaissant.
  11. Surveillez : ajoutez une vérification légère qui alerte sur les messages kernel de déconnexion ou sur les nœuds de périphérique manquants.

Checklist de rollback (parce que vous en aurez besoin)

  • Conservez une copie de l’original /etc/default/grub et des fichiers de règles udev.
  • Appliquez un changement à la fois si possible. Si vous changez hub + paramètres noyau + mode de passthrough, vous ne saurez pas ce qui a résolu le problème.
  • Planifiez les reboot comme il faut. Certains réglages USB PM nécessitent un reboot pour s’appliquer ; les règles udev non.

Trois mini-récits d’entreprise depuis le terrain

Incident causé par une mauvaise hypothèse : « C’est dans la VM, donc c’est un problème VM »

Dans une entreprise de taille moyenne, une équipe gérait un cluster Proxmox supportant quelques services « petits mais critiques ». L’un d’eux : une VM qui communiquait avec un UPS connecté en USB pour le signal de shutdown. Ils ont passé le périphérique HID USB à la VM et sont passés à autre chose.

Des mois plus tard, ils ont observé des erreurs sporadiques côté VM : le logiciel UPS perdait le périphérique pendant quelques secondes, puis se reconnectait. L’équipe a supposé un bug de pilote invité parce que les logs VM montraient le symptôme en premier. Ils ont mis à jour le noyau invité, épinglé des paquets, et même changé le logiciel UPS. Rien n’a amélioré.

Pendant une panne plus longue, quelqu’un a finalement suivi dmesg côté hôte en reproduisant le problème. L’hôte loggait des déconnexions USB aux mêmes horodatages. Ce n’était pas la VM. C’était l’hôte qui suspendait le périphérique et qui échouait parfois à reprendre proprement.

Le fix était ennuyeux : une règle udev a forcé power/control=on pour ce VID:PID, et le périphérique est resté éveillé. Ils ont aussi déplacé le câble UPS vers un port arrière loin d’un hub bruyant utilisé pour du matériel de labo. Le post-mortem a corrigé une règle clé : « Toujours prouver quel noyau a loggé la déconnexion en premier. »

Optimisation qui a mal tourné : « Économie d’énergie partout »

Dans une autre organisation, quelqu’un a voulu être agressif sur l’efficacité énergétique. C’était un rack de petits serveurs dans un bureau avec une climatisation limitée. Ils ont activé un ensemble d’optimisations d’économie d’énergie, incluant des C-states plus profonds et des valeurs de runtime PM plus agressives.

Les victimes USB ont commencé discrètement : un coordinateur Zigbee dans une VM domotique tombait une fois par jour. Puis un SSD USB externe utilisé pour une exportation hebdomadaire a commencé à renvoyer des erreurs I/O sous écriture soutenue. Ça ne tombait pas en labo ; ça tombait dans le bureau à 2h du matin, le moment traditionnel des surprises.

Les ingénieurs ont chassé des bugs applicatifs, puis des problèmes de stockage, puis des problèmes QEMU. Le facteur commun était les transitions idle→busy. Autosuspend et runtime PM économisaient de l’énergie de la seule façon qu’ils connaissaient : en faisant des siestes au pire moment.

Ils ont annulé le comportement agressif d’autosuspend périphérique par périphérique au lieu de globalement, et ont gardé les économies CPU car elles n’étaient pas en cause. La leçon n’était pas « l’économie d’énergie est mauvaise ». C’était « l’économie d’énergie nécessite des exceptions par périphérique quand des périphériques USB font partie de votre chaîne de fiabilité ».

Pratique ennuyeuse mais correcte qui a sauvé la journée : contrôleurs dédiés et câblage déterministe

Une entreprise du secteur financier avait un hôte Proxmox exécutant divers services, incluant une VM qui gérait un petit module de sécurité matériel connecté en USB. Pas un dongle grand public ; toujours USB, toujours capricieux.

Ils l’ont traité comme toute autre dépendance de production. Le périphérique USB vivait sur un contrôleur PCIe USB dédié. Ce contrôleur était passé à la VM via PCI passthrough. Le port physique était étiqueté, le câble était court et connu bon, et il y avait un hub alimenté seulement là où il apportait de la stabilité électrique (pas parce qu’ils manquaient de ports).

Quand l’hôte a reçu des mises à jour du noyau plus tard, une poignée de périphériques USB non liés sur les ports de la carte mère ont commencé à montrer des resets occasionnels. Personne ne s’en est soucié. La chaîne USB critique était isolée. La VM a conservé son contrôleur, son périphérique et sa stabilité.

La pratique était ennuyeuse parce qu’elle demandait de la planification, pas des exploits. Elle a aussi fait en sorte que les incidents portaient sur l’application réelle, pas sur le fait qu’un dongle ait décidé de se ré-énumérer aujourd’hui.

FAQ

1) Dois-je désactiver l’autosuspend USB globalement sur Proxmox ?

Seulement comme test de diagnostic court. Si ça aide, implémentez une règle udev par périphérique qui force power/control=on. La désactivation globale est un instrument brutal.

2) Pourquoi passer par « Bus 002 Device 008 » échoue plus tard ?

Parce que le numéro « Device 008 » est attribué lors de l’énumération et change après déconnexions/resets. Utilisez VID:PID, serial, by-path, ou passez tout le contrôleur.

3) Mon stick Zigbee/Z-Wave reset quand je le branche sur un port USB 3. Pourquoi ?

Les ports USB 3 peuvent être électriquement plus bruyants et partager les hubs différemment. Certaines radios 2,4 GHz sont sensibles aux interférences, et certains dongles se comportent mieux en USB 2. Utilisez une rallonge USB 2 ou un hub alimenté pour l’éloigner de l’hôte.

4) Le passthrough PCI est-il toujours meilleur ?

C’est souvent le plus stable, mais pas toujours le plus pratique. Il réduit la flexibilité (l’hôte ne peut plus utiliser ces ports) et peut compliquer les migrations. Servez-vous-en quand le passthrough au niveau périphérique casse sans cesse.

5) Comment savoir si c’est l’alimentation et non la gestion d’énergie Linux ?

Les problèmes d’alimentation se corrèlent avec la charge et peuvent affecter plusieurs périphériques ; l’autosuspend se corrèle avec l’inactivité et affiche runtime_status=suspended. Les logs plus le timing racontent l’histoire.

6) Pourquoi mon conteneur LXC perd /dev/ttyUSB0 après une reconnexion ?

Parce que le noyau peut réassigner le nœud en /dev/ttyUSB1, etc. Utilisez des symlinks stables dans /dev/serial/by-id ou by-path et bind-montez-les dans le conteneur.

7) Les hubs peuvent-ils causer des déconnexions même si le périphérique consomme très peu ?

Oui. Les hubs peuvent être instables à cause d’une mauvaise régulation d’alimentation, de quirks de firmware ou d’intégrité de signal. Un hub alimenté et de qualité corrige souvent des drops « mystères ».

8) Mon périphérique a deux VID:PID différents selon le mode. Comment gérer le passthrough ?

Soit passez par le port physique/path pour que la ré-énumération soit encore capturée, soit incluez les deux IDs, soit utilisez le passthrough de contrôleur pendant les mises à jour de firmware.

9) Est-ce un problème Proxmox ou un problème du noyau Linux ?

La plupart du temps ce n’est ni l’un ni l’autre ; c’est le matériel, les valeurs par défaut de gestion d’énergie, ou le comportement du contrôleur. Proxmox repose sur le noyau Linux ; les logs hôte sont l’arbitre.

10) Quelle est la configuration la plus fiable pour un périphérique USB « qui ne doit pas tomber » ?

Contrôleur PCIe USB dédié, contrôleur passé en PCI à la VM, autosuspend désactivé spécifiquement si l’hôte y touche encore, câble court et connu bon, et port étiqueté de façon déterministe.

Conclusion : prochaines étapes qui tiennent

Si vous luttez contre des déconnexions USB en passthrough sur Proxmox, ne commencez pas par des flags noyau exotiques. Commencez par des preuves, puis appliquez des correctifs qui survivent aux reboots et aux upgrades.

  1. Prouvez où la déconnexion se produit : dmesg -Tw sur l’hôte est votre première source de vérité.
  2. Stabilisez la couche physique : port arrière, bon câble, hub alimenté si nécessaire.
  3. Tuez l’autosuspend pour le périphérique spécifique en utilisant une règle udev ; vérifiez power/control et runtime_status.
  4. Si le contrôleur reset : isolez avec un contrôleur USB PCIe dédié et envisagez le passthrough PCI.
  5. Rendez l’identité déterministe : serial/by-id/by-path, pas les numéros tty.
  6. Documentez et surveillez : la meilleure correction est celle que vous pouvez expliquer pendant un incident à 3h du matin.

L’USB peut être stable dans un hyperviseur. Il faut juste lui donner le même respect que vous accordez aux disques et aux réseaux : alimentation propre, câblage déterministe et configurations qui supposent que le périphérique finira par mal se comporter un jour.

← Précédent
MariaDB vs SQLite pour petits projets sur VPS : quand MariaDB est excessif
Suivant →
Debian 13 : Journald a mangé votre disque — limiter les logs sans perdre l’essentiel

Laisser un commentaire