Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1f87f7d3 authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville
Browse files

cfg80211: add rfkill support



To be easier on drivers and users, have cfg80211 register an
rfkill structure that drivers can access. When soft-killed,
simply take down all interfaces; when hard-killed the driver
needs to notify us and we will take down the interfaces
after the fact. While rfkilled, interfaces cannot be set UP.

Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 6081162e
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -106,4 +106,6 @@
#define	EOWNERDEAD	130	/* Owner died */
#define	ENOTRECOVERABLE	131	/* State not recoverable */

#define ERFKILL		132	/* Operation not possible due to RF-kill */

#endif
+25 −4
Original line number Diff line number Diff line
@@ -757,13 +757,11 @@ enum wiphy_params_flags {
 * @TX_POWER_AUTOMATIC: the dbm parameter is ignored
 * @TX_POWER_LIMITED: limit TX power by the dbm parameter
 * @TX_POWER_FIXED: fix TX power to the dbm parameter
 * @TX_POWER_OFF: turn off completely (will go away)
 */
enum tx_power_setting {
	TX_POWER_AUTOMATIC,
	TX_POWER_LIMITED,
	TX_POWER_FIXED,
	TX_POWER_OFF,
};

/**
@@ -855,8 +853,10 @@ enum tx_power_setting {
 *
 * @set_tx_power: set the transmit power according to the parameters
 * @get_tx_power: store the current TX power into the dbm variable;
 *	return 0 if successful; or -ENETDOWN if successful but power
 *	is disabled (this will go away)
 *	return 0 if successful
 *
 * @rfkill_poll: polls the hw rfkill line, use cfg80211 reporting
 *	functions to adjust rfkill hw state
 */
struct cfg80211_ops {
	int	(*suspend)(struct wiphy *wiphy);
@@ -952,6 +952,8 @@ struct cfg80211_ops {
	int	(*set_tx_power)(struct wiphy *wiphy,
				enum tx_power_setting type, int dbm);
	int	(*get_tx_power)(struct wiphy *wiphy, int *dbm);

	void	(*rfkill_poll)(struct wiphy *wiphy);
};

/*
@@ -1666,4 +1668,23 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
 */
void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp);

/**
 * wiphy_rfkill_set_hw_state - notify cfg80211 about hw block state
 * @wiphy: the wiphy
 * @blocked: block status
 */
void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked);

/**
 * wiphy_rfkill_start_polling - start polling rfkill
 * @wiphy: the wiphy
 */
void wiphy_rfkill_start_polling(struct wiphy *wiphy);

/**
 * wiphy_rfkill_stop_polling - stop polling rfkill
 * @wiphy: the wiphy
 */
void wiphy_rfkill_stop_polling(struct wiphy *wiphy);

