xref: /openbmc/linux/drivers/net/wireless/zydas/zd1211rw/zd_mac.c (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
11ccea77eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
26948300cSKalle Valo /* ZD1211 USB-WLAN driver for Linux
36948300cSKalle Valo  *
46948300cSKalle Valo  * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
56948300cSKalle Valo  * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
66948300cSKalle Valo  * Copyright (C) 2006-2007 Michael Wu <flamingice@sourmilk.net>
76948300cSKalle Valo  * Copyright (C) 2007-2008 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
86948300cSKalle Valo  */
96948300cSKalle Valo 
106948300cSKalle Valo #include <linux/netdevice.h>
116948300cSKalle Valo #include <linux/etherdevice.h>
126948300cSKalle Valo #include <linux/slab.h>
136948300cSKalle Valo #include <linux/usb.h>
146948300cSKalle Valo #include <linux/jiffies.h>
156948300cSKalle Valo #include <net/ieee80211_radiotap.h>
166948300cSKalle Valo 
176948300cSKalle Valo #include "zd_def.h"
186948300cSKalle Valo #include "zd_chip.h"
196948300cSKalle Valo #include "zd_mac.h"
206948300cSKalle Valo #include "zd_rf.h"
216948300cSKalle Valo 
226948300cSKalle Valo struct zd_reg_alpha2_map {
236948300cSKalle Valo 	u32 reg;
246948300cSKalle Valo 	char alpha2[2];
256948300cSKalle Valo };
266948300cSKalle Valo 
276948300cSKalle Valo static struct zd_reg_alpha2_map reg_alpha2_map[] = {
286948300cSKalle Valo 	{ ZD_REGDOMAIN_FCC, "US" },
296948300cSKalle Valo 	{ ZD_REGDOMAIN_IC, "CA" },
306948300cSKalle Valo 	{ ZD_REGDOMAIN_ETSI, "DE" }, /* Generic ETSI, use most restrictive */
316948300cSKalle Valo 	{ ZD_REGDOMAIN_JAPAN, "JP" },
326948300cSKalle Valo 	{ ZD_REGDOMAIN_JAPAN_2, "JP" },
336948300cSKalle Valo 	{ ZD_REGDOMAIN_JAPAN_3, "JP" },
346948300cSKalle Valo 	{ ZD_REGDOMAIN_SPAIN, "ES" },
356948300cSKalle Valo 	{ ZD_REGDOMAIN_FRANCE, "FR" },
366948300cSKalle Valo };
376948300cSKalle Valo 
386948300cSKalle Valo /* This table contains the hardware specific values for the modulation rates. */
396948300cSKalle Valo static const struct ieee80211_rate zd_rates[] = {
406948300cSKalle Valo 	{ .bitrate = 10,
416948300cSKalle Valo 	  .hw_value = ZD_CCK_RATE_1M, },
426948300cSKalle Valo 	{ .bitrate = 20,
436948300cSKalle Valo 	  .hw_value = ZD_CCK_RATE_2M,
446948300cSKalle Valo 	  .hw_value_short = ZD_CCK_RATE_2M | ZD_CCK_PREA_SHORT,
456948300cSKalle Valo 	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
466948300cSKalle Valo 	{ .bitrate = 55,
476948300cSKalle Valo 	  .hw_value = ZD_CCK_RATE_5_5M,
486948300cSKalle Valo 	  .hw_value_short = ZD_CCK_RATE_5_5M | ZD_CCK_PREA_SHORT,
496948300cSKalle Valo 	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
506948300cSKalle Valo 	{ .bitrate = 110,
516948300cSKalle Valo 	  .hw_value = ZD_CCK_RATE_11M,
526948300cSKalle Valo 	  .hw_value_short = ZD_CCK_RATE_11M | ZD_CCK_PREA_SHORT,
536948300cSKalle Valo 	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
546948300cSKalle Valo 	{ .bitrate = 60,
556948300cSKalle Valo 	  .hw_value = ZD_OFDM_RATE_6M,
566948300cSKalle Valo 	  .flags = 0 },
576948300cSKalle Valo 	{ .bitrate = 90,
586948300cSKalle Valo 	  .hw_value = ZD_OFDM_RATE_9M,
596948300cSKalle Valo 	  .flags = 0 },
606948300cSKalle Valo 	{ .bitrate = 120,
616948300cSKalle Valo 	  .hw_value = ZD_OFDM_RATE_12M,
626948300cSKalle Valo 	  .flags = 0 },
636948300cSKalle Valo 	{ .bitrate = 180,
646948300cSKalle Valo 	  .hw_value = ZD_OFDM_RATE_18M,
656948300cSKalle Valo 	  .flags = 0 },
666948300cSKalle Valo 	{ .bitrate = 240,
676948300cSKalle Valo 	  .hw_value = ZD_OFDM_RATE_24M,
686948300cSKalle Valo 	  .flags = 0 },
696948300cSKalle Valo 	{ .bitrate = 360,
706948300cSKalle Valo 	  .hw_value = ZD_OFDM_RATE_36M,
716948300cSKalle Valo 	  .flags = 0 },
726948300cSKalle Valo 	{ .bitrate = 480,
736948300cSKalle Valo 	  .hw_value = ZD_OFDM_RATE_48M,
746948300cSKalle Valo 	  .flags = 0 },
756948300cSKalle Valo 	{ .bitrate = 540,
766948300cSKalle Valo 	  .hw_value = ZD_OFDM_RATE_54M,
776948300cSKalle Valo 	  .flags = 0 },
786948300cSKalle Valo };
796948300cSKalle Valo 
806948300cSKalle Valo /*
816948300cSKalle Valo  * Zydas retry rates table. Each line is listed in the same order as
826948300cSKalle Valo  * in zd_rates[] and contains all the rate used when a packet is sent
836948300cSKalle Valo  * starting with a given rates. Let's consider an example :
846948300cSKalle Valo  *
856948300cSKalle Valo  * "11 Mbits : 4, 3, 2, 1, 0" means :
866948300cSKalle Valo  * - packet is sent using 4 different rates
876948300cSKalle Valo  * - 1st rate is index 3 (ie 11 Mbits)
886948300cSKalle Valo  * - 2nd rate is index 2 (ie 5.5 Mbits)
896948300cSKalle Valo  * - 3rd rate is index 1 (ie 2 Mbits)
906948300cSKalle Valo  * - 4th rate is index 0 (ie 1 Mbits)
916948300cSKalle Valo  */
926948300cSKalle Valo 
936948300cSKalle Valo static const struct tx_retry_rate zd_retry_rates[] = {
946948300cSKalle Valo 	{ /*  1 Mbits */	1, { 0 }},
956948300cSKalle Valo 	{ /*  2 Mbits */	2, { 1,  0 }},
966948300cSKalle Valo 	{ /*  5.5 Mbits */	3, { 2,  1, 0 }},
976948300cSKalle Valo 	{ /* 11 Mbits */	4, { 3,  2, 1, 0 }},
986948300cSKalle Valo 	{ /*  6 Mbits */	5, { 4,  3, 2, 1, 0 }},
996948300cSKalle Valo 	{ /*  9 Mbits */	6, { 5,  4, 3, 2, 1, 0}},
1006948300cSKalle Valo 	{ /* 12 Mbits */	5, { 6,  3, 2, 1, 0 }},
1016948300cSKalle Valo 	{ /* 18 Mbits */	6, { 7,  6, 3, 2, 1, 0 }},
1026948300cSKalle Valo 	{ /* 24 Mbits */	6, { 8,  6, 3, 2, 1, 0 }},
1036948300cSKalle Valo 	{ /* 36 Mbits */	7, { 9,  8, 6, 3, 2, 1, 0 }},
1046948300cSKalle Valo 	{ /* 48 Mbits */	8, {10,  9, 8, 6, 3, 2, 1, 0 }},
1056948300cSKalle Valo 	{ /* 54 Mbits */	9, {11, 10, 9, 8, 6, 3, 2, 1, 0 }}
1066948300cSKalle Valo };
1076948300cSKalle Valo 
1086948300cSKalle Valo static const struct ieee80211_channel zd_channels[] = {
1096948300cSKalle Valo 	{ .center_freq = 2412, .hw_value = 1 },
1106948300cSKalle Valo 	{ .center_freq = 2417, .hw_value = 2 },
1116948300cSKalle Valo 	{ .center_freq = 2422, .hw_value = 3 },
1126948300cSKalle Valo 	{ .center_freq = 2427, .hw_value = 4 },
1136948300cSKalle Valo 	{ .center_freq = 2432, .hw_value = 5 },
1146948300cSKalle Valo 	{ .center_freq = 2437, .hw_value = 6 },
1156948300cSKalle Valo 	{ .center_freq = 2442, .hw_value = 7 },
1166948300cSKalle Valo 	{ .center_freq = 2447, .hw_value = 8 },
1176948300cSKalle Valo 	{ .center_freq = 2452, .hw_value = 9 },
1186948300cSKalle Valo 	{ .center_freq = 2457, .hw_value = 10 },
1196948300cSKalle Valo 	{ .center_freq = 2462, .hw_value = 11 },
1206948300cSKalle Valo 	{ .center_freq = 2467, .hw_value = 12 },
1216948300cSKalle Valo 	{ .center_freq = 2472, .hw_value = 13 },
1226948300cSKalle Valo 	{ .center_freq = 2484, .hw_value = 14 },
1236948300cSKalle Valo };
1246948300cSKalle Valo 
1256948300cSKalle Valo static void housekeeping_init(struct zd_mac *mac);
1266948300cSKalle Valo static void housekeeping_enable(struct zd_mac *mac);
1276948300cSKalle Valo static void housekeeping_disable(struct zd_mac *mac);
1286948300cSKalle Valo static void beacon_init(struct zd_mac *mac);
1296948300cSKalle Valo static void beacon_enable(struct zd_mac *mac);
1306948300cSKalle Valo static void beacon_disable(struct zd_mac *mac);
1316948300cSKalle Valo static void set_rts_cts(struct zd_mac *mac, unsigned int short_preamble);
1326948300cSKalle Valo static int zd_mac_config_beacon(struct ieee80211_hw *hw,
1336948300cSKalle Valo 				struct sk_buff *beacon, bool in_intr);
1346948300cSKalle Valo 
zd_reg2alpha2(u8 regdomain,char * alpha2)1356948300cSKalle Valo static int zd_reg2alpha2(u8 regdomain, char *alpha2)
1366948300cSKalle Valo {
1376948300cSKalle Valo 	unsigned int i;
1386948300cSKalle Valo 	struct zd_reg_alpha2_map *reg_map;
1396948300cSKalle Valo 	for (i = 0; i < ARRAY_SIZE(reg_alpha2_map); i++) {
1406948300cSKalle Valo 		reg_map = &reg_alpha2_map[i];
1416948300cSKalle Valo 		if (regdomain == reg_map->reg) {
1426948300cSKalle Valo 			alpha2[0] = reg_map->alpha2[0];
1436948300cSKalle Valo 			alpha2[1] = reg_map->alpha2[1];
1446948300cSKalle Valo 			return 0;
1456948300cSKalle Valo 		}
1466948300cSKalle Valo 	}
1476948300cSKalle Valo 	return 1;
1486948300cSKalle Valo }
1496948300cSKalle Valo 
zd_check_signal(struct ieee80211_hw * hw,int signal)1506948300cSKalle Valo static int zd_check_signal(struct ieee80211_hw *hw, int signal)
1516948300cSKalle Valo {
1526948300cSKalle Valo 	struct zd_mac *mac = zd_hw_mac(hw);
1536948300cSKalle Valo 
1546948300cSKalle Valo 	dev_dbg_f_cond(zd_mac_dev(mac), signal < 0 || signal > 100,
1556948300cSKalle Valo 			"%s: signal value from device not in range 0..100, "
1566948300cSKalle Valo 			"but %d.\n", __func__, signal);
1576948300cSKalle Valo 
1586948300cSKalle Valo 	if (signal < 0)
1596948300cSKalle Valo 		signal = 0;
1606948300cSKalle Valo 	else if (signal > 100)
1616948300cSKalle Valo 		signal = 100;
1626948300cSKalle Valo 
1636948300cSKalle Valo 	return signal;
1646948300cSKalle Valo }
1656948300cSKalle Valo 
zd_mac_preinit_hw(struct ieee80211_hw * hw)1666948300cSKalle Valo int zd_mac_preinit_hw(struct ieee80211_hw *hw)
1676948300cSKalle Valo {
1686948300cSKalle Valo 	int r;
1696948300cSKalle Valo 	u8 addr[ETH_ALEN];
1706948300cSKalle Valo 	struct zd_mac *mac = zd_hw_mac(hw);
1716948300cSKalle Valo 
1726948300cSKalle Valo 	r = zd_chip_read_mac_addr_fw(&mac->chip, addr);
1736948300cSKalle Valo 	if (r)
1746948300cSKalle Valo 		return r;
1756948300cSKalle Valo 
1766948300cSKalle Valo 	SET_IEEE80211_PERM_ADDR(hw, addr);
1776948300cSKalle Valo 
1786948300cSKalle Valo 	return 0;
1796948300cSKalle Valo }
1806948300cSKalle Valo 
zd_mac_init_hw(struct ieee80211_hw * hw)1816948300cSKalle Valo int zd_mac_init_hw(struct ieee80211_hw *hw)
1826948300cSKalle Valo {
1836948300cSKalle Valo 	int r;
1846948300cSKalle Valo 	struct zd_mac *mac = zd_hw_mac(hw);
1856948300cSKalle Valo 	struct zd_chip *chip = &mac->chip;
1866948300cSKalle Valo 	char alpha2[2];
1876948300cSKalle Valo 	u8 default_regdomain;
1886948300cSKalle Valo 
1896948300cSKalle Valo 	r = zd_chip_enable_int(chip);
1906948300cSKalle Valo 	if (r)
1916948300cSKalle Valo 		goto out;
1926948300cSKalle Valo 	r = zd_chip_init_hw(chip);
1936948300cSKalle Valo 	if (r)
1946948300cSKalle Valo 		goto disable_int;
1956948300cSKalle Valo 
1966948300cSKalle Valo 	ZD_ASSERT(!irqs_disabled());
1976948300cSKalle Valo 
1986948300cSKalle Valo 	r = zd_read_regdomain(chip, &default_regdomain);
1996948300cSKalle Valo 	if (r)
2006948300cSKalle Valo 		goto disable_int;
2016948300cSKalle Valo 	spin_lock_irq(&mac->lock);
2026948300cSKalle Valo 	mac->regdomain = mac->default_regdomain = default_regdomain;
2036948300cSKalle Valo 	spin_unlock_irq(&mac->lock);
2046948300cSKalle Valo 
2056948300cSKalle Valo 	/* We must inform the device that we are doing encryption/decryption in
2066948300cSKalle Valo 	 * software at the moment. */
2076948300cSKalle Valo 	r = zd_set_encryption_type(chip, ENC_SNIFFER);
2086948300cSKalle Valo 	if (r)
2096948300cSKalle Valo 		goto disable_int;
2106948300cSKalle Valo 
2116948300cSKalle Valo 	r = zd_reg2alpha2(mac->regdomain, alpha2);
2126948300cSKalle Valo 	if (r)
2136948300cSKalle Valo 		goto disable_int;
2146948300cSKalle Valo 
2156948300cSKalle Valo 	r = regulatory_hint(hw->wiphy, alpha2);
2166948300cSKalle Valo disable_int:
2176948300cSKalle Valo 	zd_chip_disable_int(chip);
2186948300cSKalle Valo out:
2196948300cSKalle Valo 	return r;
2206948300cSKalle Valo }
2216948300cSKalle Valo 
zd_mac_clear(struct zd_mac * mac)2226948300cSKalle Valo void zd_mac_clear(struct zd_mac *mac)
2236948300cSKalle Valo {
2246948300cSKalle Valo 	flush_workqueue(zd_workqueue);
2256948300cSKalle Valo 	zd_chip_clear(&mac->chip);
2266948300cSKalle Valo 	ZD_MEMCLEAR(mac, sizeof(struct zd_mac));
2276948300cSKalle Valo }
2286948300cSKalle Valo 
set_rx_filter(struct zd_mac * mac)2296948300cSKalle Valo static int set_rx_filter(struct zd_mac *mac)
2306948300cSKalle Valo {
2316948300cSKalle Valo 	unsigned long flags;
2326948300cSKalle Valo 	u32 filter = STA_RX_FILTER;
2336948300cSKalle Valo 
2346948300cSKalle Valo 	spin_lock_irqsave(&mac->lock, flags);
2356948300cSKalle Valo 	if (mac->pass_ctrl)
2366948300cSKalle Valo 		filter |= RX_FILTER_CTRL;
2376948300cSKalle Valo 	spin_unlock_irqrestore(&mac->lock, flags);
2386948300cSKalle Valo 
2396948300cSKalle Valo 	return zd_iowrite32(&mac->chip, CR_RX_FILTER, filter);
2406948300cSKalle Valo }
2416948300cSKalle Valo 
set_mac_and_bssid(struct zd_mac * mac)2426948300cSKalle Valo static int set_mac_and_bssid(struct zd_mac *mac)
2436948300cSKalle Valo {
2446948300cSKalle Valo 	int r;
2456948300cSKalle Valo 
2466948300cSKalle Valo 	if (!mac->vif)
2476948300cSKalle Valo 		return -1;
2486948300cSKalle Valo 
2496948300cSKalle Valo 	r = zd_write_mac_addr(&mac->chip, mac->vif->addr);
2506948300cSKalle Valo 	if (r)
2516948300cSKalle Valo 		return r;
2526948300cSKalle Valo 
2536948300cSKalle Valo 	/* Vendor driver after setting MAC either sets BSSID for AP or
2546948300cSKalle Valo 	 * filter for other modes.
2556948300cSKalle Valo 	 */
2566948300cSKalle Valo 	if (mac->type != NL80211_IFTYPE_AP)
2576948300cSKalle Valo 		return set_rx_filter(mac);
2586948300cSKalle Valo 	else
2596948300cSKalle Valo 		return zd_write_bssid(&mac->chip, mac->vif->addr);
2606948300cSKalle Valo }
2616948300cSKalle Valo 
set_mc_hash(struct zd_mac * mac)2626948300cSKalle Valo static int set_mc_hash(struct zd_mac *mac)
2636948300cSKalle Valo {
2646948300cSKalle Valo 	struct zd_mc_hash hash;
2656948300cSKalle Valo 	zd_mc_clear(&hash);
2666948300cSKalle Valo 	return zd_chip_set_multicast_hash(&mac->chip, &hash);
2676948300cSKalle Valo }
2686948300cSKalle Valo 
zd_op_start(struct ieee80211_hw * hw)2696948300cSKalle Valo int zd_op_start(struct ieee80211_hw *hw)
2706948300cSKalle Valo {
2716948300cSKalle Valo 	struct zd_mac *mac = zd_hw_mac(hw);
2726948300cSKalle Valo 	struct zd_chip *chip = &mac->chip;
2736948300cSKalle Valo 	struct zd_usb *usb = &chip->usb;
2746948300cSKalle Valo 	int r;
2756948300cSKalle Valo 
2766948300cSKalle Valo 	if (!usb->initialized) {
2776948300cSKalle Valo 		r = zd_usb_init_hw(usb);
2786948300cSKalle Valo 		if (r)
2796948300cSKalle Valo 			goto out;
2806948300cSKalle Valo 	}
2816948300cSKalle Valo 
2826948300cSKalle Valo 	r = zd_chip_enable_int(chip);
2836948300cSKalle Valo 	if (r < 0)
2846948300cSKalle Valo 		goto out;
2856948300cSKalle Valo 
2866948300cSKalle Valo 	r = zd_chip_set_basic_rates(chip, CR_RATES_80211B | CR_RATES_80211G);
2876948300cSKalle Valo 	if (r < 0)
2886948300cSKalle Valo 		goto disable_int;
2896948300cSKalle Valo 	r = set_rx_filter(mac);
2906948300cSKalle Valo 	if (r)
2916948300cSKalle Valo 		goto disable_int;
2926948300cSKalle Valo 	r = set_mc_hash(mac);
2936948300cSKalle Valo 	if (r)
2946948300cSKalle Valo 		goto disable_int;
2956948300cSKalle Valo 
2966948300cSKalle Valo 	/* Wait after setting the multicast hash table and powering on
2976948300cSKalle Valo 	 * the radio otherwise interface bring up will fail. This matches
2986948300cSKalle Valo 	 * what the vendor driver did.
2996948300cSKalle Valo 	 */
3006948300cSKalle Valo 	msleep(10);
3016948300cSKalle Valo 
3026948300cSKalle Valo 	r = zd_chip_switch_radio_on(chip);
3036948300cSKalle Valo 	if (r < 0) {
3046948300cSKalle Valo 		dev_err(zd_chip_dev(chip),
3056948300cSKalle Valo 			"%s: failed to set radio on\n", __func__);
3066948300cSKalle Valo 		goto disable_int;
3076948300cSKalle Valo 	}
3086948300cSKalle Valo 	r = zd_chip_enable_rxtx(chip);
3096948300cSKalle Valo 	if (r < 0)
3106948300cSKalle Valo 		goto disable_radio;
3116948300cSKalle Valo 	r = zd_chip_enable_hwint(chip);
3126948300cSKalle Valo 	if (r < 0)
3136948300cSKalle Valo 		goto disable_rxtx;
3146948300cSKalle Valo 
3156948300cSKalle Valo 	housekeeping_enable(mac);
3166948300cSKalle Valo 	beacon_enable(mac);
3176948300cSKalle Valo 	set_bit(ZD_DEVICE_RUNNING, &mac->flags);
3186948300cSKalle Valo 	return 0;
3196948300cSKalle Valo disable_rxtx:
3206948300cSKalle Valo 	zd_chip_disable_rxtx(chip);
3216948300cSKalle Valo disable_radio:
3226948300cSKalle Valo 	zd_chip_switch_radio_off(chip);
3236948300cSKalle Valo disable_int:
3246948300cSKalle Valo 	zd_chip_disable_int(chip);
3256948300cSKalle Valo out:
3266948300cSKalle Valo 	return r;
3276948300cSKalle Valo }
3286948300cSKalle Valo 
zd_op_stop(struct ieee80211_hw * hw)3296948300cSKalle Valo void zd_op_stop(struct ieee80211_hw *hw)
3306948300cSKalle Valo {
3316948300cSKalle Valo 	struct zd_mac *mac = zd_hw_mac(hw);
3326948300cSKalle Valo 	struct zd_chip *chip = &mac->chip;
3336948300cSKalle Valo 	struct sk_buff *skb;
3346948300cSKalle Valo 	struct sk_buff_head *ack_wait_queue = &mac->ack_wait_queue;
3356948300cSKalle Valo 
3366948300cSKalle Valo 	clear_bit(ZD_DEVICE_RUNNING, &mac->flags);
3376948300cSKalle Valo 
3386948300cSKalle Valo 	/* The order here deliberately is a little different from the open()
3396948300cSKalle Valo 	 * method, since we need to make sure there is no opportunity for RX
3406948300cSKalle Valo 	 * frames to be processed by mac80211 after we have stopped it.
3416948300cSKalle Valo 	 */
3426948300cSKalle Valo 
3436948300cSKalle Valo 	zd_chip_disable_rxtx(chip);
3446948300cSKalle Valo 	beacon_disable(mac);
3456948300cSKalle Valo 	housekeeping_disable(mac);
3466948300cSKalle Valo 	flush_workqueue(zd_workqueue);
3476948300cSKalle Valo 
3486948300cSKalle Valo 	zd_chip_disable_hwint(chip);
3496948300cSKalle Valo 	zd_chip_switch_radio_off(chip);
3506948300cSKalle Valo 	zd_chip_disable_int(chip);
3516948300cSKalle Valo 
3526948300cSKalle Valo 
3536948300cSKalle Valo 	while ((skb = skb_dequeue(ack_wait_queue)))
3546948300cSKalle Valo 		dev_kfree_skb_any(skb);
3556948300cSKalle Valo }
3566948300cSKalle Valo 
zd_restore_settings(struct zd_mac * mac)3576948300cSKalle Valo int zd_restore_settings(struct zd_mac *mac)
3586948300cSKalle Valo {
3596948300cSKalle Valo 	struct sk_buff *beacon;
3606948300cSKalle Valo 	struct zd_mc_hash multicast_hash;
3616948300cSKalle Valo 	unsigned int short_preamble;
3626948300cSKalle Valo 	int r, beacon_interval, beacon_period;
3636948300cSKalle Valo 	u8 channel;
3646948300cSKalle Valo 
3656948300cSKalle Valo 	dev_dbg_f(zd_mac_dev(mac), "\n");
3666948300cSKalle Valo 
3676948300cSKalle Valo 	spin_lock_irq(&mac->lock);
3686948300cSKalle Valo 	multicast_hash = mac->multicast_hash;
3696948300cSKalle Valo 	short_preamble = mac->short_preamble;
3706948300cSKalle Valo 	beacon_interval = mac->beacon.interval;
3716948300cSKalle Valo 	beacon_period = mac->beacon.period;
3726948300cSKalle Valo 	channel = mac->channel;
3736948300cSKalle Valo 	spin_unlock_irq(&mac->lock);
3746948300cSKalle Valo 
3756948300cSKalle Valo 	r = set_mac_and_bssid(mac);
3766948300cSKalle Valo 	if (r < 0) {
3776948300cSKalle Valo 		dev_dbg_f(zd_mac_dev(mac), "set_mac_and_bssid failed, %d\n", r);
3786948300cSKalle Valo 		return r;
3796948300cSKalle Valo 	}
3806948300cSKalle Valo 
3816948300cSKalle Valo 	r = zd_chip_set_channel(&mac->chip, channel);
3826948300cSKalle Valo 	if (r < 0) {
3836948300cSKalle Valo 		dev_dbg_f(zd_mac_dev(mac), "zd_chip_set_channel failed, %d\n",
3846948300cSKalle Valo 			  r);
3856948300cSKalle Valo 		return r;
3866948300cSKalle Valo 	}
3876948300cSKalle Valo 
3886948300cSKalle Valo 	set_rts_cts(mac, short_preamble);
3896948300cSKalle Valo 
3906948300cSKalle Valo 	r = zd_chip_set_multicast_hash(&mac->chip, &multicast_hash);
3916948300cSKalle Valo 	if (r < 0) {
3926948300cSKalle Valo 		dev_dbg_f(zd_mac_dev(mac),
3936948300cSKalle Valo 			  "zd_chip_set_multicast_hash failed, %d\n", r);
3946948300cSKalle Valo 		return r;
3956948300cSKalle Valo 	}
3966948300cSKalle Valo 
3976948300cSKalle Valo 	if (mac->type == NL80211_IFTYPE_MESH_POINT ||
3986948300cSKalle Valo 	    mac->type == NL80211_IFTYPE_ADHOC ||
3996948300cSKalle Valo 	    mac->type == NL80211_IFTYPE_AP) {
4006948300cSKalle Valo 		if (mac->vif != NULL) {
4016e8912a5SShaul Triebitz 			beacon = ieee80211_beacon_get(mac->hw, mac->vif, 0);
4026948300cSKalle Valo 			if (beacon)
4036948300cSKalle Valo 				zd_mac_config_beacon(mac->hw, beacon, false);
4046948300cSKalle Valo 		}
4056948300cSKalle Valo 
4066948300cSKalle Valo 		zd_set_beacon_interval(&mac->chip, beacon_interval,
4076948300cSKalle Valo 					beacon_period, mac->type);
4086948300cSKalle Valo 
4096948300cSKalle Valo 		spin_lock_irq(&mac->lock);
4106948300cSKalle Valo 		mac->beacon.last_update = jiffies;
4116948300cSKalle Valo 		spin_unlock_irq(&mac->lock);
4126948300cSKalle Valo 	}
4136948300cSKalle Valo 
4146948300cSKalle Valo 	return 0;
4156948300cSKalle Valo }
4166948300cSKalle Valo 
4176948300cSKalle Valo /**
4186948300cSKalle Valo  * zd_mac_tx_status - reports tx status of a packet if required
419f3242a5bSLee Jones  * @hw: a &struct ieee80211_hw pointer
420f3242a5bSLee Jones  * @skb: a sk-buffer
4216948300cSKalle Valo  * @ackssi: ACK signal strength
422f3242a5bSLee Jones  * @tx_status: success and/or retry
4236948300cSKalle Valo  *
4246948300cSKalle Valo  * This information calls ieee80211_tx_status_irqsafe() if required by the
4256948300cSKalle Valo  * control information. It copies the control information into the status
4266948300cSKalle Valo  * information.
4276948300cSKalle Valo  *
4286948300cSKalle Valo  * If no status information has been requested, the skb is freed.
4296948300cSKalle Valo  */
zd_mac_tx_status(struct ieee80211_hw * hw,struct sk_buff * skb,int ackssi,struct tx_status * tx_status)4306948300cSKalle Valo static void zd_mac_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
4316948300cSKalle Valo 		      int ackssi, struct tx_status *tx_status)
4326948300cSKalle Valo {
4336948300cSKalle Valo 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
4346948300cSKalle Valo 	int i;
4356948300cSKalle Valo 	int success = 1, retry = 1;
4366948300cSKalle Valo 	int first_idx;
4376948300cSKalle Valo 	const struct tx_retry_rate *retries;
4386948300cSKalle Valo 
4396948300cSKalle Valo 	ieee80211_tx_info_clear_status(info);
4406948300cSKalle Valo 
4416948300cSKalle Valo 	if (tx_status) {
4426948300cSKalle Valo 		success = !tx_status->failure;
4436948300cSKalle Valo 		retry = tx_status->retry + success;
4446948300cSKalle Valo 	}
4456948300cSKalle Valo 
4466948300cSKalle Valo 	if (success) {
4476948300cSKalle Valo 		/* success */
4486948300cSKalle Valo 		info->flags |= IEEE80211_TX_STAT_ACK;
4496948300cSKalle Valo 	} else {
4506948300cSKalle Valo 		/* failure */
4516948300cSKalle Valo 		info->flags &= ~IEEE80211_TX_STAT_ACK;
4526948300cSKalle Valo 	}
4536948300cSKalle Valo 
4546948300cSKalle Valo 	first_idx = info->status.rates[0].idx;
4556948300cSKalle Valo 	ZD_ASSERT(0<=first_idx && first_idx<ARRAY_SIZE(zd_retry_rates));
4566948300cSKalle Valo 	retries = &zd_retry_rates[first_idx];
4576948300cSKalle Valo 	ZD_ASSERT(1 <= retry && retry <= retries->count);
4586948300cSKalle Valo 
4596948300cSKalle Valo 	info->status.rates[0].idx = retries->rate[0];
4606948300cSKalle Valo 	info->status.rates[0].count = 1; // (retry > 1 ? 2 : 1);
4616948300cSKalle Valo 
4626948300cSKalle Valo 	for (i=1; i<IEEE80211_TX_MAX_RATES-1 && i<retry; i++) {
4636948300cSKalle Valo 		info->status.rates[i].idx = retries->rate[i];
4646948300cSKalle Valo 		info->status.rates[i].count = 1; // ((i==retry-1) && success ? 1:2);
4656948300cSKalle Valo 	}
4666948300cSKalle Valo 	for (; i<IEEE80211_TX_MAX_RATES && i<retry; i++) {
4676948300cSKalle Valo 		info->status.rates[i].idx = retries->rate[retry - 1];
4686948300cSKalle Valo 		info->status.rates[i].count = 1; // (success ? 1:2);
4696948300cSKalle Valo 	}
4706948300cSKalle Valo 	if (i<IEEE80211_TX_MAX_RATES)
4716948300cSKalle Valo 		info->status.rates[i].idx = -1; /* terminate */
4726948300cSKalle Valo 
4736948300cSKalle Valo 	info->status.ack_signal = zd_check_signal(hw, ackssi);
4746948300cSKalle Valo 	ieee80211_tx_status_irqsafe(hw, skb);
4756948300cSKalle Valo }
4766948300cSKalle Valo 
4776948300cSKalle Valo /**
4786948300cSKalle Valo  * zd_mac_tx_failed - callback for failed frames
479f3242a5bSLee Jones  * @urb: pointer to the urb structure
4806948300cSKalle Valo  *
4816948300cSKalle Valo  * This function is called if a frame couldn't be successfully
4826948300cSKalle Valo  * transferred. The first frame from the tx queue, will be selected and
4836948300cSKalle Valo  * reported as error to the upper layers.
4846948300cSKalle Valo  */
zd_mac_tx_failed(struct urb * urb)4856948300cSKalle Valo void zd_mac_tx_failed(struct urb *urb)
4866948300cSKalle Valo {
4876948300cSKalle Valo 	struct ieee80211_hw * hw = zd_usb_to_hw(urb->context);
4886948300cSKalle Valo 	struct zd_mac *mac = zd_hw_mac(hw);
4896948300cSKalle Valo 	struct sk_buff_head *q = &mac->ack_wait_queue;
4906948300cSKalle Valo 	struct sk_buff *skb;
4916948300cSKalle Valo 	struct tx_status *tx_status = (struct tx_status *)urb->transfer_buffer;
4926948300cSKalle Valo 	unsigned long flags;
4936948300cSKalle Valo 	int success = !tx_status->failure;
4946948300cSKalle Valo 	int retry = tx_status->retry + success;
4956948300cSKalle Valo 	int found = 0;
4966948300cSKalle Valo 	int i, position = 0;
4976948300cSKalle Valo 
4986948300cSKalle Valo 	spin_lock_irqsave(&q->lock, flags);
4996948300cSKalle Valo 
5006948300cSKalle Valo 	skb_queue_walk(q, skb) {
5016948300cSKalle Valo 		struct ieee80211_hdr *tx_hdr;
5026948300cSKalle Valo 		struct ieee80211_tx_info *info;
5036948300cSKalle Valo 		int first_idx, final_idx;
5046948300cSKalle Valo 		const struct tx_retry_rate *retries;
5056948300cSKalle Valo 		u8 final_rate;
5066948300cSKalle Valo 
5076948300cSKalle Valo 		position ++;
5086948300cSKalle Valo 
5096948300cSKalle Valo 		/* if the hardware reports a failure and we had a 802.11 ACK
5106948300cSKalle Valo 		 * pending, then we skip the first skb when searching for a
5116948300cSKalle Valo 		 * matching frame */
5126948300cSKalle Valo 		if (tx_status->failure && mac->ack_pending &&
5136948300cSKalle Valo 		    skb_queue_is_first(q, skb)) {
5146948300cSKalle Valo 			continue;
5156948300cSKalle Valo 		}
5166948300cSKalle Valo 
5176948300cSKalle Valo 		tx_hdr = (struct ieee80211_hdr *)skb->data;
5186948300cSKalle Valo 
5196948300cSKalle Valo 		/* we skip all frames not matching the reported destination */
5206948300cSKalle Valo 		if (unlikely(!ether_addr_equal(tx_hdr->addr1, tx_status->mac)))
5216948300cSKalle Valo 			continue;
5226948300cSKalle Valo 
5236948300cSKalle Valo 		/* we skip all frames not matching the reported final rate */
5246948300cSKalle Valo 
5256948300cSKalle Valo 		info = IEEE80211_SKB_CB(skb);
5266948300cSKalle Valo 		first_idx = info->status.rates[0].idx;
5276948300cSKalle Valo 		ZD_ASSERT(0<=first_idx && first_idx<ARRAY_SIZE(zd_retry_rates));
5286948300cSKalle Valo 		retries = &zd_retry_rates[first_idx];
5296948300cSKalle Valo 		if (retry <= 0 || retry > retries->count)
5306948300cSKalle Valo 			continue;
5316948300cSKalle Valo 
5326948300cSKalle Valo 		final_idx = retries->rate[retry - 1];
5336948300cSKalle Valo 		final_rate = zd_rates[final_idx].hw_value;
5346948300cSKalle Valo 
5356948300cSKalle Valo 		if (final_rate != tx_status->rate) {
5366948300cSKalle Valo 			continue;
5376948300cSKalle Valo 		}
5386948300cSKalle Valo 
5396948300cSKalle Valo 		found = 1;
5406948300cSKalle Valo 		break;
5416948300cSKalle Valo 	}
5426948300cSKalle Valo 
5436948300cSKalle Valo 	if (found) {
5446948300cSKalle Valo 		for (i=1; i<=position; i++) {
5456948300cSKalle Valo 			skb = __skb_dequeue(q);
5466948300cSKalle Valo 			zd_mac_tx_status(hw, skb,
5476948300cSKalle Valo 					 mac->ack_pending ? mac->ack_signal : 0,
5486948300cSKalle Valo 					 i == position ? tx_status : NULL);
5496948300cSKalle Valo 			mac->ack_pending = 0;
5506948300cSKalle Valo 		}
5516948300cSKalle Valo 	}
5526948300cSKalle Valo 
5536948300cSKalle Valo 	spin_unlock_irqrestore(&q->lock, flags);
5546948300cSKalle Valo }
5556948300cSKalle Valo 
5566948300cSKalle Valo /**
5576948300cSKalle Valo  * zd_mac_tx_to_dev - callback for USB layer
5586948300cSKalle Valo  * @skb: a &sk_buff pointer
5596948300cSKalle Valo  * @error: error value, 0 if transmission successful
5606948300cSKalle Valo  *
5616948300cSKalle Valo  * Informs the MAC layer that the frame has successfully transferred to the
5626948300cSKalle Valo  * device. If an ACK is required and the transfer to the device has been
5636948300cSKalle Valo  * successful, the packets are put on the @ack_wait_queue with
5646948300cSKalle Valo  * the control set removed.
5656948300cSKalle Valo  */
zd_mac_tx_to_dev(struct sk_buff * skb,int error)5666948300cSKalle Valo void zd_mac_tx_to_dev(struct sk_buff *skb, int error)
5676948300cSKalle Valo {
5686948300cSKalle Valo 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
5696948300cSKalle Valo 	struct ieee80211_hw *hw = info->rate_driver_data[0];
5706948300cSKalle Valo 	struct zd_mac *mac = zd_hw_mac(hw);
5716948300cSKalle Valo 
5726948300cSKalle Valo 	ieee80211_tx_info_clear_status(info);
5736948300cSKalle Valo 
5746948300cSKalle Valo 	skb_pull(skb, sizeof(struct zd_ctrlset));
5756948300cSKalle Valo 	if (unlikely(error ||
5766948300cSKalle Valo 	    (info->flags & IEEE80211_TX_CTL_NO_ACK))) {
5776948300cSKalle Valo 		/*
5786948300cSKalle Valo 		 * FIXME : do we need to fill in anything ?
5796948300cSKalle Valo 		 */
5806948300cSKalle Valo 		ieee80211_tx_status_irqsafe(hw, skb);
5816948300cSKalle Valo 	} else {
5826948300cSKalle Valo 		struct sk_buff_head *q = &mac->ack_wait_queue;
5836948300cSKalle Valo 
5846948300cSKalle Valo 		skb_queue_tail(q, skb);
5856948300cSKalle Valo 		while (skb_queue_len(q) > ZD_MAC_MAX_ACK_WAITERS) {
5866948300cSKalle Valo 			zd_mac_tx_status(hw, skb_dequeue(q),
5876948300cSKalle Valo 					 mac->ack_pending ? mac->ack_signal : 0,
5886948300cSKalle Valo 					 NULL);
5896948300cSKalle Valo 			mac->ack_pending = 0;
5906948300cSKalle Valo 		}
5916948300cSKalle Valo 	}
5926948300cSKalle Valo }
5936948300cSKalle Valo 
zd_calc_tx_length_us(u8 * service,u8 zd_rate,u16 tx_length)5946948300cSKalle Valo static int zd_calc_tx_length_us(u8 *service, u8 zd_rate, u16 tx_length)
5956948300cSKalle Valo {
5966948300cSKalle Valo 	/* ZD_PURE_RATE() must be used to remove the modulation type flag of
5976948300cSKalle Valo 	 * the zd-rate values.
5986948300cSKalle Valo 	 */
5996948300cSKalle Valo 	static const u8 rate_divisor[] = {
6006948300cSKalle Valo 		[ZD_PURE_RATE(ZD_CCK_RATE_1M)]   =  1,
6016948300cSKalle Valo 		[ZD_PURE_RATE(ZD_CCK_RATE_2M)]	 =  2,
6026948300cSKalle Valo 		/* Bits must be doubled. */
6036948300cSKalle Valo 		[ZD_PURE_RATE(ZD_CCK_RATE_5_5M)] = 11,
6046948300cSKalle Valo 		[ZD_PURE_RATE(ZD_CCK_RATE_11M)]	 = 11,
6056948300cSKalle Valo 		[ZD_PURE_RATE(ZD_OFDM_RATE_6M)]  =  6,
6066948300cSKalle Valo 		[ZD_PURE_RATE(ZD_OFDM_RATE_9M)]  =  9,
6076948300cSKalle Valo 		[ZD_PURE_RATE(ZD_OFDM_RATE_12M)] = 12,
6086948300cSKalle Valo 		[ZD_PURE_RATE(ZD_OFDM_RATE_18M)] = 18,
6096948300cSKalle Valo 		[ZD_PURE_RATE(ZD_OFDM_RATE_24M)] = 24,
6106948300cSKalle Valo 		[ZD_PURE_RATE(ZD_OFDM_RATE_36M)] = 36,
6116948300cSKalle Valo 		[ZD_PURE_RATE(ZD_OFDM_RATE_48M)] = 48,
6126948300cSKalle Valo 		[ZD_PURE_RATE(ZD_OFDM_RATE_54M)] = 54,
6136948300cSKalle Valo 	};
6146948300cSKalle Valo 
6156948300cSKalle Valo 	u32 bits = (u32)tx_length * 8;
6166948300cSKalle Valo 	u32 divisor;
6176948300cSKalle Valo 
6186948300cSKalle Valo 	divisor = rate_divisor[ZD_PURE_RATE(zd_rate)];
6196948300cSKalle Valo 	if (divisor == 0)
6206948300cSKalle Valo 		return -EINVAL;
6216948300cSKalle Valo 
6226948300cSKalle Valo 	switch (zd_rate) {
6236948300cSKalle Valo 	case ZD_CCK_RATE_5_5M:
6246948300cSKalle Valo 		bits = (2*bits) + 10; /* round up to the next integer */
6256948300cSKalle Valo 		break;
6266948300cSKalle Valo 	case ZD_CCK_RATE_11M:
6276948300cSKalle Valo 		if (service) {
6286948300cSKalle Valo 			u32 t = bits % 11;
6296948300cSKalle Valo 			*service &= ~ZD_PLCP_SERVICE_LENGTH_EXTENSION;
6306948300cSKalle Valo 			if (0 < t && t <= 3) {
6316948300cSKalle Valo 				*service |= ZD_PLCP_SERVICE_LENGTH_EXTENSION;
6326948300cSKalle Valo 			}
6336948300cSKalle Valo 		}
6346948300cSKalle Valo 		bits += 10; /* round up to the next integer */
6356948300cSKalle Valo 		break;
6366948300cSKalle Valo 	}
6376948300cSKalle Valo 
6386948300cSKalle Valo 	return bits/divisor;
6396948300cSKalle Valo }
6406948300cSKalle Valo 
cs_set_control(struct zd_mac * mac,struct zd_ctrlset * cs,struct ieee80211_hdr * header,struct ieee80211_tx_info * info)6416948300cSKalle Valo static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
6426948300cSKalle Valo 	                   struct ieee80211_hdr *header,
6436948300cSKalle Valo 	                   struct ieee80211_tx_info *info)
6446948300cSKalle Valo {
6456948300cSKalle Valo 	/*
6466948300cSKalle Valo 	 * CONTROL TODO:
6476948300cSKalle Valo 	 * - if backoff needed, enable bit 0
6486948300cSKalle Valo 	 * - if burst (backoff not needed) disable bit 0
6496948300cSKalle Valo 	 */
6506948300cSKalle Valo 
6516948300cSKalle Valo 	cs->control = 0;
6526948300cSKalle Valo 
6536948300cSKalle Valo 	/* First fragment */
6546948300cSKalle Valo 	if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
6556948300cSKalle Valo 		cs->control |= ZD_CS_NEED_RANDOM_BACKOFF;
6566948300cSKalle Valo 
6576948300cSKalle Valo 	/* No ACK expected (multicast, etc.) */
6586948300cSKalle Valo 	if (info->flags & IEEE80211_TX_CTL_NO_ACK)
6596948300cSKalle Valo 		cs->control |= ZD_CS_NO_ACK;
6606948300cSKalle Valo 
6616948300cSKalle Valo 	/* PS-POLL */
6626948300cSKalle Valo 	if (ieee80211_is_pspoll(header->frame_control))
6636948300cSKalle Valo 		cs->control |= ZD_CS_PS_POLL_FRAME;
6646948300cSKalle Valo 
6656948300cSKalle Valo 	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
6666948300cSKalle Valo 		cs->control |= ZD_CS_RTS;
6676948300cSKalle Valo 
6686948300cSKalle Valo 	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
6696948300cSKalle Valo 		cs->control |= ZD_CS_SELF_CTS;
6706948300cSKalle Valo 
6716948300cSKalle Valo 	/* FIXME: Management frame? */
6726948300cSKalle Valo }
6736948300cSKalle Valo 
zd_mac_match_cur_beacon(struct zd_mac * mac,struct sk_buff * beacon)6746948300cSKalle Valo static bool zd_mac_match_cur_beacon(struct zd_mac *mac, struct sk_buff *beacon)
6756948300cSKalle Valo {
6766948300cSKalle Valo 	if (!mac->beacon.cur_beacon)
6776948300cSKalle Valo 		return false;
6786948300cSKalle Valo 
6796948300cSKalle Valo 	if (mac->beacon.cur_beacon->len != beacon->len)
6806948300cSKalle Valo 		return false;
6816948300cSKalle Valo 
6826948300cSKalle Valo 	return !memcmp(beacon->data, mac->beacon.cur_beacon->data, beacon->len);
6836948300cSKalle Valo }
6846948300cSKalle Valo 
zd_mac_free_cur_beacon_locked(struct zd_mac * mac)6856948300cSKalle Valo static void zd_mac_free_cur_beacon_locked(struct zd_mac *mac)
6866948300cSKalle Valo {
6876948300cSKalle Valo 	ZD_ASSERT(mutex_is_locked(&mac->chip.mutex));
6886948300cSKalle Valo 
6896948300cSKalle Valo 	kfree_skb(mac->beacon.cur_beacon);
6906948300cSKalle Valo 	mac->beacon.cur_beacon = NULL;
6916948300cSKalle Valo }
6926948300cSKalle Valo 
zd_mac_free_cur_beacon(struct zd_mac * mac)6936948300cSKalle Valo static void zd_mac_free_cur_beacon(struct zd_mac *mac)
6946948300cSKalle Valo {
6956948300cSKalle Valo 	mutex_lock(&mac->chip.mutex);
6966948300cSKalle Valo 	zd_mac_free_cur_beacon_locked(mac);
6976948300cSKalle Valo 	mutex_unlock(&mac->chip.mutex);
6986948300cSKalle Valo }
6996948300cSKalle Valo 
zd_mac_config_beacon(struct ieee80211_hw * hw,struct sk_buff * beacon,bool in_intr)7006948300cSKalle Valo static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon,
7016948300cSKalle Valo 				bool in_intr)
7026948300cSKalle Valo {
7036948300cSKalle Valo 	struct zd_mac *mac = zd_hw_mac(hw);
7046948300cSKalle Valo 	int r, ret, num_cmds, req_pos = 0;
7056948300cSKalle Valo 	u32 tmp, j = 0;
7066948300cSKalle Valo 	/* 4 more bytes for tail CRC */
7076948300cSKalle Valo 	u32 full_len = beacon->len + 4;
7086948300cSKalle Valo 	unsigned long end_jiffies, message_jiffies;
7096948300cSKalle Valo 	struct zd_ioreq32 *ioreqs;
7106948300cSKalle Valo 
7116948300cSKalle Valo 	mutex_lock(&mac->chip.mutex);
7126948300cSKalle Valo 
7136948300cSKalle Valo 	/* Check if hw already has this beacon. */
7146948300cSKalle Valo 	if (zd_mac_match_cur_beacon(mac, beacon)) {
7156948300cSKalle Valo 		r = 0;
7166948300cSKalle Valo 		goto out_nofree;
7176948300cSKalle Valo 	}
7186948300cSKalle Valo 
7196948300cSKalle Valo 	/* Alloc memory for full beacon write at once. */
7206948300cSKalle Valo 	num_cmds = 1 + zd_chip_is_zd1211b(&mac->chip) + full_len;
7216da2ec56SKees Cook 	ioreqs = kmalloc_array(num_cmds, sizeof(struct zd_ioreq32),
7226da2ec56SKees Cook 			       GFP_KERNEL);
7236948300cSKalle Valo 	if (!ioreqs) {
7246948300cSKalle Valo 		r = -ENOMEM;
7256948300cSKalle Valo 		goto out_nofree;
7266948300cSKalle Valo 	}
7276948300cSKalle Valo 
7286948300cSKalle Valo 	r = zd_iowrite32_locked(&mac->chip, 0, CR_BCN_FIFO_SEMAPHORE);
7296948300cSKalle Valo 	if (r < 0)
7306948300cSKalle Valo 		goto out;
7316948300cSKalle Valo 	r = zd_ioread32_locked(&mac->chip, &tmp, CR_BCN_FIFO_SEMAPHORE);
7326948300cSKalle Valo 	if (r < 0)
7336948300cSKalle Valo 		goto release_sema;
7346948300cSKalle Valo 	if (in_intr && tmp & 0x2) {
7356948300cSKalle Valo 		r = -EBUSY;
7366948300cSKalle Valo 		goto release_sema;
7376948300cSKalle Valo 	}
7386948300cSKalle Valo 
7396948300cSKalle Valo 	end_jiffies = jiffies + HZ / 2; /*~500ms*/
7406948300cSKalle Valo 	message_jiffies = jiffies + HZ / 10; /*~100ms*/
7416948300cSKalle Valo 	while (tmp & 0x2) {
7426948300cSKalle Valo 		r = zd_ioread32_locked(&mac->chip, &tmp, CR_BCN_FIFO_SEMAPHORE);
7436948300cSKalle Valo 		if (r < 0)
7446948300cSKalle Valo 			goto release_sema;
7456948300cSKalle Valo 		if (time_is_before_eq_jiffies(message_jiffies)) {
7466948300cSKalle Valo 			message_jiffies = jiffies + HZ / 10;
7476948300cSKalle Valo 			dev_err(zd_mac_dev(mac),
7486948300cSKalle Valo 					"CR_BCN_FIFO_SEMAPHORE not ready\n");
7496948300cSKalle Valo 			if (time_is_before_eq_jiffies(end_jiffies))  {
7506948300cSKalle Valo 				dev_err(zd_mac_dev(mac),
7516948300cSKalle Valo 						"Giving up beacon config.\n");
7526948300cSKalle Valo 				r = -ETIMEDOUT;
7536948300cSKalle Valo 				goto reset_device;
7546948300cSKalle Valo 			}
7556948300cSKalle Valo 		}
7566948300cSKalle Valo 		msleep(20);
7576948300cSKalle Valo 	}
7586948300cSKalle Valo 
7596948300cSKalle Valo 	ioreqs[req_pos].addr = CR_BCN_FIFO;
7606948300cSKalle Valo 	ioreqs[req_pos].value = full_len - 1;
7616948300cSKalle Valo 	req_pos++;
7626948300cSKalle Valo 	if (zd_chip_is_zd1211b(&mac->chip)) {
7636948300cSKalle Valo 		ioreqs[req_pos].addr = CR_BCN_LENGTH;
7646948300cSKalle Valo 		ioreqs[req_pos].value = full_len - 1;
7656948300cSKalle Valo 		req_pos++;
7666948300cSKalle Valo 	}
7676948300cSKalle Valo 
7686948300cSKalle Valo 	for (j = 0 ; j < beacon->len; j++) {
7696948300cSKalle Valo 		ioreqs[req_pos].addr = CR_BCN_FIFO;
7706948300cSKalle Valo 		ioreqs[req_pos].value = *((u8 *)(beacon->data + j));
7716948300cSKalle Valo 		req_pos++;
7726948300cSKalle Valo 	}
7736948300cSKalle Valo 
7746948300cSKalle Valo 	for (j = 0; j < 4; j++) {
7756948300cSKalle Valo 		ioreqs[req_pos].addr = CR_BCN_FIFO;
7766948300cSKalle Valo 		ioreqs[req_pos].value = 0x0;
7776948300cSKalle Valo 		req_pos++;
7786948300cSKalle Valo 	}
7796948300cSKalle Valo 
7806948300cSKalle Valo 	BUG_ON(req_pos != num_cmds);
7816948300cSKalle Valo 
7826948300cSKalle Valo 	r = zd_iowrite32a_locked(&mac->chip, ioreqs, num_cmds);
7836948300cSKalle Valo 
7846948300cSKalle Valo release_sema:
7856948300cSKalle Valo 	/*
7866948300cSKalle Valo 	 * Try very hard to release device beacon semaphore, as otherwise
7876948300cSKalle Valo 	 * device/driver can be left in unusable state.
7886948300cSKalle Valo 	 */
7896948300cSKalle Valo 	end_jiffies = jiffies + HZ / 2; /*~500ms*/
7906948300cSKalle Valo 	ret = zd_iowrite32_locked(&mac->chip, 1, CR_BCN_FIFO_SEMAPHORE);
7916948300cSKalle Valo 	while (ret < 0) {
7926948300cSKalle Valo 		if (in_intr || time_is_before_eq_jiffies(end_jiffies)) {
7936948300cSKalle Valo 			ret = -ETIMEDOUT;
7946948300cSKalle Valo 			break;
7956948300cSKalle Valo 		}
7966948300cSKalle Valo 
7976948300cSKalle Valo 		msleep(20);
7986948300cSKalle Valo 		ret = zd_iowrite32_locked(&mac->chip, 1, CR_BCN_FIFO_SEMAPHORE);
7996948300cSKalle Valo 	}
8006948300cSKalle Valo 
8016948300cSKalle Valo 	if (ret < 0)
8026948300cSKalle Valo 		dev_err(zd_mac_dev(mac), "Could not release "
8036948300cSKalle Valo 					 "CR_BCN_FIFO_SEMAPHORE!\n");
8046948300cSKalle Valo 	if (r < 0 || ret < 0) {
8056948300cSKalle Valo 		if (r >= 0)
8066948300cSKalle Valo 			r = ret;
8076948300cSKalle Valo 
8086948300cSKalle Valo 		/* We don't know if beacon was written successfully or not,
8096948300cSKalle Valo 		 * so clear current. */
8106948300cSKalle Valo 		zd_mac_free_cur_beacon_locked(mac);
8116948300cSKalle Valo 
8126948300cSKalle Valo 		goto out;
8136948300cSKalle Valo 	}
8146948300cSKalle Valo 
8156948300cSKalle Valo 	/* Beacon has now been written successfully, update current. */
8166948300cSKalle Valo 	zd_mac_free_cur_beacon_locked(mac);
8176948300cSKalle Valo 	mac->beacon.cur_beacon = beacon;
8186948300cSKalle Valo 	beacon = NULL;
8196948300cSKalle Valo 
8206948300cSKalle Valo 	/* 802.11b/g 2.4G CCK 1Mb
8216948300cSKalle Valo 	 * 802.11a, not yet implemented, uses different values (see GPL vendor
8226948300cSKalle Valo 	 * driver)
8236948300cSKalle Valo 	 */
8246948300cSKalle Valo 	r = zd_iowrite32_locked(&mac->chip, 0x00000400 | (full_len << 19),
8256948300cSKalle Valo 				CR_BCN_PLCP_CFG);
8266948300cSKalle Valo out:
8276948300cSKalle Valo 	kfree(ioreqs);
8286948300cSKalle Valo out_nofree:
8296948300cSKalle Valo 	kfree_skb(beacon);
8306948300cSKalle Valo 	mutex_unlock(&mac->chip.mutex);
8316948300cSKalle Valo 
8326948300cSKalle Valo 	return r;
8336948300cSKalle Valo 
8346948300cSKalle Valo reset_device:
8356948300cSKalle Valo 	zd_mac_free_cur_beacon_locked(mac);
8366948300cSKalle Valo 	kfree_skb(beacon);
8376948300cSKalle Valo 
8386948300cSKalle Valo 	mutex_unlock(&mac->chip.mutex);
8396948300cSKalle Valo 	kfree(ioreqs);
8406948300cSKalle Valo 
8416948300cSKalle Valo 	/* semaphore stuck, reset device to avoid fw freeze later */
8426948300cSKalle Valo 	dev_warn(zd_mac_dev(mac), "CR_BCN_FIFO_SEMAPHORE stuck, "
8436948300cSKalle Valo 				  "resetting device...");
8446948300cSKalle Valo 	usb_queue_reset_device(mac->chip.usb.intf);
8456948300cSKalle Valo 
8466948300cSKalle Valo 	return r;
8476948300cSKalle Valo }
8486948300cSKalle Valo 
fill_ctrlset(struct zd_mac * mac,struct sk_buff * skb)8496948300cSKalle Valo static int fill_ctrlset(struct zd_mac *mac,
8506948300cSKalle Valo 			struct sk_buff *skb)
8516948300cSKalle Valo {
8526948300cSKalle Valo 	int r;
8536948300cSKalle Valo 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
8546948300cSKalle Valo 	unsigned int frag_len = skb->len + FCS_LEN;
8556948300cSKalle Valo 	unsigned int packet_length;
8566948300cSKalle Valo 	struct ieee80211_rate *txrate;
857d58ff351SJohannes Berg 	struct zd_ctrlset *cs = skb_push(skb, sizeof(struct zd_ctrlset));
8586948300cSKalle Valo 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
8596948300cSKalle Valo 
8606948300cSKalle Valo 	ZD_ASSERT(frag_len <= 0xffff);
8616948300cSKalle Valo 
8626948300cSKalle Valo 	/*
8636948300cSKalle Valo 	 * Firmware computes the duration itself (for all frames except PSPoll)
8646948300cSKalle Valo 	 * and needs the field set to 0 at input, otherwise firmware messes up
8656948300cSKalle Valo 	 * duration_id and sets bits 14 and 15 on.
8666948300cSKalle Valo 	 */
8676948300cSKalle Valo 	if (!ieee80211_is_pspoll(hdr->frame_control))
8686948300cSKalle Valo 		hdr->duration_id = 0;
8696948300cSKalle Valo 
8706948300cSKalle Valo 	txrate = ieee80211_get_tx_rate(mac->hw, info);
8716948300cSKalle Valo 
8726948300cSKalle Valo 	cs->modulation = txrate->hw_value;
8736948300cSKalle Valo 	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
8746948300cSKalle Valo 		cs->modulation = txrate->hw_value_short;
8756948300cSKalle Valo 
8766948300cSKalle Valo 	cs->tx_length = cpu_to_le16(frag_len);
8776948300cSKalle Valo 
8786948300cSKalle Valo 	cs_set_control(mac, cs, hdr, info);
8796948300cSKalle Valo 
8806948300cSKalle Valo 	packet_length = frag_len + sizeof(struct zd_ctrlset) + 10;
8816948300cSKalle Valo 	ZD_ASSERT(packet_length <= 0xffff);
8826948300cSKalle Valo 	/* ZD1211B: Computing the length difference this way, gives us
8836948300cSKalle Valo 	 * flexibility to compute the packet length.
8846948300cSKalle Valo 	 */
8856948300cSKalle Valo 	cs->packet_length = cpu_to_le16(zd_chip_is_zd1211b(&mac->chip) ?
8866948300cSKalle Valo 			packet_length - frag_len : packet_length);
8876948300cSKalle Valo 
8886948300cSKalle Valo 	/*
8896948300cSKalle Valo 	 * CURRENT LENGTH:
8906948300cSKalle Valo 	 * - transmit frame length in microseconds
8916948300cSKalle Valo 	 * - seems to be derived from frame length
8926948300cSKalle Valo 	 * - see Cal_Us_Service() in zdinlinef.h
8936948300cSKalle Valo 	 * - if macp->bTxBurstEnable is enabled, then multiply by 4
8946948300cSKalle Valo 	 *  - bTxBurstEnable is never set in the vendor driver
8956948300cSKalle Valo 	 *
8966948300cSKalle Valo 	 * SERVICE:
8976948300cSKalle Valo 	 * - "for PLCP configuration"
8986948300cSKalle Valo 	 * - always 0 except in some situations at 802.11b 11M
8996948300cSKalle Valo 	 * - see line 53 of zdinlinef.h
9006948300cSKalle Valo 	 */
9016948300cSKalle Valo 	cs->service = 0;
9026948300cSKalle Valo 	r = zd_calc_tx_length_us(&cs->service, ZD_RATE(cs->modulation),
9036948300cSKalle Valo 		                 le16_to_cpu(cs->tx_length));
9046948300cSKalle Valo 	if (r < 0)
9056948300cSKalle Valo 		return r;
9066948300cSKalle Valo 	cs->current_length = cpu_to_le16(r);
9076948300cSKalle Valo 	cs->next_frame_length = 0;
9086948300cSKalle Valo 
9096948300cSKalle Valo 	return 0;
9106948300cSKalle Valo }
9116948300cSKalle Valo 
9126948300cSKalle Valo /**
9136948300cSKalle Valo  * zd_op_tx - transmits a network frame to the device
9146948300cSKalle Valo  *
915f3242a5bSLee Jones  * @hw: a &struct ieee80211_hw pointer
9166948300cSKalle Valo  * @control: the control structure
917f3242a5bSLee Jones  * @skb: socket buffer
9186948300cSKalle Valo  *
9196948300cSKalle Valo  * This function transmit an IEEE 802.11 network frame to the device. The
9206948300cSKalle Valo  * control block of the skbuff will be initialized. If necessary the incoming
9216948300cSKalle Valo  * mac80211 queues will be stopped.
9226948300cSKalle Valo  */
zd_op_tx(struct ieee80211_hw * hw,struct ieee80211_tx_control * control,struct sk_buff * skb)9236948300cSKalle Valo static void zd_op_tx(struct ieee80211_hw *hw,
9246948300cSKalle Valo 		     struct ieee80211_tx_control *control,
9256948300cSKalle Valo 		     struct sk_buff *skb)
9266948300cSKalle Valo {
9276948300cSKalle Valo 	struct zd_mac *mac = zd_hw_mac(hw);
9286948300cSKalle Valo 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
9296948300cSKalle Valo 	int r;
9306948300cSKalle Valo 
9316948300cSKalle Valo 	r = fill_ctrlset(mac, skb);
9326948300cSKalle Valo 	if (r)
9336948300cSKalle Valo 		goto fail;
9346948300cSKalle Valo 
9356948300cSKalle Valo 	info->rate_driver_data[0] = hw;
9366948300cSKalle Valo 
9376948300cSKalle Valo 	r = zd_usb_tx(&mac->chip.usb, skb);
9386948300cSKalle Valo 	if (r)
9396948300cSKalle Valo 		goto fail;
9406948300cSKalle Valo 	return;
9416948300cSKalle Valo 
9426948300cSKalle Valo fail:
9436948300cSKalle Valo 	dev_kfree_skb(skb);
9446948300cSKalle Valo }
9456948300cSKalle Valo 
9466948300cSKalle Valo /**
9476948300cSKalle Valo  * filter_ack - filters incoming packets for acknowledgements
948f3242a5bSLee Jones  * @hw: a &struct ieee80211_hw pointer
9496948300cSKalle Valo  * @rx_hdr: received header
9506948300cSKalle Valo  * @stats: the status for the received packet
9516948300cSKalle Valo  *
9526948300cSKalle Valo  * This functions looks for ACK packets and tries to match them with the
9536948300cSKalle Valo  * frames in the tx queue. If a match is found the frame will be dequeued and
9546948300cSKalle Valo  * the upper layers is informed about the successful transmission. If
9556948300cSKalle Valo  * mac80211 queues have been stopped and the number of frames still to be
9566948300cSKalle Valo  * transmitted is low the queues will be opened again.
9576948300cSKalle Valo  *
9586948300cSKalle Valo  * Returns 1 if the frame was an ACK, 0 if it was ignored.
9596948300cSKalle Valo  */
filter_ack(struct ieee80211_hw * hw,struct ieee80211_hdr * rx_hdr,struct ieee80211_rx_status * stats)9606948300cSKalle Valo static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr,
9616948300cSKalle Valo 		      struct ieee80211_rx_status *stats)
9626948300cSKalle Valo {
9636948300cSKalle Valo 	struct zd_mac *mac = zd_hw_mac(hw);
9646948300cSKalle Valo 	struct sk_buff *skb;
9656948300cSKalle Valo 	struct sk_buff_head *q;
9666948300cSKalle Valo 	unsigned long flags;
9676948300cSKalle Valo 	int found = 0;
9686948300cSKalle Valo 	int i, position = 0;
9696948300cSKalle Valo 
9706948300cSKalle Valo 	if (!ieee80211_is_ack(rx_hdr->frame_control))
9716948300cSKalle Valo 		return 0;
9726948300cSKalle Valo 
9736948300cSKalle Valo 	q = &mac->ack_wait_queue;
9746948300cSKalle Valo 	spin_lock_irqsave(&q->lock, flags);
9756948300cSKalle Valo 	skb_queue_walk(q, skb) {
9766948300cSKalle Valo 		struct ieee80211_hdr *tx_hdr;
9776948300cSKalle Valo 
9786948300cSKalle Valo 		position ++;
9796948300cSKalle Valo 
9806948300cSKalle Valo 		if (mac->ack_pending && skb_queue_is_first(q, skb))
9816948300cSKalle Valo 		    continue;
9826948300cSKalle Valo 
9836948300cSKalle Valo 		tx_hdr = (struct ieee80211_hdr *)skb->data;
9846948300cSKalle Valo 		if (likely(ether_addr_equal(tx_hdr->addr2, rx_hdr->addr1)))
9856948300cSKalle Valo 		{
9866948300cSKalle Valo 			found = 1;
9876948300cSKalle Valo 			break;
9886948300cSKalle Valo 		}
9896948300cSKalle Valo 	}
9906948300cSKalle Valo 
9916948300cSKalle Valo 	if (found) {
9926948300cSKalle Valo 		for (i=1; i<position; i++) {
9936948300cSKalle Valo 			skb = __skb_dequeue(q);
9946948300cSKalle Valo 			zd_mac_tx_status(hw, skb,
9956948300cSKalle Valo 					 mac->ack_pending ? mac->ack_signal : 0,
9966948300cSKalle Valo 					 NULL);
9976948300cSKalle Valo 			mac->ack_pending = 0;
9986948300cSKalle Valo 		}
9996948300cSKalle Valo 
10006948300cSKalle Valo 		mac->ack_pending = 1;
10016948300cSKalle Valo 		mac->ack_signal = stats->signal;
10026948300cSKalle Valo 
10036948300cSKalle Valo 		/* Prevent pending tx-packet on AP-mode */
10046948300cSKalle Valo 		if (mac->type == NL80211_IFTYPE_AP) {
10056948300cSKalle Valo 			skb = __skb_dequeue(q);
10066948300cSKalle Valo 			zd_mac_tx_status(hw, skb, mac->ack_signal, NULL);
10076948300cSKalle Valo 			mac->ack_pending = 0;
10086948300cSKalle Valo 		}
10096948300cSKalle Valo 	}
10106948300cSKalle Valo 
10116948300cSKalle Valo 	spin_unlock_irqrestore(&q->lock, flags);
10126948300cSKalle Valo 	return 1;
10136948300cSKalle Valo }
10146948300cSKalle Valo 
zd_mac_rx(struct ieee80211_hw * hw,const u8 * buffer,unsigned int length)10156948300cSKalle Valo int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
10166948300cSKalle Valo {
10176948300cSKalle Valo 	struct zd_mac *mac = zd_hw_mac(hw);
10186948300cSKalle Valo 	struct ieee80211_rx_status stats;
10196948300cSKalle Valo 	const struct rx_status *status;
10206948300cSKalle Valo 	struct sk_buff *skb;
10216948300cSKalle Valo 	int bad_frame = 0;
10226948300cSKalle Valo 	__le16 fc;
10236948300cSKalle Valo 	int need_padding;
10246948300cSKalle Valo 	int i;
10256948300cSKalle Valo 	u8 rate;
10266948300cSKalle Valo 
10276948300cSKalle Valo 	if (length < ZD_PLCP_HEADER_SIZE + 10 /* IEEE80211_1ADDR_LEN */ +
10286948300cSKalle Valo 	             FCS_LEN + sizeof(struct rx_status))
10296948300cSKalle Valo 		return -EINVAL;
10306948300cSKalle Valo 
10316948300cSKalle Valo 	memset(&stats, 0, sizeof(stats));
10326948300cSKalle Valo 
10336948300cSKalle Valo 	/* Note about pass_failed_fcs and pass_ctrl access below:
10346948300cSKalle Valo 	 * mac locking intentionally omitted here, as this is the only unlocked
10356948300cSKalle Valo 	 * reader and the only writer is configure_filter. Plus, if there were
10366948300cSKalle Valo 	 * any races accessing these variables, it wouldn't really matter.
10376948300cSKalle Valo 	 * If mac80211 ever provides a way for us to access filter flags
10386948300cSKalle Valo 	 * from outside configure_filter, we could improve on this. Also, this
10396948300cSKalle Valo 	 * situation may change once we implement some kind of DMA-into-skb
10406948300cSKalle Valo 	 * RX path. */
10416948300cSKalle Valo 
10426948300cSKalle Valo 	/* Caller has to ensure that length >= sizeof(struct rx_status). */
10436948300cSKalle Valo 	status = (struct rx_status *)
10446948300cSKalle Valo 		(buffer + (length - sizeof(struct rx_status)));
10456948300cSKalle Valo 	if (status->frame_status & ZD_RX_ERROR) {
10466948300cSKalle Valo 		if (mac->pass_failed_fcs &&
10476948300cSKalle Valo 				(status->frame_status & ZD_RX_CRC32_ERROR)) {
10486948300cSKalle Valo 			stats.flag |= RX_FLAG_FAILED_FCS_CRC;
10496948300cSKalle Valo 			bad_frame = 1;
10506948300cSKalle Valo 		} else {
10516948300cSKalle Valo 			return -EINVAL;
10526948300cSKalle Valo 		}
10536948300cSKalle Valo 	}
10546948300cSKalle Valo 
10556948300cSKalle Valo 	stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq;
105657fbcce3SJohannes Berg 	stats.band = NL80211_BAND_2GHZ;
10576948300cSKalle Valo 	stats.signal = zd_check_signal(hw, status->signal_strength);
10586948300cSKalle Valo 
10596948300cSKalle Valo 	rate = zd_rx_rate(buffer, status);
10606948300cSKalle Valo 
10616948300cSKalle Valo 	/* todo: return index in the big switches in zd_rx_rate instead */
10626948300cSKalle Valo 	for (i = 0; i < mac->band.n_bitrates; i++)
10636948300cSKalle Valo 		if (rate == mac->band.bitrates[i].hw_value)
10646948300cSKalle Valo 			stats.rate_idx = i;
10656948300cSKalle Valo 
10666948300cSKalle Valo 	length -= ZD_PLCP_HEADER_SIZE + sizeof(struct rx_status);
10676948300cSKalle Valo 	buffer += ZD_PLCP_HEADER_SIZE;
10686948300cSKalle Valo 
10696948300cSKalle Valo 	/* Except for bad frames, filter each frame to see if it is an ACK, in
10706948300cSKalle Valo 	 * which case our internal TX tracking is updated. Normally we then
10716948300cSKalle Valo 	 * bail here as there's no need to pass ACKs on up to the stack, but
10726948300cSKalle Valo 	 * there is also the case where the stack has requested us to pass
10736948300cSKalle Valo 	 * control frames on up (pass_ctrl) which we must consider. */
10746948300cSKalle Valo 	if (!bad_frame &&
10756948300cSKalle Valo 			filter_ack(hw, (struct ieee80211_hdr *)buffer, &stats)
10766948300cSKalle Valo 			&& !mac->pass_ctrl)
10776948300cSKalle Valo 		return 0;
10786948300cSKalle Valo 
10796948300cSKalle Valo 	fc = get_unaligned((__le16*)buffer);
10806948300cSKalle Valo 	need_padding = ieee80211_is_data_qos(fc) ^ ieee80211_has_a4(fc);
10816948300cSKalle Valo 
10826948300cSKalle Valo 	skb = dev_alloc_skb(length + (need_padding ? 2 : 0));
10836948300cSKalle Valo 	if (skb == NULL)
10846948300cSKalle Valo 		return -ENOMEM;
10856948300cSKalle Valo 	if (need_padding) {
10866948300cSKalle Valo 		/* Make sure the payload data is 4 byte aligned. */
10876948300cSKalle Valo 		skb_reserve(skb, 2);
10886948300cSKalle Valo 	}
10896948300cSKalle Valo 
10906948300cSKalle Valo 	/* FIXME : could we avoid this big memcpy ? */
109159ae1d12SJohannes Berg 	skb_put_data(skb, buffer, length);
10926948300cSKalle Valo 
10936948300cSKalle Valo 	memcpy(IEEE80211_SKB_RXCB(skb), &stats, sizeof(stats));
10946948300cSKalle Valo 	ieee80211_rx_irqsafe(hw, skb);
10956948300cSKalle Valo 	return 0;
10966948300cSKalle Valo }
10976948300cSKalle Valo 
zd_op_add_interface(struct ieee80211_hw * hw,struct ieee80211_vif * vif)10986948300cSKalle Valo static int zd_op_add_interface(struct ieee80211_hw *hw,
10996948300cSKalle Valo 				struct ieee80211_vif *vif)
11006948300cSKalle Valo {
11016948300cSKalle Valo 	struct zd_mac *mac = zd_hw_mac(hw);
11026948300cSKalle Valo 
11036948300cSKalle Valo 	/* using NL80211_IFTYPE_UNSPECIFIED to indicate no mode selected */
11046948300cSKalle Valo 	if (mac->type != NL80211_IFTYPE_UNSPECIFIED)
11056948300cSKalle Valo 		return -EOPNOTSUPP;
11066948300cSKalle Valo 
11076948300cSKalle Valo 	switch (vif->type) {
11086948300cSKalle Valo 	case NL80211_IFTYPE_MONITOR:
11096948300cSKalle Valo 	case NL80211_IFTYPE_MESH_POINT:
11106948300cSKalle Valo 	case NL80211_IFTYPE_STATION:
11116948300cSKalle Valo 	case NL80211_IFTYPE_ADHOC:
11126948300cSKalle Valo 	case NL80211_IFTYPE_AP:
11136948300cSKalle Valo 		mac->type = vif->type;
11146948300cSKalle Valo 		break;
11156948300cSKalle Valo 	default:
11166948300cSKalle Valo 		return -EOPNOTSUPP;
11176948300cSKalle Valo 	}
11186948300cSKalle Valo 
11196948300cSKalle Valo 	mac->vif = vif;
11206948300cSKalle Valo 
11216948300cSKalle Valo 	return set_mac_and_bssid(mac);
11226948300cSKalle Valo }
11236948300cSKalle Valo 
zd_op_remove_interface(struct ieee80211_hw * hw,struct ieee80211_vif * vif)11246948300cSKalle Valo static void zd_op_remove_interface(struct ieee80211_hw *hw,
11256948300cSKalle Valo 				    struct ieee80211_vif *vif)
11266948300cSKalle Valo {
11276948300cSKalle Valo 	struct zd_mac *mac = zd_hw_mac(hw);
11286948300cSKalle Valo 	mac->type = NL80211_IFTYPE_UNSPECIFIED;
11296948300cSKalle Valo 	mac->vif = NULL;
11306948300cSKalle Valo 	zd_set_beacon_interval(&mac->chip, 0, 0, NL80211_IFTYPE_UNSPECIFIED);
11316948300cSKalle Valo 	zd_write_mac_addr(&mac->chip, NULL);
11326948300cSKalle Valo 
11336948300cSKalle Valo 	zd_mac_free_cur_beacon(mac);
11346948300cSKalle Valo }
11356948300cSKalle Valo 
zd_op_config(struct ieee80211_hw * hw,u32 changed)11366948300cSKalle Valo static int zd_op_config(struct ieee80211_hw *hw, u32 changed)
11376948300cSKalle Valo {
11386948300cSKalle Valo 	struct zd_mac *mac = zd_hw_mac(hw);
11396948300cSKalle Valo 	struct ieee80211_conf *conf = &hw->conf;
11406948300cSKalle Valo 
11416948300cSKalle Valo 	spin_lock_irq(&mac->lock);
11426948300cSKalle Valo 	mac->channel = conf->chandef.chan->hw_value;
11436948300cSKalle Valo 	spin_unlock_irq(&mac->lock);
11446948300cSKalle Valo 
11456948300cSKalle Valo 	return zd_chip_set_channel(&mac->chip, conf->chandef.chan->hw_value);
11466948300cSKalle Valo }
11476948300cSKalle Valo 
zd_beacon_done(struct zd_mac * mac)11486948300cSKalle Valo static void zd_beacon_done(struct zd_mac *mac)
11496948300cSKalle Valo {
11506948300cSKalle Valo 	struct sk_buff *skb, *beacon;
11516948300cSKalle Valo 
11526948300cSKalle Valo 	if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags))
11536948300cSKalle Valo 		return;
11546948300cSKalle Valo 	if (!mac->vif || mac->vif->type != NL80211_IFTYPE_AP)
11556948300cSKalle Valo 		return;
11566948300cSKalle Valo 
11576948300cSKalle Valo 	/*
11586948300cSKalle Valo 	 * Send out buffered broad- and multicast frames.
11596948300cSKalle Valo 	 */
11606948300cSKalle Valo 	while (!ieee80211_queue_stopped(mac->hw, 0)) {
11616948300cSKalle Valo 		skb = ieee80211_get_buffered_bc(mac->hw, mac->vif);
11626948300cSKalle Valo 		if (!skb)
11636948300cSKalle Valo 			break;
11646948300cSKalle Valo 		zd_op_tx(mac->hw, NULL, skb);
11656948300cSKalle Valo 	}
11666948300cSKalle Valo 
11676948300cSKalle Valo 	/*
11686948300cSKalle Valo 	 * Fetch next beacon so that tim_count is updated.
11696948300cSKalle Valo 	 */
11706e8912a5SShaul Triebitz 	beacon = ieee80211_beacon_get(mac->hw, mac->vif, 0);
11716948300cSKalle Valo 	if (beacon)
11726948300cSKalle Valo 		zd_mac_config_beacon(mac->hw, beacon, true);
11736948300cSKalle Valo 
11746948300cSKalle Valo 	spin_lock_irq(&mac->lock);
11756948300cSKalle Valo 	mac->beacon.last_update = jiffies;
11766948300cSKalle Valo 	spin_unlock_irq(&mac->lock);
11776948300cSKalle Valo }
11786948300cSKalle Valo 
zd_process_intr(struct work_struct * work)11796948300cSKalle Valo static void zd_process_intr(struct work_struct *work)
11806948300cSKalle Valo {
11816948300cSKalle Valo 	u16 int_status;
11826948300cSKalle Valo 	unsigned long flags;
11836948300cSKalle Valo 	struct zd_mac *mac = container_of(work, struct zd_mac, process_intr);
11846948300cSKalle Valo 
11856948300cSKalle Valo 	spin_lock_irqsave(&mac->lock, flags);
11866948300cSKalle Valo 	int_status = le16_to_cpu(*(__le16 *)(mac->intr_buffer + 4));
11876948300cSKalle Valo 	spin_unlock_irqrestore(&mac->lock, flags);
11886948300cSKalle Valo 
11896948300cSKalle Valo 	if (int_status & INT_CFG_NEXT_BCN) {
11906948300cSKalle Valo 		/*dev_dbg_f_limit(zd_mac_dev(mac), "INT_CFG_NEXT_BCN\n");*/
11916948300cSKalle Valo 		zd_beacon_done(mac);
11926948300cSKalle Valo 	} else {
11936948300cSKalle Valo 		dev_dbg_f(zd_mac_dev(mac), "Unsupported interrupt\n");
11946948300cSKalle Valo 	}
11956948300cSKalle Valo 
11966948300cSKalle Valo 	zd_chip_enable_hwint(&mac->chip);
11976948300cSKalle Valo }
11986948300cSKalle Valo 
11996948300cSKalle Valo 
zd_op_prepare_multicast(struct ieee80211_hw * hw,struct netdev_hw_addr_list * mc_list)12006948300cSKalle Valo static u64 zd_op_prepare_multicast(struct ieee80211_hw *hw,
12016948300cSKalle Valo 				   struct netdev_hw_addr_list *mc_list)
12026948300cSKalle Valo {
12036948300cSKalle Valo 	struct zd_mac *mac = zd_hw_mac(hw);
12046948300cSKalle Valo 	struct zd_mc_hash hash;
12056948300cSKalle Valo 	struct netdev_hw_addr *ha;
12066948300cSKalle Valo 
12076948300cSKalle Valo 	zd_mc_clear(&hash);
12086948300cSKalle Valo 
12096948300cSKalle Valo 	netdev_hw_addr_list_for_each(ha, mc_list) {
12106948300cSKalle Valo 		dev_dbg_f(zd_mac_dev(mac), "mc addr %pM\n", ha->addr);
12116948300cSKalle Valo 		zd_mc_add_addr(&hash, ha->addr);
12126948300cSKalle Valo 	}
12136948300cSKalle Valo 
12146948300cSKalle Valo 	return hash.low | ((u64)hash.high << 32);
12156948300cSKalle Valo }
12166948300cSKalle Valo 
12176948300cSKalle Valo #define SUPPORTED_FIF_FLAGS \
12186948300cSKalle Valo 	(FIF_ALLMULTI | FIF_FCSFAIL | FIF_CONTROL | \
12196948300cSKalle Valo 	FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC)
zd_op_configure_filter(struct ieee80211_hw * hw,unsigned int changed_flags,unsigned int * new_flags,u64 multicast)12206948300cSKalle Valo static void zd_op_configure_filter(struct ieee80211_hw *hw,
12216948300cSKalle Valo 			unsigned int changed_flags,
12226948300cSKalle Valo 			unsigned int *new_flags,
12236948300cSKalle Valo 			u64 multicast)
12246948300cSKalle Valo {
12256948300cSKalle Valo 	struct zd_mc_hash hash = {
12266948300cSKalle Valo 		.low = multicast,
12276948300cSKalle Valo 		.high = multicast >> 32,
12286948300cSKalle Valo 	};
12296948300cSKalle Valo 	struct zd_mac *mac = zd_hw_mac(hw);
12306948300cSKalle Valo 	unsigned long flags;
12316948300cSKalle Valo 	int r;
12326948300cSKalle Valo 
12336948300cSKalle Valo 	/* Only deal with supported flags */
12346948300cSKalle Valo 	changed_flags &= SUPPORTED_FIF_FLAGS;
12356948300cSKalle Valo 	*new_flags &= SUPPORTED_FIF_FLAGS;
12366948300cSKalle Valo 
12376948300cSKalle Valo 	/*
12386948300cSKalle Valo 	 * If multicast parameter (as returned by zd_op_prepare_multicast)
12396948300cSKalle Valo 	 * has changed, no bit in changed_flags is set. To handle this
12406948300cSKalle Valo 	 * situation, we do not return if changed_flags is 0. If we do so,
12416948300cSKalle Valo 	 * we will have some issue with IPv6 which uses multicast for link
12426948300cSKalle Valo 	 * layer address resolution.
12436948300cSKalle Valo 	 */
12446948300cSKalle Valo 	if (*new_flags & FIF_ALLMULTI)
12456948300cSKalle Valo 		zd_mc_add_all(&hash);
12466948300cSKalle Valo 
12476948300cSKalle Valo 	spin_lock_irqsave(&mac->lock, flags);
12486948300cSKalle Valo 	mac->pass_failed_fcs = !!(*new_flags & FIF_FCSFAIL);
12496948300cSKalle Valo 	mac->pass_ctrl = !!(*new_flags & FIF_CONTROL);
12506948300cSKalle Valo 	mac->multicast_hash = hash;
12516948300cSKalle Valo 	spin_unlock_irqrestore(&mac->lock, flags);
12526948300cSKalle Valo 
12536948300cSKalle Valo 	zd_chip_set_multicast_hash(&mac->chip, &hash);
12546948300cSKalle Valo 
12556948300cSKalle Valo 	if (changed_flags & FIF_CONTROL) {
12566948300cSKalle Valo 		r = set_rx_filter(mac);
12576948300cSKalle Valo 		if (r)
12586948300cSKalle Valo 			dev_err(zd_mac_dev(mac), "set_rx_filter error %d\n", r);
12596948300cSKalle Valo 	}
12606948300cSKalle Valo 
12616948300cSKalle Valo 	/* no handling required for FIF_OTHER_BSS as we don't currently
12626948300cSKalle Valo 	 * do BSSID filtering */
12636948300cSKalle Valo 	/* FIXME: in future it would be nice to enable the probe response
12646948300cSKalle Valo 	 * filter (so that the driver doesn't see them) until
12656948300cSKalle Valo 	 * FIF_BCN_PRBRESP_PROMISC is set. however due to atomicity here, we'd
12666948300cSKalle Valo 	 * have to schedule work to enable prbresp reception, which might
12676948300cSKalle Valo 	 * happen too late. For now we'll just listen and forward them all the
12686948300cSKalle Valo 	 * time. */
12696948300cSKalle Valo }
12706948300cSKalle Valo 
set_rts_cts(struct zd_mac * mac,unsigned int short_preamble)12716948300cSKalle Valo static void set_rts_cts(struct zd_mac *mac, unsigned int short_preamble)
12726948300cSKalle Valo {
12736948300cSKalle Valo 	mutex_lock(&mac->chip.mutex);
12746948300cSKalle Valo 	zd_chip_set_rts_cts_rate_locked(&mac->chip, short_preamble);
12756948300cSKalle Valo 	mutex_unlock(&mac->chip.mutex);
12766948300cSKalle Valo }
12776948300cSKalle Valo 
zd_op_bss_info_changed(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_bss_conf * bss_conf,u64 changes)12786948300cSKalle Valo static void zd_op_bss_info_changed(struct ieee80211_hw *hw,
12796948300cSKalle Valo 				   struct ieee80211_vif *vif,
12806948300cSKalle Valo 				   struct ieee80211_bss_conf *bss_conf,
12817b7090b4SJohannes Berg 				   u64 changes)
12826948300cSKalle Valo {
12836948300cSKalle Valo 	struct zd_mac *mac = zd_hw_mac(hw);
12846948300cSKalle Valo 	int associated;
12856948300cSKalle Valo 
12867b7090b4SJohannes Berg 	dev_dbg_f(zd_mac_dev(mac), "changes: %llx\n", changes);
12876948300cSKalle Valo 
12886948300cSKalle Valo 	if (mac->type == NL80211_IFTYPE_MESH_POINT ||
12896948300cSKalle Valo 	    mac->type == NL80211_IFTYPE_ADHOC ||
12906948300cSKalle Valo 	    mac->type == NL80211_IFTYPE_AP) {
12916948300cSKalle Valo 		associated = true;
12926948300cSKalle Valo 		if (changes & BSS_CHANGED_BEACON) {
12936e8912a5SShaul Triebitz 			struct sk_buff *beacon = ieee80211_beacon_get(hw, vif,
12946e8912a5SShaul Triebitz 								      0);
12956948300cSKalle Valo 
12966948300cSKalle Valo 			if (beacon) {
12976948300cSKalle Valo 				zd_chip_disable_hwint(&mac->chip);
12986948300cSKalle Valo 				zd_mac_config_beacon(hw, beacon, false);
12996948300cSKalle Valo 				zd_chip_enable_hwint(&mac->chip);
13006948300cSKalle Valo 			}
13016948300cSKalle Valo 		}
13026948300cSKalle Valo 
13036948300cSKalle Valo 		if (changes & BSS_CHANGED_BEACON_ENABLED) {
13046948300cSKalle Valo 			u16 interval = 0;
13056948300cSKalle Valo 			u8 period = 0;
13066948300cSKalle Valo 
13076948300cSKalle Valo 			if (bss_conf->enable_beacon) {
13086948300cSKalle Valo 				period = bss_conf->dtim_period;
13096948300cSKalle Valo 				interval = bss_conf->beacon_int;
13106948300cSKalle Valo 			}
13116948300cSKalle Valo 
13126948300cSKalle Valo 			spin_lock_irq(&mac->lock);
13136948300cSKalle Valo 			mac->beacon.period = period;
13146948300cSKalle Valo 			mac->beacon.interval = interval;
13156948300cSKalle Valo 			mac->beacon.last_update = jiffies;
13166948300cSKalle Valo 			spin_unlock_irq(&mac->lock);
13176948300cSKalle Valo 
13186948300cSKalle Valo 			zd_set_beacon_interval(&mac->chip, interval, period,
13196948300cSKalle Valo 					       mac->type);
13206948300cSKalle Valo 		}
13216948300cSKalle Valo 	} else
13226948300cSKalle Valo 		associated = is_valid_ether_addr(bss_conf->bssid);
13236948300cSKalle Valo 
13246948300cSKalle Valo 	spin_lock_irq(&mac->lock);
13256948300cSKalle Valo 	mac->associated = associated;
13266948300cSKalle Valo 	spin_unlock_irq(&mac->lock);
13276948300cSKalle Valo 
13286948300cSKalle Valo 	/* TODO: do hardware bssid filtering */
13296948300cSKalle Valo 
13306948300cSKalle Valo 	if (changes & BSS_CHANGED_ERP_PREAMBLE) {
13316948300cSKalle Valo 		spin_lock_irq(&mac->lock);
13326948300cSKalle Valo 		mac->short_preamble = bss_conf->use_short_preamble;
13336948300cSKalle Valo 		spin_unlock_irq(&mac->lock);
13346948300cSKalle Valo 
13356948300cSKalle Valo 		set_rts_cts(mac, bss_conf->use_short_preamble);
13366948300cSKalle Valo 	}
13376948300cSKalle Valo }
13386948300cSKalle Valo 
zd_op_get_tsf(struct ieee80211_hw * hw,struct ieee80211_vif * vif)13396948300cSKalle Valo static u64 zd_op_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
13406948300cSKalle Valo {
13416948300cSKalle Valo 	struct zd_mac *mac = zd_hw_mac(hw);
13426948300cSKalle Valo 	return zd_chip_get_tsf(&mac->chip);
13436948300cSKalle Valo }
13446948300cSKalle Valo 
13456948300cSKalle Valo static const struct ieee80211_ops zd_ops = {
13466948300cSKalle Valo 	.tx			= zd_op_tx,
1347*a790cc3aSAlexander Wetzel 	.wake_tx_queue		= ieee80211_handle_wake_tx_queue,
13486948300cSKalle Valo 	.start			= zd_op_start,
13496948300cSKalle Valo 	.stop			= zd_op_stop,
13506948300cSKalle Valo 	.add_interface		= zd_op_add_interface,
13516948300cSKalle Valo 	.remove_interface	= zd_op_remove_interface,
13526948300cSKalle Valo 	.config			= zd_op_config,
13536948300cSKalle Valo 	.prepare_multicast	= zd_op_prepare_multicast,
13546948300cSKalle Valo 	.configure_filter	= zd_op_configure_filter,
13556948300cSKalle Valo 	.bss_info_changed	= zd_op_bss_info_changed,
13566948300cSKalle Valo 	.get_tsf		= zd_op_get_tsf,
13576948300cSKalle Valo };
13586948300cSKalle Valo 
zd_mac_alloc_hw(struct usb_interface * intf)13596948300cSKalle Valo struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
13606948300cSKalle Valo {
13616948300cSKalle Valo 	struct zd_mac *mac;
13626948300cSKalle Valo 	struct ieee80211_hw *hw;
13636948300cSKalle Valo 
13646948300cSKalle Valo 	hw = ieee80211_alloc_hw(sizeof(struct zd_mac), &zd_ops);
13656948300cSKalle Valo 	if (!hw) {
13666948300cSKalle Valo 		dev_dbg_f(&intf->dev, "out of memory\n");
13676948300cSKalle Valo 		return NULL;
13686948300cSKalle Valo 	}
13696948300cSKalle Valo 
13706948300cSKalle Valo 	mac = zd_hw_mac(hw);
13716948300cSKalle Valo 
13726948300cSKalle Valo 	memset(mac, 0, sizeof(*mac));
13736948300cSKalle Valo 	spin_lock_init(&mac->lock);
13746948300cSKalle Valo 	mac->hw = hw;
13756948300cSKalle Valo 
13766948300cSKalle Valo 	mac->type = NL80211_IFTYPE_UNSPECIFIED;
13776948300cSKalle Valo 
13786948300cSKalle Valo 	memcpy(mac->channels, zd_channels, sizeof(zd_channels));
13796948300cSKalle Valo 	memcpy(mac->rates, zd_rates, sizeof(zd_rates));
13806948300cSKalle Valo 	mac->band.n_bitrates = ARRAY_SIZE(zd_rates);
13816948300cSKalle Valo 	mac->band.bitrates = mac->rates;
13826948300cSKalle Valo 	mac->band.n_channels = ARRAY_SIZE(zd_channels);
13836948300cSKalle Valo 	mac->band.channels = mac->channels;
13846948300cSKalle Valo 
138557fbcce3SJohannes Berg 	hw->wiphy->bands[NL80211_BAND_2GHZ] = &mac->band;
13866948300cSKalle Valo 
13876948300cSKalle Valo 	ieee80211_hw_set(hw, MFP_CAPABLE);
13886948300cSKalle Valo 	ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING);
13896948300cSKalle Valo 	ieee80211_hw_set(hw, RX_INCLUDES_FCS);
13906948300cSKalle Valo 	ieee80211_hw_set(hw, SIGNAL_UNSPEC);
13916948300cSKalle Valo 
13926948300cSKalle Valo 	hw->wiphy->interface_modes =
13936948300cSKalle Valo 		BIT(NL80211_IFTYPE_MESH_POINT) |
13946948300cSKalle Valo 		BIT(NL80211_IFTYPE_STATION) |
13956948300cSKalle Valo 		BIT(NL80211_IFTYPE_ADHOC) |
13966948300cSKalle Valo 		BIT(NL80211_IFTYPE_AP);
13976948300cSKalle Valo 
1398ae44b502SAndrew Zaborowski 	wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
1399ae44b502SAndrew Zaborowski 
14006948300cSKalle Valo 	hw->max_signal = 100;
14016948300cSKalle Valo 	hw->queues = 1;
14026948300cSKalle Valo 	hw->extra_tx_headroom = sizeof(struct zd_ctrlset);
14036948300cSKalle Valo 
14046948300cSKalle Valo 	/*
14056948300cSKalle Valo 	 * Tell mac80211 that we support multi rate retries
14066948300cSKalle Valo 	 */
14076948300cSKalle Valo 	hw->max_rates = IEEE80211_TX_MAX_RATES;
14086948300cSKalle Valo 	hw->max_rate_tries = 18;	/* 9 rates * 2 retries/rate */
14096948300cSKalle Valo 
14106948300cSKalle Valo 	skb_queue_head_init(&mac->ack_wait_queue);
14116948300cSKalle Valo 	mac->ack_pending = 0;
14126948300cSKalle Valo 
14136948300cSKalle Valo 	zd_chip_init(&mac->chip, hw, intf);
14146948300cSKalle Valo 	housekeeping_init(mac);
14156948300cSKalle Valo 	beacon_init(mac);
14166948300cSKalle Valo 	INIT_WORK(&mac->process_intr, zd_process_intr);
14176948300cSKalle Valo 
14186948300cSKalle Valo 	SET_IEEE80211_DEV(hw, &intf->dev);
14196948300cSKalle Valo 	return hw;
14206948300cSKalle Valo }
14216948300cSKalle Valo 
14226948300cSKalle Valo #define BEACON_WATCHDOG_DELAY round_jiffies_relative(HZ)
14236948300cSKalle Valo 
beacon_watchdog_handler(struct work_struct * work)14246948300cSKalle Valo static void beacon_watchdog_handler(struct work_struct *work)
14256948300cSKalle Valo {
14266948300cSKalle Valo 	struct zd_mac *mac =
14276948300cSKalle Valo 		container_of(work, struct zd_mac, beacon.watchdog_work.work);
14286948300cSKalle Valo 	struct sk_buff *beacon;
14296948300cSKalle Valo 	unsigned long timeout;
14306948300cSKalle Valo 	int interval, period;
14316948300cSKalle Valo 
14326948300cSKalle Valo 	if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags))
14336948300cSKalle Valo 		goto rearm;
14346948300cSKalle Valo 	if (mac->type != NL80211_IFTYPE_AP || !mac->vif)
14356948300cSKalle Valo 		goto rearm;
14366948300cSKalle Valo 
14376948300cSKalle Valo 	spin_lock_irq(&mac->lock);
14386948300cSKalle Valo 	interval = mac->beacon.interval;
14396948300cSKalle Valo 	period = mac->beacon.period;
14406948300cSKalle Valo 	timeout = mac->beacon.last_update +
14416948300cSKalle Valo 			msecs_to_jiffies(interval * 1024 / 1000) * 3;
14426948300cSKalle Valo 	spin_unlock_irq(&mac->lock);
14436948300cSKalle Valo 
14446948300cSKalle Valo 	if (interval > 0 && time_is_before_jiffies(timeout)) {
14456948300cSKalle Valo 		dev_dbg_f(zd_mac_dev(mac), "beacon interrupt stalled, "
14466948300cSKalle Valo 					   "restarting. "
14476948300cSKalle Valo 					   "(interval: %d, dtim: %d)\n",
14486948300cSKalle Valo 					   interval, period);
14496948300cSKalle Valo 
14506948300cSKalle Valo 		zd_chip_disable_hwint(&mac->chip);
14516948300cSKalle Valo 
14526e8912a5SShaul Triebitz 		beacon = ieee80211_beacon_get(mac->hw, mac->vif, 0);
14536948300cSKalle Valo 		if (beacon) {
14546948300cSKalle Valo 			zd_mac_free_cur_beacon(mac);
14556948300cSKalle Valo 
14566948300cSKalle Valo 			zd_mac_config_beacon(mac->hw, beacon, false);
14576948300cSKalle Valo 		}
14586948300cSKalle Valo 
14596948300cSKalle Valo 		zd_set_beacon_interval(&mac->chip, interval, period, mac->type);
14606948300cSKalle Valo 
14616948300cSKalle Valo 		zd_chip_enable_hwint(&mac->chip);
14626948300cSKalle Valo 
14636948300cSKalle Valo 		spin_lock_irq(&mac->lock);
14646948300cSKalle Valo 		mac->beacon.last_update = jiffies;
14656948300cSKalle Valo 		spin_unlock_irq(&mac->lock);
14666948300cSKalle Valo 	}
14676948300cSKalle Valo 
14686948300cSKalle Valo rearm:
14696948300cSKalle Valo 	queue_delayed_work(zd_workqueue, &mac->beacon.watchdog_work,
14706948300cSKalle Valo 			   BEACON_WATCHDOG_DELAY);
14716948300cSKalle Valo }
14726948300cSKalle Valo 
beacon_init(struct zd_mac * mac)14736948300cSKalle Valo static void beacon_init(struct zd_mac *mac)
14746948300cSKalle Valo {
14756948300cSKalle Valo 	INIT_DELAYED_WORK(&mac->beacon.watchdog_work, beacon_watchdog_handler);
14766948300cSKalle Valo }
14776948300cSKalle Valo 
beacon_enable(struct zd_mac * mac)14786948300cSKalle Valo static void beacon_enable(struct zd_mac *mac)
14796948300cSKalle Valo {
14806948300cSKalle Valo 	dev_dbg_f(zd_mac_dev(mac), "\n");
14816948300cSKalle Valo 
14826948300cSKalle Valo 	mac->beacon.last_update = jiffies;
14836948300cSKalle Valo 	queue_delayed_work(zd_workqueue, &mac->beacon.watchdog_work,
14846948300cSKalle Valo 			   BEACON_WATCHDOG_DELAY);
14856948300cSKalle Valo }
14866948300cSKalle Valo 
beacon_disable(struct zd_mac * mac)14876948300cSKalle Valo static void beacon_disable(struct zd_mac *mac)
14886948300cSKalle Valo {
14896948300cSKalle Valo 	dev_dbg_f(zd_mac_dev(mac), "\n");
14906948300cSKalle Valo 	cancel_delayed_work_sync(&mac->beacon.watchdog_work);
14916948300cSKalle Valo 
14926948300cSKalle Valo 	zd_mac_free_cur_beacon(mac);
14936948300cSKalle Valo }
14946948300cSKalle Valo 
14956948300cSKalle Valo #define LINK_LED_WORK_DELAY HZ
14966948300cSKalle Valo 
link_led_handler(struct work_struct * work)14976948300cSKalle Valo static void link_led_handler(struct work_struct *work)
14986948300cSKalle Valo {
14996948300cSKalle Valo 	struct zd_mac *mac =
15006948300cSKalle Valo 		container_of(work, struct zd_mac, housekeeping.link_led_work.work);
15016948300cSKalle Valo 	struct zd_chip *chip = &mac->chip;
15026948300cSKalle Valo 	int is_associated;
15036948300cSKalle Valo 	int r;
15046948300cSKalle Valo 
15056948300cSKalle Valo 	if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags))
15066948300cSKalle Valo 		goto requeue;
15076948300cSKalle Valo 
15086948300cSKalle Valo 	spin_lock_irq(&mac->lock);
15096948300cSKalle Valo 	is_associated = mac->associated;
15106948300cSKalle Valo 	spin_unlock_irq(&mac->lock);
15116948300cSKalle Valo 
15126948300cSKalle Valo 	r = zd_chip_control_leds(chip,
15136948300cSKalle Valo 		                 is_associated ? ZD_LED_ASSOCIATED : ZD_LED_SCANNING);
15146948300cSKalle Valo 	if (r)
15156948300cSKalle Valo 		dev_dbg_f(zd_mac_dev(mac), "zd_chip_control_leds error %d\n", r);
15166948300cSKalle Valo 
15176948300cSKalle Valo requeue:
15186948300cSKalle Valo 	queue_delayed_work(zd_workqueue, &mac->housekeeping.link_led_work,
15196948300cSKalle Valo 		           LINK_LED_WORK_DELAY);
15206948300cSKalle Valo }
15216948300cSKalle Valo 
housekeeping_init(struct zd_mac * mac)15226948300cSKalle Valo static void housekeeping_init(struct zd_mac *mac)
15236948300cSKalle Valo {
15246948300cSKalle Valo 	INIT_DELAYED_WORK(&mac->housekeeping.link_led_work, link_led_handler);
15256948300cSKalle Valo }
15266948300cSKalle Valo 
housekeeping_enable(struct zd_mac * mac)15276948300cSKalle Valo static void housekeeping_enable(struct zd_mac *mac)
15286948300cSKalle Valo {
15296948300cSKalle Valo 	dev_dbg_f(zd_mac_dev(mac), "\n");
15306948300cSKalle Valo 	queue_delayed_work(zd_workqueue, &mac->housekeeping.link_led_work,
15316948300cSKalle Valo 			   0);
15326948300cSKalle Valo }
15336948300cSKalle Valo 
housekeeping_disable(struct zd_mac * mac)15346948300cSKalle Valo static void housekeeping_disable(struct zd_mac *mac)
15356948300cSKalle Valo {
15366948300cSKalle Valo 	dev_dbg_f(zd_mac_dev(mac), "\n");
15376948300cSKalle Valo 	cancel_delayed_work_sync(&mac->housekeeping.link_led_work);
15386948300cSKalle Valo 	zd_chip_control_leds(&mac->chip, ZD_LED_OFF);
15396948300cSKalle Valo }
1540