| #!/bin/sh |
| # |
| # Copyright (c) 2014 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| # |
| # UDEV event helper script that restarts a hung WiFi device. |
| |
| POWER_DOWN_TIME_SECONDS=1 |
| DEVICE_REINITIALIZE_TIME_SECONDS=5 |
| |
| set -e |
| |
| error () { |
| logger -t $0 "Error: $1" |
| exit 1 |
| } |
| |
| if [ -n "${1}" ] ; then |
| eval $(udevadm info --query=property --path="/sys/class/net/${1}" | |
| egrep '^(DEVPATH|DEVTYPE|SUBSYSTEM|INTERFACE)') |
| EVENT=device_hang |
| fi |
| |
| if [ "${SUBSYSTEM}" != "net" -o |
| "${DEVTYPE}" != "wlan" -o |
| "${EVENT}" != "device_hang" -o |
| -z "${DEVPATH}" ] ; then |
| exit 0 |
| fi |
| |
| logger -t $0 "Restarting wireless lan network interface ${INTERFACE}" |
| |
| # The DEVPATH for a wlan network interface should look something like: |
| # /devices/pci0000:00/0000:00:1c.0/0000:01:00.0/net/wlan0 |
| if [ $(basename $(dirname "${DEVPATH}")) != 'net' ] ; then |
| error "Device path for ${INTERFACE} (${DEVPATH}) is invalid." |
| fi |
| |
| device_path=$(dirname $(dirname "/sys${DEVPATH}")) |
| device_remove_path="${device_path}/remove" |
| bus_rescan_path=$(dirname "${device_path}")/rescan |
| |
| if [ ! -e "${device_remove_path}" ] ; then |
| error "Device remove path ${device_remove_path} does not exist" |
| fi |
| |
| if [ ! -e "${bus_rescan_path}" ] ; then |
| error "Bus rescan path ${bus_rescan_path} does not exist" |
| fi |
| |
| echo 1 > "${device_remove_path}" |
| ectool wireless 0xe # Disable wireless lan. |
| ectool wireless 0x6 # Power down wireless lan. |
| |
| sleep ${POWER_DOWN_TIME_SECONDS} |
| |
| ectool wireless 0xe # Power up wireless lan. |
| ectool wireless 0xf # Enable wireless lan. |
| |
| sleep ${DEVICE_REINITIALIZE_TIME_SECONDS} |
| |
| echo 1 > "${bus_rescan_path}" |