^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");