blob: ef013616b65d06c9d732b27e7bb5121d91034fbf [file] [log] [blame]
# Copyright (c) 2012 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.
description "Preload network drivers"
author "chromium-os-dev@chromium.org"
# Run on boot-services; "stay running" until we stop system-services
# (which is shutdown).
start on starting boot-services
# crbug.com/810916: Use an event where we are confident all needed "net"
# driver modules have registered with "net" subsystem. The assumption is
# this set of drivers will be used again on next boot.
#
# "stop on stopped udev-trigger" has proven to be too early.
#
# "stop on starting system-services" means boot-services have completed
# (including udev-trigger) and conditions are meet to start system-services.
# But it's still racing.
# "stop on started system-services" is slightly better as this indicates
# some system-services have started. But it's still racing too.
#
# "stop on stopping system-services" would certainly qualify (shutdown) - but
# slows down shutdown which is expected to be quick (no benchmark though).
#
# Compromise is to check for WiFi (wlan0) device well after system services
# have been started. "failsafe" service meets that criteria even though
# it's not a 100% guarantee either that any given WiFi driver has registered
# with "net" subsystem.
#
# We also try to mitigate this race by looping for "expected" (WiFi) devices.
#
# https://dev.chromium.org/chromium-os/chromiumos-design-docs/boot-design#TOC-Failsafe-service
stop on started failsafe
env drvfile=/var/lib/preload-network-drivers
pre-start script
# Drivers for Ethernet and WiFi devices are generally modules.
# Our post-stop script will have recorded the driver names on the
# previous boot cycle. Load those drivers now so shill can config
# the network sooner.
#
# Note: failure to probe the module here is NOT fatal.
if [ -s "${drvfile}" ] ; then
for drv in $(head -1 "${drvfile}"); do
if ! modprobe -q -- "${drv}"; then
# If modprobe didn't like the alias file for some reason, just
# move it out of the way. The post-stop script will make a new
# one.
mv "${drvfile}" "${drvfile}.bad"
logger -t "${UPSTART_JOB}" \
"modprobe ${drv} failed. Renamed ${drvfile} with .bad suffix."
fi
done
fi
end script
post-stop script
# Create/Update list of networking driver names (i.e. Ethernet and WiFi).
# Used to preload Ethernet and WiFi drivers in pre-start script.
newdrv=''
# "found" is set when an interface we are looking for is present.
found=0
probe_driver() {
local mod_dev="$1"
local mod_link="/sys/class/net/${mod_dev}/device/driver/module"
local drvmod=''
if [ -e "${mod_link}" ] ; then
drvmod="$(basename "$(readlink "${mod_link}")")"
newdrv="${drvmod} ${newdrv}"
found=1
fi
}
for n in $(seq 30); do
# We will only find one of the following. Only Marvell WiFi uses "mlan".
probe_driver "wlan0"
probe_driver "mlan0"
if [ "${found}" -eq 1 ] ; then
break
fi
sleep 1
done
# We expect to find WiFi in all Chrome OS devices. Announce results here.
if [ "${found}" -eq 1 ] ; then
logger -t "${UPSTART_JOB}" "WiFi ${newdrv} found after ${n} seconds."
else
logger -t "${UPSTART_JOB}" "WiFi interface not found after ${n} seconds."
fi
# USB wired ethernet driver is optional - add it if present.
# TODO(grundler): PCI wired ethernet is "built-in" to chromeboxes and
# it would be nice to warn when the PCI driver isn't registering.
probe_driver "eth0"
if [ -s "${drvfile}" ] ; then
olddrv=$(head -1 "${drvfile}")
fi
# Only update contents if they've changed.
if [ "${newdrv}" != "${olddrv}" ] ; then
echo "${newdrv}" > "${drvfile}"
# Force ureadahead to rebuild its block list.
rm -f /var/lib/ureadahead/pack
fi
end script