Purism

Purism

Beautiful, Secure, Privacy-Respecting Laptops, Tablets, PCs, and Phones
Purism

An unexpected breakthrough

Great to see you again!  In our January update, we worked on enabling essential functionality for the Librem 5 in PureOS Crimson.  This time, we’re working on something a little different – a solution to a longstanding issue that applies to both Byzantium and Crimson.

Automatic suspend greatly improves the Librem 5’s battery life, but there are some limitations that prevent us from enabling it by default.  Sometimes, when resuming, the SD card stops responding.

We thought this might have been a quirk of the internal USB hub or the USB-attached SD card reader on the Librem 5, until Sebastian Krzyszkowiak found that it also can occur on a PC with a USB SD card reader under the right circumstances.

Internal USB?

Yes, the SD card reader in the Librem 5 is attached via USB using an internal hub:

Block diagram showing i.MX8MQ CPU connected to a combined USB hub and SD card reader
From the Librem 5 block diagram. The USB2642 is a combined USB hub and USB SD card reader.

The Librem 5’s CPU, the NXP i.MX8MQ, has two SD interfaces.  We use one for the internal storage (eMMC) and the second for the Wi-Fi card (SDIO).  While laptops and desktops usually use PCI Express for internal Wi-Fi cards, SDIO is common in mobile devices and generally uses less power.  Since both SD interfaces are in use, we connect the microSD card using USB.

To save power, the Librem 5 can put the USB hub and the card reader into low-power states when they’re not actively in use.  That’s called “runtime suspend”.  This can happen when the phone is awake, but it will always happen when the phone suspends.  We thought this problem was caused by putting the USB devices in runtime suspend, but it wasn’t.

Changing cards

Diagram of the Librem 5 SIM and SD tray insertion

Most USB SD card readers allow you to remove or insert an SD card without unplugging the device.  To support this, the host needs to know when the inserted card has changed.  If the card does change, the card reader will go to a “media changed” state.  The host must acknowledge the change before the card reader will accept reads or writes again.  That avoids mistakenly sending reads and writes to the wrong card.

So, the host must poll the card reader periodically to see if the card has changed.  However, the Librem 5’s microSD card is not intended to change while the phone is powered on.  The phone must off to eject or insert the tray if there is a SIM card installed.  We also want to save as much power as we can, so this is a sensible trade-off.

The perfect storm

There are still two situations where the Librem 5’s SD card reader could enter a media-changed state: runtime suspend of the card reader itself, or when the whole phone has suspended.

In either case, the card reader was powered down, so it doesn’t really know if the card had changed.  When it comes back up, it just assumes that the media might have changed, and the host has to decide what to do.

The runtime resume path worked on the Librem 5.  We specifically checked if the card reader was in a media-changed state, and if so we ignored it.  Since we acknowledged it, we can read and write the card again.

System suspend though, did not do this.  But it would still work if you avoid reading the card for about 1.5 seconds after system resume.  After 1.5 seconds, we’d runtime-suspend the card reader because it’s idle, and then the runtime resume logic would clear the media-change state.  It would also still work if polling had been enabled, because polling would notice the state and clear it.

If you try to read the card within 1.5 seconds of system resume, and polling was disabled like on the Librem 5, then the perfect storm occurs.  The card reader still thinks the card has changed, and Linux has not acknowledged it.  Reads and writes will fail, and Linux will give up on the card.

As a result, you can reproduce this on a PC too just by disabling this event polling, then suspending the system.

Solving the issue

With that understanding, Sebastian simply moved the relevant logic from the runtime-suspend path to a common path that applies to both types of suspend.  We’re validating this fix and will roll it out to Byzantium and Crimson when we’re confident that there are no side effects.

This brings us one step closer to enabling suspend by default without limitations, which will make the Librem 5 run longer, cooler, and with more responsiveness.

While that fix was ongoing, other work related to our first PureOS Crimson milestone is advancing too.  The updates to librem5-base that we discussed last month are in crimson-updates-proposed and will migrate to crimson-updates soon.  We’re also fixing the PureOS Docker images that we use in CI.

Additionally, we now allow polling for external SD card readers on the Librem 5.  The Librem 5 is often used with external SD card readers, like those built into a dock.  Since you can change the card in those, we need to poll them.

This work is possible thanks to your continued support.  Thank you, and watch out for our next post in April!

Recent Posts

Related Content

Tags