#endif /* __NET_CFG80211_H */
+17 −3
Original line number Diff line number Diff line
@@ -526,7 +526,7 @@ enum ieee80211_conf_flags {
/**
 * enum ieee80211_conf_changed - denotes which configuration changed
 *
 * @IEEE80211_CONF_CHANGE_RADIO_ENABLED: the value of radio_enabled changed
 * @_IEEE80211_CONF_CHANGE_RADIO_ENABLED: DEPRECATED
 * @IEEE80211_CONF_CHANGE_LISTEN_INTERVAL: the listen interval changed
 * @IEEE80211_CONF_CHANGE_RADIOTAP: the radiotap flag changed
 * @IEEE80211_CONF_CHANGE_PS: the PS flag or dynamic PS timeout changed
@@ -536,7 +536,7 @@ enum ieee80211_conf_flags {
 * @IEEE80211_CONF_CHANGE_IDLE: Idle flag changed
 */
enum ieee80211_conf_changed {
	IEEE80211_CONF_CHANGE_RADIO_ENABLED	= BIT(0),
	_IEEE80211_CONF_CHANGE_RADIO_ENABLED	= BIT(0),
	IEEE80211_CONF_CHANGE_LISTEN_INTERVAL	= BIT(2),
	IEEE80211_CONF_CHANGE_RADIOTAP		= BIT(3),
	IEEE80211_CONF_CHANGE_PS		= BIT(4),
@@ -546,6 +546,14 @@ enum ieee80211_conf_changed {
	IEEE80211_CONF_CHANGE_IDLE		= BIT(8),
};

static inline __deprecated enum ieee80211_conf_changed
__IEEE80211_CONF_CHANGE_RADIO_ENABLED(void)
{
	return _IEEE80211_CONF_CHANGE_RADIO_ENABLED;
}
#define IEEE80211_CONF_CHANGE_RADIO_ENABLED \
	__IEEE80211_CONF_CHANGE_RADIO_ENABLED()

/**
 * struct ieee80211_conf - configuration of the device
 *
@@ -585,7 +593,7 @@ struct ieee80211_conf {
	int max_sleep_period;

	u16 listen_interval;
	bool radio_enabled;
	bool __deprecated radio_enabled;

	u8 long_frame_max_tx_count, short_frame_max_tx_count;

@@ -1396,6 +1404,10 @@ enum ieee80211_ampdu_mlme_action {
 * 	is the first frame we expect to perform the action on. Notice
 * 	that TX/RX_STOP can pass NULL for this parameter.
 *	Returns a negative error code on failure.
 *
 * @rfkill_poll: Poll rfkill hardware state. If you need this, you also
 *	need to set wiphy->rfkill_poll to %true before registration,
 *	and need to call wiphy_rfkill_set_hw_state() in the callback.
 */
struct ieee80211_ops {
	int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
@@ -1444,6 +1456,8 @@ struct ieee80211_ops {
	int (*ampdu_action)(struct ieee80211_hw *hw,
			    enum ieee80211_ampdu_mlme_action action,
			    struct ieee80211_sta *sta, u16 tid, u16 *ssn);

	void (*rfkill_poll)(struct ieee80211_hw *hw);
};

/**
+8 −12
Original line number Diff line number Diff line
@@ -1340,7 +1340,6 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
	struct ieee80211_local *local = wiphy_priv(wiphy);
	struct ieee80211_channel *chan = local->hw.conf.channel;
	u32 changes = 0;
	bool radio_enabled = true;

	switch (type) {
	case TX_POWER_AUTOMATIC:
@@ -1359,14 +1358,6 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
			return -EINVAL;
		local->user_power_level = dbm;
		break;
	case TX_POWER_OFF:
		radio_enabled = false;
		break;
	}

	if (radio_enabled != local->hw.conf.radio_enabled) {
		changes |= IEEE80211_CONF_CHANGE_RADIO_ENABLED;
		local->hw.conf.radio_enabled = radio_enabled;
	}

	ieee80211_hw_config(local, changes);
@@ -1380,12 +1371,16 @@ static int ieee80211_get_tx_power(struct wiphy *wiphy, int *dbm)

	*dbm = local->hw.conf.power_level;

	if (!local->hw.conf.radio_enabled)
		return -ENETDOWN;

	return 0;
}

static void ieee80211_rfkill_poll(struct wiphy *wiphy)
{
	struct ieee80211_local *local = wiphy_priv(wiphy);

	drv_rfkill_poll(local);
}

struct cfg80211_ops mac80211_config_ops = {
	.add_virtual_intf = ieee80211_add_iface,
	.del_virtual_intf = ieee80211_del_iface,
@@ -1427,4 +1422,5 @@ struct cfg80211_ops mac80211_config_ops = {
	.set_wiphy_params = ieee80211_set_wiphy_params,
	.set_tx_power = ieee80211_set_tx_power,
	.get_tx_power = ieee80211_get_tx_power,
	.rfkill_poll = ieee80211_rfkill_poll,
};
+7 −0
Original line number Diff line number Diff line
@@ -181,4 +181,11 @@ static inline int drv_ampdu_action(struct ieee80211_local *local,
						sta, tid, ssn);
	return -EOPNOTSUPP;
}


static inline void drv_rfkill_poll(struct ieee80211_local *local)
{
	if (local->ops->rfkill_poll)
		local->ops->rfkill_poll(&local->hw);
}
#endif /* __MAC80211_DRIVER_OPS */
Loading