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

Commit 3a643d24 authored by Ivo van Doorn's avatar Ivo van Doorn Committed by John W. Linville
Browse files

rt2x00: Fix in_atomic() usage



rt73usb and rt2500usb used in_atomic to determine
if a configuration step should be rescheduled or not.
Since in_atomic() is not a valid method to determine
if sleeping is allowed we should fix the way this is handled
by adding a new flag to rt2x00.

In addition mark LED class support for the drivers broken
since that also uses the broken in_atomic() method but
so far no solution exists to have LED triggers work only
in scheduled context.

Signed-off-by: default avatarIvo van Doorn <IvDoorn@gmail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 866a0503
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -134,7 +134,7 @@ config RT2500USB

config RT2500USB_LEDS
	bool "RT2500 leds support"
	depends on RT2500USB
	depends on RT2500USB && BROKEN
	select RT2X00_LIB_LEDS
	---help---
	  This adds support for led triggers provided my mac80211.
@@ -152,7 +152,7 @@ config RT73USB

config RT73USB_LEDS
	bool "RT73 leds support"
	depends on RT73USB
	depends on RT73USB && BROKEN
	select RT2X00_LIB_LEDS
	---help---
	  This adds support for led triggers provided my mac80211.
+29 −63
Original line number Diff line number Diff line
@@ -270,6 +270,31 @@ static void rt2400pci_led_brightness(struct led_classdev *led_cdev,
/*
 * Configuration handlers.
 */
static void rt2400pci_config_filter(struct rt2x00_dev *rt2x00dev,
				    const unsigned int filter_flags)
{
	u32 reg;

	/*
	 * Start configuration steps.
	 * Note that the version error will always be dropped
	 * since there is no filter for it at this time.
	 */
	rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
	rt2x00_set_field32(&reg, RXCSR0_DROP_CRC,
			   !(filter_flags & FIF_FCSFAIL));
	rt2x00_set_field32(&reg, RXCSR0_DROP_PHYSICAL,
			   !(filter_flags & FIF_PLCPFAIL));
	rt2x00_set_field32(&reg, RXCSR0_DROP_CONTROL,
			   !(filter_flags & FIF_CONTROL));
	rt2x00_set_field32(&reg, RXCSR0_DROP_NOT_TO_ME,
			   !(filter_flags & FIF_PROMISC_IN_BSS));
	rt2x00_set_field32(&reg, RXCSR0_DROP_TODS,
			   !(filter_flags & FIF_PROMISC_IN_BSS));
	rt2x00_set_field32(&reg, RXCSR0_DROP_VERSION_ERROR, 1);
	rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
}

static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev,
				  struct rt2x00_intf *intf,
				  struct rt2x00intf_conf *conf,
@@ -306,7 +331,7 @@ static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev,
					      conf->bssid, sizeof(conf->bssid));
}

static int rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,
static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,
				 struct rt2x00lib_erp *erp)
{
	int preamble_mask;
@@ -347,8 +372,6 @@ static int rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,
	rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
	rt2x00_set_field32(&reg, ARCSR2_LENGTH, get_duration(ACK_SIZE, 110));
	rt2x00pci_register_write(rt2x00dev, ARCSR5, reg);

	return 0;
}

