Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Linux WiMAX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Initialization, addition and removal of wimax devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Copyright (C) 2005-2006 Intel Corporation <linux-wimax@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * This implements:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  *   - basic life cycle of 'struct wimax_dev' [wimax_dev_*()]; on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  *     addition/registration initialize all subfields and allocate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  *     generic netlink resources for user space communication. On
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  *     removal/unregistration, undo all that.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  *   - device state machine [wimax_state_change()] and support to send
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  *     reports to user space when the state changes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  *     [wimax_gnl_re_state_change*()].
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  * See include/net/wimax.h for rationales and design.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  * ROADMAP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  * [__]wimax_state_change()     Called by drivers to update device's state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  *   wimax_gnl_re_state_change_alloc()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  *   wimax_gnl_re_state_change_send()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)  * wimax_dev_init()	        Init a device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)  * wimax_dev_add()              Register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)  *   wimax_rfkill_add()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)  *   wimax_gnl_add()            Register all the generic netlink resources.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)  *   wimax_id_table_add()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)  * wimax_dev_rm()               Unregister
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34)  *   wimax_id_table_rm()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35)  *   wimax_gnl_rm()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36)  *   wimax_rfkill_rm()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) #include <linux/gfp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) #include <net/genetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) #include <linux/wimax.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) #include "wimax-internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) #define D_SUBMODULE stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) #include "debug-levels.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) static char wimax_debug_params[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) module_param_string(debug, wimax_debug_params, sizeof(wimax_debug_params),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 		    0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) MODULE_PARM_DESC(debug,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 		 "String of space-separated NAME:VALUE pairs, where NAMEs "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 		 "are the different debug submodules and VALUE are the "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 		 "initial debug value to set.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59)  * Authoritative source for the RE_STATE_CHANGE attribute policy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61)  * We don't really use it here, but /me likes to keep the definition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)  * close to where the data is generated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) static const struct nla_policy wimax_gnl_re_status_change[WIMAX_GNL_ATTR_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	[WIMAX_GNL_STCH_STATE_OLD] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	[WIMAX_GNL_STCH_STATE_NEW] = { .type = NLA_U8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73)  * Allocate a Report State Change message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)  * @header: save it, you need it for _send()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77)  * Creates and fills a basic state change message; different code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78)  * paths can then add more attributes to the message as needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80)  * Use wimax_gnl_re_state_change_send() to send the returned skb.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82)  * Returns: skb with the genl message if ok, IS_ERR() ptr on error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83)  *     with an errno code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) struct sk_buff *wimax_gnl_re_state_change_alloc(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	struct wimax_dev *wimax_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	enum wimax_st new_state, enum wimax_st old_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	void **header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	struct device *dev = wimax_dev_to_dev(wimax_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	void *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	struct sk_buff *report_skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	d_fnstart(3, dev, "(wimax_dev %p new_state %u old_state %u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 		  wimax_dev, new_state, old_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	result = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	report_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	if (report_skb == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		dev_err(dev, "RE_STCH: can't create message\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		goto error_new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	/* FIXME: sending a group ID as the seq is wrong */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	data = genlmsg_put(report_skb, 0, wimax_gnl_family.mcgrp_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 			   &wimax_gnl_family, 0, WIMAX_GNL_RE_STATE_CHANGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	if (data == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		dev_err(dev, "RE_STCH: can't put data into message\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		goto error_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	*header = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	result = nla_put_u8(report_skb, WIMAX_GNL_STCH_STATE_OLD, old_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	if (result < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 		dev_err(dev, "RE_STCH: Error adding OLD attr: %d\n", result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		goto error_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	result = nla_put_u8(report_skb, WIMAX_GNL_STCH_STATE_NEW, new_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	if (result < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 		dev_err(dev, "RE_STCH: Error adding NEW attr: %d\n", result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 		goto error_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	result = nla_put_u32(report_skb, WIMAX_GNL_STCH_IFIDX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 			     wimax_dev->net_dev->ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	if (result < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 		dev_err(dev, "RE_STCH: Error adding IFINDEX attribute\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		goto error_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	d_fnend(3, dev, "(wimax_dev %p new_state %u old_state %u) = %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		wimax_dev, new_state, old_state, report_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	return report_skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) error_put:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	nlmsg_free(report_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) error_new:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	d_fnend(3, dev, "(wimax_dev %p new_state %u old_state %u) = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		wimax_dev, new_state, old_state, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	return ERR_PTR(result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)  * Send a Report State Change message (as created with _alloc).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)  * @report_skb: as returned by wimax_gnl_re_state_change_alloc()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)  * @header: as returned by wimax_gnl_re_state_change_alloc()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)  * Returns: 0 if ok, < 0 errno code on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)  * If the message is  NULL, pretend it didn't happen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) int wimax_gnl_re_state_change_send(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	struct wimax_dev *wimax_dev, struct sk_buff *report_skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	void *header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	int result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	struct device *dev = wimax_dev_to_dev(wimax_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	d_fnstart(3, dev, "(wimax_dev %p report_skb %p)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		  wimax_dev, report_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	if (report_skb == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 		result = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	genlmsg_end(report_skb, header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	genlmsg_multicast(&wimax_gnl_family, report_skb, 0, 0, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	d_fnend(3, dev, "(wimax_dev %p report_skb %p) = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		wimax_dev, report_skb, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) void __check_new_state(enum wimax_st old_state, enum wimax_st new_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 		       unsigned int allowed_states_bm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	if (WARN_ON(((1 << new_state) & allowed_states_bm) == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 		pr_err("SW BUG! Forbidden state change %u -> %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 		       old_state, new_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)  * Set the current state of a WiMAX device [unlocking version of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)  * wimax_state_change().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) void __wimax_state_change(struct wimax_dev *wimax_dev, enum wimax_st new_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	struct device *dev = wimax_dev_to_dev(wimax_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	enum wimax_st old_state = wimax_dev->state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	struct sk_buff *stch_skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	void *header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	d_fnstart(3, dev, "(wimax_dev %p new_state %u [old %u])\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		  wimax_dev, new_state, old_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	if (WARN_ON(new_state >= __WIMAX_ST_INVALID)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 		dev_err(dev, "SW BUG: requesting invalid state %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 			new_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	if (old_state == new_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	header = NULL;	/* gcc complains? can't grok why */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	stch_skb = wimax_gnl_re_state_change_alloc(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 		wimax_dev, new_state, old_state, &header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	/* Verify the state transition and do exit-from-state actions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	switch (old_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	case __WIMAX_ST_NULL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		__check_new_state(old_state, new_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 				  1 << WIMAX_ST_DOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	case WIMAX_ST_DOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 		__check_new_state(old_state, new_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 				  1 << __WIMAX_ST_QUIESCING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 				  | 1 << WIMAX_ST_UNINITIALIZED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 				  | 1 << WIMAX_ST_RADIO_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	case __WIMAX_ST_QUIESCING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 		__check_new_state(old_state, new_state, 1 << WIMAX_ST_DOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	case WIMAX_ST_UNINITIALIZED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 		__check_new_state(old_state, new_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 				  1 << __WIMAX_ST_QUIESCING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 				  | 1 << WIMAX_ST_RADIO_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	case WIMAX_ST_RADIO_OFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 		__check_new_state(old_state, new_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 				  1 << __WIMAX_ST_QUIESCING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 				  | 1 << WIMAX_ST_READY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	case WIMAX_ST_READY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 		__check_new_state(old_state, new_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 				  1 << __WIMAX_ST_QUIESCING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 				  | 1 << WIMAX_ST_RADIO_OFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 				  | 1 << WIMAX_ST_SCANNING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 				  | 1 << WIMAX_ST_CONNECTING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 				  | 1 << WIMAX_ST_CONNECTED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	case WIMAX_ST_SCANNING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 		__check_new_state(old_state, new_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 				  1 << __WIMAX_ST_QUIESCING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 				  | 1 << WIMAX_ST_RADIO_OFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 				  | 1 << WIMAX_ST_READY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 				  | 1 << WIMAX_ST_CONNECTING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 				  | 1 << WIMAX_ST_CONNECTED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	case WIMAX_ST_CONNECTING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 		__check_new_state(old_state, new_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 				  1 << __WIMAX_ST_QUIESCING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 				  | 1 << WIMAX_ST_RADIO_OFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 				  | 1 << WIMAX_ST_READY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 				  | 1 << WIMAX_ST_SCANNING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 				  | 1 << WIMAX_ST_CONNECTED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	case WIMAX_ST_CONNECTED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		__check_new_state(old_state, new_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 				  1 << __WIMAX_ST_QUIESCING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 				  | 1 << WIMAX_ST_RADIO_OFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 				  | 1 << WIMAX_ST_READY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 		netif_tx_disable(wimax_dev->net_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 		netif_carrier_off(wimax_dev->net_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	case __WIMAX_ST_INVALID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 		dev_err(dev, "SW BUG: wimax_dev %p is in unknown state %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 			wimax_dev, wimax_dev->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 		WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	/* Execute the actions of entry to the new state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	switch (new_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	case __WIMAX_ST_NULL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 		dev_err(dev, "SW BUG: wimax_dev %p entering NULL state "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 			"from %u\n", wimax_dev, wimax_dev->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 		WARN_ON(1);		/* Nobody can enter this state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	case WIMAX_ST_DOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	case __WIMAX_ST_QUIESCING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	case WIMAX_ST_UNINITIALIZED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	case WIMAX_ST_RADIO_OFF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	case WIMAX_ST_READY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	case WIMAX_ST_SCANNING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	case WIMAX_ST_CONNECTING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	case WIMAX_ST_CONNECTED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 		netif_carrier_on(wimax_dev->net_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		netif_wake_queue(wimax_dev->net_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	case __WIMAX_ST_INVALID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 		BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	__wimax_state_set(wimax_dev, new_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	if (!IS_ERR(stch_skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 		wimax_gnl_re_state_change_send(wimax_dev, stch_skb, header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	d_fnend(3, dev, "(wimax_dev %p new_state %u [old %u]) = void\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 		wimax_dev, new_state, old_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)  * wimax_state_change - Set the current state of a WiMAX device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)  * @wimax_dev: WiMAX device descriptor (properly referenced)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)  * @new_state: New state to switch to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)  * This implements the state changes for the wimax devices. It will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)  * - verify that the state transition is legal (for now it'll just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)  *   print a warning if not) according to the table in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)  *   linux/wimax.h's documentation for 'enum wimax_st'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)  * - perform the actions needed for leaving the current state and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)  *   whichever are needed for entering the new state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)  * - issue a report to user space indicating the new state (and an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)  *   optional payload with information about the new state).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)  * NOTE: @wimax_dev must be locked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) void wimax_state_change(struct wimax_dev *wimax_dev, enum wimax_st new_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	 * A driver cannot take the wimax_dev out of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	 * __WIMAX_ST_NULL state unless by calling wimax_dev_add(). If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	 * the wimax_dev's state is still NULL, we ignore any request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	 * to change its state because it means it hasn't been yet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	 * registered.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	 * There is no need to complain about it, as routines that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	 * call this might be shared from different code paths that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	 * are called before or after wimax_dev_add() has done its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	 * job.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	mutex_lock(&wimax_dev->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	if (wimax_dev->state > __WIMAX_ST_NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 		__wimax_state_change(wimax_dev, new_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	mutex_unlock(&wimax_dev->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) EXPORT_SYMBOL_GPL(wimax_state_change);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)  * wimax_state_get() - Return the current state of a WiMAX device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)  * @wimax_dev: WiMAX device descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)  * Returns: Current state of the device according to its driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) enum wimax_st wimax_state_get(struct wimax_dev *wimax_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	enum wimax_st state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	mutex_lock(&wimax_dev->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 	state = wimax_dev->state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	mutex_unlock(&wimax_dev->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	return state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) EXPORT_SYMBOL_GPL(wimax_state_get);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)  * wimax_dev_init - initialize a newly allocated instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)  * @wimax_dev: WiMAX device descriptor to initialize.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)  * Initializes fields of a freshly allocated @wimax_dev instance. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)  * function assumes that after allocation, the memory occupied by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)  * @wimax_dev was zeroed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) void wimax_dev_init(struct wimax_dev *wimax_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	INIT_LIST_HEAD(&wimax_dev->id_table_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	__wimax_state_set(wimax_dev, __WIMAX_ST_NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	mutex_init(&wimax_dev->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	mutex_init(&wimax_dev->mutex_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) EXPORT_SYMBOL_GPL(wimax_dev_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) static const struct nla_policy wimax_gnl_policy[WIMAX_GNL_ATTR_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	[WIMAX_GNL_RESET_IFIDX] = { .type = NLA_U32, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	[WIMAX_GNL_RFKILL_IFIDX] = { .type = NLA_U32, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	[WIMAX_GNL_RFKILL_STATE] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 		.type = NLA_U32		/* enum wimax_rf_state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 	[WIMAX_GNL_STGET_IFIDX] = { .type = NLA_U32, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	[WIMAX_GNL_MSG_IFIDX] = { .type = NLA_U32, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	[WIMAX_GNL_MSG_DATA] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 		.type = NLA_UNSPEC,	/* libnl doesn't grok BINARY yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) static const struct genl_small_ops wimax_gnl_ops[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 		.cmd = WIMAX_GNL_OP_MSG_FROM_USER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 		.flags = GENL_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 		.doit = wimax_gnl_doit_msg_from_user,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 		.cmd = WIMAX_GNL_OP_RESET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 		.flags = GENL_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 		.doit = wimax_gnl_doit_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 		.cmd = WIMAX_GNL_OP_RFKILL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 		.flags = GENL_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 		.doit = wimax_gnl_doit_rfkill,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 		.cmd = WIMAX_GNL_OP_STATE_GET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 		.flags = GENL_ADMIN_PERM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 		.doit = wimax_gnl_doit_state_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) size_t wimax_addr_scnprint(char *addr_str, size_t addr_str_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 			   unsigned char *addr, size_t addr_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 	unsigned int cnt, total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 	for (total = cnt = 0; cnt < addr_len; cnt++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 		total += scnprintf(addr_str + total, addr_str_size - total,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 				   "%02x%c", addr[cnt],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 				   cnt == addr_len - 1 ? '\0' : ':');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	return total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)  * wimax_dev_add - Register a new WiMAX device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)  * @wimax_dev: WiMAX device descriptor (as embedded in your @net_dev's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)  *     priv data). You must have called wimax_dev_init() on it before.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)  * @net_dev: net device the @wimax_dev is associated with. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)  *     function expects SET_NETDEV_DEV() and register_netdev() were
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)  *     already called on it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)  * Registers the new WiMAX device, sets up the user-kernel control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)  * interface (generic netlink) and common WiMAX infrastructure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)  * Note that the parts that will allow interaction with user space are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)  * setup at the very end, when the rest is in place, as once that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)  * happens, the driver might get user space control requests via
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)  * netlink or from debugfs that might translate into calls into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)  * wimax_dev->op_*().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) int wimax_dev_add(struct wimax_dev *wimax_dev, struct net_device *net_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 	int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	struct device *dev = net_dev->dev.parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 	char addr_str[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 	d_fnstart(3, dev, "(wimax_dev %p net_dev %p)\n", wimax_dev, net_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 	/* Do the RFKILL setup before locking, as RFKILL will call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 	 * into our functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 	wimax_dev->net_dev = net_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	result = wimax_rfkill_add(wimax_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 	if (result < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 		goto error_rfkill_add;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 	/* Set up user-space interaction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	mutex_lock(&wimax_dev->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 	wimax_id_table_add(wimax_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	wimax_debugfs_add(wimax_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	__wimax_state_set(wimax_dev, WIMAX_ST_DOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	mutex_unlock(&wimax_dev->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	wimax_addr_scnprint(addr_str, sizeof(addr_str),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 			    net_dev->dev_addr, net_dev->addr_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	dev_err(dev, "WiMAX interface %s (%s) ready\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 		net_dev->name, addr_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	d_fnend(3, dev, "(wimax_dev %p net_dev %p) = 0\n", wimax_dev, net_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) error_rfkill_add:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 	d_fnend(3, dev, "(wimax_dev %p net_dev %p) = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 		wimax_dev, net_dev, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) EXPORT_SYMBOL_GPL(wimax_dev_add);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)  * wimax_dev_rm - Unregister an existing WiMAX device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)  * @wimax_dev: WiMAX device descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)  * Unregisters a WiMAX device previously registered for use with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)  * wimax_add_rm().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)  * IMPORTANT! Must call before calling unregister_netdev().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)  * After this function returns, you will not get any more user space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)  * control requests (via netlink or debugfs) and thus to wimax_dev->ops.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)  * Reentrancy control is ensured by setting the state to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)  * %__WIMAX_ST_QUIESCING. rfkill operations coming through
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)  * wimax_*rfkill*() will be stopped by the quiescing state; ops coming
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)  * from the rfkill subsystem will be stopped by the support being
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)  * removed by wimax_rfkill_rm().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) void wimax_dev_rm(struct wimax_dev *wimax_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 	d_fnstart(3, NULL, "(wimax_dev %p)\n", wimax_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 	mutex_lock(&wimax_dev->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 	__wimax_state_change(wimax_dev, __WIMAX_ST_QUIESCING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 	wimax_debugfs_rm(wimax_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 	wimax_id_table_rm(wimax_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 	__wimax_state_change(wimax_dev, WIMAX_ST_DOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 	mutex_unlock(&wimax_dev->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 	wimax_rfkill_rm(wimax_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 	d_fnend(3, NULL, "(wimax_dev %p) = void\n", wimax_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) EXPORT_SYMBOL_GPL(wimax_dev_rm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) /* Debug framework control of debug levels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) struct d_level D_LEVEL[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 	D_SUBMODULE_DEFINE(debugfs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 	D_SUBMODULE_DEFINE(id_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 	D_SUBMODULE_DEFINE(op_msg),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 	D_SUBMODULE_DEFINE(op_reset),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 	D_SUBMODULE_DEFINE(op_rfkill),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 	D_SUBMODULE_DEFINE(op_state_get),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 	D_SUBMODULE_DEFINE(stack),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) static const struct genl_multicast_group wimax_gnl_mcgrps[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 	{ .name = "msg", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) struct genl_family wimax_gnl_family __ro_after_init = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 	.name = "WiMAX",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 	.version = WIMAX_GNL_VERSION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 	.hdrsize = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 	.maxattr = WIMAX_GNL_ATTR_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 	.policy = wimax_gnl_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 	.module = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 	.small_ops = wimax_gnl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 	.n_small_ops = ARRAY_SIZE(wimax_gnl_ops),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 	.mcgrps = wimax_gnl_mcgrps,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 	.n_mcgrps = ARRAY_SIZE(wimax_gnl_mcgrps),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) /* Shutdown the wimax stack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) int __init wimax_subsys_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 	int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 	d_fnstart(4, NULL, "()\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 	d_parse_params(D_LEVEL, D_LEVEL_SIZE, wimax_debug_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 		       "wimax.debug");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 	result = genl_register_family(&wimax_gnl_family);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 	if (unlikely(result < 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 		pr_err("cannot register generic netlink family: %d\n", result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 		goto error_register_family;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 	d_fnend(4, NULL, "() = 0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) error_register_family:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 	d_fnend(4, NULL, "() = %d\n", result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 	return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) module_init(wimax_subsys_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) /* Shutdown the wimax stack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) void __exit wimax_subsys_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 	wimax_id_table_release();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 	genl_unregister_family(&wimax_gnl_family);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) module_exit(wimax_subsys_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) MODULE_AUTHOR("Intel Corporation <linux-wimax@intel.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) MODULE_DESCRIPTION("Linux WiMAX stack");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) MODULE_LICENSE("GPL");