diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-21 04:04:47 (GMT) |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-21 04:04:47 (GMT) |
commit | 3b59bf081622b6446db77ad06c93fe23677bc533 (patch) | |
tree | 3f4bb5a27c90cc86994a1f6d3c53fbf9208003cb /drivers/net/wireless/brcm80211 | |
parent | e45836fafe157df137a837093037f741ad8f4c90 (diff) | |
parent | bbdb32cb5b73597386913d052165423b9d736145 (diff) | |
download | linux-3b59bf081622b6446db77ad06c93fe23677bc533.tar.xz |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking merge from David Miller:
"1) Move ixgbe driver over to purely page based buffering on receive.
From Alexander Duyck.
2) Add receive packet steering support to e1000e, from Bruce Allan.
3) Convert TCP MD5 support over to RCU, from Eric Dumazet.
4) Reduce cpu usage in handling out-of-order TCP packets on modern
systems, also from Eric Dumazet.
5) Support the IP{,V6}_UNICAST_IF socket options, making the wine
folks happy, from Erich Hoover.
6) Support VLAN trunking from guests in hyperv driver, from Haiyang
Zhang.
7) Support byte-queue-limtis in r8169, from Igor Maravic.
8) Outline code intended for IP_RECVTOS in IP_PKTOPTIONS existed but
was never properly implemented, Jiri Benc fixed that.
9) 64-bit statistics support in r8169 and 8139too, from Junchang Wang.
10) Support kernel side dump filtering by ctmark in netfilter
ctnetlink, from Pablo Neira Ayuso.
11) Support byte-queue-limits in gianfar driver, from Paul Gortmaker.
12) Add new peek socket options to assist with socket migration, from
Pavel Emelyanov.
13) Add sch_plug packet scheduler whose queue is controlled by
userland daemons using explicit freeze and release commands. From
Shriram Rajagopalan.
14) Fix FCOE checksum offload handling on transmit, from Yi Zou."
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1846 commits)
Fix pppol2tp getsockname()
Remove printk from rds_sendmsg
ipv6: fix incorrent ipv6 ipsec packet fragment
cpsw: Hook up default ndo_change_mtu.
net: qmi_wwan: fix build error due to cdc-wdm dependecy
netdev: driver: ethernet: Add TI CPSW driver
netdev: driver: ethernet: add cpsw address lookup engine support
phy: add am79c874 PHY support
mlx4_core: fix race on comm channel
bonding: send igmp report for its master
fs_enet: Add MPC5125 FEC support and PHY interface selection
net: bpf_jit: fix BPF_S_LDX_B_MSH compilation
net: update the usage of CHECKSUM_UNNECESSARY
fcoe: use CHECKSUM_UNNECESSARY instead of CHECKSUM_PARTIAL on tx
net: do not do gso for CHECKSUM_UNNECESSARY in netif_needs_gso
ixgbe: Fix issues with SR-IOV loopback when flow control is disabled
net/hyperv: Fix the code handling tx busy
ixgbe: fix namespace issues when FCoE/DCB is not enabled
rtlwifi: Remove unused ETH_ADDR_LEN defines
igbvf: Use ETH_ALEN
...
Fix up fairly trivial conflicts in drivers/isdn/gigaset/interface.c and
drivers/net/usb/{Kconfig,qmi_wwan.c} as per David.
Diffstat (limited to 'drivers/net/wireless/brcm80211')
29 files changed, 2219 insertions, 432 deletions
diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig index cd6375d..c510453 100644 --- a/drivers/net/wireless/brcm80211/Kconfig +++ b/drivers/net/wireless/brcm80211/Kconfig @@ -26,16 +26,25 @@ config BRCMFMAC it'll be called brcmfmac.ko. config BRCMFMAC_SDIO - bool "SDIO bus interface support for FullMAC" + bool "SDIO bus interface support for FullMAC driver" depends on MMC depends on BRCMFMAC select FW_LOADER default y ---help--- This option enables the SDIO bus interface support for Broadcom - FullMAC WLAN driver. - Say Y if you want to use brcmfmac for a compatible SDIO interface - wireless card. + IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to + use the driver for a SDIO wireless card. + +config BRCMFMAC_USB + bool "USB bus interface support for FullMAC driver" + depends on USB + depends on BRCMFMAC + select FW_LOADER + ---help--- + This option enables the USB bus interface support for Broadcom + IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to + use the driver for an USB wireless card. config BRCMDBG bool "Broadcom driver debug functions" diff --git a/drivers/net/wireless/brcm80211/Makefile b/drivers/net/wireless/brcm80211/Makefile index f41c047..b987920 100644 --- a/drivers/net/wireless/brcm80211/Makefile +++ b/drivers/net/wireless/brcm80211/Makefile @@ -16,7 +16,7 @@ # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # common flags -subdir-ccflags-$(CONFIG_BRCMDBG) += -DBCMDBG +subdir-ccflags-$(CONFIG_BRCMDBG) += -DDEBUG obj-$(CONFIG_BRCMUTIL) += brcmutil/ obj-$(CONFIG_BRCMFMAC) += brcmfmac/ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile index 9ca9ea1..abb48032 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile +++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile @@ -19,6 +19,8 @@ ccflags-y += \ -Idrivers/net/wireless/brcm80211/brcmfmac \ -Idrivers/net/wireless/brcm80211/include +ccflags-y += -D__CHECK_ENDIAN__ + obj-$(CONFIG_BRCMFMAC) += brcmfmac.o brcmfmac-objs += \ wl_cfg80211.o \ @@ -30,5 +32,5 @@ brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \ bcmsdh.o \ bcmsdh_sdmmc.o \ sdio_chip.o - -ccflags-y += -D__CHECK_ENDIAN__ +brcmfmac-$(CONFIG_BRCMFMAC_USB) += \ + usb.o diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 4bc8d25..e925290 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c @@ -15,6 +15,8 @@ */ /* ****************** SDIO CARD Interface Functions **************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/types.h> #include <linux/netdevice.h> #include <linux/export.h> diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index 9b8c0ed..4688904 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c @@ -13,6 +13,9 @@ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/types.h> #include <linux/netdevice.h> #include <linux/mmc/sdio.h> @@ -291,13 +294,14 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev, struct sk_buff *pkt) { int status; - uint pkt_len = pkt->len; + uint pkt_len; bool fifo = (fix_inc == SDIOH_DATA_FIX); brcmf_dbg(TRACE, "Enter\n"); if (pkt == NULL) return -EINVAL; + pkt_len = pkt->len; brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait); if (brcmf_pm_resume_error(sdiodev)) @@ -485,7 +489,7 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, sdiodev->func[0] = func->card->sdio_func[0]; sdiodev->func[1] = func; sdiodev->bus_if = bus_if; - bus_if->bus_priv = sdiodev; + bus_if->bus_priv.sdio = sdiodev; bus_if->type = SDIO_BUS; bus_if->align = BRCMF_SDALIGN; dev_set_drvdata(&func->card->dev, sdiodev); @@ -526,7 +530,7 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func) if (func->num == 2) { bus_if = dev_get_drvdata(&func->dev); - sdiodev = bus_if->bus_priv; + sdiodev = bus_if->bus_priv.sdio; brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_remove...\n"); brcmf_sdio_remove(sdiodev); dev_set_drvdata(&func->card->dev, NULL); @@ -593,14 +597,14 @@ static struct sdio_driver brcmf_sdmmc_driver = { #endif /* CONFIG_PM_SLEEP */ }; -static void __exit brcmf_sdio_exit(void) +void brcmf_sdio_exit(void) { brcmf_dbg(TRACE, "Enter\n"); sdio_unregister_driver(&brcmf_sdmmc_driver); } -static int __init brcmf_sdio_init(void) +void brcmf_sdio_init(void) { int ret; @@ -610,9 +614,4 @@ static int __init brcmf_sdio_init(void) if (ret) brcmf_dbg(ERROR, "sdio_register_driver failed: %d\n", ret); - - return ret; } - -module_init(brcmf_sdio_init); -module_exit(brcmf_sdio_exit); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index e58ea40..07686a7 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h @@ -644,9 +644,9 @@ extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx); extern int brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf, uint len); -#ifdef BCMDBG +#ifdef DEBUG extern int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size); -#endif /* BCMDBG */ +#endif /* DEBUG */ extern int brcmf_ifname2idx(struct brcmf_pub *drvr, char *name); extern int brcmf_c_host_event(struct brcmf_pub *drvr, int *idx, diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h index ad9be24..3669164 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h @@ -39,8 +39,11 @@ struct dngl_stats { /* interface structure between common and bus layer */ struct brcmf_bus { u8 type; /* bus type */ - void *bus_priv; /* pointer to bus private structure */ - void *drvr; /* pointer to driver pub structure brcmf_pub */ + union { + struct brcmf_sdio_dev *sdio; + struct brcmf_usbdev *usb; + } bus_priv; + struct brcmf_pub *drvr; /* pointer to driver pub structure brcmf_pub */ enum brcmf_bus_state state; uint maxctl; /* Max size rxctl request from proto to bus */ bool drvr_up; /* Status flag of driver up/down */ @@ -102,4 +105,14 @@ extern int brcmf_bus_start(struct device *dev); extern int brcmf_add_if(struct device *dev, int ifidx, char *name, u8 *mac_addr); + +#ifdef CONFIG_BRCMFMAC_SDIO +extern void brcmf_sdio_exit(void); +extern void brcmf_sdio_init(void); +#endif +#ifdef CONFIG_BRCMFMAC_USB +extern void brcmf_usb_exit(void); +extern void brcmf_usb_init(void); +#endif + #endif /* _BRCMF_BUS_H_ */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c index ac8d1f4..b3e3b7f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c @@ -19,6 +19,8 @@ * For certain dcmd codes, the dongle interprets string data from the host. ******************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/types.h> #include <linux/netdevice.h> #include <linux/sched.h> diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c index a51d8f5..4187435 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c @@ -13,6 +13,9 @@ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/kernel.h> #include <linux/string.h> #include <linux/sched.h> @@ -38,7 +41,7 @@ #define BRCMF_PKT_FILTER_PATTERN_FIXED_LEN \ offsetof(struct brcmf_pkt_filter_pattern_le, mask_and_pattern) -#ifdef BCMDBG +#ifdef DEBUG static const char brcmf_version[] = "Dongle Host Driver, version " BRCMF_VERSION_STR "\nCompiled on " __DATE__ " at " __TIME__; @@ -133,7 +136,7 @@ bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, return p != NULL; } -#ifdef BCMDBG +#ifdef DEBUG static void brcmf_c_show_host_event(struct brcmf_event_msg *event, void *event_data) { @@ -399,10 +402,10 @@ brcmf_c_show_host_event(struct brcmf_event_msg *event, void *event_data) p = (char *)&buf[sizeof(struct msgtrace_hdr)]; while ((s = strstr(p, "\n")) != NULL) { *s = '\0'; - printk(KERN_DEBUG"%s\n", p); + pr_debug("%s\n", p); p = s + 1; } - printk(KERN_DEBUG "%s\n", p); + pr_debug("%s\n", p); /* Reset datalen to avoid display below */ datalen = 0; @@ -430,7 +433,7 @@ brcmf_c_show_host_event(struct brcmf_event_msg *event, void *event_data) brcmf_dbg(EVENT, "\n"); } } -#endif /* BCMDBG */ +#endif /* DEBUG */ int brcmf_c_host_event(struct brcmf_pub *drvr, int *ifidx, void *pktdata, @@ -518,9 +521,9 @@ brcmf_c_host_event(struct brcmf_pub *drvr, int *ifidx, void *pktdata, break; } -#ifdef BCMDBG +#ifdef DEBUG brcmf_c_show_host_event(event, event_data); -#endif /* BCMDBG */ +#endif /* DEBUG */ return 0; } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h index bb26ee3..a2c4576 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h @@ -32,20 +32,20 @@ #define BRCMF_BTA_VAL 0x1000 #define BRCMF_ISCAN_VAL 0x2000 -#if defined(BCMDBG) +#if defined(DEBUG) #define brcmf_dbg(level, fmt, ...) \ do { \ if (BRCMF_ERROR_VAL == BRCMF_##level##_VAL) { \ if (brcmf_msg_level & BRCMF_##level##_VAL) { \ if (net_ratelimit()) \ - printk(KERN_DEBUG "%s: " fmt, \ - __func__, ##__VA_ARGS__); \ + pr_debug("%s: " fmt, \ + __func__, ##__VA_ARGS__); \ } \ } else { \ if (brcmf_msg_level & BRCMF_##level##_VAL) { \ - printk(KERN_DEBUG "%s: " fmt, \ - __func__, ##__VA_ARGS__); \ + pr_debug("%s: " fmt, \ + __func__, ##__VA_ARGS__); \ } \ } \ } while (0) @@ -56,7 +56,7 @@ do { \ #define BRCMF_BYTES_ON() (brcmf_msg_level & BRCMF_BYTES_VAL) #define BRCMF_GLOM_ON() (brcmf_msg_level & BRCMF_GLOM_VAL) -#else /* (defined BCMDBG) || (defined BCMDBG) */ +#else /* (defined DEBUG) || (defined DEBUG) */ #define brcmf_dbg(level, fmt, ...) no_printk(fmt, ##__VA_ARGS__) @@ -66,7 +66,13 @@ do { \ #define BRCMF_BYTES_ON() 0 #define BRCMF_GLOM_ON() 0 -#endif /* defined(BCMDBG) */ +#endif /* defined(DEBUG) */ + +#define brcmf_dbg_hex_dump(test, data, len, fmt, ...) \ +do { \ + if (test) \ + brcmu_dbg_hex_dump(data, len, fmt, ##__VA_ARGS__); \ +} while (0) extern int brcmf_msg_level; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index eb9eb76..2a1e5ae 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c @@ -14,6 +14,8 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/init.h> #include <linux/kernel.h> #include <linux/kthread.h> @@ -590,8 +592,8 @@ static void brcmf_ethtool_get_drvinfo(struct net_device *ndev, sprintf(info->bus_info, "%s", dev_name(drvr->dev)); } -static struct ethtool_ops brcmf_ethtool_ops = { - .get_drvinfo = brcmf_ethtool_get_drvinfo +static const struct ethtool_ops brcmf_ethtool_ops = { + .get_drvinfo = brcmf_ethtool_get_drvinfo, }; static int brcmf_ethtool(struct brcmf_pub *drvr, void __user *uaddr) @@ -794,18 +796,19 @@ static int brcmf_netdev_open(struct net_device *ndev) { struct brcmf_if *ifp = netdev_priv(ndev); struct brcmf_pub *drvr = ifp->drvr; + struct brcmf_bus *bus_if = drvr->bus_if; u32 toe_ol; s32 ret = 0; brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx); if (ifp->idx == 0) { /* do it only for primary eth0 */ - /* try to bring up bus */ - ret = brcmf_bus_start(drvr->dev); - if (ret != 0) { - brcmf_dbg(ERROR, "failed with code %d\n", ret); - return -1; + /* If bus is not ready, can't continue */ + if (bus_if->state != BRCMF_BUS_DATA) { + brcmf_dbg(ERROR, "failed bus is not ready\n"); + return -EAGAIN; } + atomic_set(&drvr->pend_8021x_cnt, 0); memcpy(ndev->dev_addr, drvr->mac, ETH_ALEN); @@ -977,12 +980,6 @@ int brcmf_bus_start(struct device *dev) return ret; } - /* If bus is not ready, can't come up */ - if (bus_if->state != BRCMF_BUS_DATA) { - brcmf_dbg(ERROR, "failed bus is not ready\n"); - return -ENODEV; - } - brcmf_c_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf)); brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, iovbuf, @@ -1019,6 +1016,8 @@ int brcmf_bus_start(struct device *dev) if (ret < 0) return ret; + /* signal bus ready */ + bus_if->state = BRCMF_BUS_DATA; return 0; } @@ -1107,13 +1106,13 @@ void brcmf_detach(struct device *dev) if (drvr->iflist[i]) brcmf_del_if(drvr, i); - cancel_work_sync(&drvr->setmacaddr_work); - cancel_work_sync(&drvr->multicast_work); - brcmf_bus_detach(drvr); - if (drvr->prot) + if (drvr->prot) { + cancel_work_sync(&drvr->setmacaddr_work); + cancel_work_sync(&drvr->multicast_work); brcmf_proto_detach(drvr); + } bus_if->drvr = NULL; kfree(drvr); @@ -1146,7 +1145,7 @@ int brcmf_netdev_wait_pend8021x(struct net_device *ndev) return pend; } -#ifdef BCMDBG +#ifdef DEBUG int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size) { int ret = 0; @@ -1180,4 +1179,38 @@ exit: return ret; } -#endif /* BCMDBG */ +#endif /* DEBUG */ + +static void brcmf_driver_init(struct work_struct *work) +{ +#ifdef CONFIG_BRCMFMAC_SDIO + brcmf_sdio_init(); +#endif +#ifdef CONFIG_BRCMFMAC_USB + brcmf_usb_init(); +#endif +} +static DECLARE_WORK(brcmf_driver_work, brcmf_driver_init); + +static int __init brcmfmac_module_init(void) +{ + if (!schedule_work(&brcmf_driver_work)) + return -EBUSY; + + return 0; +} + +static void __exit brcmfmac_module_exit(void) +{ + cancel_work_sync(&brcmf_driver_work); + +#ifdef CONFIG_BRCMFMAC_SDIO + brcmf_sdio_exit(); +#endif +#ifdef CONFIG_BRCMFMAC_USB + brcmf_usb_exit(); +#endif +} + +module_init(brcmfmac_module_init); +module_exit(brcmfmac_module_exit); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index f7eeee1..2bf5dda 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c @@ -14,6 +14,8 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/types.h> #include <linux/kernel.h> #include <linux/kthread.h> @@ -40,7 +42,7 @@ #define DCMD_RESP_TIMEOUT 2000 /* In milli second */ -#ifdef BCMDBG +#ifdef DEBUG #define BRCMF_TRAP_INFO_SIZE 80 @@ -84,7 +86,7 @@ struct rte_console { char cbuf[CBUF_LEN]; }; -#endif /* BCMDBG */ +#endif /* DEBUG */ #include <chipcommon.h> #include "dhd_bus.h" @@ -307,10 +309,10 @@ struct rte_console { /* Flags for SDH calls */ #define F2SYNC (SDIO_REQ_4BYTE | SDIO_REQ_FIXED) -#define BRCMFMAC_FW_NAME "brcm/brcmfmac.bin" -#define BRCMFMAC_NV_NAME "brcm/brcmfmac.txt" -MODULE_FIRMWARE(BRCMFMAC_FW_NAME); -MODULE_FIRMWARE(BRCMFMAC_NV_NAME); +#define BRCMF_SDIO_FW_NAME "brcm/brcmfmac-sdio.bin" +#define BRCMF_SDIO_NV_NAME "brcm/brcmfmac-sdio.txt" +MODULE_FIRMWARE(BRCMF_SDIO_FW_NAME); +MODULE_FIRMWARE(BRCMF_SDIO_NV_NAME); #define BRCMF_IDLE_IMMEDIATE (-1) /* Enter idle immediately */ #define BRCMF_IDLE_ACTIVE 0 /* Do not request any SD clock change @@ -416,7 +418,7 @@ struct sdpcmd_regs { u16 PAD[0x80]; }; -#ifdef BCMDBG +#ifdef DEBUG /* Device console log buffer state */ struct brcmf_console { uint count; /* Poll interval msec counter */ @@ -426,7 +428,7 @@ struct brcmf_console { u8 *buf; /* Log buffer (host copy) */ uint last; /* Last buffer read index */ }; -#endif /* BCMDBG */ +#endif /* DEBUG */ struct sdpcm_shared { u32 flags; @@ -507,11 +509,11 @@ struct brcmf_sdio { uint polltick; /* Tick counter */ uint pollcnt; /* Count of active polls */ -#ifdef BCMDBG +#ifdef DEBUG uint console_interval; struct brcmf_console console; /* Console output polling support */ uint console_addr; /* Console address from shared struct */ -#endif /* BCMDBG */ +#endif /* DEBUG */ uint regfails; /* Count of R_REG failures */ @@ -587,10 +589,10 @@ struct brcmf_sdio { #define CLK_PENDING 2 /* Not used yet */ #define CLK_AVAIL 3 -#ifdef BCMDBG +#ifdef DEBUG static int qcount[NUMPRIO]; static int tx_packets[NUMPRIO]; -#endif /* BCMDBG */ +#endif /* DEBUG */ #define SDIO_DRIVE_STRENGTH 6 /* in milliamps */ @@ -764,12 +766,12 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) bus->clkstate = CLK_AVAIL; brcmf_dbg(INFO, "CLKCTL: turned ON\n"); -#if defined(BCMDBG) - if (bus->alp_only != true) { +#if defined(DEBUG) + if (!bus->alp_only) { if (SBSDIO_ALPONLY(clkctl)) brcmf_dbg(ERROR, "HT Clock should be on\n"); } -#endif /* defined (BCMDBG) */ +#endif /* defined (DEBUG) */ bus->activity = true; } else { @@ -814,9 +816,9 @@ static int brcmf_sdbrcm_sdclk(struct brcmf_sdio *bus, bool on) /* Transition SD and backplane clock readiness */ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok) { -#ifdef BCMDBG +#ifdef DEBUG uint oldstate = bus->clkstate; -#endif /* BCMDBG */ +#endif /* DEBUG */ brcmf_dbg(TRACE, "Enter\n"); @@ -861,9 +863,9 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok) brcmf_sdbrcm_wd_timer(bus, 0); break; } -#ifdef BCMDBG +#ifdef DEBUG brcmf_dbg(INFO, "%d -> %d\n", oldstate, bus->clkstate); -#endif /* BCMDBG */ +#endif /* DEBUG */ return 0; } @@ -1279,13 +1281,10 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) } return 0; } -#ifdef BCMDBG - if (BRCMF_GLOM_ON()) { - printk(KERN_DEBUG "SUPERFRAME:\n"); - print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, - pfirst->data, min_t(int, pfirst->len, 48)); - } -#endif + + brcmf_dbg_hex_dump(BRCMF_GLOM_ON(), + pfirst->data, min_t(int, pfirst->len, 48), + "SUPERFRAME:\n"); /* Validate the superframe header */ dptr = (u8 *) (pfirst->data); @@ -1362,13 +1361,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) check = get_unaligned_le16(dptr + sizeof(u16)); chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); -#ifdef BCMDBG - if (BRCMF_GLOM_ON()) { - printk(KERN_DEBUG "subframe:\n"); - print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, - dptr, 32); - } -#endif + brcmf_dbg_hex_dump(BRCMF_GLOM_ON(), + dptr, 32, "subframe:\n"); if ((u16)~(sublen ^ check)) { brcmf_dbg(ERROR, "(subframe %d): HW hdr error: len/check 0x%04x/0x%04x\n", @@ -1433,13 +1427,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) } rxseq++; -#ifdef BCMDBG - if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) { - printk(KERN_DEBUG "Rx Subframe Data:\n"); - print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, - dptr, dlen); - } -#endif + brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_DATA_ON(), + dptr, dlen, "Rx Subframe Data:\n"); __skb_trim(pfirst, sublen); skb_pull(pfirst, doff); @@ -1457,17 +1446,13 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) continue; } -#ifdef BCMDBG - if (BRCMF_GLOM_ON()) { - brcmf_dbg(GLOM, "subframe %d to stack, %p (%p/%d) nxt/lnk %p/%p\n", - bus->glom.qlen, pfirst, pfirst->data, - pfirst->len, pfirst->next, - pfirst->prev); - print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, - pfirst->data, - min_t(int, pfirst->len, 32)); - } -#endif /* BCMDBG */ + brcmf_dbg_hex_dump(BRCMF_GLOM_ON(), + pfirst->data, + min_t(int, pfirst->len, 32), + "subframe %d to stack, %p (%p/%d) nxt/lnk %p/%p\n", + bus->glom.qlen, pfirst, pfirst->data, + pfirst->len, pfirst->next, + pfirst->prev); } /* sent any remaining packets up */ if (bus->glom.qlen) { @@ -1584,12 +1569,8 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff) gotpkt: -#ifdef BCMDBG - if (BRCMF_BYTES_ON() && BRCMF_CTL_ON()) { - printk(KERN_DEBUG "RxCtrl:\n"); - print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, bus->rxctl, len); - } -#endif + brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_CTL_ON(), + bus->rxctl, len, "RxCtrl:\n"); /* Point to valid data and indicate its length */ bus->rxctl += doff; @@ -1818,17 +1799,13 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) } bus->tx_max = txmax; -#ifdef BCMDBG - if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) { - printk(KERN_DEBUG "Rx Data:\n"); - print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, - rxbuf, len); - } else if (BRCMF_HDRS_ON()) { - printk(KERN_DEBUG "RxHdr:\n"); - print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, - bus->rxhdr, SDPCM_HDRLEN); - } -#endif + brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_DATA_ON(), + rxbuf, len, "Rx Data:\n"); + brcmf_dbg_hex_dump(!(BRCMF_BYTES_ON() && + BRCMF_DATA_ON()) && + BRCMF_HDRS_ON(), + bus->rxhdr, SDPCM_HDRLEN, + "RxHdr:\n"); if (chan == SDPCM_CONTROL_CHANNEL) { brcmf_dbg(ERROR, "(nextlen): readahead on control packet %d?\n", @@ -1865,13 +1842,9 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) brcmf_sdbrcm_rxfail(bus, true, true); continue; } -#ifdef BCMDBG - if (BRCMF_BYTES_ON() || BRCMF_HDRS_ON()) { - printk(KERN_DEBUG "RxHdr:\n"); - print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, - bus->rxhdr, SDPCM_HDRLEN); - } -#endif + brcmf_dbg_hex_dump(BRCMF_BYTES_ON() || BRCMF_HDRS_ON(), + bus->rxhdr, SDPCM_HDRLEN, "RxHdr:\n"); + /* Extract hardware header fields */ len = get_unaligned_le16(bus->rxhdr); @@ -2024,13 +1997,8 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) skb_push(pkt, BRCMF_FIRSTREAD); memcpy(pkt->data, bus->rxhdr, BRCMF_FIRSTREAD); -#ifdef BCMDBG - if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) { - printk(KERN_DEBUG "Rx Data:\n"); - print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, - pkt->data, len); - } -#endif + brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_DATA_ON(), + pkt->data, len, "Rx Data:\n"); deliver: /* Save superframe descriptor and allocate packet frame */ @@ -2038,14 +2006,9 @@ deliver: if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) { brcmf_dbg(GLOM, "glom descriptor, %d bytes:\n", len); -#ifdef BCMDBG - if (BRCMF_GLOM_ON()) { - printk(KERN_DEBUG "Glom Data:\n"); - print_hex_dump_bytes("", - DUMP_PREFIX_OFFSET, - pkt->data, len); - } -#endif + brcmf_dbg_hex_dump(BRCMF_GLOM_ON(), + pkt->data, len, + "Glom Data:\n"); __skb_trim(pkt, len); skb_pull(pkt, SDPCM_HDRLEN); bus->glomd = pkt; @@ -2078,13 +2041,11 @@ deliver: down(&bus->sdsem); } rxcount = maxframes - rxleft; -#ifdef BCMDBG /* Message if we hit the limit */ if (!rxleft) brcmf_dbg(DATA, "hit rx limit of %d frames\n", maxframes); else -#endif /* BCMDBG */ brcmf_dbg(DATA, "processed %d frames\n", rxcount); /* Back off rxseq if awaiting rtx, update rx_seq */ if (bus->rxskip) @@ -2098,8 +2059,7 @@ static void brcmf_sdbrcm_wait_for_event(struct brcmf_sdio *bus, bool *lockvar) { up(&bus->sdsem); - wait_event_interruptible_timeout(bus->ctrl_wait, - (*lockvar == false), HZ * 2); + wait_event_interruptible_timeout(bus->ctrl_wait, !*lockvar, HZ * 2); down(&bus->sdsem); return; } @@ -2176,20 +2136,22 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN); put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader)); -#ifdef BCMDBG +#ifdef DEBUG tx_packets[pkt->priority]++; - if (BRCMF_BYTES_ON() && - (((BRCMF_CTL_ON() && (chan == SDPCM_CONTROL_CHANNEL)) || - (BRCMF_DATA_ON() && (chan != SDPCM_CONTROL_CHANNEL))))) { - printk(KERN_DEBUG "Tx Frame:\n"); - print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, frame, len); - } else if (BRCMF_HDRS_ON()) { - printk(KERN_DEBUG "TxHdr:\n"); - print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, - frame, min_t(u16, len, 16)); - } #endif + brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && + ((BRCMF_CTL_ON() && chan == SDPCM_CONTROL_CHANNEL) || + (BRCMF_DATA_ON() && chan != SDPCM_CONTROL_CHANNEL)), + frame, len, "Tx Frame:\n"); + brcmf_dbg_hex_dump(!(BRCMF_BYTES_ON() && + ((BRCMF_CTL_ON() && + chan == SDPCM_CONTROL_CHANNEL) || + (BRCMF_DATA_ON() && + chan != SDPCM_CONTROL_CHANNEL))) && + BRCMF_HDRS_ON(), + frame, min_t(u16, len, 16), "TxHdr:\n"); + /* Raise len to next SDIO block to eliminate tail command */ if (bus->roundup && bus->blocksize && (len > bus->blocksize)) { u16 pad = bus->blocksize - (len % bus->blocksize); @@ -2314,7 +2276,7 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev) uint retries; int err; struct brcmf_bus *bus_if = dev_get_drvdata(dev); - struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv; + struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; struct brcmf_sdio *bus = sdiodev->bus; brcmf_dbg(TRACE, "Enter\n"); @@ -2410,7 +2372,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) int err; u8 clkctl, devctl = 0; -#ifdef BCMDBG +#ifdef DEBUG /* Check for inconsistent device control */ devctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err); @@ -2418,7 +2380,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) brcmf_dbg(ERROR, "error reading DEVCTL: %d\n", err); bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; } -#endif /* BCMDBG */ +#endif /* DEBUG */ /* Read CSR, if clock on switch to AVAIL, else ignore */ clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, @@ -2664,7 +2626,7 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) int ret = -EBADE; uint datalen, prec; struct brcmf_bus *bus_if = dev_get_drvdata(dev); - struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv; + struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; struct brcmf_sdio *bus = sdiodev->bus; brcmf_dbg(TRACE, "Enter\n"); @@ -2684,8 +2646,7 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) /* Priority based enq */ spin_lock_bh(&bus->txqlock); - if (brcmf_c_prec_enq(bus->sdiodev->dev, &bus->txq, pkt, prec) == - false) { + if (!brcmf_c_prec_enq(bus->sdiodev->dev, &bus->txq, pkt, prec)) { skb_pull(pkt, SDPCM_HDRLEN); brcmf_txcomplete(bus->sdiodev->dev, pkt, false); brcmu_pkt_buf_free_skb(pkt); @@ -2701,7 +2662,7 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) brcmf_txflowcontrol(bus->sdiodev->dev, 0, ON); } -#ifdef BCMDBG +#ifdef DEBUG if (pktq_plen(&bus->txq, prec) > qcount[prec]) qcount[prec] = pktq_plen(&bus->txq, prec); #endif @@ -2774,7 +2735,7 @@ xfer_done: return bcmerror; } -#ifdef BCMDBG +#ifdef DEBUG #define CONSOLE_LINE_MAX 192 static int brcmf_sdbrcm_readconsole(struct brcmf_sdio *bus) @@ -2845,14 +2806,14 @@ static int brcmf_sdbrcm_readconsole(struct brcmf_sdio *bus) if (line[n - 1] == '\r') n--; line[n] = 0; - printk(KERN_DEBUG "CONSOLE: %s\n", line); + pr_debug("CONSOLE: %s\n", line); } } break2: return 0; } -#endif /* BCMDBG */ +#endif /* DEBUG */ static int brcmf_tx_frame(struct brcmf_sdio *bus, u8 *frame, u16 len) { @@ -2906,7 +2867,7 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) u8 doff = 0; int ret = -1; struct brcmf_bus *bus_if = dev_get_drvdata(dev); - struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv; + struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; struct brcmf_sdio *bus = sdiodev->bus; brcmf_dbg(TRACE, "Enter\n"); @@ -2972,7 +2933,7 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) brcmf_sdbrcm_wait_for_event(bus, &bus->ctrl_frame_stat); - if (bus->ctrl_frame_stat == false) { + if (!bus->ctrl_frame_stat) { brcmf_dbg(INFO, "ctrl_frame_stat == false\n"); ret = 0; } else { @@ -2982,17 +2943,11 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) } if (ret == -1) { -#ifdef BCMDBG - if (BRCMF_BYTES_ON() && BRCMF_CTL_ON()) { - printk(KERN_DEBUG "Tx Frame:\n"); - print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, - frame, len); - } else if (BRCMF_HDRS_ON()) { - printk(KERN_DEBUG "TxHdr:\n"); - print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, - frame, min_t(u16, len, 16)); - } -#endif + brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_CTL_ON(), + frame, len, "Tx Frame:\n"); + brcmf_dbg_hex_dump(!(BRCMF_BYTES_ON() && BRCMF_CTL_ON()) && + BRCMF_HDRS_ON(), + frame, min_t(u16, len, 16), "TxHdr:\n"); do { ret = brcmf_tx_frame(bus, frame, len); @@ -3021,7 +2976,7 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen) uint rxlen = 0; bool pending; struct brcmf_bus *bus_if = dev_get_drvdata(dev); - struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv; + struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; struct brcmf_sdio *bus = sdiodev->bus; brcmf_dbg(TRACE, "Enter\n"); @@ -3040,7 +2995,7 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen) rxlen, msglen); } else if (timeleft == 0) { brcmf_dbg(ERROR, "resumed on timeout\n"); - } else if (pending == true) { + } else if (pending) { brcmf_dbg(CTL, "cancelled\n"); return -ERESTARTSYS; } else { @@ -3096,9 +3051,9 @@ static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus) u8 *vbuffer; u32 varsizew; __le32 varsizew_le; -#ifdef BCMDBG +#ifdef DEBUG char *nvram_ularray; -#endif /* BCMDBG */ +#endif /* DEBUG */ /* Even if there are no vars are to be written, we still need to set the ramsize. */ @@ -3115,7 +3070,7 @@ static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus) /* Write the vars list */ bcmerror = brcmf_sdbrcm_membytes(bus, true, varaddr, vbuffer, varsize); -#ifdef BCMDBG +#ifdef DEBUG /* Verify NVRAM bytes */ brcmf_dbg(INFO, "Compare NVRAM dl & ul; varsize=%d\n", varsize); nvram_ularray = kmalloc(varsize, GFP_ATOMIC); @@ -3142,7 +3097,7 @@ static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus) brcmf_dbg(ERROR, "Download/Upload/Compare of NVRAM ok\n"); kfree(nvram_ularray); -#endif /* BCMDBG */ +#endif /* DEBUG */ kfree(vbuffer); } @@ -3245,7 +3200,7 @@ static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus) brcmf_dbg(INFO, "Enter\n"); - ret = request_firmware(&bus->firmware, BRCMFMAC_FW_NAME, + ret = request_firmware(&bus->firmware, BRCMF_SDIO_FW_NAME, &bus->sdiodev->func[2]->dev); if (ret) { brcmf_dbg(ERROR, "Fail to request firmware %d\n", ret); @@ -3342,7 +3297,7 @@ static int brcmf_sdbrcm_download_nvram(struct brcmf_sdio *bus) char *bufp; int ret; - ret = request_firmware(&bus->firmware, BRCMFMAC_NV_NAME, + ret = request_firmware(&bus->firmware, BRCMF_SDIO_NV_NAME, &bus->sdiodev->func[2]->dev); if (ret) { brcmf_dbg(ERROR, "Fail to request nvram %d\n", ret); @@ -3432,7 +3387,7 @@ brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus) static int brcmf_sdbrcm_bus_init(struct device *dev) { struct brcmf_bus *bus_if = dev_get_drvdata(dev); - struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv; + struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; struct brcmf_sdio *bus = sdiodev->bus; unsigned long timeout; uint retries = 0; @@ -3507,16 +3462,12 @@ static int brcmf_sdbrcm_bus_init(struct device *dev) brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, SBSDIO_WATERMARK, 8, &err); - - /* Set bus state according to enable result */ - bus_if->state = BRCMF_BUS_DATA; - } - - else { + } else { /* Disable F2 again */ enable = SDIO_FUNC_ENABLE_1; brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx, enable, NULL); + ret = -ENODEV; } /* Restore previous clock setting */ @@ -3524,7 +3475,7 @@ static int brcmf_sdbrcm_bus_init(struct device *dev) SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err); /* If we didn't come up, turn off backplane clock */ - if (bus_if->state != BRCMF_BUS_DATA) + if (!ret) brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); exit: @@ -3569,9 +3520,9 @@ void brcmf_sdbrcm_isr(void *arg) static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) { -#ifdef BCMDBG +#ifdef DEBUG struct brcmf_bus *bus_if = dev_get_drvdata(bus->sdiodev->dev); -#endif /* BCMDBG */ +#endif /* DEBUG */ brcmf_dbg(TIMER, "Enter\n"); @@ -3616,7 +3567,7 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) /* Update interrupt tracking */ bus->lastintrs = bus->intrcount; } -#ifdef BCMDBG +#ifdef DEBUG /* Poll for console output periodically */ if (bus_if->state == BRCMF_BUS_DATA && bus->console_interval != 0) { @@ -3630,7 +3581,7 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) bus->console_interval = 0; } } -#endif /* BCMDBG */ +#endif /* DEBUG */ /* On idle timeout clear activity flag and/or turn off clock */ if ((bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) { @@ -3721,11 +3672,8 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva) if (brcmf_sdcard_set_sbaddr_window(bus->sdiodev, SI_ENUM_BASE)) brcmf_dbg(ERROR, "FAILED to return to SI_ENUM_BASE\n"); -#ifdef BCMDBG - printk(KERN_DEBUG "F1 signature read @0x18000000=0x%4x\n", - brcmf_sdcard_reg_read(bus->sdiodev, SI_ENUM_BASE, 4)); - -#endif /* BCMDBG */ + pr_debug("F1 signature read @0x18000000=0x%4x\n", + brcmf_sdcard_reg_read(bus->sdiodev, SI_ENUM_BASE, 4)); /* * Force PLL off until brcmf_sdio_chip_attach() @@ -3944,8 +3892,7 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) bus->watchdog_tsk = kthread_run(brcmf_sdbrcm_watchdog_thread, bus, "brcmf_watchdog"); if (IS_ERR(bus->watchdog_tsk)) { - printk(KERN_WARNING - "brcmf_watchdog thread failed to start\n"); + pr_warn("brcmf_watchdog thread failed to start\n"); bus->watchdog_tsk = NULL; } /* Initialize DPC thread */ @@ -3953,8 +3900,7 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) bus->dpc_tsk = kthread_run(brcmf_sdbrcm_dpc_thread, bus, "brcmf_dpc"); if (IS_ERR(bus->dpc_tsk)) { - printk(KERN_WARNING - "brcmf_dpc thread failed to start\n"); + pr_warn("brcmf_dpc thread failed to start\n"); bus->dpc_tsk = NULL; } @@ -4031,7 +3977,7 @@ void brcmf_sdbrcm_wd_timer(struct brcmf_sdio *bus, uint wdtick) { /* Totally stop the timer */ - if (!wdtick && bus->wd_timer_valid == true) { + if (!wdtick && bus->wd_timer_valid) { del_timer_sync(&bus->timer); bus->wd_timer_valid = false; bus->save_ms = wdtick; @@ -4044,7 +3990,7 @@ brcmf_sdbrcm_wd_timer(struct brcmf_sdio *bus, uint wdtick) if (wdtick) { if (bus->save_ms != BRCMF_WD_POLL_MS) { - if (bus->wd_timer_valid == true) + if (bus->wd_timer_valid) /* Stop timer and restart at new value */ del_timer_sync(&bus->timer); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c index 11b2d7c..1534efc 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c @@ -15,6 +15,8 @@ */ /* ***** SDIO interface chip backplane handle functions ***** */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/types.h> #include <linux/netdevice.h> #include <linux/mmc/card.h> diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c new file mode 100644 index 0000000..8236422 --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -0,0 +1,1621 @@ +/* + * Copyright (c) 2011 Broadcom Corporation + * + * 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. + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/kthread.h> +#include <linux/slab.h> +#include <linux/skbuff.h> +#include <linux/netdevice.h> +#include <linux/spinlock.h> +#include <linux/ethtool.h> +#include <linux/fcntl.h> +#include <linux/fs.h> +#include <linux/uaccess.h> +#include <linux/firmware.h> +#include <linux/usb.h> +#include <net/cfg80211.h> + +#include <defs.h> +#include <brcmu_utils.h> +#include <brcmu_wifi.h> +#include <dhd_bus.h> +#include <dhd_dbg.h> + +#include "usb_rdl.h" +#include "usb.h" + +#define IOCTL_RESP_TIMEOUT 2000 + +#define BRCMF_USB_SYNC_TIMEOUT 300 /* ms */ +#define BRCMF_USB_DLIMAGE_SPINWAIT 100 /* in unit of ms */ +#define BRCMF_USB_DLIMAGE_LIMIT 500 /* spinwait limit (ms) */ + +#define BRCMF_POSTBOOT_ID 0xA123 /* ID to detect if dongle + has boot up */ +#define BRCMF_USB_RESETCFG_SPINWAIT 1 /* wait after resetcfg (ms) */ + +#define BRCMF_USB_NRXQ 50 +#define BRCMF_USB_NTXQ 50 + +#define CONFIGDESC(usb) (&((usb)->actconfig)->desc) +#define IFPTR(usb, idx) ((usb)->actconfig->interface[(idx)]) +#define IFALTS(usb, idx) (IFPTR((usb), (idx))->altsetting[0]) +#define IFDESC(usb, idx) IFALTS((usb), (idx)).desc +#define IFEPDESC(usb, idx, ep) (IFALTS((usb), (idx)).endpoint[(ep)]).desc + +#define CONTROL_IF 0 +#define BULK_IF 0 + +#define BRCMF_USB_CBCTL_WRITE 0 +#define BRCMF_USB_CBCTL_READ 1 +#define BRCMF_USB_MAX_PKT_SIZE 1600 + +#define BRCMF_USB_43236_FW_NAME "brcm/brcmfmac43236b.bin" + +enum usbdev_suspend_state { + USBOS_SUSPEND_STATE_DEVICE_ACTIVE = 0, /* Device is busy, won't allow + suspend */ + USBOS_SUSPEND_STATE_SUSPEND_PENDING, /* Device is idle, can be + * suspended. Wating PM to + * suspend the device + */ + USBOS_SUSPEND_STATE_SUSPENDED /* Device suspended */ +}; + +struct brcmf_usb_probe_info { + void *usbdev_info; + struct usb_device *usb; /* USB device pointer from OS */ + uint rx_pipe, tx_pipe, intr_pipe, rx_pipe2; + int intr_size; /* Size of interrupt message */ + int interval; /* Interrupt polling interval */ + int vid; + int pid; + enum usb_device_speed device_speed; + enum usbdev_suspend_state suspend_state; + struct usb_interface *intf; +}; +static struct brcmf_usb_probe_info usbdev_probe_info; + +struct brcmf_usb_image { + void *data; + u32 len; +}; +static struct brcmf_usb_image g_image = { NULL, 0 }; + +struct intr_transfer_buf { + u32 notification; + u32 reserved; +}; + +struct brcmf_usbdev_info { + struct brcmf_usbdev bus_pub; /* MUST BE FIRST */ + spinlock_t qlock; + struct list_head rx_freeq; + struct list_head rx_postq; + struct list_head tx_freeq; + struct list_head tx_postq; + enum usbdev_suspend_state suspend_state; + uint rx_pipe, tx_pipe, intr_pipe, rx_pipe2; + + bool activity; + int rx_low_watermark; + int tx_low_watermark; + int tx_high_watermark; + bool txoff; + bool rxoff; + bool txoverride; + + struct brcmf_usbreq *tx_reqs; + struct brcmf_usbreq *rx_reqs; + + u8 *image; /* buffer for combine fw and nvram */ + int image_len; + + wait_queue_head_t wait; + bool waitdone; + int sync_urb_status; + + struct usb_device *usbdev; + struct device *dev; + enum usb_device_speed device_speed; + + int ctl_in_pipe, ctl_out_pipe; + struct urb *ctl_urb; /* URB for control endpoint */ + struct usb_ctrlrequest ctl_write; + struct usb_ctrlrequest ctl_read; + u32 ctl_urb_actual_length; + int ctl_urb_status; + int ctl_completed; + wait_queue_head_t ioctl_resp_wait; + wait_queue_head_t ctrl_wait; + ulong ctl_op; + + bool rxctl_deferrespok; + + struct urb *bulk_urb; /* used for FW download */ + struct urb *intr_urb; /* URB for interrupt endpoint */ + int intr_size; /* Size of interrupt message */ + int interval; /* Interrupt polling interval */ + struct intr_transfer_buf intr; /* Data buffer for interrupt endpoint */ + + struct brcmf_usb_probe_info probe_info; + +}; + +static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo, + struct brcmf_usbreq *req); + +MODULE_AUTHOR("Broadcom Corporation"); +MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN fullmac usb driver."); +MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN fullmac usb cards"); +MODULE_LICENSE("Dual BSD/GPL"); + +static struct brcmf_usbdev *brcmf_usb_get_buspub(struct device *dev) +{ + struct brcmf_bus *bus_if = dev_get_drvdata(dev); + return bus_if->bus_priv.usb; +} + +static struct brcmf_usbdev_info *brcmf_usb_get_businfo(struct device *dev) +{ + return brcmf_usb_get_buspub(dev)->devinfo; +} + +#if 0 +static void +brcmf_usb_txflowcontrol(struct brcmf_usbdev_info *devinfo, bool onoff) +{ + dhd_txflowcontrol(devinfo->bus_pub.netdev, 0, onoff); +} +#endif + +static int brcmf_usb_ioctl_resp_wait(struct brcmf_usbdev_info *devinfo, + uint *condition, bool *pending) +{ + DECLARE_WAITQUEUE(wait, current); + int timeout = IOCTL_RESP_TIMEOUT; + + /* Convert timeout in millsecond to jiffies */ + timeout = msecs_to_jiffies(timeout); + /* Wait until control frame is available */ + add_wait_queue(&devinfo->ioctl_resp_wait, &wait); + set_current_state(TASK_INTERRUPTIBLE); + + smp_mb(); + while (!(*condition) && (!signal_pending(current) && timeout)) { + timeout = schedule_timeout(timeout); + /* Wait until control frame is available */ + smp_mb(); + } + + if (signal_pending(current)) + *pending = true; + + set_current_state(TASK_RUNNING); + remove_wait_queue(&devinfo->ioctl_resp_wait, &wait); + + return timeout; +} + +static int brcmf_usb_ioctl_resp_wake(struct brcmf_usbdev_info *devinfo) +{ + if (waitqueue_active(&devinfo->ioctl_resp_wait)) + wake_up_interruptible(&devinfo->ioctl_resp_wait); + + return 0; +} + +static void +brcmf_usb_ctl_complete(struct brcmf_usbdev_info *devinfo, int type, int status) +{ + + if (unlikely(devinfo == NULL)) + return; + + if (type == BRCMF_USB_CBCTL_READ) { + if (status == 0) + devinfo->bus_pub.stats.rx_ctlpkts++; + else + devinfo->bus_pub.stats.rx_ctlerrs++; + } else if (type == BRCMF_USB_CBCTL_WRITE) { + if (status == 0) + devinfo->bus_pub.stats.tx_ctlpkts++; + else + devinfo->bus_pub.stats.tx_ctlerrs++; + } + + devinfo->ctl_urb_status = status; + devinfo->ctl_completed = true; + brcmf_usb_ioctl_resp_wake(devinfo); +} + +static void +brcmf_usb_ctlread_complete(struct urb *urb) +{ + struct brcmf_usbdev_info *devinfo = + (struct brcmf_usbdev_info *)urb->context; + + devinfo->ctl_urb_actual_length = urb->actual_length; + brcmf_usb_ctl_complete(devinfo, BRCMF_USB_CBCTL_READ, + urb->status); +} + +static void +brcmf_usb_ctlwrite_complete(struct urb *urb) +{ + struct brcmf_usbdev_info *devinfo = + (struct brcmf_usbdev_info *)urb->context; + + brcmf_usb_ctl_complete(devinfo, BRCMF_USB_CBCTL_WRITE, + urb->status); +} + +static int brcmf_usb_pnp(struct brcmf_usbdev_info *devinfo, uint state) +{ + return 0; +} + +static int +brcmf_usb_send_ctl(struct brcmf_usbdev_info *devinfo, u8 *buf, int len) +{ + int ret; + u16 size; + + if (devinfo == NULL || buf == NULL || + len == 0 || devinfo->ctl_urb == NULL) + return -EINVAL; + + /* If the USB/HSIC bus in sleep state, wake it up */ + if (devinfo->suspend_state == USBOS_SUSPEND_STATE_SUSPENDED) + if (brcmf_usb_pnp(devinfo, BCMFMAC_USB_PNP_RESUME) != 0) { + brcmf_dbg(ERROR, "Could not Resume the bus!\n"); + return -EIO; + } + + devinfo->activity = true; + size = len; + devinfo->ctl_write.wLength = cpu_to_le16p(&size); + devinfo->ctl_urb->transfer_buffer_length = size; + devinfo->ctl_urb_status = 0; + devinfo->ctl_urb_actual_length = 0; + + usb_fill_control_urb(devinfo->ctl_urb, + devinfo->usbdev, + devinfo->ctl_out_pipe, + (unsigned char *) &devinfo->ctl_write, + buf, size, + (usb_complete_t)brcmf_usb_ctlwrite_complete, + devinfo); + + ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC); + if (ret < 0) + brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret); + + return ret; +} + +static int +brcmf_usb_recv_ctl(struct brcmf_usbdev_info *devinfo, u8 *buf, int len) +{ + int ret; + u16 size; + + if ((devinfo == NULL) || (buf == NULL) || (len == 0) + || (devinfo->ctl_urb == NULL)) + return -EINVAL; + + size = len; + devinfo->ctl_read.wLength = cpu_to_le16p(&size); + devinfo->ctl_urb->transfer_buffer_length = size; + + if (devinfo->rxctl_deferrespok) { + /* BMAC model */ + devinfo->ctl_read.bRequestType = USB_DIR_IN + | USB_TYPE_VENDOR | USB_RECIP_INTERFACE; + devinfo->ctl_read.bRequest = DL_DEFER_RESP_OK; + } else { + /* full dongle model */ + devinfo->ctl_read.bRequestType = USB_DIR_IN + | USB_TYPE_CLASS | USB_RECIP_INTERFACE; + devinfo->ctl_read.bRequest = 1; + } + + usb_fill_control_urb(devinfo->ctl_urb, + devinfo->usbdev, + devinfo->ctl_in_pipe, + (unsigned char *) &devinfo->ctl_read, + buf, size, + (usb_complete_t)brcmf_usb_ctlread_complete, + devinfo); + + ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC); + if (ret < 0) + brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret); + + return ret; +} + +static int brcmf_usb_tx_ctlpkt(struct device *dev, u8 *buf, u32 len) +{ + int err = 0; + int timeout = 0; + bool pending; + struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); + + if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) { + /* TODO: handle suspend/resume */ + return -EIO; + } + + if (test_and_set_bit(0, &devinfo->ctl_op)) + return -EIO; + + err = brcmf_usb_send_ctl(devinfo, buf, len); + if (err) { + brcmf_dbg(ERROR, "fail %d bytes: %d\n", err, len); + return err; + } + + devinfo->ctl_completed = false; + timeout = brcmf_usb_ioctl_resp_wait(devinfo, &devinfo->ctl_completed, + &pending); + clear_bit(0, &devinfo->ctl_op); + if (!timeout) { + brcmf_dbg(ERROR, "Txctl wait timed out\n"); + err = -EIO; + } + return err; +} + +static int brcmf_usb_rx_ctlpkt(struct device *dev, u8 *buf, u32 len) +{ + int err = 0; + int timeout = 0; + bool pending; + struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); + + if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) { + /* TODO: handle suspend/resume */ + return -EIO; + } + if (test_and_set_bit(0, &devinfo->ctl_op)) + return -EIO; + + err = brcmf_usb_recv_ctl(devinfo, buf, len); + if (err) { + brcmf_dbg(ERROR, "fail %d bytes: %d\n", err, len); + return err; + } + devinfo->ctl_completed = false; + timeout = brcmf_usb_ioctl_resp_wait(devinfo, &devinfo->ctl_completed, + &pending); + err = devinfo->ctl_urb_status; + clear_bit(0, &devinfo->ctl_op); + if (!timeout) { + brcmf_dbg(ERROR, "rxctl wait timed out\n"); + err = -EIO; + } + if (!err) + return devinfo->ctl_urb_actual_length; + else + return err; +} + +static struct brcmf_usbreq *brcmf_usb_deq(struct brcmf_usbdev_info *devinfo, + struct list_head *q) +{ + unsigned long flags; + struct brcmf_usbreq *req; + spin_lock_irqsave(&devinfo->qlock, flags); + if (list_empty(q)) { + spin_unlock_irqrestore(&devinfo->qlock, flags); + return NULL; + } + req = list_entry(q->next, struct brcmf_usbreq, list); + list_del_init(q->next); + spin_unlock_irqrestore(&devinfo->qlock, flags); + return req; + +} + +static void brcmf_usb_enq(struct brcmf_usbdev_info *devinfo, + struct list_head *q, struct brcmf_usbreq *req) +{ + unsigned long flags; + spin_lock_irqsave(&devinfo->qlock, flags); + list_add_tail(&req->list, q); + spin_unlock_irqrestore(&devinfo->qlock, flags); +} + +static struct brcmf_usbreq * +brcmf_usbdev_qinit(struct list_head *q, int qsize) +{ + int i; + struct brcmf_usbreq *req, *reqs; + + reqs = kzalloc(sizeof(struct brcmf_usbreq) * qsize, GFP_ATOMIC); + if (reqs == NULL) { + brcmf_dbg(ERROR, "fail to allocate memory!\n"); + return NULL; + } + req = reqs; + + for (i = 0; i < qsize; i++) { + req->urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!req->urb) + goto fail; + + INIT_LIST_HEAD(&req->list); + list_add_tail(&req->list, q); + req++; + } + return reqs; +fail: + brcmf_dbg(ERROR, "fail!\n"); + while (!list_empty(q)) { + req = list_entry(q->next, struct brcmf_usbreq, list); + if (req && req->urb) + usb_free_urb(req->urb); + list_del(q->next); + } + return NULL; + +} + +static void brcmf_usb_free_q(struct list_head *q, bool pending) +{ + struct brcmf_usbreq *req, *next; + int i = 0; + list_for_each_entry_safe(req, next, q, list) { + if (!req->urb) { + brcmf_dbg(ERROR, "bad req\n"); + break; + } + i++; + if (pending) { + usb_kill_urb(req->urb); + } else { + usb_free_urb(req->urb); + list_del_init(&req->list); + } + } +} + +static void brcmf_usb_del_fromq(struct brcmf_usbdev_info *devinfo, + struct brcmf_usbreq *req) +{ + unsigned long flags; + + spin_lock_irqsave(&devinfo->qlock, flags); + list_del_init(&req->list); + spin_unlock_irqrestore(&devinfo->qlock, flags); +} + + +static void brcmf_usb_tx_complete(struct urb *urb) +{ + struct brcmf_usbreq *req = (struct brcmf_usbreq *)urb->context; + struct brcmf_usbdev_info *devinfo = req->devinfo; + + brcmf_usb_del_fromq(devinfo, req); + if (urb->status == 0) + devinfo->bus_pub.bus->dstats.tx_packets++; + else + devinfo->bus_pub.bus->dstats.tx_errors++; + + dev_kfree_skb(req->skb); + req->skb = NULL; + brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req); + +} + +static void brcmf_usb_rx_complete(struct urb *urb) +{ + struct brcmf_usbreq *req = (struct brcmf_usbreq *)urb->context; + struct brcmf_usbdev_info *devinfo = req->devinfo; + struct sk_buff *skb; + int ifidx = 0; + + brcmf_usb_del_fromq(devinfo, req); + skb = req->skb; + req->skb = NULL; + + if (urb->status == 0) { + devinfo->bus_pub.bus->dstats.rx_packets++; + } else { + devinfo->bus_pub.bus->dstats.rx_errors++; + dev_kfree_skb(skb); + brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); + return; + } + + if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP) { + skb_put(skb, urb->actual_length); + if (brcmf_proto_hdrpull(devinfo->dev, &ifidx, skb) != 0) { + brcmf_dbg(ERROR, "rx protocol error\n"); + brcmu_pkt_buf_free_skb(skb); + devinfo->bus_pub.bus->dstats.rx_errors++; + } else { + brcmf_rx_packet(devinfo->dev, ifidx, skb); + brcmf_usb_rx_refill(devinfo, req); + } + } else { + dev_kfree_skb(skb); + } + return; + +} + +static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo, + struct brcmf_usbreq *req) +{ + struct sk_buff *skb; + int ret; + + if (!req || !devinfo) + return; + + skb = dev_alloc_skb(devinfo->bus_pub.bus_mtu); + if (!skb) { + brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); + return; + } + req->skb = skb; + + usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->rx_pipe, + skb->data, skb_tailroom(skb), brcmf_usb_rx_complete, + req); + req->urb->transfer_flags |= URB_ZERO_PACKET; + req->devinfo = devinfo; + + ret = usb_submit_urb(req->urb, GFP_ATOMIC); + if (ret == 0) { + brcmf_usb_enq(devinfo, &devinfo->rx_postq, req); + } else { + dev_kfree_skb(req->skb); + req->skb = NULL; + brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); + } + return; +} + +static void brcmf_usb_rx_fill_all(struct brcmf_usbdev_info *devinfo) +{ + struct brcmf_usbreq *req; + + if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) { + brcmf_dbg(ERROR, "bus is not up\n"); + return; + } + while ((req = brcmf_usb_deq(devinfo, &devinfo->rx_freeq)) != NULL) + brcmf_usb_rx_refill(devinfo, req); +} + +static void +brcmf_usb_state_change(struct brcmf_usbdev_info *devinfo, int state) +{ + struct brcmf_bus *bcmf_bus = devinfo->bus_pub.bus; + int old_state; + + + if (devinfo->bus_pub.state == state) + return; + + old_state = devinfo->bus_pub.state; + brcmf_dbg(TRACE, "dbus state change from %d to to %d\n", + old_state, state); + + /* Don't update state if it's PnP firmware re-download */ + if (state != BCMFMAC_USB_STATE_PNP_FWDL) /* TODO */ + devinfo->bus_pub.state = state; + + if ((old_state == BCMFMAC_USB_STATE_SLEEP) + && (state == BCMFMAC_USB_STATE_UP)) { + brcmf_usb_rx_fill_all(devinfo); + } + + /* update state of upper layer */ + if (state == BCMFMAC_USB_STATE_DOWN) { + brcmf_dbg(INFO, "DBUS is down\n"); + bcmf_bus->state = BRCMF_BUS_DOWN; + } else { + brcmf_dbg(INFO, "DBUS current state=%d\n", state); + } +} + +static void +brcmf_usb_intr_complete(struct urb *urb) +{ + struct brcmf_usbdev_info *devinfo = + (struct brcmf_usbdev_info *)urb->context; + bool killed; + + if (devinfo == NULL) + return; + + if (unlikely(urb->status)) { + if (devinfo->suspend_state == + USBOS_SUSPEND_STATE_SUSPEND_PENDING) + killed = true; + + if ((urb->status == -ENOENT && (!killed)) + || urb->status == -ESHUTDOWN || + urb->status == -ENODEV) { + brcmf_usb_state_change(devinfo, BCMFMAC_USB_STATE_DOWN); + } + } + + if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_DOWN) { + brcmf_dbg(ERROR, "intr cb when DBUS down, ignoring\n"); + return; + } + + if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP) + usb_submit_urb(devinfo->intr_urb, GFP_ATOMIC); +} + +static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb) +{ + struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); + struct brcmf_usbreq *req; + int ret; + + if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) { + /* TODO: handle suspend/resume */ + return -EIO; + } + + req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq); + if (!req) { + brcmf_dbg(ERROR, "no req to send\n"); + return -ENOMEM; + } + if (!req->urb) { + brcmf_dbg(ERROR, "no urb for req %p\n", req); + return -ENOBUFS; + } + + req->skb = skb; + req->devinfo = devinfo; + usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->tx_pipe, + skb->data, skb->len, brcmf_usb_tx_complete, req); + req->urb->transfer_flags |= URB_ZERO_PACKET; + ret = usb_submit_urb(req->urb, GFP_ATOMIC); + if (!ret) { + brcmf_usb_enq(devinfo, &devinfo->tx_postq, req); + } else { + req->skb = NULL; + brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req); + } + + return ret; +} + + +static int brcmf_usb_up(struct device *dev) +{ + struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); + u16 ifnum; + + if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP) + return 0; + + /* If the USB/HSIC bus in sleep state, wake it up */ + if (devinfo->suspend_state == USBOS_SUSPEND_STATE_SUSPENDED) { + if (brcmf_usb_pnp(devinfo, BCMFMAC_USB_PNP_RESUME) != 0) { + brcmf_dbg(ERROR, "Could not Resume the bus!\n"); + return -EIO; + } + } + devinfo->activity = true; + + /* Success, indicate devinfo is fully up */ + brcmf_usb_state_change(devinfo, BCMFMAC_USB_STATE_UP); + + if (devinfo->intr_urb) { + int ret; + + usb_fill_int_urb(devinfo->intr_urb, devinfo->usbdev, + devinfo->intr_pipe, + &devinfo->intr, + devinfo->intr_size, + (usb_complete_t)brcmf_usb_intr_complete, + devinfo, + devinfo->interval); + + ret = usb_submit_urb(devinfo->intr_urb, GFP_ATOMIC); + if (ret) { + brcmf_dbg(ERROR, "USB_SUBMIT_URB failed with status %d\n", + ret); + return -EINVAL; + } + } + + if (devinfo->ctl_urb) { + devinfo->ctl_in_pipe = usb_rcvctrlpipe(devinfo->usbdev, 0); + devinfo->ctl_out_pipe = usb_sndctrlpipe(devinfo->usbdev, 0); + + ifnum = IFDESC(devinfo->usbdev, CONTROL_IF).bInterfaceNumber; + + /* CTL Write */ + devinfo->ctl_write.bRequestType = + USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE; + devinfo->ctl_write.bRequest = 0; + devinfo->ctl_write.wValue = cpu_to_le16(0); + devinfo->ctl_write.wIndex = cpu_to_le16p(&ifnum); + + /* CTL Read */ + devinfo->ctl_read.bRequestType = + USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE; + devinfo->ctl_read.bRequest = 1; + devinfo->ctl_read.wValue = cpu_to_le16(0); + devinfo->ctl_read.wIndex = cpu_to_le16p(&ifnum); + } + brcmf_usb_rx_fill_all(devinfo); + return 0; +} + +static void brcmf_usb_down(struct device *dev) +{ + struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); + + if (devinfo == NULL) + return; + + brcmf_dbg(TRACE, "enter\n"); + if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_DOWN) + return; + + brcmf_usb_state_change(devinfo, BCMFMAC_USB_STATE_DOWN); + if (devinfo->intr_urb) + usb_kill_urb(devinfo->intr_urb); + + if (devinfo->ctl_urb) + usb_kill_urb(devinfo->ctl_urb); + + if (devinfo->bulk_urb) + usb_kill_urb(devinfo->bulk_urb); + brcmf_usb_free_q(&devinfo->tx_postq, true); + + brcmf_usb_free_q(&devinfo->rx_postq, true); +} + +static int +brcmf_usb_sync_wait(struct brcmf_usbdev_info *devinfo, u16 time) +{ + int ret; + int err = 0; + int ms = time; + + ret = wait_event_interruptible_timeout(devinfo->wait, + devinfo->waitdone == true, (ms * HZ / 1000)); + + if ((devinfo->waitdone == false) || (devinfo->sync_urb_status)) { + brcmf_dbg(ERROR, "timeout(%d) or urb err=%d\n", + ret, devinfo->sync_urb_status); + err = -EINVAL; + } + devinfo->waitdone = false; + return err; +} + +static void +brcmf_usb_sync_complete(struct urb *urb) +{ + struct brcmf_usbdev_info *devinfo = + (struct brcmf_usbdev_info *)urb->context; + + devinfo->waitdone = true; + wake_up_interruptible(&devinfo->wait); + devinfo->sync_urb_status = urb->status; +} + +static bool brcmf_usb_dl_cmd(struct brcmf_usbdev_info *devinfo, u8 cmd, + void *buffer, int buflen) +{ + int ret = 0; + char *tmpbuf; + u16 size; + + if ((!devinfo) || (devinfo->ctl_urb == NULL)) + return false; + + tmpbuf = kmalloc(buflen, GFP_ATOMIC); + if (!tmpbuf) + return false; + + size = buflen; + devinfo->ctl_urb->transfer_buffer_length = size; + + devinfo->ctl_read.wLength = cpu_to_le16p(&size); + devinfo->ctl_read.bRequestType = USB_DIR_IN | USB_TYPE_VENDOR | + USB_RECIP_INTERFACE; + devinfo->ctl_read.bRequest = cmd; + + usb_fill_control_urb(devinfo->ctl_urb, + devinfo->usbdev, + usb_rcvctrlpipe(devinfo->usbdev, 0), + (unsigned char *) &devinfo->ctl_read, + (void *) tmpbuf, size, + (usb_complete_t)brcmf_usb_sync_complete, devinfo); + + ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC); + if (ret < 0) { + brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret); + kfree(tmpbuf); + return false; + } + + ret = brcmf_usb_sync_wait(devinfo, BRCMF_USB_SYNC_TIMEOUT); + memcpy(buffer, tmpbuf, buflen); + kfree(tmpbuf); + + return (ret == 0); +} + +static bool +brcmf_usb_dlneeded(struct brcmf_usbdev_info *devinfo) +{ + struct bootrom_id_le id; + u32 chipid, chiprev; + + brcmf_dbg(TRACE, "enter\n"); + + if (devinfo == NULL) + return false; + + /* Check if firmware downloaded already by querying runtime ID */ + id.chip = cpu_to_le32(0xDEAD); + brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id, + sizeof(struct bootrom_id_le)); + + chipid = le32_to_cpu(id.chip); + chiprev = le32_to_cpu(id.chiprev); + + if ((chipid & 0x4300) == 0x4300) + brcmf_dbg(INFO, "chip %x rev 0x%x\n", chipid, chiprev); + else + brcmf_dbg(INFO, "chip %d rev 0x%x\n", chipid, chiprev); + if (chipid == BRCMF_POSTBOOT_ID) { + brcmf_dbg(INFO, "firmware already downloaded\n"); + brcmf_usb_dl_cmd(devinfo, DL_RESETCFG, &id, + sizeof(struct bootrom_id_le)); + return false; + } else { + devinfo->bus_pub.devid = chipid; + devinfo->bus_pub.chiprev = chiprev; + } + return true; +} + +static int +brcmf_usb_resetcfg(struct brcmf_usbdev_info *devinfo) +{ + struct bootrom_id_le id; + u16 wait = 0, wait_time; + + brcmf_dbg(TRACE, "enter\n"); + + if (devinfo == NULL) + return -EINVAL; + + /* Give dongle chance to boot */ + wait_time = BRCMF_USB_DLIMAGE_SPINWAIT; + while (wait < BRCMF_USB_DLIMAGE_LIMIT) { + mdelay(wait_time); + wait += wait_time; + id.chip = cpu_to_le32(0xDEAD); /* Get the ID */ + brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id, + sizeof(struct bootrom_id_le)); + if (id.chip == cpu_to_le32(BRCMF_POSTBOOT_ID)) + break; + } + + if (id.chip == cpu_to_le32(BRCMF_POSTBOOT_ID)) { + brcmf_dbg(INFO, "download done %d ms postboot chip 0x%x/rev 0x%x\n", + wait, le32_to_cpu(id.chip), le32_to_cpu(id.chiprev)); + + brcmf_usb_dl_cmd(devinfo, DL_RESETCFG, &id, + sizeof(struct bootrom_id_le)); + + /* XXX this wait may not be necessary */ + mdelay(BRCMF_USB_RESETCFG_SPINWAIT); + return 0; + } else { + brcmf_dbg(ERROR, "Cannot talk to Dongle. Firmware is not UP, %d ms\n", + wait); + return -EINVAL; + } +} + + +static int +brcmf_usb_dl_send_bulk(struct brcmf_usbdev_info *devinfo, void *buffer, int len) +{ + int ret; + + if ((devinfo == NULL) || (devinfo->bulk_urb == NULL)) + return -EINVAL; + + /* Prepare the URB */ + usb_fill_bulk_urb(devinfo->bulk_urb, devinfo->usbdev, + devinfo->tx_pipe, buffer, len, + (usb_complete_t)brcmf_usb_sync_complete, devinfo); + + devinfo->bulk_urb->transfer_flags |= URB_ZERO_PACKET; + + ret = usb_submit_urb(devinfo->bulk_urb, GFP_ATOMIC); + if (ret) { + brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret); + return ret; + } + ret = brcmf_usb_sync_wait(devinfo, BRCMF_USB_SYNC_TIMEOUT); + return ret; +} + +static int +brcmf_usb_dl_writeimage(struct brcmf_usbdev_info *devinfo, u8 *fw, int fwlen) +{ + unsigned int sendlen, sent, dllen; + char *bulkchunk = NULL, *dlpos; + struct rdl_state_le state; + u32 rdlstate, rdlbytes; + int err = 0; + brcmf_dbg(TRACE, "fw %p, len %d\n", fw, fwlen); + + bulkchunk = kmalloc(RDL_CHUNK, GFP_ATOMIC); + if (bulkchunk == NULL) { + err = -ENOMEM; + goto fail; + } + + /* 1) Prepare USB boot loader for runtime image */ + brcmf_usb_dl_cmd(devinfo, DL_START, &state, + sizeof(struct rdl_state_le)); + + rdlstate = le32_to_cpu(state.state); + rdlbytes = le32_to_cpu(state.bytes); + + /* 2) Check we are in the Waiting state */ + if (rdlstate != DL_WAITING) { + brcmf_dbg(ERROR, "Failed to DL_START\n"); + err = -EINVAL; + goto fail; + } + sent = 0; + dlpos = fw; + dllen = fwlen; + + /* Get chip id and rev */ + while (rdlbytes != dllen) { + /* Wait until the usb device reports it received all + * the bytes we sent */ + if ((rdlbytes == sent) && (rdlbytes != dllen)) { + if ((dllen-sent) < RDL_CHUNK) + sendlen = dllen-sent; + else + sendlen = RDL_CHUNK; + + /* simply avoid having to send a ZLP by ensuring we + * never have an even + * multiple of 64 + */ + if (!(sendlen % 64)) + sendlen -= 4; + + /* send data */ + memcpy(bulkchunk, dlpos, sendlen); + if (brcmf_usb_dl_send_bulk(devinfo, bulkchunk, + sendlen)) { + brcmf_dbg(ERROR, "send_bulk failed\n"); + err = -EINVAL; + goto fail; + } + + dlpos += sendlen; + sent += sendlen; + } + if (!brcmf_usb_dl_cmd(devinfo, DL_GETSTATE, &state, + sizeof(struct rdl_state_le))) { + brcmf_dbg(ERROR, "DL_GETSTATE Failed xxxx\n"); + err = -EINVAL; + goto fail; + } + + rdlstate = le32_to_cpu(state.state); + rdlbytes = le32_to_cpu(state.bytes); + + /* restart if an error is reported */ + if (rdlstate == DL_BAD_HDR || rdlstate == DL_BAD_CRC) { + brcmf_dbg(ERROR, "Bad Hdr or Bad CRC state %d\n", + rdlstate); + err = -EINVAL; + goto fail; + } + } + +fail: + kfree(bulkchunk); + brcmf_dbg(TRACE, "err=%d\n", err); + return err; +} + +static int brcmf_usb_dlstart(struct brcmf_usbdev_info *devinfo, u8 *fw, int len) +{ + int err; + + brcmf_dbg(TRACE, "enter\n"); + + if (devinfo == NULL) + return -EINVAL; + + if (devinfo->bus_pub.devid == 0xDEAD) + return -EINVAL; + + err = brcmf_usb_dl_writeimage(devinfo, fw, len); + if (err == 0) + devinfo->bus_pub.state = BCMFMAC_USB_STATE_DL_DONE; + else + devinfo->bus_pub.state = BCMFMAC_USB_STATE_DL_PENDING; + brcmf_dbg(TRACE, "exit: err=%d\n", err); + + return err; +} + +static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo) +{ + struct rdl_state_le state; + + brcmf_dbg(TRACE, "enter\n"); + if (!devinfo) + return -EINVAL; + + if (devinfo->bus_pub.devid == 0xDEAD) + return -EINVAL; + + /* Check we are runnable */ + brcmf_usb_dl_cmd(devinfo, DL_GETSTATE, &state, + sizeof(struct rdl_state_le)); + + /* Start the image */ + if (state.state == cpu_to_le32(DL_RUNNABLE)) { + if (!brcmf_usb_dl_cmd(devinfo, DL_GO, &state, + sizeof(struct rdl_state_le))) + return -ENODEV; + if (brcmf_usb_resetcfg(devinfo)) + return -ENODEV; + /* The Dongle may go for re-enumeration. */ + } else { + brcmf_dbg(ERROR, "Dongle not runnable\n"); + return -EINVAL; + } + brcmf_dbg(TRACE, "exit\n"); + return 0; +} + +static bool brcmf_usb_chip_support(int chipid, int chiprev) +{ + switch(chipid) { + case 43235: + case 43236: + case 43238: + return (chiprev == 3); + default: + break; + } + return false; +} + +static int +brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo) +{ + int devid, chiprev; + int err; + + brcmf_dbg(TRACE, "enter\n"); + if (devinfo == NULL) + return -ENODEV; + + devid = devinfo->bus_pub.devid; + chiprev = devinfo->bus_pub.chiprev; + + if (!brcmf_usb_chip_support(devid, chiprev)) { + brcmf_dbg(ERROR, "unsupported chip %d rev %d\n", + devid, chiprev); + return -EINVAL; + } + + if (!devinfo->image) { + brcmf_dbg(ERROR, "No firmware!\n"); + return -ENOENT; + } + + err = brcmf_usb_dlstart(devinfo, + devinfo->image, devinfo->image_len); + if (err == 0) + err = brcmf_usb_dlrun(devinfo); + return err; +} + + +static void brcmf_usb_detach(const struct brcmf_usbdev *bus_pub) +{ + struct brcmf_usbdev_info *devinfo = + (struct brcmf_usbdev_info *)bus_pub; + + brcmf_dbg(TRACE, "devinfo %p\n", devinfo); + + /* store the image globally */ + g_image.data = devinfo->image; + g_image.len = devinfo->image_len; + + /* free the URBS */ + brcmf_usb_free_q(&devinfo->rx_freeq, false); + brcmf_usb_free_q(&devinfo->tx_freeq, false); + + usb_free_urb(devinfo->intr_urb); + usb_free_urb(devinfo->ctl_urb); + usb_free_urb(devinfo->bulk_urb); + + kfree(devinfo->tx_reqs); + kfree(devinfo->rx_reqs); + kfree(devinfo); +} + +#define TRX_MAGIC 0x30524448 /* "HDR0" */ +#define TRX_VERSION 1 /* Version 1 */ +#define TRX_MAX_LEN 0x3B0000 /* Max length */ +#define TRX_NO_HEADER 1 /* Do not write TRX header */ +#define TRX_MAX_OFFSET 3 /* Max number of individual files */ +#define TRX_UNCOMP_IMAGE 0x20 /* Trx contains uncompressed image */ + +struct trx_header_le { + __le32 magic; /* "HDR0" */ + __le32 len; /* Length of file including header */ + __le32 crc32; /* CRC from flag_version to end of file */ + __le32 flag_version; /* 0:15 flags, 16:31 version */ + __le32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of + * header */ +}; + +static int check_file(const u8 *headers) +{ + struct trx_header_le *trx; + int actual_len = -1; + + /* Extract trx header */ + trx = (struct trx_header_le *) headers; + if (trx->magic != cpu_to_le32(TRX_MAGIC)) + return -1; + + headers += sizeof(struct trx_header_le); + + if (le32_to_cpu(trx->flag_version) & TRX_UNCOMP_IMAGE) { + actual_len = le32_to_cpu(trx->offsets[TRX_OFFSETS_DLFWLEN_IDX]); + return actual_len + sizeof(struct trx_header_le); + } + return -1; +} + +static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo) +{ + s8 *fwname; + const struct firmware *fw; + int err; + + devinfo->image = g_image.data; + devinfo->image_len = g_image.len; + + /* + * if we have an image we can leave here. + */ + if (devinfo->image) + return 0; + + fwname = BRCMF_USB_43236_FW_NAME; + + err = request_firmware(&fw, fwname, devinfo->dev); + if (!fw) { + brcmf_dbg(ERROR, "fail to request firmware %s\n", fwname); + return err; + } + if (check_file(fw->data) < 0) { + brcmf_dbg(ERROR, "invalid firmware %s\n", fwname); + return -EINVAL; + } + + devinfo->image = kmalloc(fw->size, GFP_ATOMIC); /* plus nvram */ + if (!devinfo->image) + return -ENOMEM; + + memcpy(devinfo->image, fw->data, fw->size); + devinfo->image_len = fw->size; + + release_firmware(fw); + return 0; +} + + +static +struct brcmf_usbdev *brcmf_usb_attach(int nrxq, int ntxq, struct device *dev) +{ + struct brcmf_usbdev_info *devinfo; + + devinfo = kzalloc(sizeof(struct brcmf_usbdev_info), GFP_ATOMIC); + if (devinfo == NULL) + return NULL; + + devinfo->bus_pub.nrxq = nrxq; + devinfo->rx_low_watermark = nrxq / 2; + devinfo->bus_pub.devinfo = devinfo; + devinfo->bus_pub.ntxq = ntxq; + + /* flow control when too many tx urbs posted */ + devinfo->tx_low_watermark = ntxq / 4; + devinfo->tx_high_watermark = devinfo->tx_low_watermark * 3; + devinfo->dev = dev; + devinfo->usbdev = usbdev_probe_info.usb; + devinfo->tx_pipe = usbdev_probe_info.tx_pipe; + devinfo->rx_pipe = usbdev_probe_info.rx_pipe; + devinfo->rx_pipe2 = usbdev_probe_info.rx_pipe2; + devinfo->intr_pipe = usbdev_probe_info.intr_pipe; + + devinfo->interval = usbdev_probe_info.interval; + devinfo->intr_size = usbdev_probe_info.intr_size; + + memcpy(&devinfo->probe_info, &usbdev_probe_info, + sizeof(struct brcmf_usb_probe_info)); + devinfo->bus_pub.bus_mtu = BRCMF_USB_MAX_PKT_SIZE; + + /* Initialize other structure content */ + init_waitqueue_head(&devinfo->ioctl_resp_wait); + + /* Initialize the spinlocks */ + spin_lock_init(&devinfo->qlock); + + INIT_LIST_HEAD(&devinfo->rx_freeq); + INIT_LIST_HEAD(&devinfo->rx_postq); + + INIT_LIST_HEAD(&devinfo->tx_freeq); + INIT_LIST_HEAD(&devinfo->tx_postq); + + devinfo->rx_reqs = brcmf_usbdev_qinit(&devinfo->rx_freeq, nrxq); + if (!devinfo->rx_reqs) + goto error; + + devinfo->tx_reqs = brcmf_usbdev_qinit(&devinfo->tx_freeq, ntxq); + if (!devinfo->tx_reqs) + goto error; + + devinfo->intr_urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!devinfo->intr_urb) { + brcmf_dbg(ERROR, "usb_alloc_urb (intr) failed\n"); + goto error; + } + devinfo->ctl_urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!devinfo->ctl_urb) { + brcmf_dbg(ERROR, "usb_alloc_urb (ctl) failed\n"); + goto error; + } + devinfo->rxctl_deferrespok = 0; + + devinfo->bulk_urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!devinfo->bulk_urb) { + brcmf_dbg(ERROR, "usb_alloc_urb (bulk) failed\n"); + goto error; + } + + init_waitqueue_head(&devinfo->wait); + if (!brcmf_usb_dlneeded(devinfo)) + return &devinfo->bus_pub; + + brcmf_dbg(TRACE, "start fw downloading\n"); + if (brcmf_usb_get_fw(devinfo)) + goto error; + + if (brcmf_usb_fw_download(devinfo)) + goto error; + + return &devinfo->bus_pub; + +error: + brcmf_dbg(ERROR, "failed!\n"); + brcmf_usb_detach(&devinfo->bus_pub); + return NULL; +} + +static int brcmf_usb_probe_cb(struct device *dev, const char *desc, + u32 bustype, u32 hdrlen) +{ + struct brcmf_bus *bus = NULL; + struct brcmf_usbdev *bus_pub = NULL; + int ret; + + + bus_pub = brcmf_usb_attach(BRCMF_USB_NRXQ, BRCMF_USB_NTXQ, dev); + if (!bus_pub) { + ret = -ENODEV; + goto fail; + } + + bus = kzalloc(sizeof(struct brcmf_bus), GFP_ATOMIC); + if (!bus) { + ret = -ENOMEM; + goto fail; + } + + bus_pub->bus = bus; + bus->brcmf_bus_txdata = brcmf_usb_tx; + bus->brcmf_bus_init = brcmf_usb_up; + bus->brcmf_bus_stop = brcmf_usb_down; + bus->brcmf_bus_txctl = brcmf_usb_tx_ctlpkt; + bus->brcmf_bus_rxctl = brcmf_usb_rx_ctlpkt; + bus->type = bustype; + bus->bus_priv.usb = bus_pub; + dev_set_drvdata(dev, bus); + + /* Attach to the common driver interface */ + ret = brcmf_attach(hdrlen, dev); + if (ret) { + brcmf_dbg(ERROR, "dhd_attach failed\n"); + goto fail; + } + + ret = brcmf_bus_start(dev); + if (ret == -ENOLINK) { + brcmf_dbg(ERROR, "dongle is not responding\n"); + brcmf_detach(dev); + goto fail; + } + + /* add interface and open for business */ + ret = brcmf_add_if(dev, 0, "wlan%d", NULL); + if (ret) { + brcmf_dbg(ERROR, "Add primary net device interface failed!!\n"); + brcmf_detach(dev); + goto fail; + } + + return 0; +fail: + /* Release resources in reverse order */ + if (bus_pub) + brcmf_usb_detach(bus_pub); + kfree(bus); + return ret; +} + +static void +brcmf_usb_disconnect_cb(struct brcmf_usbdev *bus_pub) +{ + if (!bus_pub) + return; + brcmf_dbg(TRACE, "enter: bus_pub %p\n", bus_pub); + + brcmf_detach(bus_pub->devinfo->dev); + kfree(bus_pub->bus); + brcmf_usb_detach(bus_pub); + +} + +static int +brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + int ep; + struct usb_endpoint_descriptor *endpoint; + int ret = 0; + struct usb_device *usb = interface_to_usbdev(intf); + int num_of_eps; + u8 endpoint_num; + + brcmf_dbg(TRACE, "enter\n"); + + usbdev_probe_info.usb = usb; + usbdev_probe_info.intf = intf; + + if (id != NULL) { + usbdev_probe_info.vid = id->idVendor; + usbdev_probe_info.pid = id->idProduct; + } + + usb_set_intfdata(intf, &usbdev_probe_info); + + /* Check that the device supports only one configuration */ + if (usb->descriptor.bNumConfigurations != 1) { + ret = -1; + goto fail; + } + + if (usb->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) { + ret = -1; + goto fail; + } + + /* + * Only the BDC interface configuration is supported: + * Device class: USB_CLASS_VENDOR_SPEC + * if0 class: USB_CLASS_VENDOR_SPEC + * if0/ep0: control + * if0/ep1: bulk in + * if0/ep2: bulk out (ok if swapped with bulk in) + */ + if (CONFIGDESC(usb)->bNumInterfaces != 1) { + ret = -1; + goto fail; + } + + /* Check interface */ + if (IFDESC(usb, CONTROL_IF).bInterfaceClass != USB_CLASS_VENDOR_SPEC || + IFDESC(usb, CONTROL_IF).bInterfaceSubClass != 2 || + IFDESC(usb, CONTROL_IF).bInterfaceProtocol != 0xff) { + brcmf_dbg(ERROR, "invalid control interface: class %d, subclass %d, proto %d\n", + IFDESC(usb, CONTROL_IF).bInterfaceClass, + IFDESC(usb, CONTROL_IF).bInterfaceSubClass, + IFDESC(usb, CONTROL_IF).bInterfaceProtocol); + ret = -1; + goto fail; + } + + /* Check control endpoint */ + endpoint = &IFEPDESC(usb, CONTROL_IF, 0); + if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + != USB_ENDPOINT_XFER_INT) { + brcmf_dbg(ERROR, "invalid control endpoint %d\n", + endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); + ret = -1; + goto fail; + } + + endpoint_num = endpoint->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + usbdev_probe_info.intr_pipe = usb_rcvintpipe(usb, endpoint_num); + + usbdev_probe_info.rx_pipe = 0; + usbdev_probe_info.rx_pipe2 = 0; + usbdev_probe_info.tx_pipe = 0; + num_of_eps = IFDESC(usb, BULK_IF).bNumEndpoints - 1; + + /* Check data endpoints and get pipes */ + for (ep = 1; ep <= num_of_eps; ep++) { + endpoint = &IFEPDESC(usb, BULK_IF, ep); + if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != + USB_ENDPOINT_XFER_BULK) { + brcmf_dbg(ERROR, "invalid data endpoint %d\n", ep); + ret = -1; + goto fail; + } + + endpoint_num = endpoint->bEndpointAddress & + USB_ENDPOINT_NUMBER_MASK; + if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + == USB_DIR_IN) { + if (!usbdev_probe_info.rx_pipe) { + usbdev_probe_info.rx_pipe = + usb_rcvbulkpipe(usb, endpoint_num); + } else { + usbdev_probe_info.rx_pipe2 = + usb_rcvbulkpipe(usb, endpoint_num); + } + } else { + usbdev_probe_info.tx_pipe = + usb_sndbulkpipe(usb, endpoint_num); + } + } + + /* Allocate interrupt URB and data buffer */ + /* RNDIS says 8-byte intr, our old drivers used 4-byte */ + if (IFEPDESC(usb, CONTROL_IF, 0).wMaxPacketSize == cpu_to_le16(16)) + usbdev_probe_info.intr_size = 8; + else + usbdev_probe_info.intr_size = 4; + + usbdev_probe_info.interval = IFEPDESC(usb, CONTROL_IF, 0).bInterval; + + usbdev_probe_info.device_speed = usb->speed; + if (usb->speed == USB_SPEED_HIGH) + brcmf_dbg(INFO, "Broadcom high speed USB wireless device detected\n"); + else + brcmf_dbg(INFO, "Broadcom full speed USB wireless device detected\n"); + + ret = brcmf_usb_probe_cb(&usb->dev, "", USB_BUS, 0); + if (ret) + goto fail; + + /* Success */ + return 0; + +fail: + brcmf_dbg(ERROR, "failed with errno %d\n", ret); + usb_set_intfdata(intf, NULL); + return ret; + +} + +static void +brcmf_usb_disconnect(struct usb_interface *intf) +{ + struct usb_device *usb = interface_to_usbdev(intf); + + brcmf_dbg(TRACE, "enter\n"); + brcmf_usb_disconnect_cb(brcmf_usb_get_buspub(&usb->dev)); + usb_set_intfdata(intf, NULL); +} + +/* + * only need to signal the bus being down and update the suspend state. + */ +static int brcmf_usb_suspend(struct usb_interface *intf, pm_message_t state) +{ + struct usb_device *usb = interface_to_usbdev(intf); + struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev); + + brcmf_dbg(TRACE, "enter\n"); + devinfo->bus_pub.state = BCMFMAC_USB_STATE_DOWN; + devinfo->suspend_state = USBOS_SUSPEND_STATE_SUSPENDED; + return 0; +} + +/* + * mark suspend state active and crank up the bus. + */ +static int brcmf_usb_resume(struct usb_interface *intf) +{ + struct usb_device *usb = interface_to_usbdev(intf); + struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev); + + brcmf_dbg(TRACE, "enter\n"); + devinfo->suspend_state = USBOS_SUSPEND_STATE_DEVICE_ACTIVE; + brcmf_bus_start(&usb->dev); + return 0; +} + +#define BRCMF_USB_VENDOR_ID_BROADCOM 0x0a5c +#define BRCMF_USB_DEVICE_ID_43236 0xbd17 +#define BRCMF_USB_DEVICE_ID_BCMFW 0x0bdc + +static struct usb_device_id brcmf_usb_devid_table[] = { + { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43236) }, + /* special entry for device with firmware loaded and running */ + { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_BCMFW) }, + { } +}; +MODULE_DEVICE_TABLE(usb, brcmf_usb_devid_table); +MODULE_FIRMWARE(BRCMF_USB_43236_FW_NAME); + +/* TODO: suspend and resume entries */ +static struct usb_driver brcmf_usbdrvr = { + .name = KBUILD_MODNAME, + .probe = brcmf_usb_probe, + .disconnect = brcmf_usb_disconnect, + .id_table = brcmf_usb_devid_table, + .suspend = brcmf_usb_suspend, + .resume = brcmf_usb_resume, + .supports_autosuspend = 1 +}; + +void brcmf_usb_exit(void) +{ + usb_deregister(&brcmf_usbdrvr); + kfree(g_image.data); + g_image.data = NULL; + g_image.len = 0; +} + +void brcmf_usb_init(void) +{ + usb_register(&brcmf_usbdrvr); +} diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.h b/drivers/net/wireless/brcm80211/brcmfmac/usb.h new file mode 100644 index 0000000..acfa5e8 --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2011 Broadcom Corporation + * + * 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. + */ +#ifndef BRCMFMAC_USB_H +#define BRCMFMAC_USB_H + +enum brcmf_usb_state { + BCMFMAC_USB_STATE_DL_PENDING, + BCMFMAC_USB_STATE_DL_DONE, + BCMFMAC_USB_STATE_UP, + BCMFMAC_USB_STATE_DOWN, + BCMFMAC_USB_STATE_PNP_FWDL, + BCMFMAC_USB_STATE_DISCONNECT, + BCMFMAC_USB_STATE_SLEEP +}; + +enum brcmf_usb_pnp_state { + BCMFMAC_USB_PNP_DISCONNECT, + BCMFMAC_USB_PNP_SLEEP, + BCMFMAC_USB_PNP_RESUME, +}; + +struct brcmf_stats { + u32 tx_ctlpkts; + u32 tx_ctlerrs; + u32 rx_ctlpkts; + u32 rx_ctlerrs; +}; + +struct brcmf_usbdev { + struct brcmf_bus *bus; + struct brcmf_usbdev_info *devinfo; + enum brcmf_usb_state state; + struct brcmf_stats stats; + int ntxq, nrxq, rxsize; + u32 bus_mtu; + int devid; + int chiprev; /* chip revsion number */ +}; + +/* IO Request Block (IRB) */ +struct brcmf_usbreq { + struct list_head list; + struct brcmf_usbdev_info *devinfo; + struct urb *urb; + struct sk_buff *skb; +}; + +#endif /* BRCMFMAC_USB_H */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h b/drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h new file mode 100644 index 0000000..0a35c51 --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2011 Broadcom Corporation + * + * 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. + */ + +#ifndef _USB_RDL_H +#define _USB_RDL_H + +/* Control messages: bRequest values */ +#define DL_GETSTATE 0 /* returns the rdl_state_t struct */ +#define DL_CHECK_CRC 1 /* currently unused */ +#define DL_GO 2 /* execute downloaded image */ +#define DL_START 3 /* initialize dl state */ +#define DL_REBOOT 4 /* reboot the device in 2 seconds */ +#define DL_GETVER 5 /* returns the bootrom_id_t struct */ +#define DL_GO_PROTECTED 6 /* execute the downloaded code and set reset + * event to occur in 2 seconds. It is the + * responsibility of the downloaded code to + * clear this event + */ +#define DL_EXEC 7 /* jump to a supplied address */ +#define DL_RESETCFG 8 /* To support single enum on dongle + * - Not used by bootloader + */ +#define DL_DEFER_RESP_OK 9 /* Potentially defer the response to setup + * if resp unavailable + */ + +/* states */ +#define DL_WAITING 0 /* waiting to rx first pkt */ +#define DL_READY 1 /* hdr was good, waiting for more of the + * compressed image */ +#define DL_BAD_HDR 2 /* hdr was corrupted */ +#define DL_BAD_CRC 3 /* compressed image was corrupted */ +#define DL_RUNNABLE 4 /* download was successful,waiting for go cmd */ +#define DL_START_FAIL 5 /* failed to initialize correctly */ +#define DL_NVRAM_TOOBIG 6 /* host specified nvram data exceeds DL_NVRAM + * value */ +#define DL_IMAGE_TOOBIG 7 /* download image too big (exceeds DATA_START + * for rdl) */ + +struct rdl_state_le { + __le32 state; + __le32 bytes; +}; + +struct bootrom_id_le { + __le32 chip; /* Chip id */ + __le32 chiprev; /* Chip rev */ + __le32 ramsize; /* Size of RAM */ + __le32 remapbase; /* Current remap base address */ + __le32 boardtype; /* Type of board */ + __le32 boardrev; /* Board revision */ +}; + +#define RDL_CHUNK 1500 /* size of each dl transfer */ + +#define TRX_OFFSETS_DLFWLEN_IDX 0 +#define TRX_OFFSETS_JUMPTO_IDX 1 +#define TRX_OFFSETS_NVM_LEN_IDX 2 + +#define TRX_OFFSETS_DLBASE_IDX 0 + +#endif /* _USB_RDL_H */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index bf11850..d13ae9c 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -16,6 +16,8 @@ /* Toplevel file. Relies on dhd_linux.c to send commands to the dongle. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/kernel.h> #include <linux/if_arp.h> #include <linux/sched.h> @@ -1374,7 +1376,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, memset(&join_params, 0, sizeof(join_params)); join_params_size = sizeof(join_params.ssid_le); - ssid.SSID_len = min_t(u32, sizeof(ssid.SSID), sme->ssid_len); + ssid.SSID_len = min_t(u32, sizeof(ssid.SSID), (u32)sme->ssid_len); memcpy(&join_params.ssid_le.SSID, sme->ssid, ssid.SSID_len); memcpy(&ssid.SSID, sme->ssid, ssid.SSID_len); join_params.ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len); @@ -2001,7 +2003,6 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv, s32 err = 0; u16 channel; u32 freq; - u64 notify_timestamp; u16 notify_capability; u16 notify_interval; u8 *notify_ie; @@ -2024,7 +2025,6 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv, freq = ieee80211_channel_to_frequency(channel, band->band); notify_channel = ieee80211_get_channel(wiphy, freq); - notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */ notify_capability = le16_to_cpu(bi->capability); notify_interval = le16_to_cpu(bi->beacon_period); notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset); @@ -2038,10 +2038,9 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv, WL_CONN("Capability: %X\n", notify_capability); WL_CONN("Beacon interval: %d\n", notify_interval); WL_CONN("Signal: %d\n", notify_signal); - WL_CONN("notify_timestamp: %#018llx\n", notify_timestamp); bss = cfg80211_inform_bss(wiphy, notify_channel, (const u8 *)bi->BSSID, - notify_timestamp, notify_capability, notify_interval, notify_ie, + 0, notify_capability, notify_interval, notify_ie, notify_ielen, notify_signal, GFP_KERNEL); if (!bss) @@ -2096,7 +2095,6 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv, s32 err = 0; u16 channel; u32 freq; - u64 notify_timestamp; u16 notify_capability; u16 notify_interval; u8 *notify_ie; @@ -2132,7 +2130,6 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv, freq = ieee80211_channel_to_frequency(channel, band->band); notify_channel = ieee80211_get_channel(wiphy, freq); - notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */ notify_capability = le16_to_cpu(bi->capability); notify_interval = le16_to_cpu(bi->beacon_period); notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset); @@ -2143,10 +2140,9 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv, WL_CONN("capability: %X\n", notify_capability); WL_CONN("beacon interval: %d\n", notify_interval); WL_CONN("signal: %d\n", notify_signal); - WL_CONN("notify_timestamp: %#018llx\n", notify_timestamp); bss = cfg80211_inform_bss(wiphy, notify_channel, bssid, - notify_timestamp, notify_capability, notify_interval, + 0, notify_capability, notify_interval, notify_ie, notify_ielen, notify_signal, GFP_KERNEL); if (!bss) { @@ -2783,7 +2779,7 @@ static struct wireless_dev *brcmf_alloc_wdev(s32 sizeof_iface, wiphy_new(&wl_cfg80211_ops, sizeof(struct brcmf_cfg80211_priv) + sizeof_iface); if (!wdev->wiphy) { - WL_ERR("Couldn not allocate wiphy device\n"); + WL_ERR("Could not allocate wiphy device\n"); err = -ENOMEM; goto wiphy_new_out; } @@ -2809,7 +2805,7 @@ static struct wireless_dev *brcmf_alloc_wdev(s32 sizeof_iface, */ err = wiphy_register(wdev->wiphy); if (err < 0) { - WL_ERR("Couldn not register wiphy device (%d)\n", err); + WL_ERR("Could not register wiphy device (%d)\n", err); goto wiphy_register_out; } return wdev; @@ -3295,7 +3291,9 @@ static struct brcmf_cfg80211_event_q *brcmf_deq_event( } /* -** push event to tail of the queue +* push event to tail of the queue +* +* remark: this function may not sleep as it is called in atomic context. */ static s32 @@ -3304,17 +3302,18 @@ brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 event, { struct brcmf_cfg80211_event_q *e; s32 err = 0; + ulong flags; - e = kzalloc(sizeof(struct brcmf_cfg80211_event_q), GFP_KERNEL); + e = kzalloc(sizeof(struct brcmf_cfg80211_event_q), GFP_ATOMIC); if (!e) return -ENOMEM; e->etype = event; memcpy(&e->emsg, msg, sizeof(struct brcmf_event_msg)); - spin_lock_irq(&cfg_priv->evt_q_lock); + spin_lock_irqsave(&cfg_priv->evt_q_lock, flags); list_add_tail(&e->evt_q_list, &cfg_priv->evt_q_list); - spin_unlock_irq(&cfg_priv->evt_q_lock); + spin_unlock_irqrestore(&cfg_priv->evt_q_lock, flags); return err; } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index a613b49..b5d9b36 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h @@ -32,63 +32,63 @@ struct brcmf_cfg80211_ibss; #define WL_DBG_MASK ((WL_DBG_INFO | WL_DBG_ERR | WL_DBG_TRACE) | \ (WL_DBG_SCAN) | (WL_DBG_CONN)) -#define WL_ERR(fmt, args...) \ +#define WL_ERR(fmt, ...) \ do { \ if (brcmf_dbg_level & WL_DBG_ERR) { \ if (net_ratelimit()) { \ - printk(KERN_ERR "ERROR @%s : " fmt, \ - __func__, ##args); \ + pr_err("ERROR @%s : " fmt, \ + __func__, ##__VA_ARGS__); \ } \ } \ } while (0) -#if (defined BCMDBG) -#define WL_INFO(fmt, args...) \ +#if (defined DEBUG) +#define WL_INFO(fmt, ...) \ do { \ if (brcmf_dbg_level & WL_DBG_INFO) { \ if (net_ratelimit()) { \ - printk(KERN_ERR "INFO @%s : " fmt, \ - __func__, ##args); \ + pr_err("INFO @%s : " fmt, \ + __func__, ##__VA_ARGS__); \ } \ } \ } while (0) -#define WL_TRACE(fmt, args...) \ +#define WL_TRACE(fmt, ...) \ do { \ if (brcmf_dbg_level & WL_DBG_TRACE) { \ if (net_ratelimit()) { \ - printk(KERN_ERR "TRACE @%s : " fmt, \ - __func__, ##args); \ + pr_err("TRACE @%s : " fmt, \ + __func__, ##__VA_ARGS__); \ } \ } \ } while (0) -#define WL_SCAN(fmt, args...) \ +#define WL_SCAN(fmt, ...) \ do { \ if (brcmf_dbg_level & WL_DBG_SCAN) { \ if (net_ratelimit()) { \ - printk(KERN_ERR "SCAN @%s : " fmt, \ - __func__, ##args); \ + pr_err("SCAN @%s : " fmt, \ + __func__, ##__VA_ARGS__); \ } \ } \ } while (0) -#define WL_CONN(fmt, args...) \ +#define WL_CONN(fmt, ...) \ do { \ if (brcmf_dbg_level & WL_DBG_CONN) { \ if (net_ratelimit()) { \ - printk(KERN_ERR "CONN @%s : " fmt, \ - __func__, ##args); \ + pr_err("CONN @%s : " fmt, \ + __func__, ##__VA_ARGS__); \ } \ } \ } while (0) -#else /* (defined BCMDBG) */ +#else /* (defined DEBUG) */ #define WL_INFO(fmt, args...) #define WL_TRACE(fmt, args...) #define WL_SCAN(fmt, args...) #define WL_CONN(fmt, args...) -#endif /* (defined BCMDBG) */ +#endif /* (defined DEBUG) */ #define WL_NUM_SCAN_MAX 1 #define WL_NUM_PMKIDS_MAX MAXPMKID /* will be used diff --git a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c index ab9bb11a..c93ea35 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c @@ -326,11 +326,11 @@ #define PCI_FORCEHT(sih) (PCIE(sih) && (ai_get_chip_id(sih) == BCM4716_CHIP_ID)) -#ifdef BCMDBG +#ifdef DEBUG #define SI_MSG(fmt, ...) pr_debug(fmt, ##__VA_ARGS__) #else #define SI_MSG(fmt, ...) no_printk(fmt, ##__VA_ARGS__) -#endif /* BCMDBG */ +#endif /* DEBUG */ #define GOODCOREADDR(x, b) \ (((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \ diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c index 30b5887..95b5902 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c @@ -915,7 +915,7 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p); struct wiphy *wiphy = wlc->wiphy; -#ifdef BCMDBG +#ifdef DEBUG u8 hole[AMPDU_MAX_MPDU]; memset(hole, 0, sizeof(hole)); #endif @@ -959,14 +959,13 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, if (supr_status) { update_rate = false; if (supr_status == TX_STATUS_SUPR_BADCH) { - wiphy_err(wiphy, "%s: Pkt tx suppressed, " - "illegal channel possibly %d\n", + wiphy_err(wiphy, + "%s: Pkt tx suppressed, illegal channel possibly %d\n", __func__, CHSPEC_CHANNEL( wlc->default_bss->chanspec)); } else { if (supr_status != TX_STATUS_SUPR_FRAG) - wiphy_err(wiphy, "%s:" - "supr_status 0x%x\n", + wiphy_err(wiphy, "%s: supr_status 0x%x\n", __func__, supr_status); } /* no need to retry for badch; will fail again */ @@ -988,9 +987,8 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, } } else if (txs->phyerr) { update_rate = false; - wiphy_err(wiphy, "wl%d: ampdu tx phy " - "error (0x%x)\n", wlc->pub->unit, - txs->phyerr); + wiphy_err(wiphy, "%s: ampdu tx phy error (0x%x)\n", + __func__, txs->phyerr); if (brcm_msg_level & LOG_ERROR_VAL) { brcmu_prpkt("txpkt (AMPDU)", p); @@ -1018,10 +1016,10 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, ack_recd = false; if (ba_recd) { bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX); - BCMMSG(wlc->wiphy, "tid %d seq %d," - " start_seq %d, bindex %d set %d, index %d\n", - tid, seq, start_seq, bindex, - isset(bitmap, bindex), index); + BCMMSG(wiphy, + "tid %d seq %d, start_seq %d, bindex %d set %d, index %d\n", + tid, seq, start_seq, bindex, + isset(bitmap, bindex), index); /* if acked then clear bit and free packet */ if ((bindex < AMPDU_TX_BA_MAX_WSIZE) && isset(bitmap, bindex)) { diff --git a/drivers/net/wireless/brcm80211/brcmsmac/dma.c b/drivers/net/wireless/brcm80211/brcmsmac/dma.c index 2e90a9a..11054ae 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/dma.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/dma.c @@ -177,7 +177,7 @@ #define BCMEXTRAHDROOM 172 /* debug/trace */ -#ifdef BCMDBG +#ifdef DEBUG #define DMA_ERROR(fmt, ...) \ do { \ if (*di->msg_level & 1) \ @@ -193,7 +193,7 @@ do { \ no_printk(fmt, ##__VA_ARGS__) #define DMA_TRACE(fmt, ...) \ no_printk(fmt, ##__VA_ARGS__) -#endif /* BCMDBG */ +#endif /* DEBUG */ #define DMA_NONE(fmt, ...) \ no_printk(fmt, ##__VA_ARGS__) @@ -968,7 +968,7 @@ int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list) pktcnt++; } -#ifdef BCMDBG +#ifdef DEBUG if (resid > 0) { uint cur; cur = @@ -979,7 +979,7 @@ int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list) DMA_ERROR("rxin %d rxout %d, hw_curr %d\n", di->rxin, di->rxout, cur); } -#endif /* BCMDBG */ +#endif /* DEBUG */ if ((di->dma.dmactrlflags & DMA_CTRL_RXMULTI) == 0) { DMA_ERROR("%s: bad frame length (%d)\n", diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 448ab9c..569ab8a 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -15,6 +15,7 @@ */ #define __UNDEF_NO_VERSION__ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/etherdevice.h> #include <linux/sched.h> @@ -96,10 +97,10 @@ static struct bcma_device_id brcms_coreid_table[] = { }; MODULE_DEVICE_TABLE(bcma, brcms_coreid_table); -#ifdef BCMDBG +#ifdef DEBUG static int msglevel = 0xdeadbeef; module_param(msglevel, int, 0); -#endif /* BCMDBG */ +#endif /* DEBUG */ static struct ieee80211_channel brcms_2ghz_chantable[] = { CHAN2GHZ(1, 2412, IEEE80211_CHAN_NO_HT40MINUS), @@ -857,7 +858,7 @@ static void brcms_free(struct brcms_info *wl) /* free timers */ for (t = wl->timers; t; t = next) { next = t->next; -#ifdef BCMDBG +#ifdef DEBUG kfree(t->name); #endif kfree(t); @@ -1121,8 +1122,7 @@ static int __devinit brcms_bcma_probe(struct bcma_device *pdev) wl = brcms_attach(pdev); if (!wl) { - pr_err("%s: %s: brcms_attach failed!\n", KBUILD_MODNAME, - __func__); + pr_err("%s: brcms_attach failed!\n", __func__); return -ENODEV; } return 0; @@ -1136,8 +1136,8 @@ static int brcms_suspend(struct bcma_device *pdev) hw = bcma_get_drvdata(pdev); wl = hw->priv; if (!wl) { - wiphy_err(wl->wiphy, - "brcms_suspend: bcma_get_drvdata failed\n"); + pr_err("%s: %s: no driver private struct!\n", KBUILD_MODNAME, + __func__); return -ENODEV; } @@ -1169,25 +1169,31 @@ static struct bcma_driver brcms_bcma_driver = { /** * This is the main entry point for the brcmsmac driver. * - * This function determines if a device pointed to by pdev is a WL device, - * and if so, performs a brcms_attach() on it. - * + * This function is scheduled upon module initialization and + * does the driver registration, which result in brcms_bcma_probe() + * call resulting in the driver bringup. */ -static int __init brcms_module_init(void) +static void brcms_driver_init(struct work_struct *work) { - int error = -ENODEV; + int error; + + error = bcma_driver_register(&brcms_bcma_driver); + if (error) + pr_err("%s: register returned %d\n", __func__, error); +} -#ifdef BCMDBG +static DECLARE_WORK(brcms_driver_work, brcms_driver_init); + +static int __init brcms_module_init(void) +{ +#ifdef DEBUG if (msglevel != 0xdeadbeef) brcm_msg_level = msglevel; -#endif /* BCMDBG */ - - error = bcma_driver_register(&brcms_bcma_driver); - printk(KERN_ERR "%s: register returned %d\n", __func__, error); - if (!error) - return 0; +#endif + if (!schedule_work(&brcms_driver_work)) + return -EBUSY; - return error; + return 0; } /** @@ -1199,6 +1205,7 @@ static int __init brcms_module_init(void) */ static void __exit brcms_module_exit(void) { + cancel_work_sync(&brcms_driver_work); bcma_driver_unregister(&brcms_bcma_driver); } @@ -1367,7 +1374,7 @@ struct brcms_timer *brcms_init_timer(struct brcms_info *wl, t->next = wl->timers; wl->timers = t; -#ifdef BCMDBG +#ifdef DEBUG t->name = kmalloc(strlen(name) + 1, GFP_ATOMIC); if (t->name) strcpy(t->name, name); @@ -1386,7 +1393,7 @@ void brcms_add_timer(struct brcms_timer *t, uint ms, int periodic) { struct ieee80211_hw *hw = t->wl->pub->ieee_hw; -#ifdef BCMDBG +#ifdef DEBUG if (t->set) wiphy_err(hw->wiphy, "%s: Already set. Name: %s, per %d\n", __func__, t->name, periodic); @@ -1431,7 +1438,7 @@ void brcms_free_timer(struct brcms_timer *t) if (wl->timers == t) { wl->timers = wl->timers->next; -#ifdef BCMDBG +#ifdef DEBUG kfree(t->name); #endif kfree(t); @@ -1443,7 +1450,7 @@ void brcms_free_timer(struct brcms_timer *t) while (tmp) { if (tmp->next == t) { tmp->next = t->next; -#ifdef BCMDBG +#ifdef DEBUG kfree(t->name); #endif kfree(t); diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h index 8f60419..9358bd5 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h @@ -40,7 +40,7 @@ struct brcms_timer { bool periodic; bool set; /* indicates if timer is active */ struct brcms_timer *next; /* for freeing on unload */ -#ifdef BCMDBG +#ifdef DEBUG char *name; /* Description of the timer */ #endif }; diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index f6affc6..231ddf4 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c @@ -14,6 +14,8 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/pci_ids.h> #include <linux/if_ether.h> #include <net/mac80211.h> @@ -293,11 +295,11 @@ const u8 prio2fifo[NUMPRIO] = { /* debug/trace */ uint brcm_msg_level = -#if defined(BCMDBG) +#if defined(DEBUG) LOG_ERROR_VAL; #else 0; -#endif /* BCMDBG */ +#endif /* DEBUG */ /* TX FIFO number to WME/802.1E Access Category */ static const u8 wme_fifo2ac[] = { @@ -342,14 +344,14 @@ static const u16 xmtfifo_sz[][NFIFO] = { {9, 58, 22, 14, 14, 5}, }; -#ifdef BCMDBG +#ifdef DEBUG static const char * const fifo_names[] = { "AC_BK", "AC_BE", "AC_VI", "AC_VO", "BCMC", "ATIM" }; #else static const char fifo_names[6][0]; #endif -#ifdef BCMDBG +#ifdef DEBUG /* pointer to most recently allocated wl/wlc */ static struct brcms_c_info *wlc_info_dbg = (struct brcms_c_info *) (NULL); #endif @@ -2899,7 +2901,6 @@ brcms_b_read_objmem(struct brcms_hardware *wlc_hw, uint offset, u32 sel) objoff += 2; return bcma_read16(core, objoff); -; } static void @@ -3075,30 +3076,30 @@ static void brcms_c_statsupd(struct brcms_c_info *wlc) { int i; struct macstat macstats; -#ifdef BCMDBG +#ifdef DEBUG u16 delta; u16 rxf0ovfl; u16 txfunfl[NFIFO]; -#endif /* BCMDBG */ +#endif /* DEBUG */ /* if driver down, make no sense to update stats */ if (!wlc->pub->up) return; -#ifdef BCMDBG +#ifdef DEBUG /* save last rx fifo 0 overflow count */ rxf0ovfl = wlc->core->macstat_snapshot->rxf0ovfl; /* save last tx fifo underflow count */ for (i = 0; i < NFIFO; i++) txfunfl[i] = wlc->core->macstat_snapshot->txfunfl[i]; -#endif /* BCMDBG */ +#endif /* DEBUG */ /* Read mac stats from contiguous shared memory */ brcms_b_copyfrom_objmem(wlc->hw, M_UCODE_MACSTAT, &macstats, sizeof(struct macstat), OBJADDR_SHM_SEL); -#ifdef BCMDBG +#ifdef DEBUG /* check for rx fifo 0 overflow */ delta = (u16) (wlc->core->macstat_snapshot->rxf0ovfl - rxf0ovfl); if (delta) @@ -3114,7 +3115,7 @@ static void brcms_c_statsupd(struct brcms_c_info *wlc) wiphy_err(wlc->wiphy, "wl%d: %u tx fifo %d underflows!" "\n", wlc->pub->unit, delta, i); } -#endif /* BCMDBG */ +#endif /* DEBUG */ /* merge counters from dma module */ for (i = 0; i < NFIFO; i++) { @@ -3246,7 +3247,7 @@ static void brcms_b_coreinit(struct brcms_c_info *wlc) } /* For old ucode, txfifo sizes needs to be modified(increased) */ - if (fifosz_fixup == true) + if (fifosz_fixup) brcms_b_corerev_fifofixup(wlc_hw); /* check txfifo allocations match between ucode and driver */ @@ -5425,7 +5426,7 @@ int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config) return -EINVAL; /* update configuration value */ - if (config == true) + if (config) brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER, gmode); /* Clear rateset override */ @@ -5765,62 +5766,49 @@ int brcms_c_module_unregister(struct brcms_pub *pub, const char *name, return -ENODATA; } -#ifdef BCMDBG -static const char * const supr_reason[] = { - "None", "PMQ Entry", "Flush request", - "Previous frag failure", "Channel mismatch", - "Lifetime Expiry", "Underflow" -}; - -static void brcms_c_print_txs_status(u16 s) -{ - printk(KERN_DEBUG "[15:12] %d frame attempts\n", - (s & TX_STATUS_FRM_RTX_MASK) >> TX_STATUS_FRM_RTX_SHIFT); - printk(KERN_DEBUG " [11:8] %d rts attempts\n", - (s & TX_STATUS_RTS_RTX_MASK) >> TX_STATUS_RTS_RTX_SHIFT); - printk(KERN_DEBUG " [7] %d PM mode indicated\n", - ((s & TX_STATUS_PMINDCTD) ? 1 : 0)); - printk(KERN_DEBUG " [6] %d intermediate status\n", - ((s & TX_STATUS_INTERMEDIATE) ? 1 : 0)); - printk(KERN_DEBUG " [5] %d AMPDU\n", - (s & TX_STATUS_AMPDU) ? 1 : 0); - printk(KERN_DEBUG " [4:2] %d Frame Suppressed Reason (%s)\n", - ((s & TX_STATUS_SUPR_MASK) >> TX_STATUS_SUPR_SHIFT), - supr_reason[(s & TX_STATUS_SUPR_MASK) >> TX_STATUS_SUPR_SHIFT]); - printk(KERN_DEBUG " [1] %d acked\n", - ((s & TX_STATUS_ACK_RCV) ? 1 : 0)); -} -#endif /* BCMDBG */ - void brcms_c_print_txstatus(struct tx_status *txs) { -#if defined(BCMDBG) - u16 s = txs->status; - u16 ackphyrxsh = txs->ackphyrxsh; - - printk(KERN_DEBUG "\ntxpkt (MPDU) Complete\n"); - - printk(KERN_DEBUG "FrameID: %04x ", txs->frameid); - printk(KERN_DEBUG "TxStatus: %04x", s); - printk(KERN_DEBUG "\n"); - - brcms_c_print_txs_status(s); - - printk(KERN_DEBUG "LastTxTime: %04x ", txs->lasttxtime); - printk(KERN_DEBUG "Seq: %04x ", txs->sequence); - printk(KERN_DEBUG "PHYTxStatus: %04x ", txs->phyerr); - printk(KERN_DEBUG "RxAckRSSI: %04x ", - (ackphyrxsh & PRXS1_JSSI_MASK) >> PRXS1_JSSI_SHIFT); - printk(KERN_DEBUG "RxAckSQ: %04x", - (ackphyrxsh & PRXS1_SQ_MASK) >> PRXS1_SQ_SHIFT); - printk(KERN_DEBUG "\n"); -#endif /* defined(BCMDBG) */ + pr_debug("\ntxpkt (MPDU) Complete\n"); + + pr_debug("FrameID: %04x TxStatus: %04x\n", txs->frameid, txs->status); + + pr_debug("[15:12] %d frame attempts\n", + (txs->status & TX_STATUS_FRM_RTX_MASK) >> + TX_STATUS_FRM_RTX_SHIFT); + pr_debug(" [11:8] %d rts attempts\n", + (txs->status & TX_STATUS_RTS_RTX_MASK) >> + TX_STATUS_RTS_RTX_SHIFT); + pr_debug(" [7] %d PM mode indicated\n", + txs->status & TX_STATUS_PMINDCTD ? 1 : 0); + pr_debug(" [6] %d intermediate status\n", + txs->status & TX_STATUS_INTERMEDIATE ? 1 : 0); + pr_debug(" [5] %d AMPDU\n", + txs->status & TX_STATUS_AMPDU ? 1 : 0); + pr_debug(" [4:2] %d Frame Suppressed Reason (%s)\n", + (txs->status & TX_STATUS_SUPR_MASK) >> TX_STATUS_SUPR_SHIFT, + (const char *[]) { + "None", + "PMQ Entry", + "Flush request", + "Previous frag failure", + "Channel mismatch", + "Lifetime Expiry", + "Underflow" + } [(txs->status & TX_STATUS_SUPR_MASK) >> + TX_STATUS_SUPR_SHIFT]); + pr_debug(" [1] %d acked\n", + txs->status & TX_STATUS_ACK_RCV ? 1 : 0); + + pr_debug("LastTxTime: %04x Seq: %04x PHYTxStatus: %04x RxAckRSSI: %04x RxAckSQ: %04x\n", + txs->lasttxtime, txs->sequence, txs->phyerr, + (txs->ackphyrxsh & PRXS1_JSSI_MASK) >> PRXS1_JSSI_SHIFT, + (txs->ackphyrxsh & PRXS1_SQ_MASK) >> PRXS1_SQ_SHIFT); } bool brcms_c_chipmatch(u16 vendor, u16 device) { if (vendor != PCI_VENDOR_ID_BROADCOM) { - pr_err("chipmatch: unknown vendor id %04x\n", vendor); + pr_err("unknown vendor id %04x\n", vendor); return false; } @@ -5833,11 +5821,11 @@ bool brcms_c_chipmatch(u16 vendor, u16 device) if ((device == BCM43236_D11N_ID) || (device == BCM43236_D11N2G_ID)) return true; - pr_err("chipmatch: unknown device id %04x\n", device); + pr_err("unknown device id %04x\n", device); return false; } -#if defined(BCMDBG) +#if defined(DEBUG) void brcms_c_print_txdesc(struct d11txh *txh) { u16 mtcl = le16_to_cpu(txh->MacTxControlLow); @@ -5871,57 +5859,56 @@ void brcms_c_print_txdesc(struct d11txh *txh) struct ieee80211_rts rts = txh->rts_frame; /* add plcp header along with txh descriptor */ - printk(KERN_DEBUG "Raw TxDesc + plcp header:\n"); - print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, - txh, sizeof(struct d11txh) + 48); - - printk(KERN_DEBUG "TxCtlLow: %04x ", mtcl); - printk(KERN_DEBUG "TxCtlHigh: %04x ", mtch); - printk(KERN_DEBUG "FC: %04x ", mfc); - printk(KERN_DEBUG "FES Time: %04x\n", tfest); - printk(KERN_DEBUG "PhyCtl: %04x%s ", ptcw, + brcmu_dbg_hex_dump(txh, sizeof(struct d11txh) + 48, + "Raw TxDesc + plcp header:\n"); + + pr_debug("TxCtlLow: %04x ", mtcl); + pr_debug("TxCtlHigh: %04x ", mtch); + pr_debug("FC: %04x ", mfc); + pr_debug("FES Time: %04x\n", tfest); + pr_debug("PhyCtl: %04x%s ", ptcw, (ptcw & PHY_TXC_SHORT_HDR) ? " short" : ""); - printk(KERN_DEBUG "PhyCtl_1: %04x ", ptcw_1); - printk(KERN_DEBUG "PhyCtl_1_Fbr: %04x\n", ptcw_1_Fbr); - printk(KERN_DEBUG "PhyCtl_1_Rts: %04x ", ptcw_1_Rts); - printk(KERN_DEBUG "PhyCtl_1_Fbr_Rts: %04x\n", ptcw_1_FbrRts); - printk(KERN_DEBUG "MainRates: %04x ", mainrates); - printk(KERN_DEBUG "XtraFrameTypes: %04x ", xtraft); - printk(KERN_DEBUG "\n"); + pr_debug("PhyCtl_1: %04x ", ptcw_1); + pr_debug("PhyCtl_1_Fbr: %04x\n", ptcw_1_Fbr); + pr_debug("PhyCtl_1_Rts: %04x ", ptcw_1_Rts); + pr_debug("PhyCtl_1_Fbr_Rts: %04x\n", ptcw_1_FbrRts); + pr_debug("MainRates: %04x ", mainrates); + pr_debug("XtraFrameTypes: %04x ", xtraft); + pr_debug("\n"); print_hex_dump_bytes("SecIV:", DUMP_PREFIX_OFFSET, iv, sizeof(txh->IV)); print_hex_dump_bytes("RA:", DUMP_PREFIX_OFFSET, ra, sizeof(txh->TxFrameRA)); - printk(KERN_DEBUG "Fb FES Time: %04x ", tfestfb); + pr_debug("Fb FES Time: %04x ", tfestfb); print_hex_dump_bytes("Fb RTS PLCP:", DUMP_PREFIX_OFFSET, rtspfb, sizeof(txh->RTSPLCPFallback)); - printk(KERN_DEBUG "RTS DUR: %04x ", rtsdfb); + pr_debug("RTS DUR: %04x ", rtsdfb); print_hex_dump_bytes("PLCP:", DUMP_PREFIX_OFFSET, fragpfb, sizeof(txh->FragPLCPFallback)); - printk(KERN_DEBUG "DUR: %04x", fragdfb); - printk(KERN_DEBUG "\n"); + pr_debug("DUR: %04x", fragdfb); + pr_debug("\n"); - printk(KERN_DEBUG "MModeLen: %04x ", mmodelen); - printk(KERN_DEBUG "MModeFbrLen: %04x\n", mmodefbrlen); + pr_debug("MModeLen: %04x ", mmodelen); + pr_debug("MModeFbrLen: %04x\n", mmodefbrlen); - printk(KERN_DEBUG "FrameID: %04x\n", tfid); - printk(KERN_DEBUG "TxStatus: %04x\n", txs); + pr_debug("FrameID: %04x\n", tfid); + pr_debug("TxStatus: %04x\n", txs); - printk(KERN_DEBUG "MaxNumMpdu: %04x\n", mnmpdu); - printk(KERN_DEBUG "MaxAggbyte: %04x\n", mabyte); - printk(KERN_DEBUG "MaxAggbyte_fb: %04x\n", mabyte_f); - printk(KERN_DEBUG "MinByte: %04x\n", mmbyte); + pr_debug("MaxNumMpdu: %04x\n", mnmpdu); + pr_debug("MaxAggbyte: %04x\n", mabyte); + pr_debug("MaxAggbyte_fb: %04x\n", mabyte_f); + pr_debug("MinByte: %04x\n", mmbyte); print_hex_dump_bytes("RTS PLCP:", DUMP_PREFIX_OFFSET, rtsph, sizeof(txh->RTSPhyHeader)); print_hex_dump_bytes("RTS Frame:", DUMP_PREFIX_OFFSET, (u8 *)&rts, sizeof(txh->rts_frame)); - printk(KERN_DEBUG "\n"); + pr_debug("\n"); } -#endif /* defined(BCMDBG) */ +#endif /* defined(DEBUG) */ -#if defined(BCMDBG) +#if defined(DEBUG) static int brcms_c_format_flags(const struct brcms_c_bit_desc *bd, u32 flags, char *buf, int len) @@ -5975,9 +5962,9 @@ brcms_c_format_flags(const struct brcms_c_bit_desc *bd, u32 flags, char *buf, return (int)(p - buf); } -#endif /* defined(BCMDBG) */ +#endif /* defined(DEBUG) */ -#if defined(BCMDBG) +#if defined(DEBUG) void brcms_c_print_rxh(struct d11rxhdr *rxh) { u16 len = rxh->RxFrameSize; @@ -5999,24 +5986,22 @@ void brcms_c_print_rxh(struct d11rxhdr *rxh) {0, NULL} }; - printk(KERN_DEBUG "Raw RxDesc:\n"); - print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, rxh, - sizeof(struct d11rxhdr)); + brcmu_dbg_hex_dump(rxh, sizeof(struct d11rxhdr), "Raw RxDesc:\n"); brcms_c_format_flags(macstat_flags, macstatus1, flagstr, 64); snprintf(lenbuf, sizeof(lenbuf), "0x%x", len); - printk(KERN_DEBUG "RxFrameSize: %6s (%d)%s\n", lenbuf, len, + pr_debug("RxFrameSize: %6s (%d)%s\n", lenbuf, len, (rxh->PhyRxStatus_0 & PRXS0_SHORTH) ? " short preamble" : ""); - printk(KERN_DEBUG "RxPHYStatus: %04x %04x %04x %04x\n", + pr_debug("RxPHYStatus: %04x %04x %04x %04x\n", phystatus_0, phystatus_1, phystatus_2, phystatus_3); - printk(KERN_DEBUG "RxMACStatus: %x %s\n", macstatus1, flagstr); - printk(KERN_DEBUG "RXMACaggtype: %x\n", + pr_debug("RxMACStatus: %x %s\n", macstatus1, flagstr); + pr_debug("RXMACaggtype: %x\n", (macstatus2 & RXS_AGGTYPE_MASK)); - printk(KERN_DEBUG "RxTSFTime: %04x\n", rxh->RxTSFTime); + pr_debug("RxTSFTime: %04x\n", rxh->RxTSFTime); } -#endif /* defined(BCMDBG) */ +#endif /* defined(DEBUG) */ u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate) { @@ -8354,7 +8339,7 @@ brcms_c_attach(struct brcms_info *wl, struct bcma_device *core, uint unit, wlc->wiphy = wl->wiphy; pub = wlc->pub; -#if defined(BCMDBG) +#if defined(DEBUG) wlc_info_dbg = wlc; #endif diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.h b/drivers/net/wireless/brcm80211/brcmsmac/main.h index adb136e..8debc74 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.h @@ -648,10 +648,12 @@ extern void brcms_c_print_txstatus(struct tx_status *txs); extern int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo, uint *blocks); -#if defined(BCMDBG) +#if defined(DEBUG) extern void brcms_c_print_txdesc(struct d11txh *txh); #else -#define brcms_c_print_txdesc(a) +static inline void brcms_c_print_txdesc(struct d11txh *txh) +{ +} #endif extern int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config); diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c index a16f1ab..3909574 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c @@ -14,6 +14,8 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/kernel.h> #include <linux/delay.h> #include <linux/cordic.h> @@ -17822,8 +17824,6 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) if (pi->sh->sromrev < 4) { idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g; idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g; - target_pwr_qtrdbm[0] = 13 * 4; - target_pwr_qtrdbm[1] = 13 * 4; a1[0] = -424; a1[1] = -424; b0[0] = 5612; @@ -17837,10 +17837,6 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) case WL_CHAN_FREQ_RANGE_2G: idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g; idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g; - target_pwr_qtrdbm[0] = - pi->nphy_pwrctrl_info[0].max_pwr_2g; - target_pwr_qtrdbm[1] = - pi->nphy_pwrctrl_info[1].max_pwr_2g; a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_a1; a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_a1; b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_b0; @@ -17851,10 +17847,6 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) case WL_CHAN_FREQ_RANGE_5GL: idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g; idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g; - target_pwr_qtrdbm[0] = - pi->nphy_pwrctrl_info[0].max_pwr_5gl; - target_pwr_qtrdbm[1] = - pi->nphy_pwrctrl_info[1].max_pwr_5gl; a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1; a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1; b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0; @@ -17865,10 +17857,6 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) case WL_CHAN_FREQ_RANGE_5GM: idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g; idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g; - target_pwr_qtrdbm[0] = - pi->nphy_pwrctrl_info[0].max_pwr_5gm; - target_pwr_qtrdbm[1] = - pi->nphy_pwrctrl_info[1].max_pwr_5gm; a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_a1; a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_a1; b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_b0; @@ -17879,10 +17867,6 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) case WL_CHAN_FREQ_RANGE_5GH: idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g; idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g; - target_pwr_qtrdbm[0] = - pi->nphy_pwrctrl_info[0].max_pwr_5gh; - target_pwr_qtrdbm[1] = - pi->nphy_pwrctrl_info[1].max_pwr_5gh; a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1; a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1; b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0; @@ -17893,8 +17877,6 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) default: idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g; idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g; - target_pwr_qtrdbm[0] = 13 * 4; - target_pwr_qtrdbm[1] = 13 * 4; a1[0] = -424; a1[1] = -424; b0[0] = 5612; @@ -17905,6 +17887,7 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) } } + /* use the provided transmit power */ target_pwr_qtrdbm[0] = (s8) pi->tx_power_max; target_pwr_qtrdbm[1] = (s8) pi->tx_power_max; @@ -19987,12 +19970,11 @@ static void wlc_phy_radio_init_2057(struct brcms_phy *pi) switch (pi->pubpi.radiorev) { case 5: - if (pi->pubpi.radiover == 0x0) + if (NREV_IS(pi->pubpi.phy_rev, 8)) regs_2057_ptr = regs_2057_rev5; - else if (pi->pubpi.radiover == 0x1) + else if (NREV_IS(pi->pubpi.phy_rev, 9)) regs_2057_ptr = regs_2057_rev5v1; - else - break; + break; case 7: @@ -21462,7 +21444,7 @@ void wlc_phy_antsel_init(struct brcms_phy_pub *ppi, bool lut_init) if (NREV_GE(pi->pubpi.phy_rev, 3)) { u16 v0 = 0x211, v1 = 0x222, v2 = 0x144, v3 = 0x188; - if (lut_init == false) + if (!lut_init) return; if (pi->srom_fem2g.antswctrllut == 0) { @@ -26434,8 +26416,7 @@ cal_try: } if (bcmerror != 0) { - printk(KERN_DEBUG "%s: Failed, cnt = %d\n", __func__, - cal_retry); + pr_debug("%s: Failed, cnt = %d\n", __func__, cal_retry); if (cal_retry < CAL_RETRY_CNT) { cal_retry++; diff --git a/drivers/net/wireless/brcm80211/brcmsmac/srom.c b/drivers/net/wireless/brcm80211/brcmsmac/srom.c index 5637436..b96f4b9 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/srom.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/srom.c @@ -621,7 +621,7 @@ static inline void cpu_to_le16_buf(u16 *buf, uint nwords) /* * convert binary srom data into linked list of srom variable items. */ -static void +static int _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list) { struct brcms_srom_list_head *entry; @@ -638,6 +638,9 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list) /* first store the srom revision */ entry = kzalloc(sizeof(struct brcms_srom_list_head), GFP_KERNEL); + if (!entry) + return -ENOMEM; + entry->varid = BRCMS_SROM_REV; entry->var_type = BRCMS_SROM_UNUMBER; entry->uval = sromrev; @@ -715,6 +718,8 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list) entry = kzalloc(sizeof(struct brcms_srom_list_head) + extra_space, GFP_KERNEL); + if (!entry) + return -ENOMEM; entry->varid = id; entry->var_type = type; if (flags & SRFL_ETHADDR) { @@ -754,6 +759,8 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list) entry = kzalloc(sizeof(struct brcms_srom_list_head), GFP_KERNEL); + if (!entry) + return -ENOMEM; entry->varid = srv->varid+p; entry->var_type = BRCMS_SROM_UNUMBER; entry->uval = val; @@ -761,6 +768,7 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list) } pb += psz; } + return 0; } /* @@ -906,7 +914,9 @@ int srom_var_init(struct si_pub *sih) INIT_LIST_HEAD(&sii->var_list); /* parse SROM into name=value pairs. */ - _initvars_srom_pci(sromrev, srom, &sii->var_list); + err = _initvars_srom_pci(sromrev, srom, &sii->var_list); + if (err) + srom_free_vars(sih); } errout: diff --git a/drivers/net/wireless/brcm80211/brcmutil/utils.c b/drivers/net/wireless/brcm80211/brcmutil/utils.c index b7537f7..b45ab34 100644 --- a/drivers/net/wireless/brcm80211/brcmutil/utils.c +++ b/drivers/net/wireless/brcm80211/brcmutil/utils.c @@ -14,6 +14,8 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/netdevice.h> #include <linux/module.h> @@ -240,17 +242,35 @@ struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp, } EXPORT_SYMBOL(brcmu_pktq_mdeq); -#if defined(BCMDBG) +#if defined(DEBUG) /* pretty hex print a pkt buffer chain */ void brcmu_prpkt(const char *msg, struct sk_buff *p0) { struct sk_buff *p; if (msg && (msg[0] != '\0')) - printk(KERN_DEBUG "%s:\n", msg); + pr_debug("%s:\n", msg); for (p = p0; p; p = p->next) print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, p->data, p->len); } EXPORT_SYMBOL(brcmu_prpkt); -#endif /* defined(BCMDBG) */ + +void brcmu_dbg_hex_dump(const void *data, size_t size, const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + pr_debug("%pV", &vaf); + + va_end(args); + + print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, data, size); +} +EXPORT_SYMBOL(brcmu_dbg_hex_dump); +#endif /* defined(DEBUG) */ diff --git a/drivers/net/wireless/brcm80211/include/brcmu_utils.h b/drivers/net/wireless/brcm80211/include/brcmu_utils.h index ad249a0..477b92a 100644 --- a/drivers/net/wireless/brcm80211/include/brcmu_utils.h +++ b/drivers/net/wireless/brcm80211/include/brcmu_utils.h @@ -176,10 +176,21 @@ struct ipv4_addr; /* externs */ /* format/print */ -#ifdef BCMDBG +#ifdef DEBUG extern void brcmu_prpkt(const char *msg, struct sk_buff *p0); #else #define brcmu_prpkt(a, b) -#endif /* BCMDBG */ +#endif /* DEBUG */ + +#ifdef DEBUG +extern __printf(3, 4) +void brcmu_dbg_hex_dump(const void *data, size_t size, const char *fmt, ...); +#else +__printf(3, 4) +static inline +void brcmu_dbg_hex_dump(const void *data, size_t size, const char *fmt, ...) +{ +} +#endif #endif /* _BRCMU_UTILS_H_ */ |