static void rt2400pci_config_phymode(struct rt2x00_dev *rt2x00dev,
@@ -1397,64 +1420,6 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
 * IEEE80211 stack callback functions.
 */
static void rt2400pci_configure_filter(struct ieee80211_hw *hw,
				       unsigned int changed_flags,
				       unsigned int *total_flags,
				       int mc_count,
				       struct dev_addr_list *mc_list)
{
	struct rt2x00_dev *rt2x00dev = hw->priv;
	u32 reg;

	/*
	 * Mask off any flags we are going to ignore from
	 * the total_flags field.
	 */
	*total_flags &=
	    FIF_ALLMULTI |
	    FIF_FCSFAIL |
	    FIF_PLCPFAIL |
	    FIF_CONTROL |
	    FIF_OTHER_BSS |
	    FIF_PROMISC_IN_BSS;

	/*
	 * Apply some rules to the filters:
	 * - Some filters imply different filters to be set.
	 * - Some things we can't filter out at all.
	 */
	*total_flags |= FIF_ALLMULTI;
	if (*total_flags & FIF_OTHER_BSS ||
	    *total_flags & FIF_PROMISC_IN_BSS)
		*total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;

	/*
	 * Check if there is any work left for us.
	 */
	if (rt2x00dev->packet_filter == *total_flags)
		return;
	rt2x00dev->packet_filter = *total_flags;

	/*
	 * Start configuration steps.
	 * Note that the version error will always be dropped
	 * since there is no filter for it at this time.
	 */
	rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
	rt2x00_set_field32(&reg, RXCSR0_DROP_CRC,
			   !(*total_flags & FIF_FCSFAIL));
	rt2x00_set_field32(&reg, RXCSR0_DROP_PHYSICAL,
			   !(*total_flags & FIF_PLCPFAIL));
	rt2x00_set_field32(&reg, RXCSR0_DROP_CONTROL,
			   !(*total_flags & FIF_CONTROL));
	rt2x00_set_field32(&reg, RXCSR0_DROP_NOT_TO_ME,
			   !(*total_flags & FIF_PROMISC_IN_BSS));
	rt2x00_set_field32(&reg, RXCSR0_DROP_TODS,
			   !(*total_flags & FIF_PROMISC_IN_BSS));
	rt2x00_set_field32(&reg, RXCSR0_DROP_VERSION_ERROR, 1);
	rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
}

static int rt2400pci_set_retry_limit(struct ieee80211_hw *hw,
				     u32 short_retry, u32 long_retry)
{
@@ -1580,7 +1545,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
	.remove_interface	= rt2x00mac_remove_interface,
	.config			= rt2x00mac_config,
	.config_interface	= rt2x00mac_config_interface,
	.configure_filter	= rt2400pci_configure_filter,
	.configure_filter	= rt2x00mac_configure_filter,
	.get_stats		= rt2x00mac_get_stats,
	.set_retry_limit	= rt2400pci_set_retry_limit,
	.bss_info_changed	= rt2x00mac_bss_info_changed,
@@ -1608,6 +1573,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
	.write_tx_data		= rt2x00pci_write_tx_data,
	.kick_tx_queue		= rt2400pci_kick_tx_queue,
	.fill_rxdone		= rt2400pci_fill_rxdone,
	.config_filter		= rt2400pci_config_filter,
	.config_intf		= rt2400pci_config_intf,
	.config_erp		= rt2400pci_config_erp,
	.config			= rt2400pci_config,
+33 −68
Original line number Diff line number Diff line
@@ -270,6 +270,35 @@ static void rt2500pci_led_brightness(struct led_classdev *led_cdev,
/*
 * Configuration handlers.
 */
static void rt2500pci_config_filter(struct rt2x00_dev *rt2x00dev,
				    const unsigned int filter_flags)
{
	u32 reg;

	/*
	 * Start configuration steps.
	 * Note that the version error will always be dropped
	 * and broadcast frames will always be accepted since
	 * there is no filter for it at this time.
	 */
	rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
	rt2x00_set_field32(&reg, RXCSR0_DROP_CRC,
			   !(filter_flags & FIF_FCSFAIL));
	rt2x00_set_field32(&reg, RXCSR0_DROP_PHYSICAL,
			   !(filter_flags & FIF_PLCPFAIL));
	rt2x00_set_field32(&reg, RXCSR0_DROP_CONTROL,
			   !(filter_flags & FIF_CONTROL));
	rt2x00_set_field32(&reg, RXCSR0_DROP_NOT_TO_ME,
			   !(filter_flags & FIF_PROMISC_IN_BSS));
	rt2x00_set_field32(&reg, RXCSR0_DROP_TODS,
			   !(filter_flags & FIF_PROMISC_IN_BSS));
	rt2x00_set_field32(&reg, RXCSR0_DROP_VERSION_ERROR, 1);
	rt2x00_set_field32(&reg, RXCSR0_DROP_MCAST,
			   !(filter_flags & FIF_ALLMULTI));
	rt2x00_set_field32(&reg, RXCSR0_DROP_BCAST, 0);
	rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
}

static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev,
				  struct rt2x00_intf *intf,
				  struct rt2x00intf_conf *conf,
@@ -309,7 +338,7 @@ static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev,
					      conf->bssid, sizeof(conf->bssid));
}

static int rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev,
static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev,
				 struct rt2x00lib_erp *erp)
{
	int preamble_mask;
@@ -350,8 +379,6 @@ static int rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev,
	rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
	rt2x00_set_field32(&reg, ARCSR2_LENGTH, get_duration(ACK_SIZE, 110));
	rt2x00pci_register_write(rt2x00dev, ARCSR5, reg);

	return 0;
}

static void rt2500pci_config_phymode(struct rt2x00_dev *rt2x00dev,
@@ -1731,69 +1758,6 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
 * IEEE80211 stack callback functions.
 */
static void rt2500pci_configure_filter(struct ieee80211_hw *hw,
				       unsigned int changed_flags,
				       unsigned int *total_flags,
				       int mc_count,
				       struct dev_addr_list *mc_list)
{
	struct rt2x00_dev *rt2x00dev = hw->priv;
	u32 reg;

	/*
	 * Mask off any flags we are going to ignore from
	 * the total_flags field.
	 */
	*total_flags &=
	    FIF_ALLMULTI |
	    FIF_FCSFAIL |
	    FIF_PLCPFAIL |
	    FIF_CONTROL |
	    FIF_OTHER_BSS |
	    FIF_PROMISC_IN_BSS;

	/*
	 * Apply some rules to the filters:
	 * - Some filters imply different filters to be set.
	 * - Some things we can't filter out at all.
	 */
	if (mc_count)
		*total_flags |= FIF_ALLMULTI;
	if (*total_flags & FIF_OTHER_BSS ||
	    *total_flags & FIF_PROMISC_IN_BSS)
		*total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;

	/*
	 * Check if there is any work left for us.
	 */
	if (rt2x00dev->packet_filter == *total_flags)
		return;
	rt2x00dev->packet_filter = *total_flags;

	/*
	 * Start configuration steps.
	 * Note that the version error will always be dropped
	 * and broadcast frames will always be accepted since
	 * there is no filter for it at this time.
	 */
	rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
	rt2x00_set_field32(&reg, RXCSR0_DROP_CRC,
			   !(*total_flags & FIF_FCSFAIL));
	rt2x00_set_field32(&reg, RXCSR0_DROP_PHYSICAL,
			   !(*total_flags & FIF_PLCPFAIL));
	rt2x00_set_field32(&reg, RXCSR0_DROP_CONTROL,
			   !(*total_flags & FIF_CONTROL));
	rt2x00_set_field32(&reg, RXCSR0_DROP_NOT_TO_ME,
			   !(*total_flags & FIF_PROMISC_IN_BSS));
	rt2x00_set_field32(&reg, RXCSR0_DROP_TODS,
			   !(*total_flags & FIF_PROMISC_IN_BSS));
	rt2x00_set_field32(&reg, RXCSR0_DROP_VERSION_ERROR, 1);
	rt2x00_set_field32(&reg, RXCSR0_DROP_MCAST,
			   !(*total_flags & FIF_ALLMULTI));
	rt2x00_set_field32(&reg, RXCSR0_DROP_BCAST, 0);
	rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
}

static int rt2500pci_set_retry_limit(struct ieee80211_hw *hw,
				     u32 short_retry, u32 long_retry)
{
@@ -1894,7 +1858,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
	.remove_interface	= rt2x00mac_remove_interface,
	.config			= rt2x00mac_config,
	.config_interface	= rt2x00mac_config_interface,
	.configure_filter	= rt2500pci_configure_filter,
	.configure_filter	= rt2x00mac_configure_filter,
	.get_stats		= rt2x00mac_get_stats,
	.set_retry_limit	= rt2500pci_set_retry_limit,
	.bss_info_changed	= rt2x00mac_bss_info_changed,
@@ -1922,6 +1886,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
	.write_tx_data		= rt2x00pci_write_tx_data,
	.kick_tx_queue		= rt2500pci_kick_tx_queue,
	.fill_rxdone		= rt2500pci_fill_rxdone,
	.config_filter		= rt2500pci_config_filter,
	.config_intf		= rt2500pci_config_intf,
	.config_erp		= rt2500pci_config_erp,
	.config			= rt2500pci_config,
+34 −84
Original line number Diff line number Diff line
@@ -316,6 +316,35 @@ static void rt2500usb_led_brightness(struct led_classdev *led_cdev,
/*
 * Configuration handlers.
 */
static void rt2500usb_config_filter(struct rt2x00_dev *rt2x00dev,
				    const unsigned int filter_flags)
{
	u16 reg;

	/*
	 * Start configuration steps.
	 * Note that the version error will always be dropped
	 * and broadcast frames will always be accepted since
	 * there is no filter for it at this time.
	 */
	rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CRC,
			   !(filter_flags & FIF_FCSFAIL));
	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_PHYSICAL,
			   !(filter_flags & FIF_PLCPFAIL));
	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CONTROL,
			   !(filter_flags & FIF_CONTROL));
	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_NOT_TO_ME,
			   !(filter_flags & FIF_PROMISC_IN_BSS));
	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_TODS,
			   !(filter_flags & FIF_PROMISC_IN_BSS));
	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_VERSION_ERROR, 1);
	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_MULTICAST,
			   !(filter_flags & FIF_ALLMULTI));
	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_BROADCAST, 0);
	rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
}

static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev,
				  struct rt2x00_intf *intf,
				  struct rt2x00intf_conf *conf,
@@ -358,18 +387,11 @@ static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev,
					      (3 * sizeof(__le16)));
}

static int rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev,
static void rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev,
				 struct rt2x00lib_erp *erp)
{
	u16 reg;

	/*
	 * When in atomic context, we should let rt2x00lib
	 * try this configuration again later.
	 */
	if (in_atomic())
		return -EAGAIN;

	rt2500usb_register_read(rt2x00dev, TXRX_CSR1, &reg);
	rt2x00_set_field16(&reg, TXRX_CSR1_ACK_TIMEOUT, erp->ack_timeout);
	rt2500usb_register_write(rt2x00dev, TXRX_CSR1, reg);
@@ -378,8 +400,6 @@ static int rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev,
	rt2x00_set_field16(&reg, TXRX_CSR10_AUTORESPOND_PREAMBLE,
			   !!erp->short_preamble);
	rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg);

	return 0;
}

static void rt2500usb_config_phymode(struct rt2x00_dev *rt2x00dev,
@@ -1644,6 +1664,7 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
	 */
	__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
	__set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags);
	__set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags);

	/*
	 * Set the rssi offset.
@@ -1656,78 +1677,6 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
 * IEEE80211 stack callback functions.
 */
static void rt2500usb_configure_filter(struct ieee80211_hw *hw,
				       unsigned int changed_flags,
				       unsigned int *total_flags,
				       int mc_count,
				       struct dev_addr_list *mc_list)
{
	struct rt2x00_dev *rt2x00dev = hw->priv;
	u16 reg;

	/*
	 * Mask off any flags we are going to ignore from
	 * the total_flags field.
	 */
	*total_flags &=
	    FIF_ALLMULTI |
	    FIF_FCSFAIL |
	    FIF_PLCPFAIL |
	    FIF_CONTROL |
	    FIF_OTHER_BSS |
	    FIF_PROMISC_IN_BSS;

	/*
	 * Apply some rules to the filters:
	 * - Some filters imply different filters to be set.
	 * - Some things we can't filter out at all.
	 */
	if (mc_count)
		*total_flags |= FIF_ALLMULTI;
	if (*total_flags & FIF_OTHER_BSS ||
	    *total_flags & FIF_PROMISC_IN_BSS)
		*total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;

