Le mardi 23 octobre 2012 06:34:06, Jasmine Hassan a écrit : Hi,
> When attempting to make an upstream tarball out of the dkms package, > similar to the upstream tarball of broadcom-sta-5.100.82.112, I > noticed the dkms pacakge only includes an x86_64 binary, so that > cannot replace the current broadcom-sta package (which has an i386 > binary). So, I must separately maintain this amd64 driver for > bcm43142, on private repo, at least temporarily. Should I open an ITP? I think you should not do that because this driver doesn't seem to be only for this chipset but an enhanced version of the broadcom-sta driver which support recent chipsets (see attached diff, in particular wl_id_table declaration). I'll be pleased to upload the new version of the broadcom-sta driver when it's released (including i386 binary). Anyway this can't be done before Wheezy release. Cheers, -- Cyril Lacoux
--- amd64.orig/src/wl/sys/wl_linux.c 2012-05-24 10:48:28.000000000 +0400 +++ amd64/src/wl/sys/wl_linux.c 2012-10-23 05:24:43.000000000 +0400 @@ -2,15 +2,21 @@ * Linux-specific portion of * Broadcom 802.11abg Networking Device Driver * - * Copyright (C) 2010, Broadcom Corporation - * All Rights Reserved. + * Copyright (C) 2011, Broadcom Corporation. All Rights Reserved. * - * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY - * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM - * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $Id: wl_linux.c,v 1.524.2.40.2.15 2011-02-09 02:28:28 Exp $ + * $Id: wl_linux.c 280943 2011-08-31 21:37:04Z $ */ #define LINUX_PORT @@ -37,6 +43,7 @@ #include <linux/string.h> #include <linux/ethtool.h> #include <linux/completion.h> +#include <linux/usb.h> #include <linux/pci_ids.h> #define WLC_MAXBSSCFG 1 @@ -57,7 +64,7 @@ #include <wlioctl.h> #include <wlc_key.h> -typedef const struct si_pub si_t; +typedef const struct si_pub si_t; #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 4, 5) #error "No support for Kernel Rev <= 2.4.5, As the older kernel revs doesn't support Tasklets" @@ -77,10 +84,6 @@ #include <wl_linux.h> -#ifdef WL_THREAD -#include <linux/kthread.h> -#endif - #if defined(USE_CFG80211) #include <wl_cfg80211.h> #endif @@ -90,20 +93,6 @@ static int wl_monitor_start(struct sk_buff *skb, struct net_device *dev); -#ifdef WL_ALL_PASSIVE -static void wl_start_txqwork(struct wl_task *task); -static void wl_txq_free(wl_info_t *wl); -#define TXQ_LOCK(_wl) spin_lock_bh(&(_wl)->txq_lock) -#define TXQ_UNLOCK(_wl) spin_unlock_bh(&(_wl)->txq_lock) - -static void wl_set_multicast_list_workitem(struct work_struct *work); - -static void wl_timer_task(wl_task_t *task); -static void wl_dpc_rxwork(struct wl_task *task); -#else - -#endif - static int wl_reg_proc_entry(wl_info_t *wl); static int wl_linux_watchdog(void *ctx); @@ -139,15 +128,11 @@ u8 rx_hdr[16], tx_hdr[16]; }; -#define WL_INFO(dev) ((wl_info_t*)(WL_DEV_IF(dev)->wl)) +#define WL_INFO(dev) ((wl_info_t*)(WL_DEV_IF(dev)->wl)) static int wl_open(struct net_device *dev); static int wl_close(struct net_device *dev); -#ifdef WL_THREAD -static int wl_start_wlthread(struct sk_buff *skb, struct net_device *dev); -#else static int BCMFASTPATH wl_start(struct sk_buff *skb, struct net_device *dev); -#endif static int wl_start_int(wl_info_t *wl, wl_if_t *wlif, struct sk_buff *skb); static struct net_device_stats *wl_get_stats(struct net_device *dev); @@ -155,24 +140,13 @@ static void wl_set_multicast_list(struct net_device *dev); static void _wl_set_multicast_list(struct net_device *dev); static int wl_ethtool(wl_info_t *wl, void *uaddr, wl_if_t *wlif); -#ifdef NAPI_POLL -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) -static int wl_poll(struct napi_struct *napi, int budget); -#else -static int wl_poll(struct net_device *dev, int *budget); -#endif -#else static void wl_dpc(ulong data); -#endif static void wl_link_up(wl_info_t *wl, char * ifname); static void wl_link_down(wl_info_t *wl, char *ifname); static int wl_schedule_task(wl_info_t *wl, void (*fn)(struct wl_task *), void *context); -#ifdef WL_THREAD -static int wl_start_enqueue_wlthread(wl_info_t *wl, struct sk_buff *skb); -#endif #if defined(BCMDBG) static int wl_dump(wl_info_t *wl, struct bcmstrbuf *b); -#endif +#endif static struct wl_if *wl_alloc_if(wl_info_t *wl, int iftype, uint unit, struct wlc_if* wlc_if); static void wl_free_if(wl_info_t *wl, wl_if_t *wlif); static void wl_get_driver_info(struct net_device *dev, struct ethtool_drvinfo *info); @@ -185,27 +159,13 @@ static void wl_report_radio_state(wl_info_t *wl); #endif -static struct pci_device_id wl_id_table[] = { - { PCI_VENDOR_ID_BROADCOM, 0x4311, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_BROADCOM, 0x4312, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_BROADCOM, 0x4313, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_BROADCOM, 0x4315, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_BROADCOM, 0x4328, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_BROADCOM, 0x4329, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_BROADCOM, 0x432a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_BROADCOM, 0x432b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_BROADCOM, 0x432c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_BROADCOM, 0x432d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_BROADCOM, 0x4353, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_BROADCOM, 0xA99D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_BROADCOM, 0x4357, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_BROADCOM, 0x4727, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_BROADCOM, 0x4358, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_BROADCOM, 0x4359, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_BROADCOM, 0x435a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_BROADCOM, 0x0576, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, +static struct pci_device_id wl_id_table[] = +{ + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0 }, { 0 } }; + MODULE_DEVICE_TABLE(pci, wl_id_table); #ifdef BCMDBG @@ -217,15 +177,10 @@ module_param(phymsglevel, int, 0); #endif -#if defined(WL_ALL_PASSIVE) - -#ifdef WLP2P -static int passivemode = 1; -module_param(passivemode, int, 1); -#else -static int passivemode = 0; -module_param(passivemode, int, 0); -#endif +#ifdef WL_LIMIT_TXQ +#define WL_TXQ_THRESH 0 +static int wl_txq_thresh = WL_TXQ_THRESH; +module_param(wl_txq_thresh, int, 0); #endif static int oneonly = 0; @@ -234,7 +189,7 @@ static int piomode = 0; module_param(piomode, int, 0); -static int instance_base = 0; +static int instance_base = 0; module_param(instance_base, int, 0); #if defined(BCMDBG) @@ -259,53 +214,69 @@ #define BRCM_WLAN_IFNAME eth%d #endif -static char name[IFNAMSIZ] = quote_str(BRCM_WLAN_IFNAME); +static char intf_name[IFNAMSIZ] = quote_str(BRCM_WLAN_IFNAME); -module_param_string(name, name, IFNAMSIZ, 0); +module_param_string(intf_name, intf_name, IFNAMSIZ, 0); #define WL_RADIOTAP_BRCM_SNS 0x01 #define WL_RADIOTAP_BRCM_MCS 0x00000001 -#define IEEE80211_RADIOTAP_HTMOD_40 0x01 -#define IEEE80211_RADIOTAP_HTMOD_SGI 0x02 -#define IEEE80211_RADIOTAP_HTMOD_GF 0x04 -#define IEEE80211_RADIOTAP_HTMOD_LDPC 0x08 -#define IEEE80211_RADIOTAP_HTMOD_STBC_MASK 0x30 -#define IEEE80211_RADIOTAP_HTMOD_STBC_SHIFT 4 +#define IEEE80211_RADIOTAP_HTMOD_40 0x01 +#define IEEE80211_RADIOTAP_HTMOD_SGI 0x02 +#define IEEE80211_RADIOTAP_HTMOD_GF 0x04 +#define IEEE80211_RADIOTAP_HTMOD_LDPC 0x08 +#define IEEE80211_RADIOTAP_HTMOD_STBC_MASK 0x30 +#define IEEE80211_RADIOTAP_HTMOD_STBC_SHIFT 4 struct wl_radiotap_legacy { - struct ieee80211_radiotap_header ieee_radiotap; - uint32 tsft_h; - uint32 tsft_l; - uint8 flags; - uint8 rate; - uint16 channel_freq; - uint16 channel_flags; - uint8 signal; - uint8 noise; - uint8 antenna; -} __attribute__((__packed__)); + struct ieee80211_radiotap_header ieee_radiotap; + uint32 tsft_l; + uint32 tsft_h; + uint8 flags; + uint8 rate; + uint16 channel_freq; + uint16 channel_flags; + uint8 signal; + uint8 noise; + uint8 antenna; +} __attribute__ ((__packed__)); + +struct wl_radiotap_ht_brcm { + struct ieee80211_radiotap_header ieee_radiotap; + u_int32_t it_present_ext; + u_int32_t pad1; + uint32 tsft_l; + uint32 tsft_h; + u_int8_t flags; + u_int8_t pad2; + u_int16_t channel_freq; + u_int16_t channel_flags; + u_int8_t signal; + u_int8_t noise; + u_int8_t antenna; + u_int8_t pad3; + u_int8_t vend_oui[3]; + u_int8_t vend_sns; + u_int16_t vend_skip_len; + u_int8_t mcs; + u_int8_t htflags; +} __attribute__ ((packed)); struct wl_radiotap_ht { - struct ieee80211_radiotap_header ieee_radiotap; - uint32_t it_present_ext; - uint32_t pad1; - uint32 tsft_h; - uint32 tsft_l; - u_int8_t flags; - u_int8_t pad2; - u_int16_t channel_freq; - u_int16_t channel_flags; - u_int8_t signal; - u_int8_t noise; - u_int8_t antenna; - u_int8_t pad3; - u_int8_t vend_oui[3]; - u_int8_t vend_sns; - u_int16_t vend_skip_len; - u_int8_t mcs; - u_int8_t htflags; -} __attribute__((packed)); + struct ieee80211_radiotap_header ieee_radiotap; + uint32 tsft_l; + uint32 tsft_h; + u_int8_t flags; + u_int8_t pad1; + u_int16_t channel_freq; + u_int16_t channel_flags; + u_int8_t signal; + u_int8_t noise; + u_int8_t antenna; + u_int8_t mcs_known; + u_int8_t mcs_flags; + u_int8_t mcs_index; +} __attribute__ ((packed)); #define WL_RADIOTAP_PRESENT_LEGACY \ ((1 << IEEE80211_RADIOTAP_TSFT) | \ @@ -316,7 +287,7 @@ (1 << IEEE80211_RADIOTAP_FLAGS) | \ (1 << IEEE80211_RADIOTAP_ANTENNA)) -#define WL_RADIOTAP_PRESENT_HT \ +#define WL_RADIOTAP_PRESENT_HT_BRCM \ ((1 << IEEE80211_RADIOTAP_TSFT) | \ (1 << IEEE80211_RADIOTAP_FLAGS) | \ (1 << IEEE80211_RADIOTAP_CHANNEL) | \ @@ -326,12 +297,21 @@ (1 << IEEE80211_RADIOTAP_VENDOR_NAMESPACE) | \ (1 << IEEE80211_RADIOTAP_EXT)) +#define WL_RADIOTAP_PRESENT_HT \ + ((1 << IEEE80211_RADIOTAP_TSFT) | \ + (1 << IEEE80211_RADIOTAP_FLAGS) | \ + (1 << IEEE80211_RADIOTAP_CHANNEL) | \ + (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \ + (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | \ + (1 << IEEE80211_RADIOTAP_ANTENNA) | \ + (1 << IEEE80211_RADIOTAP_MCS)) + #ifndef ARPHRD_IEEE80211_RADIOTAP #define ARPHRD_IEEE80211_RADIOTAP 803 #endif -#ifndef SRCBASE -#define SRCBASE "." +#ifndef SRCBASE +#define SRCBASE "." #endif #if WIRELESS_EXT >= 19 || LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) @@ -344,33 +324,6 @@ .get_drvinfo = wl_get_driver_info }; #endif -#ifdef WL_THREAD -static int wl_thread_dpc_wlthread(void *data) -{ - wl_info_t *wl = (wl_info_t *) data; - - current->flags |= PF_NOFREEZE; - - while (1) { - wait_event_interruptible_timeout - (wl->thread_wqh, - skb_queue_len(&wl->rpc_queue) || - skb_queue_len(&wl->tx_queue), - 1); - - if (kthread_should_stop()) - break; - - wl_rpcq_dispatch_wlthread(wl); - wl_start_txqwork_wlthread(wl); - } - - skb_queue_purge(&wl->tx_queue); - skb_queue_purge(&wl->rpc_queue); - - return 0; -} -#endif #if defined(WL_USE_NETDEV_OPS) @@ -378,11 +331,7 @@ { .ndo_open = wl_open, .ndo_stop = wl_close, -#ifdef WL_THREAD - .ndo_start_xmit = wl_start_wlthread, -#else .ndo_start_xmit = wl_start, -#endif .ndo_get_stats = wl_get_stats, .ndo_set_mac_address = wl_set_mac_address, .ndo_set_multicast_list = wl_set_multicast_list, @@ -397,40 +346,20 @@ }; #endif -static -void wl_if_setup(struct net_device *dev) +static void +wl_if_setup(struct net_device *dev) { #if defined(WL_USE_NETDEV_OPS) dev->netdev_ops = &wl_netdev_ops; #else dev->open = wl_open; dev->stop = wl_close; -#ifdef WL_THREAD - dev->hard_start_xmit = wl_start_wlthread; -#else dev->hard_start_xmit = wl_start; -#endif dev->get_stats = wl_get_stats; dev->set_mac_address = wl_set_mac_address; dev->set_multicast_list = wl_set_multicast_list; dev->do_ioctl = wl_ioctl; #endif -#ifdef NAPI_POLL -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) - { - struct wl_info *wl = WL_INFO(dev); - - netif_napi_add(dev, &wl->napi, wl_poll, 64); - napi_enable(&wl->napi); - } -#else - dev->poll = wl_poll; - dev->weight = 64; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 21) - netif_poll_enable(dev); -#endif -#endif -#endif #ifdef USE_IW #if WIRELESS_EXT < 19 @@ -439,15 +368,11 @@ #if WIRELESS_EXT > 12 dev->wireless_handlers = (struct iw_handler_def *) &wl_iw_handler_def; #endif -#if WIRELESS_EXT >= 19 || LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) - dev->ethtool_ops = &wl_ethtool_ops; -#endif #endif -#if defined(USE_CFG80211) && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) +#if WIRELESS_EXT >= 19 || LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) dev->ethtool_ops = &wl_ethtool_ops; -#endif - +#endif } static wl_info_t * @@ -490,22 +415,6 @@ wl->unit = unit; atomic_set(&wl->callbacks, 0); -#ifdef WL_ALL_PASSIVE - wl->all_dispatch_mode = (passivemode == 0) ? TRUE : FALSE; - if (WL_ALL_PASSIVE_ENAB(wl)) { - - MY_INIT_WORK(&wl->txq_task.work, (work_func_t)wl_start_txqwork); - wl->txq_task.context = wl; - wl->txq_dispatched = FALSE; - wl->txq_head = wl->txq_tail = NULL; - - MY_INIT_WORK(&wl->multicast_task.work, (work_func_t)wl_set_multicast_list_workitem); - - MY_INIT_WORK(&wl->wl_dpc_task.work, (work_func_t)wl_dpc_rxwork); - wl->wl_dpc_task.context = wl; - } -#endif - wlif = wl_alloc_if(wl, WL_IFTYPE_BSS, unit, NULL); if (!wlif) { WL_ERROR(("wl%d: wl_alloc_if failed\n", unit)); @@ -551,15 +460,12 @@ spin_lock_init(&wl->isr_lock); if (WL_ALL_PASSIVE_ENAB(wl)) { -#ifdef WL_ALL_PASSIVE - spin_lock_init(&wl->txq_lock); -#endif sema_init(&wl->sem, 1); } if (!(wl->wlc = wlc_attach((void *) wl, vendor, device, unit, wl->piomode, osh, wl->regsva, wl->bcm_bustype, btparam, &err))) { - printf("%s: %s driver failed with code %d\n", dev->name, EPI_VERSION_STR, err); + printf("wl driver %s failed with code %d\n", EPI_VERSION_STR, err); goto fail; } wl->pub = wlc_pub(wl->wlc); @@ -575,24 +481,21 @@ wlc_iovar_setint(wl->wlc, "qtxpower", 23 * 4); #ifdef BCMDBG - if (macaddr != NULL) { - int err; + if (macaddr != NULL) { + int dbg_err; WL_ERROR(("wl%d: setting MAC ADDRESS %s\n", unit, macaddr)); bcm_ether_atoe(macaddr, &local_ea); - err = wlc_iovar_op(wl->wlc, "cur_etheraddr", NULL, 0, &local_ea, + dbg_err = wlc_iovar_op(wl->wlc, "cur_etheraddr", NULL, 0, &local_ea, ETHER_ADDR_LEN, IOV_SET, NULL); - if (err) + if (dbg_err) WL_ERROR(("wl%d: Error setting MAC ADDRESS\n", unit)); } -#endif +#endif bcopy(&wl->pub->cur_etheraddr, dev->dev_addr, ETHER_ADDR_LEN); -#ifndef NAPI_POLL - tasklet_init(&wl->tasklet, wl_dpc, (ulong)wl); -#endif { if (request_irq(irq, wl_isr, IRQF_SHARED, dev->name, wl)) { @@ -621,6 +524,7 @@ goto fail; } #else + if (wl->bcm_bustype == PCI_BUS) { struct pci_dev *pci_dev = (struct pci_dev *)btparam; if (pci_dev != NULL) @@ -674,23 +578,11 @@ WL_ERROR(("wl%d: Error setting infra_mode to infrastructure\n", unit)); } -#ifdef DEFAULT_EAPVER_AP - - if (wlc_iovar_setint(wl->wlc, "sup_wpa2_eapver", -1)) { - WL_ERROR(("wl%d: Error setting sup_wpa2_eapver \n", unit)); - } - if (wlc_iovar_setint(wl->wlc, "sup_m3sec_ok", 1)) { - WL_ERROR(("wl%d: Error setting sup_m3sec_ok \n", unit)); - } -#endif -#ifdef DISABLE_HT_RATE_FOR_WEP_TKIP - - if (wlc_iovar_setint(wl->wlc, "ht_wsec_restrict", 0x3)) { - WL_ERROR(("wl%d: Error setting ht_wsec_restrict \n", unit)); + if (wlc_module_register(wl->pub, NULL, "linux", wl, NULL, wl_linux_watchdog, NULL, NULL)) { + WL_ERROR(("wl%d: %s wlc_module_register() failed\n", + wl->pub->unit, __FUNCTION__)); + goto fail; } -#endif - - wlc_module_register(wl->pub, NULL, "linux", wl, NULL, wl_linux_watchdog, NULL); #ifdef BCMDBG wlc_dump_register(wl->pub, "wl", (dump_fn_t)wl_dump, (void *)wl); @@ -724,22 +616,22 @@ uint32 val; WL_TRACE(("%s: bus %d slot %d func %d irq %d\n", __FUNCTION__, - pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), pdev->irq)); + pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), pdev->irq)); if ((pdev->vendor != PCI_VENDOR_ID_BROADCOM) || (((pdev->device & 0xff00) != 0x4300) && - (pdev->device != 0x576) && + (pdev->device != 0x576) && ((pdev->device & 0xff00) != 0x4700) && ((pdev->device < 43000) || (pdev->device > 43999)))) { WL_TRACE(("%s: unsupported vendor %x device %x\n", __FUNCTION__, - pdev->vendor, pdev->device)); + pdev->vendor, pdev->device)); return (-ENODEV); } rc = pci_enable_device(pdev); if (rc) { WL_ERROR(("%s: Cannot enable device %d-%d_%d\n", __FUNCTION__, - pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn))); + pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn))); return (-ENODEV); } pci_set_master(pdev); @@ -792,7 +684,7 @@ if (!wl) { WL_ERROR(("wl: wl_resume: pci_get_drvdata failed\n")); - return -ENODEV; + return -ENODEV; } err = pci_set_power_state(pdev, PCI_D0); @@ -852,10 +744,6 @@ id_table: wl_id_table, }; -#define wl_read_nvram_file() do {} while (0) - -#define usbap_parse_nvram() do {} while (0) - static int __init wl_module_init(void) { @@ -865,7 +753,7 @@ if (msglevel != 0xdeadbeef) wl_msg_level = msglevel; else { - char *var = getvar(NULL, "wl_msglevel"); + const char *var = getvar(NULL, "wl_msglevel"); if (var) wl_msg_level = bcm_strtoul(var, NULL, 0); } @@ -873,7 +761,7 @@ if (msglevel2 != 0xdeadbeef) wl_msg_level2 = msglevel2; else { - char *var = getvar(NULL, "wl_msglevel2"); + const char *var = getvar(NULL, "wl_msglevel2"); if (var) wl_msg_level2 = bcm_strtoul(var, NULL, 0); } @@ -884,21 +772,23 @@ if (phymsglevel != 0xdeadbeef) phyhal_msg_level = phymsglevel; else { - char *var = getvar(NULL, "phy_msglevel"); + const char *var = getvar(NULL, "phy_msglevel"); if (var) phyhal_msg_level = bcm_strtoul(var, NULL, 0); } printf("%s: phymsglevel set to 0x%x\n", __FUNCTION__, phyhal_msg_level); } -#if defined(WL_ALL_PASSIVE) +#endif +#ifdef WL_LIMIT_TXQ { - char *var = getvar(NULL, "wl_dispatch_mode"); + char *var = getvar(NULL, "wl_txq_thresh"); if (var) - passivemode = bcm_strtoul(var, NULL, 0); - printf("%s: dhssivemode set to 0x%x\n", __FUNCTION__, passivemode); + wl_txq_thresh = bcm_strtoul(var, NULL, 0); +#ifdef BCMDBG + WL_INFORM(("%s: wl_txq_thresh set to 0x%x\n", __FUNCTION__, wl_txq_thresh)); +#endif } #endif -#endif if (!(error = pci_module_init(&wl_pci_driver))) return (0); @@ -933,37 +823,22 @@ wl_uninit_rfkill(wl); #endif -#ifdef NAPI_POLL - clear_bit(__LINK_STATE_START, &wl->dev->state); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) - napi_disable(&wl->napi); -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 21) - netif_poll_disable(wl->dev); -#endif -#endif - if (wl->dev) { wl_free_if(wl, WL_DEV_IF(wl->dev)); wl->dev = NULL; } -#ifndef NAPI_POLL - tasklet_kill(&wl->tasklet); -#endif if (wl->pub) { wlc_module_unregister(wl->pub, "linux", wl); } if (wl->wlc) { - { char tmp1[128]; sprintf(tmp1, "%s%d", HYBRID_PROC, wl->pub->unit); remove_proc_entry(tmp1, 0); } - wlc_detach(wl->wlc); wl->wlc = NULL; wl->pub = NULL; @@ -1011,11 +886,6 @@ } #endif -#ifdef WL_ALL_PASSIVE - if (WL_ALL_PASSIVE_ENAB(wl)) - wl_txq_free(wl); -#endif - MFREE(osh, wl, sizeof(wl_info_t)); if (MALLOCED(osh)) { @@ -1041,7 +911,7 @@ WL_LOCK(wl); WL_APSTA_UPDN(("wl%d: (%s): wl_open() -> wl_up()\n", - wl->pub->unit, wl->dev->name)); + wl->pub->unit, wl->dev->name)); error = wl_up(wl); if (!error) { @@ -1058,8 +928,7 @@ return -1; } #endif - - return (error? -ENODEV: 0); + return (error? -ENODEV : 0); } static int @@ -1073,7 +942,6 @@ #if defined(USE_CFG80211) wl_cfg80211_down(dev); #endif - wl = WL_INFO(dev); WL_TRACE(("wl%d: wl_close\n", wl->pub->unit)); @@ -1125,6 +993,8 @@ if (wlif == NULL) dev = wl->dev; + else if (!wlif->dev_registed) + return; else dev = wlif->dev; @@ -1162,7 +1032,7 @@ } static struct wl_if * -wl_alloc_if(wl_info_t *wl, int iftype, uint subunit, struct wlc_if* wlcif) +wl_alloc_if(wl_info_t *wl, int iftype, uint subunit, struct wlc_if *wlcif) { struct net_device *dev; wl_if_t *wlif; @@ -1171,7 +1041,7 @@ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)) if (!(wlif = MALLOC(wl->osh, sizeof(wl_if_t)))) { WL_ERROR(("wl%d: wl_alloc_if: out of memory, malloced %d bytes\n", - (wl->pub)?wl->pub->unit:subunit, MALLOCED(wl->osh))); + (wl->pub)?wl->pub->unit:subunit, MALLOCED(wl->osh))); return NULL; } bzero(wlif, sizeof(wl_if_t)); @@ -1181,20 +1051,23 @@ if (!(dev = MALLOC(wl->osh, sizeof(struct net_device)))) { MFREE(wl->osh, wlif, sizeof(wl_if_t)); WL_ERROR(("wl%d: wl_alloc_if: out of memory, malloced %d bytes\n", - (wl->pub)?wl->pub->unit:subunit, MALLOCED(wl->osh))); + (wl->pub)?wl->pub->unit:subunit, MALLOCED(wl->osh))); return NULL; } bzero(dev, sizeof(struct net_device)); ether_setup(dev); - strncpy(dev->name, name, IFNAMSIZ); + + strncpy(dev->name, intf_name, IFNAMSIZ-1); + dev->name[IFNAMSIZ-1] = '\0'; + #else #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)) - dev = alloc_netdev(sizeof(wl_if_t), name, ether_setup); + dev = alloc_netdev(sizeof(wl_if_t), intf_name, ether_setup); wlif = netdev_priv(dev); if (!dev) { #else - dev = alloc_netdev(0, name, ether_setup); + dev = alloc_netdev(0, intf_name, ether_setup); if (!dev) { MFREE(wl->osh, wlif, sizeof(wl_if_t)); #endif @@ -1237,8 +1110,7 @@ } #if defined(USE_CFG80211) - if (wlif->if_type != WL_IFTYPE_MON) - wl_cfg80211_detach(wlif->dev); + wl_cfg80211_detach(wlif->dev); #endif p = wl->if_list; @@ -1258,8 +1130,8 @@ free_netdev(wlif->dev); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)) return; -#endif -#endif +#endif +#endif } MFREE(wl->osh, wlif, sizeof(wl_if_t)); } @@ -1353,10 +1225,6 @@ } } -#ifdef NAPI_POLL - set_bit(__LINK_STATE_START, &wl->dev->state); -#endif - return (error); } @@ -1386,16 +1254,6 @@ WL_UNLOCK(wl); -#ifdef WL_ALL_PASSIVE - if (WL_ALL_PASSIVE_ENAB(wl)) { - int i = 0; - for (i = 0; (atomic_read(&wl->callbacks) > callbacks) && i < 10000; i++) { - schedule(); - flush_scheduled_work(); - } - } - else -#endif { SPINWAIT((atomic_read(&wl->callbacks) > callbacks), 100 * 1000); @@ -1430,8 +1288,9 @@ { wl_info_t *wl = WL_INFO(dev); bzero(info, sizeof(struct ethtool_drvinfo)); - sprintf(info->driver, "wl%d", wl->pub->unit); - strcpy(info->version, EPI_VERSION_STR); + snprintf(info->driver, sizeof(info->driver), "wl%d", wl->pub->unit); + strncpy(info->version, EPI_VERSION_STR, sizeof(info->version)); + info->version[(sizeof(info->version))-1] = '\0'; } static int @@ -1533,12 +1392,6 @@ WL_TRACE(("wl%d: wl_ioctl: cmd 0x%x\n", wl->pub->unit, cmd)); -#ifdef CONFIG_PREEMPT - if (preempt_count()) - WL_ERROR(("wl%d: wl_ioctl: cmd = 0x%x, preempt_count=%d\n", - wl->pub->unit, cmd, preempt_count())); -#endif - #ifdef USE_IW if ((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST)) { @@ -1731,17 +1584,6 @@ { if (!WL_ALL_PASSIVE_ENAB((wl_info_t *)WL_INFO(dev))) _wl_set_multicast_list(dev); -#ifdef WL_ALL_PASSIVE - else { - wl_info_t *wl = WL_INFO(dev); - wl->multicast_task.context = dev; - - if (schedule_work(&wl->multicast_task.work)) { - - atomic_inc(&wl->callbacks); - } - } -#endif } static void @@ -1750,7 +1592,7 @@ #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 34) struct dev_mc_list *mclist; #else - struct netdev_hw_addr *ha; + struct netdev_hw_addr *ha; int num; #endif wl_info_t *wl; @@ -1791,7 +1633,7 @@ i = 0; break; } - bcopy(ha->addr, &maclist->ea[i++], ETHER_ADDR_LEN); + bcopy(ha->addr, &maclist->ea[i++], ETHER_ADDR_LEN); } #endif maclist->count = i; @@ -1830,24 +1672,7 @@ if (wantdpc) { ASSERT(wl->resched == FALSE); -#ifdef NAPI_POLL - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) - napi_schedule(&wl->napi); -#else - netif_rx_schedule(wl->dev); -#endif -#else -#ifdef WL_ALL_PASSIVE - if (WL_ALL_PASSIVE_ENAB(wl)) { - if (schedule_work(&wl->wl_dpc_task.work)) - atomic_inc(&wl->callbacks); - else - ASSERT(0); - } else -#endif tasklet_schedule(&wl->tasklet); -#endif } } @@ -1856,37 +1681,18 @@ return IRQ_RETVAL(ours); } -#ifdef NAPI_POLL -static int BCMFASTPATH -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) -wl_poll(struct napi_struct *napi, int budget) -#else -wl_poll(struct net_device *dev, int *budget) -#endif -#else static void BCMFASTPATH wl_dpc(ulong data) -#endif { wl_info_t *wl; -#ifdef NAPI_POLL -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) - wl = (wl_info_t *)container_of(napi, wl_info_t, napi); - wl->pub->tunables->rxbnd = min(RXBND, budget); -#else - wl = WL_INFO(dev); - wl->pub->tunables->rxbnd = min(RXBND, *budget); - ASSERT(wl->pub->tunables->rxbnd <= dev->quota); -#endif -#else - wl = (wl_info_t *)data; WL_LOCK(wl); -#endif if (wl->pub->up) { + wlc_dpc_info_t dpci = {0}; + if (wl->resched) { unsigned long flags = 0; INT_LOCK(wl, flags); @@ -1894,98 +1700,26 @@ INT_UNLOCK(wl, flags); } - wl->resched = wlc_dpc(wl->wlc, TRUE); + wl->resched = wlc_dpc(wl->wlc, TRUE, &dpci); + + wl->processed = dpci.processed; } if (!wl->pub->up) { -#ifdef WL_ALL_PASSIVE - - if ((WL_ALL_PASSIVE_ENAB(wl))) { - atomic_dec(&wl->callbacks); - } -#endif goto done; } -#ifndef NAPI_POLL -#ifdef WL_ALL_PASSIVE - if (wl->resched) { - if (!(WL_ALL_PASSIVE_ENAB(wl))) - tasklet_schedule(&wl->tasklet); - else - if (!schedule_work(&wl->wl_dpc_task.work)) - - ASSERT(0); - } - else { - - if (WL_ALL_PASSIVE_ENAB(wl)) - atomic_dec(&wl->callbacks); - wl_intrson(wl); - } -#else if (wl->resched) tasklet_schedule(&wl->tasklet); else { wl_intrson(wl); } -#endif done: WL_UNLOCK(wl); return; -#else - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) - WL_TRACE(("wl%d: wl_poll: rxbnd %d budget %d processed %d\n", - wl->pub->unit, wl->pub->rxbnd, budget, wl->pub->processed)); - - ASSERT(wl->pub->processed <= wl->pub->tunables->rxbnd); - - if (!wl->resched) { - napi_complete(&wl->napi); - - wl_intrson(wl); - } - return wl->pub->processed; -done: - return 0; - -#else - WL_TRACE(("wl%d: wl_poll: rxbnd %d quota %d budget %d processed %d\n", - wl->pub->unit, wl->pub->rxbnd, dev->quota, - *budget, wl->pub->processed)); - - ASSERT(wl->pub->processed <= wl->pub->tunables->rxbnd); - - *budget -= wl->pub->processed; - dev->quota -= wl->pub->processed; - - if (wl->resched) - - return 1; - - netif_rx_complete(dev); - - wl_intrson(wl); -done: - return 0; -#endif -#endif -} - -#if defined(WL_ALL_PASSIVE) -static void -wl_dpc_rxwork(struct wl_task *task) -{ - wl_info_t *wl = (wl_info_t *)task->context; - WL_TRACE(("wl%d: %s\n", wl->pub->unit, __FUNCTION__)); - - wl_dpc((unsigned long)wl); - return; } -#endif static inline int32 wl_ctf_forward(wl_info_t *wl, struct sk_buff *skb) @@ -2018,7 +1752,7 @@ } skb->protocol = eth_type_trans(skb, skb->dev); - if (!ISALIGNED((uintptr)skb->data, 4)) { + if (!ISALIGNED(skb->data, 4)) { WL_ERROR(("Unaligned assert. skb %p. skb->data %p.\n", skb, skb->data)); if (wlif) { WL_ERROR(("wl_sendup: dev name is %s (wlif) \n", wlif->dev->name)); @@ -2027,17 +1761,13 @@ } WL_ERROR(("wl_sendup: dev name is %s (wl) \n", wl->dev->name)); WL_ERROR(("wl_sendup: hard header len %d (wl) \n", wl->dev->hard_header_len)); - ASSERT(ISALIGNED((uintptr)skb->data, 4)); + ASSERT(ISALIGNED(skb->data, 4)); } WL_APSTA_RX(("wl%d: wl_sendup(): pkt %p summed %d on interface %p (%s)\n", wl->pub->unit, p, skb->ip_summed, wlif, skb->dev->name)); -#ifdef NAPI_POLL - netif_receive_skb(skb); -#else netif_rx(skb); -#endif } void @@ -2057,8 +1787,8 @@ wl_dump_ver(wl, b); bcm_bprintf(b, "name %s dev %p tbusy %d callbacks %d malloced %d\n", - wl->dev->name, wl->dev, (uint)netif_queue_stopped(wl->dev), - atomic_read(&wl->callbacks), MALLOCED(wl->osh)); + wl->dev->name, wl->dev, (uint)netif_queue_stopped(wl->dev), + atomic_read(&wl->callbacks), MALLOCED(wl->osh)); p = wl->if_list; if (p) @@ -2076,7 +1806,7 @@ return 0; } -#endif +#endif static void wl_link_up(wl_info_t *wl, char *ifname) @@ -2100,7 +1830,6 @@ #if defined(USE_CFG80211) wl_cfg80211_event(wl->dev, &(e->event), e->data); #endif - switch (e->event.event_type) { case WLC_E_LINK: case WLC_E_NDIS_LINK: @@ -2135,7 +1864,6 @@ { } -#ifndef WL_THREAD static int BCMFASTPATH wl_start(struct sk_buff *skb, struct net_device *dev) { @@ -2150,124 +1878,9 @@ if (!WL_ALL_PASSIVE_ENAB(wl)) return wl_start_int(wl, wlif, skb); -#ifdef WL_ALL_PASSIVE - else { - skb->prev = NULL; - - TXQ_LOCK(wl); - if (wl->txq_head == NULL) - wl->txq_head = skb; - else { - wl->txq_tail->prev = skb; - } - wl->txq_tail = skb; - - if (wl->txq_dispatched == FALSE) { - wl->txq_dispatched = TRUE; - - if (schedule_work(&wl->txq_task.work)) { - atomic_inc(&wl->callbacks); - } else { - WL_ERROR(("wl%d: wl_start/schedule_work failed\n", wl->pub->unit)); - wl->txq_dispatched = FALSE; - } - } - - TXQ_UNLOCK(wl); - } -#endif return (0); } -#endif - -#ifdef WL_ALL_PASSIVE -static void -wl_start_txqwork(struct wl_task *task) -{ - wl_info_t *wl = (wl_info_t *)task->context; - struct sk_buff *skb; - uint count = 0; - - WL_TRACE(("wl%d: wl_start_txqwork\n", wl->pub->unit)); - - TXQ_LOCK(wl); - while (wl->txq_head) { - skb = wl->txq_head; - wl->txq_head = skb->prev; - skb->prev = NULL; - if (wl->txq_head == NULL) - wl->txq_tail = NULL; - TXQ_UNLOCK(wl); - - wl_start_int(wl, WL_DEV_IF(skb->dev), skb); - - if (++count >= 10) - break; - - TXQ_LOCK(wl); - } - - if (count >= 10) { - if (!schedule_work(&wl->txq_task.work)) { - WL_ERROR(("wl%d: wl_start/schedule_work failed\n", wl->pub->unit)); - atomic_dec(&wl->callbacks); - } - } else { - wl->txq_dispatched = FALSE; - TXQ_UNLOCK(wl); - atomic_dec(&wl->callbacks); - } - - return; -} - -static void -wl_txq_free(wl_info_t *wl) -{ - struct sk_buff *skb; - - if (wl->txq_head == NULL) { - ASSERT(wl->txq_tail == NULL); - return; - } - - while (wl->txq_head) { - skb = wl->txq_head; - wl->txq_head = skb->prev; - PKTFREE(wl->osh, skb, TRUE); - } - - wl->txq_tail = NULL; -} -#endif - -#ifdef WL_ALL_PASSIVE -static void -wl_set_multicast_list_workitem(struct work_struct *work) -{ - wl_task_t *task = (wl_task_t *)work; - struct net_device *dev = (struct net_device*)task->context; - wl_info_t *wl; - - wl = WL_INFO(dev); - - atomic_dec(&wl->callbacks); - - _wl_set_multicast_list(dev); -} - -static void -wl_timer_task(wl_task_t *task) -{ - wl_timer_t *t = (wl_timer_t *)task->context; - - _wl_timer(t); - MFREE(t->wl->osh, task, sizeof(wl_task_t)); - - atomic_dec(&t->wl->callbacks); -} -#endif static void wl_timer(ulong data) @@ -2276,10 +1889,6 @@ if (!WL_ALL_PASSIVE_ENAB(t->wl)) _wl_timer(t); -#ifdef WL_ALL_PASSIVE - else - wl_schedule_task(t->wl, wl_timer_task, t); -#endif } static void @@ -2312,7 +1921,7 @@ } wl_timer_t * -wl_init_timer(wl_info_t *wl, void (*fn)(void *arg), void *arg, const char *name) +wl_init_timer(wl_info_t *wl, void (*fn)(void *arg), void *arg, const char *tname) { wl_timer_t *t; @@ -2320,7 +1929,7 @@ if (t == NULL) { WL_ERROR(("wl%d: wl_init_timer: out of memory, malloced %d bytes\n", - wl->unit, MALLOCED(wl->osh))); + wl->unit, MALLOCED(wl->osh))); return 0; } @@ -2336,8 +1945,8 @@ wl->timers = t; #ifdef BCMDBG - if ((t->name = MALLOC(wl->osh, strlen(name) + 1))) - strcpy(t->name, name); + if ((t->name = MALLOC(wl->osh, strlen(tname) + 1))) + strcpy(t->name, tname); #endif return t; @@ -2433,7 +2042,7 @@ if (!wl->monitor_dev) return; - if (wl->monitor_type == ARPHRD_IEEE80211_PRISM) { + if (wl->monitor_type == 1) { p80211msg_t *phdr; len = sizeof(p80211msg_t) + oskb->len - D11_PHY_HDR_LEN; @@ -2502,18 +2111,19 @@ pdata = skb->data + sizeof(p80211msg_t); bcopy(oskb->data + D11_PHY_HDR_LEN, pdata, oskb->len - D11_PHY_HDR_LEN); - } else if (wl->monitor_type == ARPHRD_IEEE80211_RADIOTAP) { + } + else if (wl->monitor_type == 2) { int channel_frequency; uint16 channel_flags; uint8 flags; uint16 rtap_len; - struct dot11_header * mac_header; + struct dot11_header *mac_header; uint16 fc; - if (rxsts->datarate != 0) + if (rxsts->phytype != WL_RXS_PHY_N) rtap_len = sizeof(struct wl_radiotap_legacy); else - rtap_len = sizeof(struct wl_radiotap_ht); + rtap_len = sizeof(struct wl_radiotap_ht_brcm); len = rtap_len + (oskb->len - D11_PHY_HDR_LEN); if ((skb = dev_alloc_skb(len)) == NULL) @@ -2522,12 +2132,12 @@ skb_put(skb, len); if (CHSPEC_IS2G(rxsts->chanspec)) { - channel_flags = IEEE80211_CHAN_2GHZ; - channel_frequency = wf_channel2mhz(CHSPEC_CHANNEL(rxsts->chanspec), + channel_flags = IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN; + channel_frequency = wf_channel2mhz(wf_chspec_ctlchan(rxsts->chanspec), WF_CHAN_FACTOR_2_4_G); } else { - channel_flags = IEEE80211_CHAN_5GHZ; - channel_frequency = wf_channel2mhz(CHSPEC_CHANNEL(rxsts->chanspec), + channel_flags = IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM; + channel_frequency = wf_channel2mhz(wf_chspec_ctlchan(rxsts->chanspec), WF_CHAN_FACTOR_5_G); } @@ -2548,7 +2158,7 @@ if (rxsts->pkterror & WL_RXS_CRC_ERROR) flags |= IEEE80211_RADIOTAP_F_BADFCS; - if (rxsts->datarate != 0) { + if (rxsts->phytype != WL_RXS_PHY_N) { struct wl_radiotap_legacy *rtl = (struct wl_radiotap_legacy*)skb->data; rtl->ieee_radiotap.it_version = 0; @@ -2557,6 +2167,7 @@ rtl->ieee_radiotap.it_present = HTOL32(WL_RADIOTAP_PRESENT_LEGACY); rtl->tsft_l = htol32(rxsts->mactime); + rtl->tsft_h = 0; rtl->flags = flags; rtl->rate = rxsts->datarate; rtl->channel_freq = HTOL16(channel_frequency); @@ -2565,16 +2176,17 @@ rtl->noise = (int8)rxsts->noise; rtl->antenna = rxsts->antenna; } else { - struct wl_radiotap_ht *rtht = (struct wl_radiotap_ht*)skb->data; + struct wl_radiotap_ht_brcm *rtht = (struct wl_radiotap_ht_brcm *)skb->data; rtht->ieee_radiotap.it_version = 0; rtht->ieee_radiotap.it_pad = 0; rtht->ieee_radiotap.it_len = HTOL16(rtap_len); - rtht->ieee_radiotap.it_present = HTOL32(WL_RADIOTAP_PRESENT_HT); + rtht->ieee_radiotap.it_present = HTOL32(WL_RADIOTAP_PRESENT_HT_BRCM); rtht->it_present_ext = HTOL32(WL_RADIOTAP_BRCM_MCS); - rtht->pad1 = 0; + rtht->tsft_l = htol32(rxsts->mactime); + rtht->tsft_h = 0; rtht->flags = flags; rtht->pad2 = 0; rtht->channel_freq = HTOL16(channel_frequency); @@ -2582,22 +2194,21 @@ rtht->signal = (int8)rxsts->signal; rtht->noise = (int8)rxsts->noise; rtht->antenna = rxsts->antenna; - rtht->pad3 = 0; + memcpy(rtht->vend_oui, "\x00\x10\x18", 3); rtht->vend_sns = WL_RADIOTAP_BRCM_SNS; rtht->vend_skip_len = 2; - rtht->mcs = rxsts->mcs; rtht->htflags = 0; if (rxsts->htflags & WL_RXS_HTF_40) - rtht->htflags |= IEEE80211_RADIOTAP_HTMOD_40; + rtht->htflags |= IEEE80211_RADIOTAP_HTMOD_40; if (rxsts->htflags & WL_RXS_HTF_SGI) - rtht->htflags |= IEEE80211_RADIOTAP_HTMOD_SGI; + rtht->htflags |= IEEE80211_RADIOTAP_HTMOD_SGI; if (rxsts->preamble & WL_RXS_PREAMBLE_HT_GF) - rtht->htflags |= IEEE80211_RADIOTAP_HTMOD_GF; + rtht->htflags |= IEEE80211_RADIOTAP_HTMOD_GF; if (rxsts->htflags & WL_RXS_HTF_LDPC) - rtht->htflags |= IEEE80211_RADIOTAP_HTMOD_LDPC; + rtht->htflags |= IEEE80211_RADIOTAP_HTMOD_LDPC; rtht->htflags |= (rxsts->htflags & WL_RXS_HTF_STBC_MASK) << IEEE80211_RADIOTAP_HTMOD_STBC_SHIFT; @@ -2606,6 +2217,120 @@ pdata = skb->data + rtap_len; bcopy(oskb->data + D11_PHY_HDR_LEN, pdata, oskb->len - D11_PHY_HDR_LEN); } + else if (wl->monitor_type == 3) { + int channel_frequency; + uint16 channel_flags; + uint8 flags; + uint16 rtap_len; + struct dot11_header * mac_header; + uint16 fc; + + if (rxsts->phytype != WL_RXS_PHY_N) + rtap_len = sizeof(struct wl_radiotap_legacy); + else + rtap_len = sizeof(struct wl_radiotap_ht); + + len = rtap_len + (oskb->len - D11_PHY_HDR_LEN); + if ((skb = dev_alloc_skb(len)) == NULL) + return; + + skb_put(skb, len); + + if (CHSPEC_IS2G(rxsts->chanspec)) { + channel_flags = IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN; + channel_frequency = wf_channel2mhz(wf_chspec_ctlchan(rxsts->chanspec), + WF_CHAN_FACTOR_2_4_G); + } else { + channel_flags = IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM; + channel_frequency = wf_channel2mhz(wf_chspec_ctlchan(rxsts->chanspec), + WF_CHAN_FACTOR_5_G); + } + + mac_header = (struct dot11_header *)(oskb->data + D11_PHY_HDR_LEN); + fc = ntoh16(mac_header->fc); + + flags = IEEE80211_RADIOTAP_F_FCS; + + if (rxsts->preamble == WL_RXS_PREAMBLE_SHORT) + flags |= IEEE80211_RADIOTAP_F_SHORTPRE; + + if (fc & (FC_WEP >> FC_WEP_SHIFT)) + flags |= IEEE80211_RADIOTAP_F_WEP; + + if (fc & (FC_MOREFRAG >> FC_MOREFRAG_SHIFT)) + flags |= IEEE80211_RADIOTAP_F_FRAG; + + if (rxsts->pkterror & WL_RXS_CRC_ERROR) + flags |= IEEE80211_RADIOTAP_F_BADFCS; + + if (rxsts->phytype != WL_RXS_PHY_N) { + struct wl_radiotap_legacy *rtl = (struct wl_radiotap_legacy*)skb->data; + + rtl->ieee_radiotap.it_version = 0; + rtl->ieee_radiotap.it_pad = 0; + rtl->ieee_radiotap.it_len = HTOL16(rtap_len); + rtl->ieee_radiotap.it_present = HTOL32(WL_RADIOTAP_PRESENT_LEGACY); + + rtl->tsft_l = htol32(rxsts->mactime); + rtl->tsft_h = 0; + rtl->flags = flags; + rtl->rate = rxsts->datarate; + rtl->channel_freq = HTOL16(channel_frequency); + rtl->channel_flags = HTOL16(channel_flags); + rtl->signal = (int8)rxsts->signal; + rtl->noise = (int8)rxsts->noise; + rtl->antenna = rxsts->antenna; + } else { + struct wl_radiotap_ht *rtht = (struct wl_radiotap_ht *)skb->data; + + rtht->ieee_radiotap.it_version = 0; + rtht->ieee_radiotap.it_pad = 0; + rtht->ieee_radiotap.it_len = HTOL16(rtap_len); + rtht->ieee_radiotap.it_present = HTOL32(WL_RADIOTAP_PRESENT_HT); + + rtht->tsft_l = htol32(rxsts->mactime); + rtht->tsft_h = 0; + rtht->flags = flags; + rtht->pad1 = 0; + rtht->channel_freq = HTOL16(channel_frequency); + rtht->channel_flags = HTOL16(channel_flags); + rtht->signal = (int8)rxsts->signal; + rtht->noise = (int8)rxsts->noise; + rtht->antenna = rxsts->antenna; + + rtht->mcs_known = (IEEE80211_RADIOTAP_MCS_HAVE_BW | + IEEE80211_RADIOTAP_MCS_HAVE_MCS | + IEEE80211_RADIOTAP_MCS_HAVE_GI | + IEEE80211_RADIOTAP_MCS_HAVE_FEC | + IEEE80211_RADIOTAP_MCS_HAVE_FMT); + rtht->mcs_index = rxsts->mcs; + rtht->mcs_flags = 0; + if (rxsts->htflags & WL_RXS_HTF_40) { + rtht->mcs_flags |= IEEE80211_RADIOTAP_MCS_BW_40; + } else if (CHSPEC_IS40(rxsts->chanspec)) { + if (CHSPEC_SB_UPPER(rxsts->chanspec)) + rtht->mcs_flags |= IEEE80211_RADIOTAP_MCS_BW_20U; + else + rtht->mcs_flags |= IEEE80211_RADIOTAP_MCS_BW_20L; + } else + rtht->mcs_flags |= IEEE80211_RADIOTAP_MCS_BW_20; + + if (rxsts->htflags & WL_RXS_HTF_SGI) { + rtht->mcs_flags |= IEEE80211_RADIOTAP_MCS_SGI; + } + if (rxsts->preamble & WL_RXS_PREAMBLE_HT_GF) { + rtht->mcs_flags |= IEEE80211_RADIOTAP_MCS_FMT_GF; + } + if (rxsts->htflags & WL_RXS_HTF_LDPC) { + rtht->mcs_flags |= IEEE80211_RADIOTAP_MCS_FEC_LDPC; + } + } + + pdata = skb->data + rtap_len; + bcopy(oskb->data + D11_PHY_HDR_LEN, pdata, oskb->len - D11_PHY_HDR_LEN); + } + + if (skb == NULL) return; skb->dev = wl->monitor_dev; skb->dev->last_rx = jiffies; @@ -2618,11 +2343,7 @@ skb->pkt_type = PACKET_OTHERHOST; skb->protocol = htons(ETH_P_80211_RAW); -#ifdef NAPI_POLL - netif_receive_skb(skb); -#else netif_rx(skb); -#endif } static int @@ -2660,10 +2381,12 @@ bcopy(wl->dev->dev_addr, dev->dev_addr, ETHER_ADDR_LEN); dev->flags = wl->dev->flags; - dev->type = wl->monitor_type; - if (wl->monitor_type == ARPHRD_IEEE80211_PRISM) { + if (wl->monitor_type == 1) { + dev->type = ARPHRD_IEEE80211_PRISM; sprintf(dev->name, "prism%d", wl->pub->unit); - } else { + } + else { + dev->type = ARPHRD_IEEE80211_RADIOTAP; sprintf(dev->name, "radiotap%d", wl->pub->unit); } @@ -2721,10 +2444,8 @@ WL_TRACE(("wl%d: wl_set_monitor: val %d\n", wl->pub->unit, val)); if (val && !wl->monitor_dev) { - if (val == 1) - wl->monitor_type = ARPHRD_IEEE80211_PRISM; - else if (val == 2) - wl->monitor_type = ARPHRD_IEEE80211_RADIOTAP; + if (val >= 1 && val <= 3) + wl->monitor_type = val; else { WL_ERROR(("monitor type %d not supported\n", val)); ASSERT(0); @@ -2742,7 +2463,7 @@ { return ""; } -#endif +#endif struct net_device * wl_netdev_get(wl_info_t *wl) @@ -2873,7 +2594,7 @@ { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) bool group_key = FALSE; - uchar rxseq[IW_ENCODE_SEQ_MAX_SIZE]; + uchar rxseq[IW_ENCODE_SEQ_MAX_SIZE]; if (key->len != 0) { WL_WSEC(("%s: Key Length is Not zero\n", __FUNCTION__)); @@ -2979,7 +2700,7 @@ #endif } -#if defined(WL_CONFIG_RFKILL) +#if defined(WL_CONFIG_RFKILL) static int wl_set_radio_block(void *data, bool blocked) @@ -2987,6 +2708,8 @@ wl_info_t *wl = data; uint32 radioval; + WL_TRACE(("%s: kernel set blocked = %d\n", __FUNCTION__, blocked)); + radioval = WL_RADIO_SW_DISABLE << 16 | blocked; WL_LOCK(wl); @@ -3002,7 +2725,7 @@ } static const struct rfkill_ops bcmwl_rfkill_ops = { - .set_block = wl_set_radio_block, + .set_block = wl_set_radio_block }; static int @@ -3053,6 +2776,7 @@ static void wl_report_radio_state(wl_info_t *wl) { + WL_TRACE(("%s: report radio state %d\n", __FUNCTION__, wl->last_phyind)); rfkill_set_hw_state(wl->wl_rfkill.rfkill, wl->last_phyind != 0); } @@ -3143,7 +2867,7 @@ } static int -wl_proc_write(struct file *filp, const char __user *buff, unsigned long length, void *data) +wl_proc_write(struct file *filp, const char *buff, unsigned long length, void *data) { wl_info_t * wl = (wl_info_t *)data; int from_user = 0;