Commit 05318bc9 authored by David S. Miller's avatar David S. Miller
Browse files
Conflicts:
	drivers/net/wireless/libertas/host.h
parents ea812ca1 88c1f4f6
Loading
Loading
Loading
Loading
+72 −36
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
 * Copyright (c) 2004 Balint Seeber <n0_5p4m_p13453@hotmail.com>
 * Copyright (c) 2007 Guido Guenther <agx@sigxcpu.org>
 * Copyright (c) 2007 Kalle Valo <kalle.valo@iki.fi>
 * Copyright (c) 2010 Sebastian Smolorz <sesmo@gmx.net>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
@@ -1649,6 +1650,58 @@ exit:
		return NULL;
}

static int at76_join(struct at76_priv *priv)
{
	struct at76_req_join join;
	int ret;

	memset(&join, 0, sizeof(struct at76_req_join));
	memcpy(join.essid, priv->essid, priv->essid_size);
	join.essid_size = priv->essid_size;
	memcpy(join.bssid, priv->bssid, ETH_ALEN);
	join.bss_type = INFRASTRUCTURE_MODE;
	join.channel = priv->channel;
	join.timeout = cpu_to_le16(2000);

	at76_dbg(DBG_MAC80211, "%s: sending CMD_JOIN", __func__);
	ret = at76_set_card_command(priv->udev, CMD_JOIN, &join,
				    sizeof(struct at76_req_join));

	if (ret < 0) {
		printk(KERN_ERR "%s: at76_set_card_command failed: %d\n",
		       wiphy_name(priv->hw->wiphy), ret);
		return 0;
	}

	ret = at76_wait_completion(priv, CMD_JOIN);
	at76_dbg(DBG_MAC80211, "%s: CMD_JOIN returned: 0x%02x", __func__, ret);
	if (ret != CMD_STATUS_COMPLETE) {
		printk(KERN_ERR "%s: at76_wait_completion failed: %d\n",
		       wiphy_name(priv->hw->wiphy), ret);
		return 0;
	}

	at76_set_pm_mode(priv);

	return 0;
}

static void at76_work_join_bssid(struct work_struct *work)
{
	struct at76_priv *priv = container_of(work, struct at76_priv,
					      work_join_bssid);

	if (priv->device_unplugged)
		return;

	mutex_lock(&priv->mtx);

	if (is_valid_ether_addr(priv->bssid))
		at76_join(priv);

	mutex_unlock(&priv->mtx);
}

static void at76_mac80211_tx_callback(struct urb *urb)
{
	struct at76_priv *priv = urb->context;
@@ -1686,6 +1739,7 @@ static int at76_mac80211_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
	struct at76_priv *priv = hw->priv;
	struct at76_tx_buffer *tx_buffer = priv->bulk_out_buffer;
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
	int padding, submit_len, ret;

	at76_dbg(DBG_MAC80211, "%s()", __func__);
@@ -1696,6 +1750,21 @@ static int at76_mac80211_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
		return NETDEV_TX_BUSY;
	}

	/* The following code lines are important when the device is going to
	 * authenticate with a new bssid. The driver must send CMD_JOIN before
	 * an authentication frame is transmitted. For this to succeed, the
	 * correct bssid of the AP must be known. As mac80211 does not inform
	 * drivers about the bssid prior to the authentication process the
	 * following workaround is necessary. If the TX frame is an
	 * authentication frame extract the bssid and send the CMD_JOIN. */
	if (mgmt->frame_control & cpu_to_le16(IEEE80211_STYPE_AUTH)) {
		if (compare_ether_addr(priv->bssid, mgmt->bssid)) {
			memcpy(priv->bssid, mgmt->bssid, ETH_ALEN);
			ieee80211_queue_work(hw, &priv->work_join_bssid);
			return NETDEV_TX_BUSY;
		}
	}

	ieee80211_stop_queues(hw);

	at76_ledtrig_tx_activity();	/* tell ledtrigger we send a packet */
@@ -1770,6 +1839,7 @@ static void at76_mac80211_stop(struct ieee80211_hw *hw)
	at76_dbg(DBG_MAC80211, "%s()", __func__);

	cancel_delayed_work(&priv->dwork_hw_scan);
	cancel_work_sync(&priv->work_join_bssid);
	cancel_work_sync(&priv->work_set_promisc);

	mutex_lock(&priv->mtx);
@@ -1818,42 +1888,6 @@ static void at76_remove_interface(struct ieee80211_hw *hw,
	at76_dbg(DBG_MAC80211, "%s()", __func__);
}

static int at76_join(struct at76_priv *priv)
{
	struct at76_req_join join;
	int ret;

	memset(&join, 0, sizeof(struct at76_req_join));
	memcpy(join.essid, priv->essid, priv->essid_size);
	join.essid_size = priv->essid_size;
	memcpy(join.bssid, priv->bssid, ETH_ALEN);
	join.bss_type = INFRASTRUCTURE_MODE;
	join.channel = priv->channel;
	join.timeout = cpu_to_le16(2000);

	at76_dbg(DBG_MAC80211, "%s: sending CMD_JOIN", __func__);
	ret = at76_set_card_command(priv->udev, CMD_JOIN, &join,
				    sizeof(struct at76_req_join));

	if (ret < 0) {
		printk(KERN_ERR "%s: at76_set_card_command failed: %d\n",
		       wiphy_name(priv->hw->wiphy), ret);
		return 0;
	}

	ret = at76_wait_completion(priv, CMD_JOIN);
	at76_dbg(DBG_MAC80211, "%s: CMD_JOIN returned: 0x%02x", __func__, ret);
	if (ret != CMD_STATUS_COMPLETE) {
		printk(KERN_ERR "%s: at76_wait_completion failed: %d\n",
		       wiphy_name(priv->hw->wiphy), ret);
		return 0;
	}

	at76_set_pm_mode(priv);

	return 0;
}

