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)  * Intel Wireless WiMAX Connection 2400m
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Implement backend for the WiMAX stack rfkill support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Copyright (C) 2007-2008 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)  * The WiMAX kernel stack integrates into RF-Kill and keeps the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * switches's status. We just need to:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * - report changes in the HW RF Kill switch [with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  *   wimax_rfkill_{sw,hw}_report(), which happens when we detect those
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  *   indications coming through hardware reports]. We also do it on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  *   initialization to let the stack know the initial HW state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  * - implement indications from the stack to change the SW RF Kill
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  *   switch (coming from sysfs, the wimax stack or user space).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include "i2400m.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <linux/wimax/i2400m.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #define D_SUBMODULE rfkill
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #include "debug-levels.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)  * Return true if the i2400m radio is in the requested wimax_rf_state state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) int i2400m_radio_is(struct i2400m *i2400m, enum wimax_rf_state state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	if (state == WIMAX_RF_OFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 		return i2400m->state == I2400M_SS_RF_OFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 			|| i2400m->state == I2400M_SS_RF_SHUTDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	else if (state == WIMAX_RF_ON)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 		/* state == WIMAX_RF_ON */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 		return i2400m->state != I2400M_SS_RF_OFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 			&& i2400m->state != I2400M_SS_RF_SHUTDOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 		BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 		return -EINVAL;	/* shut gcc warnings on certain arches */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51)  * WiMAX stack operation: implement SW RFKill toggling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53)  * @wimax_dev: device descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)  * @skb: skb where the message has been received; skb->data is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)  *       expected to point to the message payload.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  * @genl_info: passed by the generic netlink layer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58)  * Generic Netlink will call this function when a message is sent from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59)  * userspace to change the software RF-Kill switch status.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61)  * This function will set the device's software RF-Kill switch state to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)  * match what is requested.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64)  * NOTE: the i2400m has a strict state machine; we can only set the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65)  *       RF-Kill switch when it is on, the HW RF-Kill is on and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66)  *       device is initialized. So we ignore errors steaming from not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67)  *       being in the right state (-EILSEQ).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) int i2400m_op_rfkill_sw_toggle(struct wimax_dev *wimax_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 			       enum wimax_rf_state state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	struct i2400m *i2400m = wimax_dev_to_i2400m(wimax_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	struct device *dev = i2400m_dev(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	struct sk_buff *ack_skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		struct i2400m_l3l4_hdr hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 		struct i2400m_tlv_rf_operation sw_rf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	} __packed *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	char strerr[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	d_fnstart(4, dev, "(wimax_dev %p state %d)\n", wimax_dev, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	result = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	if (cmd == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		goto error_alloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	cmd->hdr.type = cpu_to_le16(I2400M_MT_CMD_RF_CONTROL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	cmd->hdr.length = cpu_to_le16(sizeof(cmd->sw_rf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	cmd->hdr.version = cpu_to_le16(I2400M_L3L4_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	cmd->sw_rf.hdr.type = cpu_to_le16(I2400M_TLV_RF_OPERATION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	cmd->sw_rf.hdr.length = cpu_to_le16(sizeof(cmd->sw_rf.status));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	switch (state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	case WIMAX_RF_OFF:	/* RFKILL ON, radio OFF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		cmd->sw_rf.status = cpu_to_le32(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	case WIMAX_RF_ON:	/* RFKILL OFF, radio ON */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 		cmd->sw_rf.status = cpu_to_le32(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	ack_skb = i2400m_msg_to_dev(i2400m, cmd, sizeof(*cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	result = PTR_ERR(ack_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	if (IS_ERR(ack_skb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		dev_err(dev, "Failed to issue 'RF Control' command: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 			result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		goto error_msg_to_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	result = i2400m_msg_check_status(wimax_msg_data(ack_skb),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 					 strerr, sizeof(strerr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	if (result < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 		dev_err(dev, "'RF Control' (0x%04x) command failed: %d - %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 			I2400M_MT_CMD_RF_CONTROL, result, strerr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		goto error_cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	/* Now we wait for the state to change to RADIO_OFF or RADIO_ON */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	result = wait_event_timeout(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 		i2400m->state_wq, i2400m_radio_is(i2400m, state),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		5 * HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	if (result == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 		result = -ETIMEDOUT;
^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, "Error waiting for device to toggle RF state: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 			"%d\n", result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) error_cmd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	kfree_skb(ack_skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) error_msg_to_dev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) error_alloc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	d_fnend(4, dev, "(wimax_dev %p state %d) = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		wimax_dev, state, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	kfree(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^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)  * Inform the WiMAX stack of changes in the RF Kill switches reported
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)  * by the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)  * @i2400m: device descriptor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)  * @rfss: TLV for RF Switches status; already validated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)  * NOTE: the reports on RF switch status cannot be trusted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)  *       or used until the device is in a state of RADIO_OFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)  *       or greater.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) void i2400m_report_tlv_rf_switches_status(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	struct i2400m *i2400m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	const struct i2400m_tlv_rf_switches_status *rfss)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	struct device *dev = i2400m_dev(i2400m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	enum i2400m_rf_switch_status hw, sw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	enum wimax_st wimax_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	sw = le32_to_cpu(rfss->sw_rf_switch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	hw = le32_to_cpu(rfss->hw_rf_switch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	d_fnstart(3, dev, "(i2400m %p rfss %p [hw %u sw %u])\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		  i2400m, rfss, hw, sw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	/* We only process rw switch evens when the device has been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	 * fully initialized */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	wimax_state = wimax_state_get(&i2400m->wimax_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	if (wimax_state < WIMAX_ST_RADIO_OFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		d_printf(3, dev, "ignoring RF switches report, state %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 			 wimax_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	switch (sw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	case I2400M_RF_SWITCH_ON:	/* RF Kill disabled (radio on) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 		wimax_report_rfkill_sw(&i2400m->wimax_dev, WIMAX_RF_ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	case I2400M_RF_SWITCH_OFF:	/* RF Kill enabled (radio off) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		wimax_report_rfkill_sw(&i2400m->wimax_dev, WIMAX_RF_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 		dev_err(dev, "HW BUG? Unknown RF SW state 0x%x\n", sw);
^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) 	switch (hw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	case I2400M_RF_SWITCH_ON:	/* RF Kill disabled (radio on) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		wimax_report_rfkill_hw(&i2400m->wimax_dev, WIMAX_RF_ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	case I2400M_RF_SWITCH_OFF:	/* RF Kill enabled (radio off) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 		wimax_report_rfkill_hw(&i2400m->wimax_dev, WIMAX_RF_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		dev_err(dev, "HW BUG? Unknown RF HW state 0x%x\n", hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	d_fnend(3, dev, "(i2400m %p rfss %p [hw %u sw %u]) = void\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		i2400m, rfss, hw, sw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }