summaryrefslogtreecommitdiff
path: root/net/ccwgroup.sh
blob: aaf7de6b0037ed7d888c4243b8f0eae8dbcd726b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# Copyright (c) 2007-2008 Roy Marples <roy@marples.name>
# Released under the 2-clause BSD license.

_config_vars="$_config_vars ccwgroup"

ccwgroup_depend()
{
	before interface
}

ccwgroup_load_modules()
{
	# make sure we have ccwgroup support or this is a crap shoot
	if [ ! -d /sys/bus/ccwgroup ] ; then
		modprobe -q ccwgroup
		if [ ! -d /sys/bus/ccwgroup ] ; then
			eerror "ccwgroup support missing in kernel"
			return 1
		fi
	fi

	# verify the specific interface is supported
	if [ ! -d /sys/bus/ccwgroup/drivers/$1 ] ; then
		modprobe $1 >/dev/null 2>&1
		if [ ! -d /sys/bus/ccwgroup/drivers/$1 ] ; then
			eerror "$1 support missing in kernel"
			return 1
		fi
	fi

	return 0
}

ccwgroup_pre_start()
{
	local ccwgroup="$(_get_array "ccwgroup_${IFVAR}")"
	[ -z "${ccwgroup}" ] && return 0

	local ccw_type
	eval ccw_type=\${ccwgroup_type_${IFVAR}:-qeth}

	ccwgroup_load_modules ${ccw_type} || return 1

	einfo "Enabling ccwgroup/${ccw_type} on ${IFACE}"

	set -- ${ccwgroup}
	local first=$1; shift
	if [ -e /sys/devices/${ccw_type}/${first}/online ]; then
		echo "0" >/sys/devices/${ccw_type}/${first}/online
	else
		echo "${first}$(printf ',%s' "$@")" >/sys/bus/ccwgroup/drivers/${ccw_type}/group
	fi

	local var val
	for var in $(_get_array "ccwgroup_opts_${IFVAR}") online=1 ; do
		val=${var#*=}
		var=${var%%=*}
		echo "${val}" > /sys/devices/${ccw_type}/${first}/${var}
	done
	eend $?

	# Now that we've properly configured the device, we can run
	# bring the interface up.  Common code tried to do this already,
	# but it failed because we didn't setup sysfs yet.
	_up
}

ccwgroup_pre_stop()
{
	local path="/sys/class/net/${IFACE}"

	# Erase any existing ccwgroup to be safe
	service_set_value ccwgroup_device ""
	service_set_value ccwgroup_type ""

	[ ! -L "${path}"/device/driver ] && return 0
	case "$(readlink "${path}"/device/driver)" in
		*/bus/ccwgroup/*) ;;
		*) return 0;;
	esac

	local device
	device="$(readlink "${path}"/device)"
	device=${device##*/}
	service_set_value ccwgroup_device "${device}"
	device="$(readlink "${path}"/device/driver)"
	device=${device##*/}
	service_set_value ccwgroup_type "${device}"
}

ccwgroup_post_stop()
{
	local device="$(service_get_value ccwgroup_device)"
	[ -z "${device}" ] && return 0
	local ccw_type="$(service_get_value ccwgroup_type)"
	local path="/sys/devices/${ccw_type}/${device}"

	einfo "Disabling ccwgroup/${ccw_type} on ${IFACE}"
	if echo "0" >"${path}"/online &&
	   echo "1" >"${path}"/ungroup ; then
		# The device doesn't disappear right away which breaks
		# restart, or a quick start up, so wait around.
		while [ -e "${path}" ] ; do :; done
	fi
	eend $?
}