chiarire i problemi di nvme apst per linux

Sep 30 2020

Ho riscontrato un problema quasi identico a quello descritto nella comunità di askubuntu .

Come quella dell'utente che ha postato questo problema, il mio sistema è dotato di un disco Kingston NVME, e come con l'utente, il mio problema risolto aggiungendo la seguente opzione del kernel nel menu di GRUB: nvme_core.default_ps_max_latency_us=0.

La risoluzione dichiarata dall'utente inizia come segue:

Il problema era delle funzionalità SSD, le APST (Autonomous Power State Transitions) stavano causando i blocchi. Per mitigarlo, fino a quando non rilasceranno la correzione, includi la riga nvme_core.default_ps_max_latency_us=0nelle GRUB_CMDLINE_LINUX_DEFAULTopzioni.

Sebbene utile, questo commento lascia aperte diverse domande, tra cui le seguenti:

  1. Qual è e dov'è il difetto specifico che causa il problema?
  2. Cosa cambia la soluzione alternativa per impedire la presentazione del difetto?
  3. Quale funzionalità o altro effetto desiderato viene perso a causa di tale soluzione alternativa?
  4. E soprattutto, cosa è necessario correggere, il kernel, il firmware del supporto di memorizzazione, il firmware di sistema (cioè UEFI / BIOS) o qualche altro componente, per fornire una risoluzione adeguata?

Eventuali commenti sono utili per tentare di risolvere in tutto o in parte questa confusione.

Risposte

5 telcoM Sep 30 2020 at 13:26

Il commento sul codice all'interno drivers/nvme/host/core.cdel sorgente del kernel Linux sembra spiegarlo meglio:

