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 = ®_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