How to turn off and on the BM818 modem?

One of the things that has long annoyed me is that the internet periodically stops working on the Librem 5’s BM818 cellular modem. If I use the hardware kill switch to turn the modem off and then back on, the internet connection comes back.

Since I find it annoying to have to keep manually turning on and off the modem, I thought that I would write a script that periodically checks if there is internet, and if not, it would turn the modem off and then back on to bring back the internet.

However, all the ways that I have tried to turn off and on the modem don’t bring back the internet.

I tried restarting the ModemManager, but that doesn’t fix the problem:

sudo systemctl restart ModemManager

I also tried using resetting the USB connection to the modem:

sudo udevadm trigger --action=change --name-match=/sys/devices/platform/soc@0/38200000.usb/xhci-hcd.4.auto/usb1/1-1/1-1.2/1-1.2:1.0/ttyUSB0/tty/ttyUSB0

I tried unbinding the USB:

echo '1-1.2' | sudo tee /sys/bus/usb/drivers/usb/unbind
echo '1-1.2' | sudo tee /sys/bus/usb/drivers/usb/bind

Then, I found Chris Vogel’s librem5-recover-xhci-usb.sh script at: https://git.sr.ht/~chrichri/librem5-bm818-watchmodem
He uses this code to recover the USB hub and restart the modem:

	rmmod xhci_plat_hcd xhci_hcd
	echo 0 > /sys/class/leds/wwan_en/brightness
	sleep 2
	modprobe xhci_plat_hcd
	sleep 5
	echo 1 > /sys/class/leds/wwan_en/brightness

The file /sys/class/leds/wwan_en/brightness doesn’t exist in Crimson, so I tried to find equivalent files in Crimson:

	rmmod xhci_plat_hcd xhci_hcd
	echo 1 > /sys/class/leds/wwan_disable/brightness
	sleep 2
	modprobe xhci_plat_hcd
	sleep 5
	echo 0 > /sys/class/leds/wwan_disable/brightness

However, rmmod xhci_plat_hcd xhci_hcd causes the terminal to freeze and echo 1 > /sys/class/leds/wwan_disable/brightness doesn’t seem to have any effect.

Is there any way to turn the modem off and on that has the same effect as turning off and on the hardware kill switch for the modem?

PS: I wrote the following script to restart the modem if there is no internet, that I planned to execute as a cronjob, but I can’t figure out how to power cycle the modem:

#!/usr/bin/env python3
import subprocess
import logging

try:
	logger = logging.getLogger(__name__)
	logging.basicConfig(filename='/var/log/qmi_wwan.log', 
		format='%(asctime)s: %(message)s', level=logging.WARNING)
	
	result = subprocess.run(["ping", "-c 1", "-t 19", "8.8.8.8"], capture_output=True, text=True, timeout=20)
	
	#if no internet, then restart the  modem
	if result.stdout.find("ttl") == -1:
		#Can't find the darn commands to power cycle the modem:
		ret = subprocess.call("**turn off the modem**", shell=True)
		ret = subprocess.call("**turn on the modem**", shell=True)
		logging.warning("Restarted qmi_wwan.")
	else:
		logging.info("qmi_wwan working.")
	
except subprocess.CalledProcessError as e:
	logging.error(f"Command failed with return code: {e.returncode}")
	logging.error(f"stderr: {e.stderr.strip()}")

This bug has been tracked for long time, there is a hack that fix it and prevent all you did for.

I hope mario bross tackle this on gdawn as too much time to fix a simple tiny bug.

Thanks.

I curious if holy grail pmos already fixed this bug or is waiting gpure mobile for the fix?

This has seemed to work for me:

mmcli -m any --reset
sleep 30
systemctl restart NetworkManager

I’ve been restarting the USB device with sudo usbreset 2020:2060, which was shared by dos on these forums, I think, once upon a time.

I like the idea of automating this. I just stuck the command into a bash script, callable from a .desktop file in my Apps.

Thanks @Skalman and @spacemanspiffy. I stuck usbreset in my script because it is faster, but I have to wait until the next time that the internet fails to see if it works.

For what you’re trying to do, either usbreset or a bind/unbind cycle are the best choices. Is there any reason why you went looking for anything more than that?

Completely unnecessary and not a good idea at all. It used to help a long time ago with a different issue that has been fixed years ago, now it will just bring a lot of unwanted side effects.

wwan_disable is nowhere close to being an equivalent, it controls the W_DISABLE pin of the M.2 socket; in fact, I don’t think it ever had any effect with BM818 anyway.

An equivalent to what used to be done by toggling /sys/class/leds/wwan_en/brightness in the past would now be:

# off
echo 1 > /sys/devices/platform/rfkill-hks/wwan-hks/enable_soft
rfkill block wwan
# on
rfkill unblock wwan
echo 0 > /sys/devices/platform/rfkill-hks/wwan-hks/enable_soft

This performs a full modem power cycle, which shouldn’t be necessary to get a frozen network interface unstuck.

Thanks @dos. I’m not sure exactly what causes the internet connection to die with the BM818, so I’m not sure exactly what is needed to bring it back. Is there a log for the BM818 that I should be watching?

Now that I am sending a ping every 5 minutes as a cronjob, the internet connection hasn’t died for the last 7 hours. I just set the L5 to suspend after 1 minute of inactivity, to see if it is waking up from suspend that is causing the problem.

We have discussed this problem in the past and I reported that I never have the problem when I am abroad. Three months on data roaming and not a single problem, while at home I keep a shortcut that I tap to reset the modem when I see the data connection going stale.

In my case, I can always make and receive calls and SMS while the data connection is down.

I spent some time digging into logs and trying to compare what happens home vs abroad. I will be abroad again for 2-3 months from the end of november and could try looking into it (compare here vs abroad) with some guidance.

This is related to USB remote wakeups, so aside of network activity itself it will be more likely to happen when you’re in movement or in an area where the modem often relogs to a different cell tower and/or changes its reported signal strength.