static void at76_dwork_hw_scan(struct work_struct *work)
{
	struct at76_priv *priv = container_of(work, struct at76_priv,
@@ -2107,6 +2141,7 @@ static struct at76_priv *at76_alloc_new_device(struct usb_device *udev)
	mutex_init(&priv->mtx);
	INIT_WORK(&priv->work_set_promisc, at76_work_set_promisc);
	INIT_WORK(&priv->work_submit_rx, at76_work_submit_rx);
	INIT_WORK(&priv->work_join_bssid, at76_work_join_bssid);
	INIT_DELAYED_WORK(&priv->dwork_hw_scan, at76_dwork_hw_scan);

	tasklet_init(&priv->rx_tasklet, at76_rx_tasklet, 0);
@@ -2508,5 +2543,6 @@ MODULE_AUTHOR("Balint Seeber <n0_5p4m_p13453@hotmail.com>");
MODULE_AUTHOR("Pavel Roskin <proski@gnu.org>");
MODULE_AUTHOR("Guido Guenther <agx@sigxcpu.org>");
MODULE_AUTHOR("Kalle Valo <kalle.valo@iki.fi>");
MODULE_AUTHOR("Sebastian Smolorz <sesmo@gmx.net>");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
+1 −0
Original line number Diff line number Diff line
@@ -387,6 +387,7 @@ struct at76_priv {
	/* work queues */
	struct work_struct work_set_promisc;
	struct work_struct work_submit_rx;
	struct work_struct work_join_bssid;
	struct delayed_work dwork_hw_scan;

	struct tasklet_struct rx_tasklet;
+1 −1
Original line number Diff line number Diff line
@@ -1768,7 +1768,7 @@ ath5k_hw_set_fast_div(struct ath5k_hw *ah, u8 ee_mode, bool enable)

	if (enable) {
		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART,
				AR5K_PHY_RESTART_DIV_GC, 1);
				AR5K_PHY_RESTART_DIV_GC, 4);

		AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV,
					AR5K_PHY_FAST_ANT_DIV_EN);
+20 −0
Original line number Diff line number Diff line
@@ -295,6 +295,26 @@ static void ar9003_hw_configpcipowersave(struct ath_hw *ah,
		/* Several PCIe massages to ensure proper behaviour */
		if (ah->config.pcie_waen)
			REG_WRITE(ah, AR_WA, ah->config.pcie_waen);
		else
			REG_WRITE(ah, AR_WA, ah->WARegVal);
	}

	/*
	 * Configire PCIE after Ini init. SERDES values now come from ini file
	 * This enables PCIe low power mode.
	 */
	if (ah->config.pcieSerDesWrite) {
		unsigned int i;
		struct ar5416IniArray *array;

		array = power_off ? &ah->iniPcieSerdes :
				    &ah->iniPcieSerdesLowPower;

		for (i = 0; i < array->ia_rows; i++) {
			REG_WRITE(ah,
				  INI_RA(array, i, 0),
				  INI_RA(array, i, 1));
		}
	}
}

+5 −1
Original line number Diff line number Diff line
@@ -226,6 +226,7 @@ struct ath_buf_state {
	int bfs_retries;
	u8 bf_type;
	u8 bfs_paprd;
	unsigned long bfs_paprd_timestamp;
	u32 bfs_keyix;
	enum ath9k_key_type bfs_keytype;
};
@@ -425,6 +426,8 @@ int ath_beaconq_config(struct ath_softc *sc);
#define ATH_LONG_CALINTERVAL      30000   /* 30 seconds */
#define ATH_RESTART_CALINTERVAL   1200000 /* 20 minutes */

#define ATH_PAPRD_TIMEOUT	100 /* msecs */

void ath_paprd_calibrate(struct work_struct *work);
void ath_ani_calibrate(unsigned long data);

@@ -516,6 +519,7 @@ void ath_deinit_leds(struct ath_softc *sc);
#define SC_OP_TSF_RESET              BIT(11)
#define SC_OP_BT_PRIORITY_DETECTED   BIT(12)
#define SC_OP_BT_SCAN		     BIT(13)
#define SC_OP_ANI_RUN		     BIT(14)

/* Powersave flags */
#define PS_WAIT_FOR_BEACON        BIT(0)
@@ -559,7 +563,6 @@ struct ath_softc {
	struct mutex mutex;
	struct work_struct paprd_work;
	struct completion paprd_complete;
	int paprd_txok;

	u32 intrstatus;
	u32 sc_flags; /* SC_OP_* */
@@ -628,6 +631,7 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz)

extern struct ieee80211_ops ath9k_ops;
extern int modparam_nohwcrypt;
extern int led_blink;

irqreturn_t ath_isr(int irq, void *dev);
int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
Loading