	/*
	 * Check if there is any work left for us.
	 */
	if (rt2x00dev->packet_filter == *total_flags)
		return;
	rt2x00dev->packet_filter = *total_flags;

	/*
	 * When in atomic context, reschedule and let rt2x00lib
	 * call this function again.
	 */
	if (in_atomic()) {
		queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work);
		return;
	}

	/*
	 * Start configuration steps.
	 * Note that the version error will always be dropped
	 * and broadcast frames will always be accepted since
	 * there is no filter for it at this time.
	 */
	rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CRC,
			   !(*total_flags & FIF_FCSFAIL));
	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_PHYSICAL,
			   !(*total_flags & FIF_PLCPFAIL));
	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_CONTROL,
			   !(*total_flags & FIF_CONTROL));
	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_NOT_TO_ME,
			   !(*total_flags & FIF_PROMISC_IN_BSS));
	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_TODS,
			   !(*total_flags & FIF_PROMISC_IN_BSS));
	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_VERSION_ERROR, 1);
	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_MULTICAST,
			   !(*total_flags & FIF_ALLMULTI));
	rt2x00_set_field16(&reg, TXRX_CSR2_DROP_BROADCAST, 0);
	rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
}

static int rt2500usb_beacon_update(struct ieee80211_hw *hw,
				   struct sk_buff *skb,
				   struct ieee80211_tx_control *control)
@@ -1824,7 +1773,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {
	.remove_interface	= rt2x00mac_remove_interface,
	.config			= rt2x00mac_config,
	.config_interface	= rt2x00mac_config_interface,
	.configure_filter	= rt2500usb_configure_filter,
	.configure_filter	= rt2x00mac_configure_filter,
	.get_stats		= rt2x00mac_get_stats,
	.bss_info_changed	= rt2x00mac_bss_info_changed,
	.conf_tx		= rt2x00mac_conf_tx,
@@ -1848,6 +1797,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
	.get_tx_data_len	= rt2500usb_get_tx_data_len,
	.kick_tx_queue		= rt2500usb_kick_tx_queue,
	.fill_rxdone		= rt2500usb_fill_rxdone,
	.config_filter		= rt2500usb_config_filter,
	.config_intf		= rt2500usb_config_intf,
	.config_erp		= rt2500usb_config_erp,
	.config			= rt2500usb_config,
+9 −2
Original line number Diff line number Diff line
@@ -560,6 +560,8 @@ struct rt2x00lib_ops {
	/*
	 * Configuration handlers.
	 */
	void (*config_filter) (struct rt2x00_dev *rt2x00dev,
			       const unsigned int filter_flags);
	void (*config_intf) (struct rt2x00_dev *rt2x00dev,
			     struct rt2x00_intf *intf,
			     struct rt2x00intf_conf *conf,
@@ -568,7 +570,7 @@ struct rt2x00lib_ops {
#define CONFIG_UPDATE_MAC		( 1 << 2 )
#define CONFIG_UPDATE_BSSID		( 1 << 3 )

	int (*config_erp) (struct rt2x00_dev *rt2x00dev,
	void (*config_erp) (struct rt2x00_dev *rt2x00dev,
			    struct rt2x00lib_erp *erp);
	void (*config) (struct rt2x00_dev *rt2x00dev,
			struct rt2x00lib_conf *libconf,
@@ -624,6 +626,7 @@ enum rt2x00_flags {
	DRIVER_REQUIRE_FIRMWARE,
	DRIVER_REQUIRE_BEACON_GUARD,
	DRIVER_REQUIRE_ATIM_QUEUE,
	DRIVER_REQUIRE_SCHEDULED,

	/*
	 * Driver configuration
@@ -987,6 +990,10 @@ int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
int rt2x00mac_config_interface(struct ieee80211_hw *hw,
			       struct ieee80211_vif *vif,
			       struct ieee80211_if_conf *conf);
void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
				unsigned int changed_flags,
				unsigned int *total_flags,
				int mc_count, struct dev_addr_list *mc_list);
int rt2x00mac_get_stats(struct ieee80211_hw *hw,
			struct ieee80211_low_level_stats *stats);
int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw,
Loading