static int nvme_configure_apst(struct nvme_ctrl *ctrl)
{
    /*
     * APST (Autonomous Power State Transition) lets us program a
     * table of power state transitions that the controller will
     * perform automatically.  We configure it with a simple
     * heuristic: we are willing to spend at most 2% of the time
     * transitioning between power states.  Therefore, when running
     * in any given state, we will enter the next lower-power
     * non-operational state after waiting 50 * (enlat + exlat)
     * microseconds, as long as that state's exit latency is under
     * the requested maximum latency.
     *
     * We will not autonomously enter any non-operational state for
     * which the total latency exceeds ps_max_latency_us.  Users
     * can set ps_max_latency_us to zero to turn off APST.
     */

Quindi, APST è una funzionalità che consente al controller NVMe (all'interno dell'SSD NVMe) di passare da uno stato di gestione dell'alimentazione in modo autonomo, seguendo regole configurabili. Il controller NVMe specifica di quanti microsecondi ha bisogno per entrare e uscire da ogni stato di risparmio energetico; il kernel utilizza queste informazioni per configurare le regole di transizione di stato all'interno del controller NVMe.

  1. Qual è e dov'è il difetto specifico che causa il problema?

Sembra che questo particolare SSD Kingston NVMe sia troppo ottimista nelle stime del tempo di riattivazione, o non si riattivi affatto (senza resettare completamente il controller) dopo essere entrato in uno stato di risparmio energetico sufficientemente profondo. Quando viene concesso il permesso di utilizzare APST, apparentemente entra in uno stato di risparmio energetico e quindi non riesce a tornare allo stato operativo entro il tempo specificato, il che rende il kernel infelice.

  1. Cosa cambia la soluzione alternativa per impedire la presentazione del difetto?

Indica che il tempo massimo consentito per il risveglio dagli stati di gestione dell'alimentazione APST è esattamente 0 microsecondi, il che causa la disabilitazione della funzione APST.

  1. Quale funzionalità o altro effetto desiderato viene perso a causa di tale soluzione alternativa?

Se la funzione di gestione autonoma dell'alimentazione del controller NVMe non può essere utilizzata, al controller sarà consentito di entrare in stati di risparmio energetico solo quando specificamente richiesto dal kernel. Ciò significa che il risparmio energetico molto probabilmente non sarà così grande come con APST in uso.

  1. E soprattutto, cosa è necessario correggere, il kernel, il firmware del supporto di memorizzazione, il firmware di sistema (cioè UEFI / BIOS) o qualche altro componente, affinché gli utenti sperimentino una corretta risoluzione?

La soluzione ottimale sarebbe per Kingston fornire un aggiornamento del firmware del disco NVMe che fa funzionare correttamente la gestione dell'alimentazione APST o, al minimo, fa sì che l'unità non prometta qualcosa che non può fornire, ovvero non annuncia le modalità APST con tempi di transizione eccessivamente ottimistici, e / o non annunciare affatto le modalità APST che causeranno il guasto del controller se utilizzato.

Se si scopre che il problema può essere evitato, ad esempio programmando APST per evitare completamente lo stato di risparmio energetico più profondo, potrebbe essere possibile creare una soluzione alternativa a livello di kernel più specifica. Molti driver di dispositivo nel kernel Linux hanno "tabelle strane" che specificano soluzioni alternative per modelli hardware specifici. Nel caso di NVMe, puoi trovarne uno drivers/nvme/host/pci.call'interno del sorgente del kernel Linux:

static const struct pci_device_id nvme_id_table[] = {
    { PCI_VDEVICE(INTEL, 0x0953),   /* Intel 750/P3500/P3600/P3700 */
        .driver_data = NVME_QUIRK_STRIPE_SIZE |
                NVME_QUIRK_DEALLOCATE_ZEROES, },
    { PCI_VDEVICE(INTEL, 0x0a53),   /* Intel P3520 */
        .driver_data = NVME_QUIRK_STRIPE_SIZE |
                NVME_QUIRK_DEALLOCATE_ZEROES, },
    { PCI_VDEVICE(INTEL, 0x0a54),   /* Intel P4500/P4600 */
        .driver_data = NVME_QUIRK_STRIPE_SIZE |
                NVME_QUIRK_DEALLOCATE_ZEROES, },
    { PCI_VDEVICE(INTEL, 0x0a55),   /* Dell Express Flash P4600 */
        .driver_data = NVME_QUIRK_STRIPE_SIZE |
                NVME_QUIRK_DEALLOCATE_ZEROES, },
    { PCI_VDEVICE(INTEL, 0xf1a5),   /* Intel 600P/P3100 */
        .driver_data = NVME_QUIRK_NO_DEEPEST_PS |
                NVME_QUIRK_MEDIUM_PRIO_SQ |
                NVME_QUIRK_NO_TEMP_THRESH_CHANGE |
                NVME_QUIRK_DISABLE_WRITE_ZEROES, },
[...]

Qui le varie NVME_QUIRK_impostazioni attivano vari codici di soluzione alternativa all'interno del driver.

Si noti che esiste già un'impostazione strana denominata NVME_QUIRK_NO_DEEPEST_PSche impedisce le transizioni di stato allo stato di gestione dell'alimentazione più profondo. Se il problema APST del tuo Kingston NVMe risulta avere la stessa soluzione alternativa già implementata per Intel 600P / P3100 e ADATA SX8200PNP, allora tutto ciò che serve è scrivere una nuova voce di tabella strana come questa (sostituendo le cose all'interno <angle brackets>con valori appropriati, puoi ottenerli con lspci -nn):

    { PCI_DEVICE(<PCI vendor ID>, <PCI product ID of the SSD>),   /* <specify make/model of SSD here> */
        .driver_data = NVME_QUIRK_NO_DEEPEST_PS, },

e ricompilare il kernel con questa modifica.

Ovviamente, qualcuno che abbia effettivamente questo modello SSD esatto è necessario per testarlo. Se ti capita di avere familiarità con le basi della programmazione C e come compilare kernel personalizzati, questa potrebbe essere la tua occasione per far entrare il tuo nome nella lunga lista di contributori del kernel Linux! Se sei interessato, dovresti probabilmente leggere kernelnewbies.org per maggiori dettagli.

La programmazione del kernel non è sempre profondamente intricata: ci sono molte parti semplici che richiedono solo una persona con il giusto tipo di hardware e alcune conoscenze di programmazione di base. Ho inviato alcune patch minori proprio come questa.

Se l'impostazione dei NVME_QUIRK_NO_DEEPEST_PSrisultati non risolve il problema, potrebbe essere necessaria l'implementazione di una nuova stranezza. Ciò potrebbe essere più complicato e potrebbe richiedere alcuni esperimenti o idealmente informazioni da Kingston per scoprire cosa è necessario fare esattamente per evitare questo problema, e forse discutere con il manutentore del driver NVMe di Linux sul modo migliore per implementarlo.