diff options
-rw-r--r-- | bin/firmware/7.2.6.1/88W8864.bin | bin | 113244 -> 0 bytes | |||
-rwxr-xr-x | bin/firmware/88W8864.bin | bin | 0 -> 116208 bytes | |||
-rw-r--r-- | bin/firmware/Marvell_license.txt | 2 | ||||
-rw-r--r-- | bin/powertable/Mamba/Mamba_FCC_v1.2_5G4TX.ini | 39 | ||||
-rw-r--r-- | mwl_debug.c | 21 | ||||
-rw-r--r-- | mwl_debug.h | 2 | ||||
-rw-r--r-- | mwl_dev.h | 146 | ||||
-rw-r--r-- | mwl_fwcmd.c | 594 | ||||
-rw-r--r-- | mwl_fwcmd.h | 28 | ||||
-rw-r--r-- | mwl_fwdl.c | 13 | ||||
-rw-r--r-- | mwl_fwdl.h | 2 | ||||
-rw-r--r-- | mwl_mac80211.c | 304 | ||||
-rw-r--r-- | mwl_mac80211.h | 2 | ||||
-rw-r--r-- | mwl_main.c | 474 | ||||
-rw-r--r-- | mwl_rx.c | 56 | ||||
-rw-r--r-- | mwl_rx.h | 2 | ||||
-rw-r--r-- | mwl_sysadpt.h | 8 | ||||
-rw-r--r-- | mwl_tx.c | 144 | ||||
-rw-r--r-- | mwl_tx.h | 2 | ||||
-rw-r--r-- | test/README | 89 | ||||
-rw-r--r-- | test/setup.sh | 2 | ||||
-rw-r--r-- | test/setup_multi_bssid.sh | 2 | ||||
-rwxr-xr-x | test/wpa_supplicant.conf.open | 8 | ||||
-rwxr-xr-x | test/wpa_supplicant.conf.psk | 9 |
24 files changed, 915 insertions, 1034 deletions
diff --git a/bin/firmware/7.2.6.1/88W8864.bin b/bin/firmware/7.2.6.1/88W8864.bin Binary files differdeleted file mode 100644 index 6aaee12..0000000 --- a/bin/firmware/7.2.6.1/88W8864.bin +++ /dev/null diff --git a/bin/firmware/88W8864.bin b/bin/firmware/88W8864.bin Binary files differnew file mode 100755 index 0000000..ccdf825 --- /dev/null +++ b/bin/firmware/88W8864.bin diff --git a/bin/firmware/Marvell_license.txt b/bin/firmware/Marvell_license.txt index fe7d6de..945a549 100644 --- a/bin/firmware/Marvell_license.txt +++ b/bin/firmware/Marvell_license.txt @@ -1,5 +1,5 @@ WIRELESS CORE LIBRARY & FIRMWARE LICENSE TERMS
-Copyright (c) 2002-2014 Marvell International Ltd.
+Copyright (c) 2002-2015 Marvell International Ltd.
All rights reserved.
Redistribution. Redistribution and use in binary form, without modification,
diff --git a/bin/powertable/Mamba/Mamba_FCC_v1.2_5G4TX.ini b/bin/powertable/Mamba/Mamba_FCC_v1.2_5G4TX.ini deleted file mode 100644 index 11a8304..0000000 --- a/bin/powertable/Mamba/Mamba_FCC_v1.2_5G4TX.ini +++ /dev/null @@ -1,39 +0,0 @@ -1 0 0x17 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x0F 0x0F 0x0F 0x0F 0x00 0x00 0x00 0x00 off 0x00F -2 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x00 0x00 0x00 0x00 off 0x00F -3 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x00 0x00 0x00 0x00 off 0x00F -4 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x00 0x00 0x00 0x00 off 0x00F -5 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x00 0x00 0x00 0x00 off 0x00F -6 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x00 0x00 0x00 0x00 off 0x00F -7 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x00 0x00 0x00 0x00 off 0x00F -8 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x00 0x00 0x00 0x00 off 0x00F -9 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x00 0x00 0x00 0x00 off 0x00F -10 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x00 0x00 0x00 0x00 off 0x00F -11 0 0x17 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x00 0x00 0x00 0x00 off 0x00F -12 0 0x17 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x00 0x00 0x00 0x00 off 0x00F -13 0 0x17 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x00 0x00 0x00 0x00 off 0x00F -14 0 0x17 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x00 0x00 0x00 0x00 off 0x00F -36 0 0x08 0x08 0x08 0x08 0x08 0x08 0x08 0x08 0x09 0x09 0x09 0x09 0x09 0x09 0x09 0x09 off 0x00F -40 0 0x08 0x08 0x08 0x08 0x09 0x09 0x09 0x09 0x09 0x09 0x09 0x09 0x09 0x09 0x09 0x09 off 0x00F -44 0 0x08 0x08 0x08 0x08 0x09 0x09 0x09 0x09 0x09 0x09 0x09 0x09 0x09 0x09 0x09 0x09 off 0x00F -48 0 0x08 0x08 0x08 0x08 0x09 0x09 0x09 0x09 0x09 0x09 0x09 0x09 0x09 0x09 0x09 0x09 off 0x00F -52 0 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 off 0x00F -56 0 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 off 0x00F -60 0 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 off 0x00F -64 0 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x0F 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 off 0x00F -100 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 off 0x00F -104 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 off 0x00F -108 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 off 0x00F -112 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 off 0x00F -116 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 off 0x00F -120 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 off 0x00F -124 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 off 0x00F -128 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 off 0x00F -132 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 off 0x00F -136 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 off 0x00F -140 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 off 0x00F -149 0 0x16 0x16 0x16 0x16 0x14 0x14 0x14 0x14 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 off 0x00F -153 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 off 0x00F -157 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 off 0x00F -161 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 off 0x00F -165 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 off 0x00F - diff --git a/mwl_debug.c b/mwl_debug.c index 821b0c0..3402e99 100644 --- a/mwl_debug.c +++ b/mwl_debug.c @@ -1,5 +1,5 @@ /* -* Copyright (c) 2006-2014 Marvell International Ltd. +* Copyright (c) 2006-2015 Marvell International Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -59,7 +59,6 @@ void mwl_debug_prt(u32 classlevel, const char *func, const char *format, ...) return; if ((level & dbg_levels) != level) { - if (class != DBG_CLASS_PANIC && class != DBG_CLASS_ERROR) return; } @@ -69,18 +68,14 @@ void mwl_debug_prt(u32 classlevel, const char *func, const char *format, ...) return; if (format != NULL) { - va_start(a_start, format); vsprintf(debug_string, format, a_start); va_end(a_start); - } else { - debug_string[0] = '\0'; } switch (class) { - case DBG_CLASS_ENTER: printk("Enter %s() ...\n", func); break; @@ -101,7 +96,6 @@ void mwl_debug_prt(u32 classlevel, const char *func, const char *format, ...) } if (strlen(debug_string) > 0) { - if (debug_string[strlen(debug_string)-1] == '\n') debug_string[strlen(debug_string)-1] = '\0'; printk("%s(): %s\n", func, debug_string); @@ -132,31 +126,23 @@ void mwl_debug_prtdata(u32 classlevel, const char *func, const void *data, int l return; if (format != NULL) { - va_start(a_start, format); vsprintf(dbg_string, format, a_start); va_end(a_start); - } else { - dbg_string[0] = '\0'; } if (strlen(dbg_string) > 0) { - if (dbg_string[strlen(dbg_string) - 1] == '\n') dbg_string[strlen(dbg_string)-1] = '\0'; printk("%s() %s\n", func, dbg_string); - } else { - printk("%s()\n", func); } for (curr_byte = 0; curr_byte < len; curr_byte = curr_byte + 8) { - if ((curr_byte + 8) < len) { - printk("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", *(memptr + curr_byte + 0), *(memptr + curr_byte + 1), @@ -167,11 +153,9 @@ void mwl_debug_prtdata(u32 classlevel, const char *func, const void *data, int l *(memptr + curr_byte + 6), *(memptr + curr_byte + 7)); } else { - num_bytes = len - curr_byte; offset = curr_byte; for (curr_byte = 0; curr_byte < num_bytes; curr_byte++) { - sprintf(dbg_data, "0x%02x ", *(memptr + offset + curr_byte)); strcat(dbg_string, dbg_data); } @@ -193,9 +177,7 @@ void mwl_debug_dumpdata(const void *data, int len, char *marker) printk("%s\n", marker); for (curr_byte = 0; curr_byte < len; curr_byte = curr_byte + 8) { - if ((curr_byte + 8) < len) { - printk("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", *(memptr + curr_byte + 0), *(memptr + curr_byte + 1), @@ -206,7 +188,6 @@ void mwl_debug_dumpdata(const void *data, int len, char *marker) *(memptr + curr_byte + 6), *(memptr + curr_byte + 7)); } else { - num_bytes = len - curr_byte; offset = curr_byte; for (curr_byte = 0; curr_byte < num_bytes; curr_byte++) diff --git a/mwl_debug.h b/mwl_debug.h index 6e9d74e..423a409 100644 --- a/mwl_debug.h +++ b/mwl_debug.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2006-2014 Marvell International Ltd. +* Copyright (c) 2006-2015 Marvell International Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -1,5 +1,5 @@ /* -* Copyright (c) 2006-2014 Marvell International Ltd. +* Copyright (c) 2006-2015 Marvell International Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -34,24 +34,24 @@ /* Map to 0x80000000 (Bus control) on BAR0 */ -#define MACREG_REG_H2A_INTERRUPT_EVENTS 0x00000C18 /* (From host to ARM) */ -#define MACREG_REG_H2A_INTERRUPT_CAUSE 0x00000C1C /* (From host to ARM) */ -#define MACREG_REG_H2A_INTERRUPT_MASK 0x00000C20 /* (From host to ARM) */ -#define MACREG_REG_H2A_INTERRUPT_CLEAR_SEL 0x00000C24 /* (From host to ARM) */ -#define MACREG_REG_H2A_INTERRUPT_STATUS_MASK 0x00000C28 /* (From host to ARM) */ - -#define MACREG_REG_A2H_INTERRUPT_EVENTS 0x00000C2C /* (From ARM to host) */ -#define MACREG_REG_A2H_INTERRUPT_CAUSE 0x00000C30 /* (From ARM to host) */ -#define MACREG_REG_A2H_INTERRUPT_MASK 0x00000C34 /* (From ARM to host) */ -#define MACREG_REG_A2H_INTERRUPT_CLEAR_SEL 0x00000C38 /* (From ARM to host) */ -#define MACREG_REG_A2H_INTERRUPT_STATUS_MASK 0x00000C3C /* (From ARM to host) */ +#define MACREG_REG_H2A_INTERRUPT_EVENTS 0x00000C18 /* (From host to ARM) */ +#define MACREG_REG_H2A_INTERRUPT_CAUSE 0x00000C1C /* (From host to ARM) */ +#define MACREG_REG_H2A_INTERRUPT_MASK 0x00000C20 /* (From host to ARM) */ +#define MACREG_REG_H2A_INTERRUPT_CLEAR_SEL 0x00000C24 /* (From host to ARM) */ +#define MACREG_REG_H2A_INTERRUPT_STATUS_MASK 0x00000C28 /* (From host to ARM) */ + +#define MACREG_REG_A2H_INTERRUPT_EVENTS 0x00000C2C /* (From ARM to host) */ +#define MACREG_REG_A2H_INTERRUPT_CAUSE 0x00000C30 /* (From ARM to host) */ +#define MACREG_REG_A2H_INTERRUPT_MASK 0x00000C34 /* (From ARM to host) */ +#define MACREG_REG_A2H_INTERRUPT_CLEAR_SEL 0x00000C38 /* (From ARM to host) */ +#define MACREG_REG_A2H_INTERRUPT_STATUS_MASK 0x00000C3C /* (From ARM to host) */ /* Map to 0x80000000 on BAR1 */ #define MACREG_REG_GEN_PTR 0x00000C10 #define MACREG_REG_INT_CODE 0x00000C14 #define MACREG_REG_SCRATCH 0x00000C40 -#define MACREG_REG_FW_PRESENT 0x0000BFFC +#define MACREG_REG_FW_PRESENT 0x0000BFFC /* Bit definitio for MACREG_REG_A2H_INTERRUPT_CAUSE (A2HRIC) */ @@ -60,18 +60,18 @@ #define MACREG_A2HRIC_BIT_OPC_DONE 0x00000004 /* bit 2 */ #define MACREG_A2HRIC_BIT_MAC_EVENT 0x00000008 /* bit 3 */ #define MACREG_A2HRIC_BIT_RX_PROBLEM 0x00000010 /* bit 4 */ -#define MACREG_A2HRIC_BIT_RADIO_OFF 0x00000020 /* bit 5 */ -#define MACREG_A2HRIC_BIT_RADIO_ON 0x00000040 /* bit 6 */ +#define MACREG_A2HRIC_BIT_RADIO_OFF 0x00000020 /* bit 5 */ +#define MACREG_A2HRIC_BIT_RADIO_ON 0x00000040 /* bit 6 */ #define MACREG_A2HRIC_BIT_RADAR_DETECT 0x00000080 /* bit 7 - IEEE80211_DH */ #define MACREG_A2HRIC_BIT_ICV_ERROR 0x00000100 /* bit 8 */ #define MACREG_A2HRIC_BIT_WEAKIV_ERROR 0x00000200 /* bit 9 */ -#define MACREG_A2HRIC_BIT_QUEUE_EMPTY (1<<10) -#define MACREG_A2HRIC_BIT_QUEUE_FULL (1<<11) +#define MACREG_A2HRIC_BIT_QUEUE_EMPTY (1<<10) +#define MACREG_A2HRIC_BIT_QUEUE_FULL (1<<11) #define MACREG_A2HRIC_BIT_CHAN_SWITCH (1<<12) /* IEEE80211_DH */ -#define MACREG_A2HRIC_BIT_TX_WATCHDOG (1<<13) +#define MACREG_A2HRIC_BIT_TX_WATCHDOG (1<<13) #define MACREG_A2HRIC_BA_WATCHDOG (1<<14) #define MACREG_A2HRIC_BIT_SSU_DONE (1<<16) -#define MACREG_A2HRIC_CONSEC_TXFAIL (1<<17) /* 15 taken by ISR_TXACK */ +#define MACREG_A2HRIC_CONSEC_TXFAIL (1<<17) /* 15 taken by ISR_TXACK */ #define ISR_SRC_BITS ((MACREG_A2HRIC_BIT_RX_RDY) | \ (MACREG_A2HRIC_BIT_TX_DONE) | \ @@ -82,7 +82,7 @@ (MACREG_A2HRIC_BIT_SSU_DONE) | \ (MACREG_A2HRIC_BIT_RADAR_DETECT)| \ (MACREG_A2HRIC_BIT_CHAN_SWITCH)| \ - (MACREG_A2HRIC_BIT_TX_WATCHDOG)| \ + (MACREG_A2HRIC_BIT_TX_WATCHDOG)| \ (MACREG_A2HRIC_BIT_QUEUE_EMPTY)| \ (MACREG_A2HRIC_BA_WATCHDOG) | \ (MACREG_A2HRIC_CONSEC_TXFAIL)) @@ -93,9 +93,9 @@ */ #define MACREG_H2ARIC_BIT_PPA_READY 0x00000001 /* bit 0 */ #define MACREG_H2ARIC_BIT_DOOR_BELL 0x00000002 /* bit 1 */ -#define MACREG_H2ARIC_BIT_PS 0x00000004 /* bit 2 */ -#define MACREG_H2ARIC_BIT_PSPOLL 0x00000008 /* bit 3 */ -#define ISR_RESET (1<<15) +#define MACREG_H2ARIC_BIT_PS 0x00000004 /* bit 2 */ +#define MACREG_H2ARIC_BIT_PSPOLL 0x00000008 /* bit 3 */ +#define ISR_RESET (1<<15) #define ISR_RESET_AP33 (1<<26) /* Data descriptor related constants @@ -130,6 +130,13 @@ #define NBR_BYTES_FW_RX_PREPEND_LEN 2 #define NBR_BYTES_FW_TX_PREPEND_LEN 2 +/* Antenna control +*/ +#define ANTENNA_TX_4_AUTO 0 +#define ANTENNA_TX_2 3 +#define ANTENNA_RX_4_AUTO 0 +#define ANTENNA_RX_2 2 + /* Misc */ #define WL_SEC_SLEEP(num_secs) mdelay(num_secs * 1000) @@ -158,41 +165,32 @@ */ enum { - AP_MODE_11AC = 0x10, /* generic 11ac indication mode */ - AP_MODE_2_4GHZ_11AC_MIXED = 0x17, - + AP_MODE_2_4GHZ_11AC_MIXED = 0x17, }; enum { - AMPDU_NO_STREAM, AMPDU_STREAM_NEW, AMPDU_STREAM_IN_PROGRESS, AMPDU_STREAM_ACTIVE, - }; enum { - IEEE_TYPE_MANAGEMENT = 0, IEEE_TYPE_CONTROL, IEEE_TYPE_DATA - }; struct mwl_tx_pwr_tbl { - u8 channel; u8 setcap; u16 tx_power[SYSADPT_TX_POWER_LEVEL_TOTAL]; u8 cdd; /* 0: off, 1: on */ u16 txantenna2; - }; struct mwl_hw_data { - u32 fw_release_num; /* MajNbr:MinNbr:SubMin:PatchLevel */ u8 hw_version; /* plain number indicating version */ u8 host_interface; /* plain number of interface */ @@ -201,11 +199,9 @@ struct mwl_hw_data { u16 num_antennas; /* number antennas used */ u16 region_code; /* region (eg. 0x10 for USA FCC) */ unsigned char mac_addr[ETH_ALEN]; /* well known -> AA:BB:CC:DD:EE:FF */ - }; struct mwl_rate_info { - u32 format:1; /* 0 = Legacy format, 1 = Hi-throughput format */ u32 short_gi:1; /* 0 = Use standard guard interval,1 = Use short guard interval */ u32 bandwidth:1; /* 0 = Use 20 MHz channel,1 = Use 40 MHz channel */ @@ -222,11 +218,9 @@ struct mwl_rate_info { u32 count:4; u32 rsvd2:3; u32 drop:1; - } __packed; struct mwl_tx_desc { - u8 data_rate; u8 tx_priority; u16 qos_ctrl; @@ -238,41 +232,45 @@ struct mwl_tx_desc { struct mwl_rate_info rate_info; u8 type; u8 xmit_control; /* bit 0: use rateinfo, bit 1: disable ampdu */ - u16 reserved; + u16 reserved; u32 tcpack_sn; u32 tcpack_src_dst; struct sk_buff *psk_buff; struct mwl_tx_desc *pnext; - u32 soft_stat; - u32 ack_wcb_addr; + u8 reserved1[2]; + u8 packet_info; + u8 packet_id; + u16 packet_len_and_retry; + u16 packet_rate_info; u8 *sta_info; - u32 status; - + u32 status; } __packed; struct mwl_hw_rssi_info { - u32 rssi_a:8; u32 rssi_b:8; u32 rssi_c:8; u32 rssi_d:8; - } __packed; struct mwl_hw_noise_floor_info { - u32 noise_floor_a:8; u32 noise_floor_b:8; u32 noise_floor_c:8; u32 noise_floor_d:8; - } __packed; -struct mwl_rx_desc { +struct mwl_rxrate_info { + u16 format:3; /* 0: 11a, 1: 11b, 2: 11n, 4: 11ac */ + u16 nss:2; /* number space spectrum */ + u16 bw:2; /* 0: ht20, 1: ht40, 2: ht80 */ + u16 gi:1; /* 0: long interval, 1: short interval*/ + u16 rt:8; /* 11a/11b: 1,2,5,11,22,6,9,12,18,24,36,48,54,72*/ +} __packed; /* 11n/11ac: MCS */ +struct mwl_rx_desc { u16 pkt_len; /* total length of received data */ - u8 sq2; /* unused at the moment */ - u8 rate; /* received data rate */ + struct mwl_rxrate_info rate; /* receive rate information */ u32 pphys_buff_data; /* physical address of payload data */ u32 pphys_next; /* physical address of next RX desc */ u16 qos_ctrl; /* received QosCtrl field variable */ @@ -289,11 +287,9 @@ struct mwl_rx_desc { struct sk_buff *psk_buff; /* associated sk_buff for Linux */ void *pbuff_data; /* virtual address of payload data */ struct mwl_rx_desc *pnext; /* virtual address of next RX desc */ - } __packed; struct mwl_desc_data { - dma_addr_t pphys_tx_ring; /* ptr to first TX desc (phys.) */ struct mwl_tx_desc *ptx_ring; /* ptr to first TX desc (virt.) */ struct mwl_tx_desc *pnext_tx_desc; /* next TX desc that can be used */ @@ -305,32 +301,30 @@ struct mwl_desc_data { unsigned int rx_desc_write; /* FW descriptor write position */ unsigned int rx_desc_read; /* FW descriptor read position */ unsigned int rx_buf_size; /* length of the RX buffers */ - } __packed; struct mwl_locks { - DECLARE_LOCK(xmit_lock); /* used to protect TX actions */ DECLARE_LOCK(fwcmd_lock); /* used to protect FW commands */ DECLARE_LOCK(stream_lock); /* used to protect stream */ - }; struct mwl_ampdu_stream { - struct ieee80211_sta *sta; u8 tid; u8 state; u8 idx; - }; struct mwl_priv { - struct ieee80211_hw *hw; - const struct firmware *fw_ucode; - + struct device_node *dt_node; + struct device_node *pwr_node; + bool disable_2g; + bool disable_5g; + int antenna_tx; + int antenna_rx; struct mwl_tx_pwr_tbl tx_pwr_tbl[SYSADPT_MAX_NUM_CHANNELS]; u32 cdd; /* 0: off, 1: on */ u16 txantenna2; @@ -338,27 +332,20 @@ struct mwl_priv { u16 max_tx_pow[SYSADPT_TX_POWER_LEVEL_TOTAL]; /* max tx power (dBm) */ u16 target_powers[SYSADPT_TX_POWER_LEVEL_TOTAL]; /* target powers (dBm) */ u8 cal_tbl[200]; - struct pci_dev *pdev; void *iobase0; /* MEM Base Address Register 0 */ void *iobase1; /* MEM Base Address Register 1 */ u32 next_bar_num; - unsigned short *pcmd_buf; /* pointer to CmdBuf (virtual) */ dma_addr_t pphys_cmd_buf; /* pointer to CmdBuf (physical) */ bool in_send_cmd; - int irq; - struct mwl_hw_data hw_data; /* Adapter HW specific info */ - struct mwl_desc_data desc_data[SYSADPT_NUM_OF_DESC_DATA]; /* various descriptor data */ struct sk_buff_head txq[SYSADPT_NUM_OF_DESC_DATA]; struct sk_buff_head delay_freeq; int fw_desc_cnt[SYSADPT_NUM_OF_DESC_DATA]; /* number of descriptors owned by fw at any one time */ - struct mwl_locks locks; /* various spinlocks */ - struct tasklet_struct tx_task; struct tasklet_struct rx_task; int txq_limit; @@ -366,35 +353,28 @@ struct mwl_priv { int recv_limit; bool is_rx_schedule; s8 noise; /* Most recently reported noise in dBm */ - struct ieee80211_supported_band band_24; struct ieee80211_channel channels_24[14]; struct ieee80211_rate rates_24[13]; struct ieee80211_supported_band band_50; struct ieee80211_channel channels_50[24]; struct ieee80211_rate rates_50[8]; - u32 ap_macids_supported; u32 sta_macids_supported; u32 macids_used; struct list_head vif_list; /* List of interfaces. */ u32 running_bsses; /* bitmap of running BSSes */ - bool radio_on; bool radio_short_preamble; - bool wmm_enabled; struct ieee80211_tx_queue_params wmm_params[SYSADPT_TX_WMM_QUEUES]; - /* Ampdu stream information */ u8 num_ampdu_queues; struct mwl_ampdu_stream ampdu[SYSADPT_TX_AMPDU_QUEUES]; struct work_struct watchdog_ba_handle; - }; struct beacon_info { - bool valid; u16 cap_info; u8 bss_basic_rate_set[SYSADPT_MAX_DATA_RATES_G]; @@ -414,69 +394,53 @@ struct beacon_info { }; struct mwl_vif { - struct list_head list; struct ieee80211_vif *vif; - int macid; /* Firmware macid for this vif. */ - u16 seqno; /* Non AMPDU sequence number assigned by driver. */ - struct { /* Saved WEP keys */ u8 enabled; u8 key[sizeof(struct ieee80211_key_conf) + MAX_WEP_KEY_LEN]; } wep_key_conf[NUM_WEP_KEYS]; - u8 bssid[ETH_ALEN]; /* BSSID */ - + u8 sta_mac[ETH_ALEN]; /* Station mac address */ bool is_hw_crypto_enabled; /* A flag to indicate is HW crypto is enabled for this bssid */ - + bool is_sta; /* Indicate if this is station mode */ struct beacon_info beacon_info; - u16 iv16; u32 iv32; s8 keyidx; - }; struct mwl_tx_info { - u32 start_time; u32 pkts; - }; struct mwl_sta { - u8 is_ampdu_allowed; struct mwl_tx_info tx_stats[MWL_MAX_TID]; - u16 iv16; u32 iv32; - }; /* DMA header used by firmware and hardware. */ struct mwl_dma_data { - u16 fwlen; struct ieee80211_hdr wh; char data[0]; - } __packed; /* Transmission information to transmit a socket buffer. */ struct mwl_tx_ctrl { - u8 tx_priority; u16 qos_ctrl; u8 type; u8 xmit_control; u8 *sta_info; bool ccmp; - } __packed; #endif /* _mwl_dev_h_ */ diff --git a/mwl_fwcmd.c b/mwl_fwcmd.c index 9cb95bd..6270177 100644 --- a/mwl_fwcmd.c +++ b/mwl_fwcmd.c @@ -1,5 +1,5 @@ /* -* Copyright (c) 2006-2014 Marvell International Ltd. +* Copyright (c) 2006-2015 Marvell International Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -34,28 +34,32 @@ * 16 bit host command code */ #define HOSTCMD_CMD_GET_HW_SPEC 0x0003 -#define HOSTCMD_CMD_SET_HW_SPEC 0x0004 +#define HOSTCMD_CMD_SET_HW_SPEC 0x0004 #define HOSTCMD_CMD_802_11_GET_STAT 0x0014 #define HOSTCMD_CMD_802_11_RADIO_CONTROL 0x001c #define HOSTCMD_CMD_802_11_TX_POWER 0x001f #define HOSTCMD_CMD_802_11_RF_ANTENNA 0x0020 #define HOSTCMD_CMD_BROADCAST_SSID_ENABLE 0x0050 /* per-vif */ #define HOSTCMD_CMD_SET_RF_CHANNEL 0x010a +#define HOSTCMD_CMD_SET_AID 0x010d /* per-vif */ +#define HOSTCMD_CMD_SET_INFRA_MODE 0x010e /* per-vif */ #define HOSTCMD_CMD_802_11_RTS_THSD 0x0113 #define HOSTCMD_CMD_SET_EDCA_PARAMS 0x0115 #define HOSTCMD_CMD_SET_WMM_MODE 0x0123 #define HOSTCMD_CMD_SET_FIXED_RATE 0x0126 #define HOSTCMD_CMD_SET_IES 0x0127 -#define HOSTCMD_CMD_SET_RATE_ADAPT_MODE 0x0203 +#define HOSTCMD_CMD_SET_MAC_ADDR 0x0202 /* per-vif */ +#define HOSTCMD_CMD_SET_RATE_ADAPT_MODE 0x0203 #define HOSTCMD_CMD_GET_WATCHDOG_BITMAP 0x0205 +#define HOSTCMD_CMD_DEL_MAC_ADDR 0x0206 /* pre-vif */ #define HOSTCMD_CMD_BSS_START 0x1100 /* per-vif */ #define HOSTCMD_CMD_AP_BEACON 0x1101 /* per-vif */ #define HOSTCMD_CMD_SET_NEW_STN 0x1111 /* per-vif */ #define HOSTCMD_CMD_SET_APMODE 0x1114 -#define HOSTCMD_CMD_UPDATE_ENCRYPTION 0x1122 /* per-vif */ -#define HOSTCMD_CMD_BASTREAM 0x1125 -#define HOSTCMD_CMD_DWDS_ENABLE 0x1144 -#define HOSTCMD_CMD_FW_FLUSH_TIMER 0x1148 +#define HOSTCMD_CMD_UPDATE_ENCRYPTION 0x1122 /* per-vif */ +#define HOSTCMD_CMD_BASTREAM 0x1125 +#define HOSTCMD_CMD_DWDS_ENABLE 0x1144 +#define HOSTCMD_CMD_FW_FLUSH_TIMER 0x1148 #define HOSTCMD_CMD_SET_CDD 0x1150 /* @@ -71,8 +75,8 @@ /* * Define channel related constants */ -#define FREQ_BAND_2DOT4GHZ 0x1 -#define FREQ_BAND_4DOT9GHZ 0x2 +#define FREQ_BAND_2DOT4GHZ 0x1 +#define FREQ_BAND_4DOT9GHZ 0x2 #define FREQ_BAND_5GHZ 0x4 #define FREQ_BAND_5DOT2GHZ 0x8 #define CH_AUTO_WIDTH 0 @@ -111,15 +115,15 @@ #define MAX_ENCR_KEY_LENGTH 16 #define MIC_KEY_LENGTH 8 -#define KEY_TYPE_ID_WEP 0x00 /* Key type is WEP */ -#define KEY_TYPE_ID_TKIP 0x01 /* Key type is TKIP */ -#define KEY_TYPE_ID_AES 0x02 /* Key type is AES-CCMP */ +#define KEY_TYPE_ID_WEP 0x00 /* Key type is WEP */ +#define KEY_TYPE_ID_TKIP 0x01 /* Key type is TKIP */ +#define KEY_TYPE_ID_AES 0x02 /* Key type is AES-CCMP */ -#define ENCR_KEY_FLAG_TXGROUPKEY 0x00000004 /* Group key for TX */ -#define ENCR_KEY_FLAG_PAIRWISE 0x00000008 /* pairwise */ -#define ENCR_KEY_FLAG_TSC_VALID 0x00000040 /* Sequence counters are valid */ -#define ENCR_KEY_FLAG_WEP_TXKEY 0x01000000 /* Tx key for WEP */ -#define ENCR_KEY_FLAG_MICKEY_VALID 0x02000000 /* Tx/Rx MIC keys are valid */ +#define ENCR_KEY_FLAG_TXGROUPKEY 0x00000004 /* Group key for TX */ +#define ENCR_KEY_FLAG_PAIRWISE 0x00000008 /* pairwise */ +#define ENCR_KEY_FLAG_TSC_VALID 0x00000040 /* Sequence counters are valid */ +#define ENCR_KEY_FLAG_WEP_TXKEY 0x01000000 /* Tx key for WEP */ +#define ENCR_KEY_FLAG_MICKEY_VALID 0x02000000 /* Tx/Rx MIC keys are valid */ /* * Define block ack related constants @@ -137,7 +141,7 @@ /* Misc */ #define MWL_SPIN_LOCK(X) SPIN_LOCK_IRQSAVE(X, flags) -#define MWL_SPIN_UNLOCK(X) SPIN_UNLOCK_IRQRESTORE(X, flags) +#define MWL_SPIN_UNLOCK(X) SPIN_UNLOCK_IRQRESTORE(X, flags) #define MAX_ENCR_KEY_LENGTH 16 #define MIC_KEY_LENGTH 8 @@ -146,31 +150,24 @@ */ enum { - WL_DISABLE = 0, WL_ENABLE = 1, WL_DISABLE_VMAC = 0x80, - }; enum { - WL_GET = 0, WL_SET = 1, WL_RESET = 2, - }; enum { - WL_LONG_PREAMBLE = 1, WL_SHORT_PREAMBLE = 3, WL_AUTO_PREAMBLE = 5, - }; enum encr_action_type { - /* request to enable/disable HW encryption */ ENCR_ACTION_ENABLE_HW_ENCR, /* request to set encryption key */ @@ -178,17 +175,21 @@ enum encr_action_type { /* request to remove one or more keys */ ENCR_ACTION_TYPE_REMOVE_KEY, ENCR_ACTION_TYPE_SET_GROUP_KEY, - }; enum ba_action_type { - BA_CREATE_STREAM, BA_UPDATE_STREAM, BA_DESTROY_STREAM, BA_FLUSH_STREAM, BA_CHECK_STREAM, +}; +enum mac_type { + WL_MAC_TYPE_PRIMARY_CLIENT, + WL_MAC_TYPE_SECONDARY_CLIENT, + WL_MAC_TYPE_PRIMARY_AP, + WL_MAC_TYPE_SECONDARY_AP, }; /* @@ -196,13 +197,11 @@ enum ba_action_type { */ struct hostcmd_header { - u16 cmd; u16 len; u8 seq_num; u8 macid; u16 result; - } __packed; /* @@ -210,7 +209,6 @@ struct hostcmd_header { */ struct hostcmd_cmd_get_hw_spec { - struct hostcmd_header cmd_hdr; u8 version; /* version of the HW */ u8 host_if; /* host interface */ @@ -225,7 +223,6 @@ struct hostcmd_cmd_get_hw_spec { u32 rxpd_rd_ptr; u32 fw_awake_cookie; u32 wcb_base[SYSADPT_TOTAL_TX_QUEUES - 1]; - } __packed; /* @@ -233,7 +230,6 @@ struct hostcmd_cmd_get_hw_spec { */ struct hostcmd_cmd_set_hw_spec { - struct hostcmd_header cmd_hdr; u8 version; /* HW revision */ u8 host_if; /* Host interface */ @@ -259,7 +255,6 @@ struct hostcmd_cmd_set_hw_spec { u32 reserved: 21; /* Reserved */ u32 tx_wcb_num_per_queue; u32 total_rx_wcb; - } __packed; /* @@ -267,7 +262,6 @@ struct hostcmd_cmd_set_hw_spec { */ struct hostcmd_cmd_802_11_get_stat { - struct hostcmd_header cmd_hdr; u32 tx_retry_successes; u32 tx_multiple_retry_successes; @@ -302,7 +296,6 @@ struct hostcmd_cmd_802_11_get_stat { u32 rx_errors; u32 rx_rts_count; u32 tx_cts_count; - } __packed; /* @@ -310,12 +303,10 @@ struct hostcmd_cmd_802_11_get_stat { */ struct hostcmd_cmd_802_11_radio_control { - struct hostcmd_header cmd_hdr; u16 action; u16 control; /* @bit0: 1/0,on/off, @bit1: 1/0, long/short @bit2: 1/0,auto/fix */ u16 radio_on; - } __packed; /* @@ -323,7 +314,6 @@ struct hostcmd_cmd_802_11_radio_control { */ struct hostcmd_cmd_802_11_tx_power { - struct hostcmd_header cmd_hdr; u16 action; u16 band; @@ -331,7 +321,6 @@ struct hostcmd_cmd_802_11_tx_power { u16 bw; u16 sub_ch; u16 power_level_list[SYSADPT_TX_POWER_LEVEL_TOTAL]; - } __packed; /* @@ -339,11 +328,9 @@ struct hostcmd_cmd_802_11_tx_power { */ struct hostcmd_cmd_802_11_rf_antenna { - struct hostcmd_header cmd_hdr; u16 action; u16 antenna_mode; /* Number of antennas or 0xffff(diversity) */ - } __packed; /* @@ -351,10 +338,8 @@ struct hostcmd_cmd_802_11_rf_antenna { */ struct hostcmd_cmd_broadcast_ssid_enable { - struct hostcmd_header cmd_hdr; u32 enable; - } __packed; /* @@ -362,21 +347,37 @@ struct hostcmd_cmd_broadcast_ssid_enable { */ struct chnl_flags_11ac { - u32 freq_band:6; /* bit0=1: 2.4GHz,bit1=1: 4.9GHz,bit2=1: 5GHz,bit3=1: 5.2GHz, */ u32 chnl_width:5; /* bit6=1:10MHz, bit7=1:20MHz, bit8=1:40MHz */ u32 act_primary:3; /* 000: 1st 20MHz chan, 001:2nd 20MHz chan, 011:3rd 20MHz chan, 100:4th 20MHz chan */ u32 reserved:18; - } __packed; struct hostcmd_cmd_set_rf_channel { - struct hostcmd_header cmd_hdr; u16 action; u8 curr_chnl; struct chnl_flags_11ac chnl_flags; +} __packed; + +/* + * HOSTCMD_CMD_SET_AID + */ + +struct hostcmd_cmd_set_aid { + struct hostcmd_header cmd_hdr; + u16 aid; + u8 mac_addr[ETH_ALEN]; /* AP's Mac Address(BSSID) */ + u32 gprotect; + u8 ap_rates[SYSADPT_MAX_DATA_RATES_G]; +} __packed; +/* + * HOSTCMD_CMD_SET_INFRA_MODE + */ + +struct hostcmd_cmd_set_infra_mode { + struct hostcmd_header cmd_hdr; } __packed; /* @@ -384,11 +385,9 @@ struct hostcmd_cmd_set_rf_channel { */ struct hostcmd_cmd_802_11_rts_thsd { - struct hostcmd_header cmd_hdr; u16 action; u16 threshold; - } __packed; /* @@ -396,7 +395,6 @@ struct hostcmd_cmd_802_11_rts_thsd { */ struct hostcmd_cmd_set_edca_params { - struct hostcmd_header cmd_hdr; u16 action; /* 0 = get all, 0x1 =set CWMin/Max, 0x2 = set TXOP , 0x4 =set AIFSN */ u16 txop; /* in unit of 32 us */ @@ -404,7 +402,6 @@ struct hostcmd_cmd_set_edca_params { u32 cw_min; /* 0~15 */ u8 aifsn; u8 txq_num; /* Tx Queue number. */ - } __packed; /* @@ -412,33 +409,26 @@ struct hostcmd_cmd_set_edca_params { */ struct hostcmd_cmd_set_wmm_mode { - struct hostcmd_header cmd_hdr; u16 action; /* 0->unset, 1->set */ - } __packed; /* * HOSTCMD_CMD_SET_FIXED_RATE */ -struct fix_rate_flag { - /* lower rate after the retry count */ +struct fix_rate_flag { /* lower rate after the retry count */ u32 fix_rate_type; /* 0: legacy, 1: HT */ u32 retry_count_valid; /* 0: retry count is not valid, 1: use retry count specified */ - } __packed; struct fix_rate_entry { - struct fix_rate_flag fix_rate_type_flags; u32 fixed_rate; /* depending on the flags above, this can be either a legacy rate(not index) or an MCS code. */ u32 retry_count; - } __packed; struct hostcmd_cmd_set_fixed_rate { - struct hostcmd_header cmd_hdr; u32 action; /* HOSTCMD_ACT_NOT_USE_FIXED_RATE 0x0002 */ u32 allow_rate_drop; /* use fixed rate specified but firmware can drop to */ @@ -447,7 +437,6 @@ struct hostcmd_cmd_set_fixed_rate { u8 multicast_rate; u8 multi_rate_tx_type; u8 management_rate; - } __packed; /* @@ -455,7 +444,6 @@ struct hostcmd_cmd_set_fixed_rate { */ struct hostcmd_cmd_set_ies { - struct hostcmd_header cmd_hdr; u16 action; /* 0->unset, 1->set */ u16 ie_list_len_ht; @@ -465,7 +453,6 @@ struct hostcmd_cmd_set_ies { u8 ie_list_ht[148]; u8 ie_list_vht[24]; u8 ie_list_proprietary[112]; - } __packed; /* @@ -473,11 +460,19 @@ struct hostcmd_cmd_set_ies { */ struct hostcmd_cmd_set_rate_adapt_mode { - struct hostcmd_header cmd_hdr; u16 action; u16 rate_adapt_mode; /* 0:Indoor, 1:Outdoor */ +} __packed; +/* + * HOSTCMD_CMD_SET_MAC_ADDR, HOSTCMD_CMD_DEL_MAC_ADDR + */ + +struct hostcmd_cmd_set_mac_addr { + struct hostcmd_header cmd_hdr; + u16 mac_type; + u8 mac_addr[ETH_ALEN]; } __packed; /* @@ -485,10 +480,8 @@ struct hostcmd_cmd_set_rate_adapt_mode { */ struct hostcmd_cmd_get_watchdog_bitmap { - struct hostcmd_header cmd_hdr; u8 watchdog_bitmap; /* for SW/BA */ - } __packed; /* @@ -496,10 +489,8 @@ struct hostcmd_cmd_get_watchdog_bitmap { */ struct hostcmd_cmd_bss_start { - struct hostcmd_header cmd_hdr; u32 enable; /* FALSE: Disable or TRUE: Enable */ - } __packed; /* @@ -507,59 +498,46 @@ struct hostcmd_cmd_bss_start { */ struct cf_params { - u8 elem_id; u8 len; u8 cfp_cnt; u8 cfp_period; u16 cfp_max_duration; u16 cfp_duration_remaining; - } __packed; struct ibss_params { - u8 elem_id; u8 len; u16 atim_window; - } __packed; union ss_params { - struct cf_params cf_param_set; struct ibss_params ibss_param_set; - } __packed; struct fh_params { - u8 elem_id; u8 len; u16 dwell_time; u8 hop_set; u8 hop_pattern; u8 hop_index; - } __packed; struct ds_params { - u8 elem_id; u8 len; u8 current_chnl; - } __packed; union phy_params { - struct fh_params fh_param_set; struct ds_params ds_param_set; - } __packed; struct rsn_ie { - u8 elem_id; u8 len; u8 oui_type[4]; /* 00:50:f2:01 */ @@ -569,11 +547,9 @@ struct rsn_ie { u8 pws_key_cipher_list[4]; u8 auth_key_cnt[2]; u8 auth_key_list[4]; - } __packed; struct rsn48_ie { - u8 elem_id; u8 len; u8 ver[2]; @@ -583,35 +559,30 @@ struct rsn48_ie { u8 auth_key_cnt[2]; u8 auth_key_list[4]; u8 rsn_cap[2]; - + u8 pmk_id_cnt[2]; + u8 pmk_id_list[16]; /* Should modify to 16 * S */ + u8 reserved[8]; } __packed; struct aci_aifsn_field { - u8 aifsn:4; u8 acm:1; u8 aci:2; u8 rsvd:1; - } __packed; struct ecw_min_max_field { - u8 ecw_min:4; u8 ecw_max:4; - } __packed; struct ac_param_rcd { - struct aci_aifsn_field aci_aifsn; struct ecw_min_max_field ecw_min_max; u16 txop_lim; - } __packed; struct wmm_param_elem { - u8 elem_id; u8 len; u8 oui[3]; @@ -623,28 +594,22 @@ struct wmm_param_elem { struct ac_param_rcd ac_bk; struct ac_param_rcd ac_vi; struct ac_param_rcd ac_vo; - } __packed; struct channel_info { - u8 first_channel_num; u8 num_channels; u8 max_tx_pwr_level; - } __packed; struct country { - u8 elem_id; u8 len; u8 country_str[3]; struct channel_info channel_info[40]; - } __packetd; struct start_cmd { - u8 sta_mac_addr[ETH_ALEN]; u8 ssid[IEEE80211_MAX_SSID_LEN]; u8 bss_type; @@ -661,14 +626,11 @@ struct start_cmd { struct wmm_param_elem wmm_param; struct country country; u32 ap_rf_type; /* 0->B, 1->G, 2->Mixed, 3->A, 4->11J */ - } __packed; struct hostcmd_cmd_ap_beacon { - struct hostcmd_header cmd_hdr; struct start_cmd start_cmd; - } __packed; /* @@ -676,7 +638,6 @@ struct hostcmd_cmd_ap_beacon { */ struct cap_info { - u16 ess:1; u16 ibss:1; u16 cf_pollable:1; @@ -693,31 +654,25 @@ struct cap_info { u16 dsss_ofdm:1; u16 block_ack:1; u16 rsrvd2:1; - } __packed; struct add_ht_chnl { - u8 ext_chnl_offset:2; u8 sta_chnl_width:1; u8 rifs_mode:1; u8 psmp_stas_only:1; u8 srvc_intvl_gran:3; - } __packed; struct add_ht_op_mode { - u16 op_mode:2; u16 non_gf_sta_present:1; u16 rrans_burst_limit:1; u16 non_ht_sta_present:1; u16 rsrv:11; - } __packed; struct add_ht_stbc { - u16 bsc_stbc:7; u16 dual_stbc_proc:1; u16 scd_bcn:1; @@ -725,20 +680,16 @@ struct add_ht_stbc { u16 pco_active:1; u16 pco_phase:1; u16 rsrv:4; - } __packed; struct add_ht_info { - u8 control_chnl; struct add_ht_chnl add_chnl; struct add_ht_op_mode op_mode; struct add_ht_stbc stbc; - } __packed; struct peer_info { - u32 legacy_rate_bitmap; u8 ht_rates[4]; struct cap_info cap_info; @@ -750,11 +701,9 @@ struct peer_info { u32 vht_max_rx_mcs; u32 vht_cap; u8 vht_rx_channel_width; /* 0:20Mhz, 1:40Mhz, 2:80Mhz, 3:160 or 80+80Mhz */ - } __packed; struct hostcmd_cmd_set_new_stn { - struct hostcmd_header cmd_hdr; u16 aid; u8 mac_addr[ETH_ALEN]; @@ -766,7 +715,6 @@ struct hostcmd_cmd_set_new_stn { u8 qos_info; u8 is_qos_sta; u32 fw_sta_ptr; - } __packed; /* @@ -774,10 +722,8 @@ struct hostcmd_cmd_set_new_stn { */ struct hostcmd_cmd_set_apmode { - struct hostcmd_header cmd_hdr; u8 apmode; - } __packed; /* @@ -785,7 +731,6 @@ struct hostcmd_cmd_set_apmode { */ struct hostcmd_cmd_update_encryptoin { - struct hostcmd_header cmd_hdr; /* Action type - see encr_action_type */ u32 action_type; /* encr_action_type */ @@ -793,25 +738,19 @@ struct hostcmd_cmd_update_encryptoin { u32 data_length; u8 mac_addr[ETH_ALEN]; u8 action_data[1]; - } __packed; struct wep_type_key { - /* WEP key material (max 128bit) */ u8 key_material[MAX_ENCR_KEY_LENGTH]; - } __packed; struct encr_tkip_seqcnt { - u16 low; u32 high; - } __packed; struct tkip_type_key { - /* TKIP Key material. Key type (group or pairwise key) is determined by flags */ /* in KEY_PARAM_SET structure. */ u8 key_material[MAX_ENCR_KEY_LENGTH]; @@ -820,26 +759,20 @@ struct tkip_type_key { u8 tkip_rx_mic_key[MIC_KEY_LENGTH]; struct encr_tkip_seqcnt tkip_rsc; struct encr_tkip_seqcnt tkip_tsc; - } __packed; struct aes_type_key { - /* AES Key material */ u8 key_material[MAX_ENCR_KEY_LENGTH]; - } __packed; union mwl_key_type { - struct wep_type_key wep_key; struct tkip_type_key tkip_key; struct aes_type_key aes_key; - } __packed; struct key_param_set { - /* Total length of this structure (Key is variable size array) */ u16 length; /* Key type - WEP, TKIP or AES-CCMP. */ @@ -854,11 +787,9 @@ struct key_param_set { /* Key material (variable size array) */ union mwl_key_type key; u8 mac_addr[ETH_ALEN]; - } __packed; struct hostcmd_cmd_set_key { - struct hostcmd_header cmd_hdr; /* Action type - see encr_action_type */ u32 action_type; /* encr_action_type */ @@ -866,7 +797,6 @@ struct hostcmd_cmd_set_key { u32 data_length; /* data buffer - maps to one KEY_PARAM_SET structure */ struct key_param_set key_param; - } __packed; /* @@ -874,17 +804,13 @@ struct hostcmd_cmd_set_key { */ struct ba_stream_flags { - u32 ba_type:1; u32 ba_direction:3; u32 reserved:24; - } __packed; struct ba_context { - u32 context; - } __packed; /* parameters for block ack creation */ @@ -912,32 +838,26 @@ struct create_ba_params { u8 reset_seq_no; /** 0 or 1**/ u16 current_seq; u8 sta_src_mac_addr[ETH_ALEN]; /* This is for virtual station in Sta proxy mode for V6FW */ - } __packed; /* new transmit sequence number information */ struct ba_update_seq_num { - /* BA flags - see above */ struct ba_stream_flags flags; /* returned by firmware in the create ba stream response */ struct ba_context fw_ba_context; /* new sequence number for this block ack stream */ u16 ba_seq_num; - } __packed; struct ba_stream_context { - /* BA Stream flags */ struct ba_stream_flags flags; /* returned by firmware in the create ba stream response */ struct ba_context fw_ba_context; - } __packed; union ba_info { - /* information required to create BA Stream... */ struct create_ba_params create_params; /* update starting/new sequence number etc. */ @@ -946,15 +866,12 @@ union ba_info { struct ba_stream_context destroy_params; /* destroy an existing stream... */ struct ba_stream_context flush_params; - } __packed; struct hostcmd_cmd_bastream { - struct hostcmd_header cmd_hdr; u32 action_type; union ba_info ba_info; - } __packed; /* @@ -962,10 +879,8 @@ struct hostcmd_cmd_bastream { */ struct hostcmd_cmd_dwds_enable { - struct hostcmd_header cmd_hdr; u32 enable; /* 0 -- Disable. or 1 -- Enable. */ - } __packed; /* @@ -973,10 +888,8 @@ struct hostcmd_cmd_dwds_enable { */ struct hostcmd_cmd_fw_flush_timer { - struct hostcmd_header cmd_hdr; u32 value; /* 0 -- Disable. > 0 -- holds time value in usecs. */ - } __packed; /* @@ -984,10 +897,8 @@ struct hostcmd_cmd_fw_flush_timer { */ struct hostcmd_cmd_set_cdd { - struct hostcmd_header cmd_hdr; u32 enable; - } __packed; /* PRIVATE FUNCTION DECLARATION @@ -1030,7 +941,6 @@ void mwl_fwcmd_reset(struct ieee80211_hw *hw) BUG_ON(!priv); if (mwl_fwcmd_chk_adapter(priv)) { - writel(ISR_RESET, priv->iobase1 + MACREG_REG_H2A_INTERRUPT_EVENTS); } @@ -1048,9 +958,7 @@ void mwl_fwcmd_int_enable(struct ieee80211_hw *hw) BUG_ON(!priv); if (mwl_fwcmd_chk_adapter(priv)) { - writel(0x00, priv->iobase1 + MACREG_REG_A2H_INTERRUPT_MASK); - writel((MACREG_A2HRIC_BIT_MASK), priv->iobase1 + MACREG_REG_A2H_INTERRUPT_MASK); } @@ -1069,7 +977,6 @@ void mwl_fwcmd_int_disable(struct ieee80211_hw *hw) BUG_ON(!priv); if (mwl_fwcmd_chk_adapter(priv)) { - writel(0x00, priv->iobase1 + MACREG_REG_A2H_INTERRUPT_MASK); } @@ -1103,7 +1010,6 @@ int mwl_fwcmd_get_hw_specs(struct ieee80211_hw *hw) WLDBG_DUMP_DATA(DBG_LEVEL_2, (void *)pcmd, sizeof(*pcmd)); while (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_GET_HW_SPEC)) { - WLDBG_PRINT("failed execution"); WL_MSEC_SLEEP(1000); WLDBG_PRINT("repeat command = %x", (unsigned int)pcmd); @@ -1178,7 +1084,6 @@ int mwl_fwcmd_set_hw_specs(struct ieee80211_hw *hw) pcmd->disablembss = 0; if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_HW_SPEC)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; @@ -1212,7 +1117,6 @@ int mwl_fwcmd_get_stat(struct ieee80211_hw *hw, pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_802_11_GET_STAT)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; @@ -1306,7 +1210,6 @@ int mwl_fwcmd_max_tx_power(struct ieee80211_hw *hw, BUG_ON(!priv); switch (fraction) { - case 0: reduce_val = 0; /* Max */ break; @@ -1331,23 +1234,17 @@ int mwl_fwcmd_max_tx_power(struct ieee80211_hw *hw, if ((conf->chandef.width == NL80211_CHAN_WIDTH_20_NOHT) || (conf->chandef.width == NL80211_CHAN_WIDTH_20)) { - width = CH_20_MHz_WIDTH; sub_ch = NO_EXT_CHANNEL; } else if (conf->chandef.width == NL80211_CHAN_WIDTH_40) { - width = CH_40_MHz_WIDTH; - if (conf->chandef.center_freq1 > channel->center_freq) sub_ch = EXT_CH_ABOVE_CTRL_CH; else sub_ch = EXT_CH_BELOW_CTRL_CH; - } else if (conf->chandef.width == NL80211_CHAN_WIDTH_80) { - width = CH_80_MHz_WIDTH; - if (conf->chandef.center_freq1 > channel->center_freq) sub_ch = EXT_CH_ABOVE_CTRL_CH; else @@ -1355,28 +1252,22 @@ int mwl_fwcmd_max_tx_power(struct ieee80211_hw *hw, } if ((priv->powinited & 2) == 0) { - mwl_fwcmd_get_tx_powers(priv, priv->max_tx_pow, channel->hw_value, band, width, sub_ch); - priv->powinited |= 2; } if ((priv->powinited & 1) == 0) { - mwl_fwcmd_get_tx_powers(priv, priv->target_powers, channel->hw_value, band, width, sub_ch); - priv->powinited |= 1; } for (i = 0; i < SYSADPT_TX_POWER_LEVEL_TOTAL; i++) { - if (priv->target_powers[i] > priv->max_tx_pow[i]) tmp = priv->max_tx_pow[i]; else tmp = priv->target_powers[i]; - maxtxpow[i] = ((tmp - reduce_val) > 0) ? (tmp - reduce_val) : 0; } @@ -1407,7 +1298,6 @@ int mwl_fwcmd_tx_power(struct ieee80211_hw *hw, BUG_ON(!priv); switch (fraction) { - case 0: reduce_val = 0; /* Max */ break; @@ -1432,23 +1322,16 @@ int mwl_fwcmd_tx_power(struct ieee80211_hw *hw, if ((conf->chandef.width == NL80211_CHAN_WIDTH_20_NOHT) || (conf->chandef.width == NL80211_CHAN_WIDTH_20)) { - width = CH_20_MHz_WIDTH; sub_ch = NO_EXT_CHANNEL; - } else if (conf->chandef.width == NL80211_CHAN_WIDTH_40) { - width = CH_40_MHz_WIDTH; - if (conf->chandef.center_freq1 > channel->center_freq) sub_ch = EXT_CH_ABOVE_CTRL_CH; else sub_ch = EXT_CH_BELOW_CTRL_CH; - } else if (conf->chandef.width == NL80211_CHAN_WIDTH_80) { - width = CH_80_MHz_WIDTH; - if (conf->chandef.center_freq1 > channel->center_freq) sub_ch = EXT_CH_ABOVE_CTRL_CH; else @@ -1458,14 +1341,12 @@ int mwl_fwcmd_tx_power(struct ieee80211_hw *hw, /* search tx power table if exist */ for (index = 0; index < SYSADPT_MAX_NUM_CHANNELS; index++) { - /* do nothing if table is not loaded */ if (priv->tx_pwr_tbl[index].channel == 0) break; if (priv->tx_pwr_tbl[index].channel == channel->hw_value) { - priv->cdd = priv->tx_pwr_tbl[index].cdd; priv->txantenna2 = priv->tx_pwr_tbl[index].txantenna2; @@ -1475,7 +1356,6 @@ int mwl_fwcmd_tx_power(struct ieee80211_hw *hw, priv->powinited = 0x02; for (i = 0; i < SYSADPT_TX_POWER_LEVEL_TOTAL; i++) { - if (priv->tx_pwr_tbl[index].setcap) priv->max_tx_pow[i] = priv->tx_pwr_tbl[index].tx_power[i]; else @@ -1488,7 +1368,6 @@ int mwl_fwcmd_tx_power(struct ieee80211_hw *hw, } if ((priv->powinited & 2) == 0) { - mwl_fwcmd_get_tx_powers(priv, priv->max_tx_pow, channel->hw_value, band, width, sub_ch); @@ -1496,7 +1375,6 @@ int mwl_fwcmd_tx_power(struct ieee80211_hw *hw, } if ((priv->powinited & 1) == 0) { - mwl_fwcmd_get_tx_powers(priv, priv->target_powers, channel->hw_value, band, width, sub_ch); @@ -1504,17 +1382,13 @@ int mwl_fwcmd_tx_power(struct ieee80211_hw *hw, } for (i = 0; i < SYSADPT_TX_POWER_LEVEL_TOTAL; i++) { - if (found) { - if ((priv->tx_pwr_tbl[index].setcap) && (priv->tx_pwr_tbl[index].tx_power[i] > priv->max_tx_pow[i])) tmp = priv->max_tx_pow[i]; else tmp = priv->tx_pwr_tbl[index].tx_power[i]; - } else { - if (priv->target_powers[i] > priv->max_tx_pow[i]) tmp = priv->max_tx_pow[i]; else @@ -1555,29 +1429,24 @@ int mwl_fwcmd_rf_antenna(struct ieee80211_hw *hw, int dir, int antenna) pcmd->action = ENDIAN_SWAP16(dir); if (dir == WL_ANTENNATYPE_RX) { - u8 rx_antenna = 4; /* if auto, set 4 rx antennas in SC2 */ - + if (antenna != 0) pcmd->antenna_mode = ENDIAN_SWAP16(antenna); else pcmd->antenna_mode = ENDIAN_SWAP16(rx_antenna); - } else { - u8 tx_antenna = 0xf; /* if auto, set 4 tx antennas in SC2 */ if (antenna != 0) pcmd->antenna_mode = ENDIAN_SWAP16(antenna); else pcmd->antenna_mode = ENDIAN_SWAP16(tx_antenna); - } WLDBG_DUMP_DATA(DBG_LEVEL_2, (void *)pcmd, sizeof(*pcmd)); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_802_11_RF_ANTENNA)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; @@ -1618,7 +1487,6 @@ int mwl_fwcmd_broadcast_ssid_enable(struct ieee80211_hw *hw, pcmd->enable = ENDIAN_SWAP32(enable); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_BROADCAST_SSID_ENABLE)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; @@ -1661,31 +1529,103 @@ int mwl_fwcmd_set_rf_channel(struct ieee80211_hw *hw, if ((conf->chandef.width == NL80211_CHAN_WIDTH_20_NOHT) || (conf->chandef.width == NL80211_CHAN_WIDTH_20)) { - pcmd->chnl_flags.chnl_width = CH_20_MHz_WIDTH; pcmd->chnl_flags.act_primary = ACT_PRIMARY_CHAN_0; - } else if (conf->chandef.width == NL80211_CHAN_WIDTH_40) { - pcmd->chnl_flags.chnl_width = CH_40_MHz_WIDTH; - if (conf->chandef.center_freq1 > channel->center_freq) pcmd->chnl_flags.act_primary = ACT_PRIMARY_CHAN_0; else pcmd->chnl_flags.act_primary = ACT_PRIMARY_CHAN_1; - } else if (conf->chandef.width == NL80211_CHAN_WIDTH_80) { - pcmd->chnl_flags.chnl_width = CH_80_MHz_WIDTH; pcmd->chnl_flags.act_primary = mwl_fwcmd_get_80m_pri_chnl_offset(pcmd->curr_chnl); - } WLDBG_DUMP_DATA(DBG_LEVEL_2, (void *)pcmd, sizeof(*pcmd)); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_RF_CHANNEL)) { + MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); + WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + return -EIO; + } + + MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); + WLDBG_EXIT(DBG_LEVEL_2); + + return 0; +} + +int mwl_fwcmd_set_aid(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u8 *bssid, u16 aid) +{ + struct mwl_priv *priv; + struct mwl_vif *mwl_vif; + struct hostcmd_cmd_set_aid *pcmd; + unsigned long flags; + + WLDBG_ENTER(DBG_LEVEL_2); + + BUG_ON(!hw); + priv = hw->priv; + BUG_ON(!priv); + + BUG_ON(!vif); + mwl_vif = MWL_VIF(vif); + BUG_ON(!mwl_vif); + pcmd = (struct hostcmd_cmd_set_aid *)&priv->pcmd_buf[0]; + + MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + + memset(pcmd, 0x00, sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_SET_AID); + pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); + pcmd->cmd_hdr.macid = mwl_vif->macid; + pcmd->aid = ENDIAN_SWAP16(aid); + memcpy(pcmd->mac_addr, bssid, ETH_ALEN); + + if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_AID)) { + MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); + WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + return -EIO; + } + + MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); + WLDBG_EXIT(DBG_LEVEL_2); + + return 0; +} + +int mwl_fwcmd_set_infra_mode(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct mwl_priv *priv; + struct mwl_vif *mwl_vif; + struct hostcmd_cmd_set_infra_mode *pcmd; + unsigned long flags; + + WLDBG_ENTER(DBG_LEVEL_2); + + BUG_ON(!hw); + priv = hw->priv; + BUG_ON(!priv); + + BUG_ON(!vif); + mwl_vif = MWL_VIF(vif); + BUG_ON(!mwl_vif); + + pcmd = (struct hostcmd_cmd_set_infra_mode *)&priv->pcmd_buf[0]; + + MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + + memset(pcmd, 0x00, sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_SET_INFRA_MODE); + pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); + pcmd->cmd_hdr.macid = mwl_vif->macid; + + if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_INFRA_MODE)) { MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; @@ -1720,7 +1660,6 @@ int mwl_fwcmd_set_rts_threshold(struct ieee80211_hw *hw, int threshold) pcmd->threshold = ENDIAN_SWAP16(threshold); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_802_11_RTS_THSD)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; @@ -1772,7 +1711,6 @@ int mwl_fwcmd_set_edca_params(struct ieee80211_hw *hw, u8 index, WLDBG_DUMP_DATA(DBG_LEVEL_2, (void *)pcmd, sizeof(*pcmd)); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_EDCA_PARAMS)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; @@ -1806,7 +1744,6 @@ int mwl_fwcmd_set_wmm_mode(struct ieee80211_hw *hw, bool enable) pcmd->action = ENDIAN_SWAP16(enable ? WL_ENABLE : WL_DISABLE); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_WMM_MODE)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; @@ -1843,7 +1780,6 @@ int mwl_fwcmd_use_fixed_rate(struct ieee80211_hw *hw, int mcast, int mgmt) pcmd->management_rate = mgmt; if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_FIXED_RATE)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; @@ -1878,7 +1814,47 @@ int mwl_fwcmd_set_rate_adapt_mode(struct ieee80211_hw *hw, u16 mode) pcmd->rate_adapt_mode = ENDIAN_SWAP16(mode); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_RATE_ADAPT_MODE)) { + MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); + WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + return -EIO; + } + + MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); + WLDBG_EXIT(DBG_LEVEL_2); + + return 0; +} + +int mwl_fwcmd_set_mac_addr_client(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u8 *mac_addr) +{ + struct mwl_priv *priv; + struct mwl_vif *mwl_vif; + struct hostcmd_cmd_set_mac_addr *pcmd; + unsigned long flags; + + WLDBG_ENTER(DBG_LEVEL_2); + + BUG_ON(!hw); + priv = hw->priv; + BUG_ON(!priv); + + BUG_ON(!vif); + mwl_vif = MWL_VIF(vif); + BUG_ON(!mwl_vif); + + pcmd = (struct hostcmd_cmd_set_mac_addr *)&priv->pcmd_buf[0]; + MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + + memset(pcmd, 0x00, sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_SET_MAC_ADDR); + pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); + pcmd->cmd_hdr.macid = mwl_vif->macid; + pcmd->mac_type = WL_MAC_TYPE_SECONDARY_CLIENT; + memcpy(pcmd->mac_addr, mac_addr, ETH_ALEN); + + if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_MAC_ADDR)) { MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; @@ -1911,7 +1887,6 @@ int mwl_fwcmd_get_watchdog_bitmap(struct ieee80211_hw *hw, u8 *bitmap) pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_GET_WATCHDOG_BITMAP)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; @@ -1925,6 +1900,46 @@ int mwl_fwcmd_get_watchdog_bitmap(struct ieee80211_hw *hw, u8 *bitmap) return 0; } +int mwl_fwcmd_remove_mac_addr(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u8 *mac_addr) +{ + struct mwl_priv *priv; + struct mwl_vif *mwl_vif; + struct hostcmd_cmd_set_mac_addr *pcmd; + unsigned long flags; + + WLDBG_ENTER(DBG_LEVEL_2); + + BUG_ON(!hw); + priv = hw->priv; + BUG_ON(!priv); + + BUG_ON(!vif); + mwl_vif = MWL_VIF(vif); + BUG_ON(!mwl_vif); + + pcmd = (struct hostcmd_cmd_set_mac_addr *)&priv->pcmd_buf[0]; + + MWL_SPIN_LOCK(&priv->locks.fwcmd_lock); + + memset(pcmd, 0x00, sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = ENDIAN_SWAP16(HOSTCMD_CMD_DEL_MAC_ADDR); + pcmd->cmd_hdr.len = ENDIAN_SWAP16(sizeof(*pcmd)); + pcmd->cmd_hdr.macid = mwl_vif->macid; + memcpy(pcmd->mac_addr, mac_addr, ETH_ALEN); + + if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_DEL_MAC_ADDR)) { + MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); + WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + return -EIO; + } + + MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); + WLDBG_EXIT(DBG_LEVEL_2); + + return 0; +} + int mwl_fwcmd_bss_start(struct ieee80211_hw *hw, struct ieee80211_vif *vif, bool enable) { @@ -1959,20 +1974,15 @@ int mwl_fwcmd_bss_start(struct ieee80211_hw *hw, pcmd->cmd_hdr.macid = mwl_vif->macid; if (enable) { - pcmd->enable = ENDIAN_SWAP32(WL_ENABLE); - } else { - if (mwl_vif->macid == 0) pcmd->enable = ENDIAN_SWAP32(WL_DISABLE); else pcmd->enable = ENDIAN_SWAP32(WL_DISABLE_VMAC); - } if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_BSS_START)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; @@ -2030,7 +2040,7 @@ err: int mwl_fwcmd_set_new_stn_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct ieee80211_sta *sta) { struct mwl_priv *priv; struct mwl_vif *mwl_vif; @@ -2060,9 +2070,14 @@ int mwl_fwcmd_set_new_stn_add(struct ieee80211_hw *hw, pcmd->cmd_hdr.macid = mwl_vif->macid; pcmd->action = ENDIAN_SWAP16(HOSTCMD_ACT_STA_ACTION_ADD); - pcmd->aid = ENDIAN_SWAP16(sta->aid); + if (mwl_vif->is_sta == true) { + pcmd->aid = 0; + pcmd->stn_id = 0; + } else { + pcmd->aid = ENDIAN_SWAP16(sta->aid); + pcmd->stn_id = ENDIAN_SWAP16(sta->aid); + } memcpy(pcmd->mac_addr, sta->addr, ETH_ALEN); - pcmd->stn_id = ENDIAN_SWAP16(sta->aid); if (hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) rates = sta->supp_rates[IEEE80211_BAND_2GHZ]; @@ -2071,7 +2086,6 @@ int mwl_fwcmd_set_new_stn_add(struct ieee80211_hw *hw, pcmd->peer_info.legacy_rate_bitmap = ENDIAN_SWAP32(rates); if (sta->ht_cap.ht_supported) { - pcmd->peer_info.ht_rates[0] = sta->ht_cap.mcs.rx_mask[0]; pcmd->peer_info.ht_rates[1] = sta->ht_cap.mcs.rx_mask[1]; pcmd->peer_info.ht_rates[2] = sta->ht_cap.mcs.rx_mask[2]; @@ -2082,7 +2096,6 @@ int mwl_fwcmd_set_new_stn_add(struct ieee80211_hw *hw, } if (sta->vht_cap.vht_supported) { - pcmd->peer_info.vht_max_rx_mcs = ENDIAN_SWAP32(*((u32 *)&sta->vht_cap.vht_mcs.rx_mcs_map)); pcmd->peer_info.vht_cap = ENDIAN_SWAP32(sta->vht_cap.cap); pcmd->peer_info.vht_rx_channel_width = sta->bandwidth; @@ -2092,12 +2105,21 @@ int mwl_fwcmd_set_new_stn_add(struct ieee80211_hw *hw, pcmd->qos_info = ((sta->uapsd_queues << 4) | (sta->max_sp << 1)); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_NEW_STN)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; } + if (mwl_vif->is_sta == true) { + memcpy(pcmd->mac_addr, mwl_vif->sta_mac, ETH_ALEN); + + if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_NEW_STN)) { + MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); + WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + return -EIO; + } + } + MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT(DBG_LEVEL_2); @@ -2135,7 +2157,6 @@ int mwl_fwcmd_set_new_stn_add_self(struct ieee80211_hw *hw, memcpy(pcmd->mac_addr, vif->addr, ETH_ALEN); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_NEW_STN)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; @@ -2178,12 +2199,21 @@ int mwl_fwcmd_set_new_stn_del(struct ieee80211_hw *hw, memcpy(pcmd->mac_addr, addr, ETH_ALEN); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_NEW_STN)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; } + if (mwl_vif->is_sta == true) { + memcpy(pcmd->mac_addr, mwl_vif->sta_mac, ETH_ALEN); + + if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_NEW_STN)) { + MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); + WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + return -EIO; + } + } + MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT(DBG_LEVEL_2); @@ -2212,7 +2242,6 @@ int mwl_fwcmd_set_apmode(struct ieee80211_hw *hw, u8 apmode) pcmd->apmode = apmode; if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_APMODE)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; @@ -2256,12 +2285,24 @@ int mwl_fwcmd_update_encryption_enable(struct ieee80211_hw *hw, pcmd->action_data[0] = encr_type; if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_UPDATE_ENCRYPTION)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; } + if (mwl_vif->is_sta == true) { + if (memcmp(mwl_vif->bssid, addr, ETH_ALEN) == 0) + memcpy(pcmd->mac_addr, mwl_vif->sta_mac, ETH_ALEN); + else + memcpy(pcmd->mac_addr, mwl_vif->bssid, ETH_ALEN); + + if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_UPDATE_ENCRYPTION)) { + MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); + WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + return -EIO; + } + } + MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT(DBG_LEVEL_2); @@ -2270,7 +2311,7 @@ int mwl_fwcmd_update_encryption_enable(struct ieee80211_hw *hw, int mwl_fwcmd_encryption_set_key(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u8 *addr, - struct ieee80211_key_conf *key) + struct ieee80211_key_conf *key) { struct mwl_priv *priv; struct mwl_vif *mwl_vif; @@ -2302,7 +2343,6 @@ int mwl_fwcmd_encryption_set_key(struct ieee80211_hw *hw, rc = mwl_fwcmd_encryption_set_cmd_info(pcmd, addr, key); if (rc) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "encryption not support"); return rc; @@ -2316,12 +2356,9 @@ int mwl_fwcmd_encryption_set_key(struct ieee80211_hw *hw, action = ENCR_ACTION_TYPE_SET_GROUP_KEY; switch (key->cipher) { - case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: - if (!mwl_vif->wep_key_conf[idx].enabled) { - memcpy(mwl_vif->wep_key_conf[idx].key, key, sizeof(*key) + key->keylen); mwl_vif->wep_key_conf[idx].enabled = 1; @@ -2330,19 +2367,13 @@ int mwl_fwcmd_encryption_set_key(struct ieee80211_hw *hw, keymlen = key->keylen; action = ENCR_ACTION_TYPE_SET_KEY; break; - case WLAN_CIPHER_SUITE_TKIP: - keymlen = MAX_ENCR_KEY_LENGTH + 2 * MIC_KEY_LENGTH; break; - case WLAN_CIPHER_SUITE_CCMP: - keymlen = key->keylen; break; - default: - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "encryption not support"); return -ENOTSUPP; @@ -2352,12 +2383,24 @@ int mwl_fwcmd_encryption_set_key(struct ieee80211_hw *hw, pcmd->action_type = ENDIAN_SWAP32(action); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_UPDATE_ENCRYPTION)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; } + if (mwl_vif->is_sta == true) { + if (memcmp(mwl_vif->bssid, addr, ETH_ALEN) == 0) + memcpy(pcmd->key_param.mac_addr, mwl_vif->sta_mac, ETH_ALEN); + else + memcpy(pcmd->key_param.mac_addr, mwl_vif->bssid, ETH_ALEN); + + if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_UPDATE_ENCRYPTION)) { + MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); + WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); + return -EIO; + } + } + MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT(DBG_LEVEL_2); @@ -2366,7 +2409,7 @@ int mwl_fwcmd_encryption_set_key(struct ieee80211_hw *hw, int mwl_fwcmd_encryption_remove_key(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u8 *addr, - struct ieee80211_key_conf *key) + struct ieee80211_key_conf *key) { struct mwl_priv *priv; struct mwl_vif *mwl_vif; @@ -2395,7 +2438,6 @@ int mwl_fwcmd_encryption_remove_key(struct ieee80211_hw *hw, rc = mwl_fwcmd_encryption_set_cmd_info(pcmd, addr, key); if (rc) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "encryption not support"); return rc; @@ -2408,7 +2450,6 @@ int mwl_fwcmd_encryption_remove_key(struct ieee80211_hw *hw, mwl_vif->wep_key_conf[key->keyidx].enabled = 0; if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_UPDATE_ENCRYPTION)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; @@ -2422,7 +2463,7 @@ int mwl_fwcmd_encryption_remove_key(struct ieee80211_hw *hw, int mwl_fwcmd_check_ba(struct ieee80211_hw *hw, struct mwl_ampdu_stream *stream, - struct ieee80211_vif *vif) + struct ieee80211_vif *vif) { struct mwl_priv *priv; struct mwl_vif *mwl_vif; @@ -2464,14 +2505,12 @@ int mwl_fwcmd_check_ba(struct ieee80211_hw *hw, WLDBG_DUMP_DATA(DBG_LEVEL_2, (void *)pcmd, sizeof(*pcmd)); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_BASTREAM)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; } if (pcmd->cmd_hdr.result != 0) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "result error"); return -EINVAL; @@ -2485,7 +2524,7 @@ int mwl_fwcmd_check_ba(struct ieee80211_hw *hw, int mwl_fwcmd_create_ba(struct ieee80211_hw *hw, struct mwl_ampdu_stream *stream, - u8 buf_size, struct ieee80211_vif *vif) + u8 buf_size, struct ieee80211_vif *vif) { struct mwl_priv *priv; struct mwl_vif *mwl_vif; @@ -2536,14 +2575,12 @@ int mwl_fwcmd_create_ba(struct ieee80211_hw *hw, WLDBG_DUMP_DATA(DBG_LEVEL_2, (void *)pcmd, sizeof(*pcmd)); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_BASTREAM)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; } if (pcmd->cmd_hdr.result != 0) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "result error"); return -EINVAL; @@ -2558,7 +2595,6 @@ int mwl_fwcmd_create_ba(struct ieee80211_hw *hw, int mwl_fwcmd_destroy_ba(struct ieee80211_hw *hw, u8 idx) { - struct mwl_priv *priv; struct hostcmd_cmd_bastream *pcmd; unsigned long flags; @@ -2585,7 +2621,6 @@ int mwl_fwcmd_destroy_ba(struct ieee80211_hw *hw, pcmd->ba_info.destroy_params.fw_ba_context.context = ENDIAN_SWAP32(idx); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_BASTREAM)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; @@ -2613,11 +2648,9 @@ struct mwl_ampdu_stream *mwl_fwcmd_add_stream(struct ieee80211_hw *hw, BUG_ON(!sta); for (i = 0; i < SYSADPT_TX_AMPDU_QUEUES; i++) { - stream = &priv->ampdu[i]; if (stream->state == AMPDU_NO_STREAM) { - stream->sta = sta; stream->state = AMPDU_STREAM_NEW; stream->tid = tid; @@ -2664,7 +2697,6 @@ struct mwl_ampdu_stream *mwl_fwcmd_lookup_stream(struct ieee80211_hw *hw, BUG_ON(!priv); for (i = 0; i < SYSADPT_TX_AMPDU_QUEUES; i++) { - stream = &priv->ampdu[i]; if (stream->state == AMPDU_NO_STREAM) @@ -2673,7 +2705,6 @@ struct mwl_ampdu_stream *mwl_fwcmd_lookup_stream(struct ieee80211_hw *hw, if (!memcmp(stream->sta->addr, addr, ETH_ALEN) && stream->tid == tid) return stream; - } return NULL; @@ -2718,7 +2749,6 @@ int mwl_fwcmd_set_dwds_stamode(struct ieee80211_hw *hw, bool enable) pcmd->enable = ENDIAN_SWAP32(enable); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_DWDS_ENABLE)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; @@ -2752,7 +2782,6 @@ int mwl_fwcmd_set_fw_flush_timer(struct ieee80211_hw *hw, u32 value) pcmd->value = ENDIAN_SWAP32(value); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_FW_FLUSH_TIMER)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; @@ -2786,7 +2815,6 @@ int mwl_fwcmd_set_cdd(struct ieee80211_hw *hw) pcmd->enable = ENDIAN_SWAP32(priv->cdd); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_CDD)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; @@ -2812,7 +2840,6 @@ static bool mwl_fwcmd_chk_adapter(struct mwl_priv *priv) regval = readl(priv->iobase1 + MACREG_REG_INT_CODE); if (regval == 0xffffffff) { - WLDBG_ERROR(DBG_LEVEL_2, "adapter is not existed"); WLDBG_EXIT_INFO(DBG_LEVEL_2, "adapter is not existed"); @@ -2833,7 +2860,6 @@ static int mwl_fwcmd_exec_cmd(struct mwl_priv *priv, unsigned short cmd) BUG_ON(!priv); if (!mwl_fwcmd_chk_adapter(priv)) { - WLDBG_ERROR(DBG_LEVEL_2, "no adapter existed"); WLDBG_EXIT_INFO(DBG_LEVEL_2, "no adapter plugged in"); priv->in_send_cmd = false; @@ -2841,21 +2867,15 @@ static int mwl_fwcmd_exec_cmd(struct mwl_priv *priv, unsigned short cmd) } if (!priv->in_send_cmd) { - priv->in_send_cmd = true; - mwl_fwcmd_send_cmd(priv); - if (mwl_fwcmd_wait_complete(priv, 0x8000 | cmd)) { - WLDBG_ERROR(DBG_LEVEL_2, "timeout"); WLDBG_EXIT_INFO(DBG_LEVEL_2, "timeout"); priv->in_send_cmd = false; return -EIO; } - } else { - WLDBG_WARNING(DBG_LEVEL_2, "previous command is still running"); busy = true; } @@ -2891,19 +2911,14 @@ static int mwl_fwcmd_wait_complete(struct mwl_priv *priv, unsigned short cmd) BUG_ON(!priv); do { - int_code = ENDIAN_SWAP16(priv->pcmd_buf[0]); WL_MSEC_SLEEP(1); - } while ((int_code != cmd) && (--curr_iteration)); - if (curr_iteration == 0) - { + if (curr_iteration == 0) { WLDBG_ERROR(DBG_LEVEL_2, "cmd 0x%04x=%s timed out", cmd, mwl_fwcmd_get_cmd_string(cmd)); - WLDBG_EXIT_INFO(DBG_LEVEL_2, "timeout"); - return -EIO; } @@ -2941,7 +2956,6 @@ static int mwl_fwcmd_802_11_radio_control(struct mwl_priv *priv, bool enable, bo WLDBG_DUMP_DATA(DBG_LEVEL_2, (void *)pcmd, sizeof(*pcmd)); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_802_11_RADIO_CONTROL)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; @@ -2980,7 +2994,6 @@ static int mwl_fwcmd_get_tx_powers(struct mwl_priv *priv, u16 *powlist, u16 ch, pcmd->sub_ch = ENDIAN_SWAP16(sub_ch); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_802_11_TX_POWER)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; @@ -3023,7 +3036,6 @@ static int mwl_fwcmd_set_tx_powers(struct mwl_priv *priv, u16 txpow[], u8 action pcmd->power_level_list[i] = ENDIAN_SWAP16(txpow[i]); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_802_11_TX_POWER)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; @@ -3040,7 +3052,6 @@ static u8 mwl_fwcmd_get_80m_pri_chnl_offset(u8 channel) u8 act_primary = ACT_PRIMARY_CHAN_0; switch (channel) { - case 36: act_primary = ACT_PRIMARY_CHAN_0; break; @@ -3053,7 +3064,6 @@ static u8 mwl_fwcmd_get_80m_pri_chnl_offset(u8 channel) case 48: act_primary = ACT_PRIMARY_CHAN_3; break; - case 52: act_primary = ACT_PRIMARY_CHAN_0; break; @@ -3066,7 +3076,6 @@ static u8 mwl_fwcmd_get_80m_pri_chnl_offset(u8 channel) case 64: act_primary = ACT_PRIMARY_CHAN_3; break; - case 100: act_primary = ACT_PRIMARY_CHAN_0; break; @@ -3079,7 +3088,6 @@ static u8 mwl_fwcmd_get_80m_pri_chnl_offset(u8 channel) case 112: act_primary = ACT_PRIMARY_CHAN_3; break; - case 116: act_primary = ACT_PRIMARY_CHAN_0; break; @@ -3092,7 +3100,6 @@ static u8 mwl_fwcmd_get_80m_pri_chnl_offset(u8 channel) case 128: act_primary = ACT_PRIMARY_CHAN_3; break; - case 132: act_primary = ACT_PRIMARY_CHAN_0; break; @@ -3105,7 +3112,6 @@ static u8 mwl_fwcmd_get_80m_pri_chnl_offset(u8 channel) case 144: act_primary = ACT_PRIMARY_CHAN_3; break; - case 149: act_primary = ACT_PRIMARY_CHAN_0; break; @@ -3158,7 +3164,6 @@ static void mwl_fwcmd_parse_beacon(struct mwl_priv *priv, elem_parse_failed = false; while (left >= 2) { - u8 id, elen; id = *pos++; @@ -3166,13 +3171,11 @@ static void mwl_fwcmd_parse_beacon(struct mwl_priv *priv, left -= 2; if (elen > left) { - elem_parse_failed = true; break; } switch (id) { - case WLAN_EID_SUPP_RATES: case WLAN_EID_EXT_SUPP_RATES: { @@ -3180,23 +3183,19 @@ static void mwl_fwcmd_parse_beacon(struct mwl_priv *priv, u8 rate; for (basic_idx = 0; basic_idx < SYSADPT_MAX_DATA_RATES_G; basic_idx++) { - if (beacon_info->bss_basic_rate_set[basic_idx] == 0) break; } for (oprate_idx = 0; oprate_idx < SYSADPT_MAX_DATA_RATES_G; oprate_idx++) { - if (beacon_info->op_rate_set[oprate_idx] == 0) break; } for (idx = 0; idx < elen; idx++) { - rate = pos[idx]; if ((rate & 0x80) != 0) { - if (basic_idx < SYSADPT_MAX_DATA_RATES_G) beacon_info->bss_basic_rate_set[basic_idx++] = rate & 0x7f; else { @@ -3214,12 +3213,10 @@ static void mwl_fwcmd_parse_beacon(struct mwl_priv *priv, } } break; - case WLAN_EID_RSN: beacon_info->ie_rsn48_len = (elen + 2); beacon_info->ie_rsn48_ptr = (pos - 2); break; - case WLAN_EID_HT_CAPABILITY: case WLAN_EID_HT_OPERATION: case WLAN_EID_OVERLAP_BSS_SCAN_PARAM: @@ -3235,7 +3232,6 @@ static void mwl_fwcmd_parse_beacon(struct mwl_priv *priv, beacon_info->ie_ht_ptr += elen; } break; - case WLAN_EID_VHT_CAPABILITY: case WLAN_EID_VHT_OPERATION: case WLAN_EID_OPMODE_NOTIF: @@ -3250,10 +3246,8 @@ static void mwl_fwcmd_parse_beacon(struct mwl_priv *priv, beacon_info->ie_vht_ptr += elen; } break; - case WLAN_EID_VENDOR_SPECIFIC: if ((pos[0] == 0x00) && (pos[1] == 0x50) && (pos[2] == 0xf2)) { - if (pos[3] == 0x01) { beacon_info->ie_rsn_len = (elen + 2); beacon_info->ie_rsn_ptr = (pos - 2); @@ -3265,10 +3259,8 @@ static void mwl_fwcmd_parse_beacon(struct mwl_priv *priv, } } break; - default: break; - } left -= elen; @@ -3276,7 +3268,6 @@ static void mwl_fwcmd_parse_beacon(struct mwl_priv *priv, } if (elem_parse_failed == false) { - beacon_info->ie_ht_ptr = &beacon_info->ie_list_ht[0]; beacon_info->ie_vht_ptr = &beacon_info->ie_list_vht[0]; beacon_info->valid = true; @@ -3338,7 +3329,6 @@ static int mwl_fwcmd_set_ies(struct mwl_priv *priv, struct mwl_vif *mwl_vif) WLDBG_DUMP_DATA(DBG_LEVEL_2, (void *)pcmd, sizeof(*pcmd)); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_IES)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; @@ -3425,7 +3415,6 @@ static int mwl_fwcmd_set_ap_beacon(struct mwl_priv *priv, struct mwl_vif *mwl_vi WLDBG_DUMP_DATA(DBG_LEVEL_2, (void *)pcmd, sizeof(*pcmd)); if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_AP_BEACON)) { - MWL_SPIN_UNLOCK(&priv->locks.fwcmd_lock); WLDBG_EXIT_INFO(DBG_LEVEL_2, "failed execution"); return -EIO; @@ -3455,18 +3444,13 @@ static int mwl_fwcmd_encryption_set_cmd_info(struct hostcmd_cmd_set_key *cmd, memcpy(cmd->key_param.mac_addr, addr, ETH_ALEN); switch (key->cipher) { - case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: - cmd->key_param.key_type_id = ENDIAN_SWAP16(KEY_TYPE_ID_WEP); if (key->keyidx == 0) cmd->key_param.key_info = ENDIAN_SWAP32(ENCR_KEY_FLAG_WEP_TXKEY); - break; - case WLAN_CIPHER_SUITE_TKIP: - cmd->key_param.key_type_id = ENDIAN_SWAP16(KEY_TYPE_ID_TKIP); cmd->key_param.key_info = (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) ? ENDIAN_SWAP32(ENCR_KEY_FLAG_PAIRWISE) @@ -3474,17 +3458,13 @@ static int mwl_fwcmd_encryption_set_cmd_info(struct hostcmd_cmd_set_key *cmd, cmd->key_param.key_info |= ENDIAN_SWAP32(ENCR_KEY_FLAG_MICKEY_VALID | ENCR_KEY_FLAG_TSC_VALID); break; - case WLAN_CIPHER_SUITE_CCMP: - cmd->key_param.key_type_id = ENDIAN_SWAP16(KEY_TYPE_ID_AES); cmd->key_param.key_info = (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) ? ENDIAN_SWAP32(ENCR_KEY_FLAG_PAIRWISE) : ENDIAN_SWAP32(ENCR_KEY_FLAG_TXGROUPKEY); break; - default: - return -ENOTSUPP; } @@ -3498,12 +3478,9 @@ static char *mwl_fwcmd_get_cmd_string(unsigned short cmd) int curr_cmd = 0; static const struct { - u16 cmd; char *cmd_string; - } cmds[] = { - { HOSTCMD_CMD_GET_HW_SPEC, "GetHwSpecifications" }, { HOSTCMD_CMD_SET_HW_SPEC, "SetHwSepcifications" }, { HOSTCMD_CMD_802_11_GET_STAT, "80211GetStat" }, @@ -3512,14 +3489,18 @@ static char *mwl_fwcmd_get_cmd_string(unsigned short cmd) { HOSTCMD_CMD_802_11_RF_ANTENNA, "80211RfAntenna" }, { HOSTCMD_CMD_BROADCAST_SSID_ENABLE, "broadcast_ssid_enable" }, { HOSTCMD_CMD_SET_RF_CHANNEL, "SetRfChannel" }, - { HOSTCMD_CMD_802_11_RTS_THSD, "80211RtsThreshold" }, - { HOSTCMD_CMD_SET_EDCA_PARAMS, "SetEDCAParams" }, + { HOSTCMD_CMD_SET_AID, "SetAid" }, + { HOSTCMD_CMD_SET_INFRA_MODE, "SetInfraMode" }, + { HOSTCMD_CMD_802_11_RTS_THSD, "80211RtsThreshold" }, + { HOSTCMD_CMD_SET_EDCA_PARAMS, "SetEDCAParams" }, { HOSTCMD_CMD_SET_WMM_MODE, "SetWMMMode" }, { HOSTCMD_CMD_SET_FIXED_RATE, "SetFixedRate" }, { HOSTCMD_CMD_SET_IES, "SetInformationElements" }, { HOSTCMD_CMD_SET_RATE_ADAPT_MODE, "SetRateAdaptationMode" }, + { HOSTCMD_CMD_SET_MAC_ADDR, "SetMacAddr" }, { HOSTCMD_CMD_GET_WATCHDOG_BITMAP, "GetWatchdogBitMap" }, - { HOSTCMD_CMD_BSS_START, "BssStart" }, + { HOSTCMD_CMD_DEL_MAC_ADDR. "DelMacAddr" }, + { HOSTCMD_CMD_BSS_START, "BssStart" }, { HOSTCMD_CMD_AP_BEACON, "SetApBeacon" }, { HOSTCMD_CMD_SET_NEW_STN, "SetNewStation" }, { HOSTCMD_CMD_SET_APMODE, "SetApMode" }, @@ -3535,11 +3516,8 @@ static char *mwl_fwcmd_get_cmd_string(unsigned short cmd) max_entries = sizeof(cmds) / sizeof(cmds[0]); for (curr_cmd = 0; curr_cmd < max_entries; curr_cmd++) { - if ((cmd & 0x7fff) == cmds[curr_cmd].cmd) { - WLDBG_EXIT(DBG_LEVEL_2); - return cmds[curr_cmd].cmd_string; } } diff --git a/mwl_fwcmd.h b/mwl_fwcmd.h index fed69ba..70749b6 100644 --- a/mwl_fwcmd.h +++ b/mwl_fwcmd.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2006-2014 Marvell International Ltd. +* Copyright (c) 2006-2015 Marvell International Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -44,20 +44,16 @@ */ enum { - WL_ANTENNATYPE_RX = 1, WL_ANTENNATYPE_TX = 2, - }; enum encr_type { - ENCR_TYPE_WEP = 0, ENCR_TYPE_DISABLE = 1, ENCR_TYPE_TKIP = 4, ENCR_TYPE_AES = 6, ENCR_TYPE_MIX = 7, - }; /* PUBLIC FUNCTION DECLARATION @@ -97,6 +93,12 @@ int mwl_fwcmd_broadcast_ssid_enable(struct ieee80211_hw *hw, int mwl_fwcmd_set_rf_channel(struct ieee80211_hw *hw, struct ieee80211_conf *conf); +int mwl_fwcmd_set_aid(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u8 *bssid, u16 aid); + +int mwl_fwcmd_set_infra_mode(struct ieee80211_hw *hw, + struct ieee80211_vif *vif); + int mwl_fwcmd_set_rts_threshold(struct ieee80211_hw *hw, int threshold); @@ -112,9 +114,15 @@ int mwl_fwcmd_use_fixed_rate(struct ieee80211_hw *hw, int mwl_fwcmd_set_rate_adapt_mode(struct ieee80211_hw *hw, u16 mode); +int mwl_fwcmd_set_mac_addr_client(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u8 *mac_addr); + int mwl_fwcmd_get_watchdog_bitmap(struct ieee80211_hw *hw, u8 *bitmap); +int mwl_fwcmd_remove_mac_addr(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, u8 *mac_addr); + int mwl_fwcmd_bss_start(struct ieee80211_hw *hw, struct ieee80211_vif *vif, bool enable); @@ -123,7 +131,7 @@ int mwl_fwcmd_set_beacon(struct ieee80211_hw *hw, int mwl_fwcmd_set_new_stn_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); + struct ieee80211_sta *sta); int mwl_fwcmd_set_new_stn_add_self(struct ieee80211_hw *hw, struct ieee80211_vif *vif); @@ -138,19 +146,19 @@ int mwl_fwcmd_update_encryption_enable(struct ieee80211_hw *hw, int mwl_fwcmd_encryption_set_key(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u8 *addr, - struct ieee80211_key_conf *key); + struct ieee80211_key_conf *key); int mwl_fwcmd_encryption_remove_key(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u8 *addr, - struct ieee80211_key_conf *key); + struct ieee80211_key_conf *key); int mwl_fwcmd_check_ba(struct ieee80211_hw *hw, struct mwl_ampdu_stream *stream, - struct ieee80211_vif *vif); + struct ieee80211_vif *vif); int mwl_fwcmd_create_ba(struct ieee80211_hw *hw, struct mwl_ampdu_stream *stream, - u8 buf_size, struct ieee80211_vif *vif); + u8 buf_size, struct ieee80211_vif *vif); int mwl_fwcmd_destroy_ba(struct ieee80211_hw *hw, u8 idx); @@ -1,5 +1,5 @@ /* -* Copyright (c) 2006-2014 Marvell International Ltd. +* Copyright (c) 2006-2015 Marvell International Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -16,7 +16,7 @@ /* * -* Description: This file implements frimware downloa related functions. +* Description: This file implements firmware download related functions. * */ @@ -89,7 +89,6 @@ int mwl_fwdl_download_firmware(struct ieee80211_hw *hw) while (readl(priv->iobase1 + 0xc40) == 0); while (size_fw_downloaded < fw->size) { - len = readl(priv->iobase1 + 0xc40); if (!len) @@ -112,25 +111,20 @@ int mwl_fwdl_download_firmware(struct ieee80211_hw *hw) * can alternatively tweak this routines to fit your platform */ do { - int_code = readl(priv->iobase1 + 0xc1c); if (int_code != 0) break; curr_iteration--; - } while (curr_iteration); do { - int_code = readl(priv->iobase1 + 0xc1c); if ((int_code & MACREG_H2ARIC_BIT_DOOR_BELL) != MACREG_H2ARIC_BIT_DOOR_BELL) break; curr_iteration--; - } while (curr_iteration); if (curr_iteration == 0) { - /* This limited loop check allows you to exit gracefully without locking up * your entire system just because fw download failed */ @@ -153,18 +147,15 @@ int mwl_fwdl_download_firmware(struct ieee80211_hw *hw) mwl_fwdl_trig_pcicmd(priv); curr_iteration = FW_MAX_NUM_CHECKS; do { - curr_iteration--; writel(HOSTCMD_SOFTAP_MODE, priv->iobase1 + MACREG_REG_GEN_PTR); WL_MSEC_SLEEP(FW_CHECK_MSECS); int_code = readl(priv->iobase1 + MACREG_REG_INT_CODE); if (!(curr_iteration % 0xff)) WLDBG_PRINT("%x;", int_code); - } while ((curr_iteration) && (int_code != HOSTCMD_SOFTAP_FWRDY_SIGNATURE)); if (curr_iteration == 0) { - WLDBG_PRINT("Exhausted curr_iteration waiting for fw signature; firmware seems failed to operate"); goto err_download; } @@ -1,5 +1,5 @@ /* -* Copyright (c) 2006-2014 Marvell International Ltd. +* Copyright (c) 2006-2015 Marvell International Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/mwl_mac80211.c b/mwl_mac80211.c index 5f14bdc..17a9438 100644 --- a/mwl_mac80211.c +++ b/mwl_mac80211.c @@ -1,5 +1,5 @@ /* -* Copyright (c) 2006-2014 Marvell International Ltd. +* Copyright (c) 2006-2015 Marvell International Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -39,7 +39,7 @@ static void mwl_mac80211_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, - struct sk_buff *skb); + struct sk_buff *skb); static int mwl_mac80211_start(struct ieee80211_hw *hw); static void mwl_mac80211_stop(struct ieee80211_hw *hw); static int mwl_mac80211_add_interface(struct ieee80211_hw *hw, @@ -50,42 +50,49 @@ static int mwl_mac80211_config(struct ieee80211_hw *hw, u32 changed); static void mwl_mac80211_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, - u32 changed); + struct ieee80211_bss_conf *info, + u32 changed); static void mwl_mac80211_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, - unsigned int *total_flags, - u64 multicast); + unsigned int *total_flags, + u64 multicast); static int mwl_mac80211_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd_param, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *key); + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key); static int mwl_mac80211_set_rts_threshold(struct ieee80211_hw *hw, u32 value); static int mwl_mac80211_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); + struct ieee80211_sta *sta); static int mwl_mac80211_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta); + struct ieee80211_sta *sta); static int mwl_mac80211_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u16 queue, - const struct ieee80211_tx_queue_params *params); + u16 queue, + const struct ieee80211_tx_queue_params *params); static int mwl_mac80211_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats); static int mwl_mac80211_get_survey(struct ieee80211_hw *hw, int idx, - struct survey_info *survey); + struct survey_info *survey); static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, - u16 tid, u16 *ssn, u8 buf_size); - + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, + u16 tid, u16 *ssn, u8 buf_size); static void mwl_mac80211_remove_vif(struct mwl_priv *priv, struct mwl_vif *vif); +static void mwl_mac80211_bss_info_changed_sta(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, + u32 changed); +static void mwl_mac80211_bss_info_changed_ap(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, + u32 changed); /* PRIVATE VARIABLES */ @@ -174,7 +181,6 @@ static void mwl_mac80211_tx(struct ieee80211_hw *hw, BUG_ON(!skb); if (!priv->radio_on) { - WLDBG_EXIT_INFO(DBG_LEVEL_5, "dropped TX frame since radio disabled"); dev_kfree_skb_any(skb); @@ -232,17 +238,13 @@ static int mwl_mac80211_start(struct ieee80211_hw *hw) rc = mwl_fwcmd_set_fw_flush_timer(hw, 0); if (rc) { - mwl_fwcmd_int_disable(hw); free_irq(priv->pdev->irq, hw); priv->irq = -1; tasklet_disable(&priv->tx_task); tasklet_disable(&priv->rx_task); - } else { - ieee80211_wake_queues(hw); - } WLDBG_EXIT(DBG_LEVEL_5); @@ -297,12 +299,20 @@ static int mwl_mac80211_add_interface(struct ieee80211_hw *hw, WLDBG_ENTER(DBG_LEVEL_5); - macids_supported = priv->ap_macids_supported; + switch (vif->type) { + case NL80211_IFTYPE_AP: + macids_supported = priv->ap_macids_supported; + break; + case NL80211_IFTYPE_STATION: + macids_supported = priv->sta_macids_supported; + break; + default: + return -EINVAL; + } macid = ffs(macids_supported & ~priv->macids_used); if (!macid--) { - WLDBG_EXIT_INFO(DBG_LEVEL_5, "no macid can be allocated"); return -EBUSY; } @@ -314,13 +324,25 @@ static int mwl_mac80211_add_interface(struct ieee80211_hw *hw, mwl_vif->vif = vif; mwl_vif->macid = macid; mwl_vif->seqno = 0; - memcpy(mwl_vif->bssid, vif->addr, ETH_ALEN); mwl_vif->is_hw_crypto_enabled = false; + mwl_vif->is_sta = false; mwl_vif->beacon_info.valid = false; mwl_vif->iv16 = 1; mwl_vif->iv32 = 0; + mwl_vif->keyidx = 0; + + if (vif->type == NL80211_IFTYPE_STATION) { + memcpy(mwl_vif->sta_mac, vif->addr, ETH_ALEN); + mwl_vif->is_sta = true; + mwl_fwcmd_bss_start(hw, vif, true); + mwl_fwcmd_set_infra_mode(hw, vif); + mwl_fwcmd_set_mac_addr_client(hw, vif, vif->addr); + } - mwl_fwcmd_set_new_stn_add_self(hw, vif); + if (vif->type == NL80211_IFTYPE_AP) { + memcpy(mwl_vif->bssid, vif->addr, ETH_ALEN); + mwl_fwcmd_set_new_stn_add_self(hw, vif); + } priv->macids_used |= 1 << mwl_vif->macid; list_add_tail(&mwl_vif->list, &priv->vif_list); @@ -338,7 +360,11 @@ static void mwl_mac80211_remove_interface(struct ieee80211_hw *hw, WLDBG_ENTER(DBG_LEVEL_5); - mwl_fwcmd_set_new_stn_del(hw, vif, vif->addr); + if (vif->type == NL80211_IFTYPE_STATION) + mwl_fwcmd_remove_mac_addr(hw, vif, vif->addr); + + if (vif->type == NL80211_IFTYPE_AP) + mwl_fwcmd_set_new_stn_del(hw, vif, vif->addr); mwl_mac80211_remove_vif(priv, mwl_vif); @@ -364,17 +390,26 @@ static int mwl_mac80211_config(struct ieee80211_hw *hw, goto out; if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { - - if (conf->chandef.chan->band == IEEE80211_BAND_2GHZ) + int rate = 0; + + if (conf->chandef.chan->band == IEEE80211_BAND_2GHZ) { mwl_fwcmd_set_apmode(hw, AP_MODE_2_4GHZ_11AC_MIXED); - else if (conf->chandef.chan->band == IEEE80211_BAND_5GHZ) + rate = mwl_rates_24[0].hw_value; + } else if (conf->chandef.chan->band == IEEE80211_BAND_5GHZ) { mwl_fwcmd_set_apmode(hw, AP_MODE_11AC); + rate = mwl_rates_50[0].hw_value; + } rc = mwl_fwcmd_set_rf_channel(hw, conf); if (rc) goto out; + rc = mwl_fwcmd_use_fixed_rate(hw, rate, rate); + + if (rc) + goto out; + rc = mwl_fwcmd_max_tx_power(hw, conf, 0); if (rc) @@ -397,71 +432,26 @@ out: static void mwl_mac80211_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, - u32 changed) + struct ieee80211_bss_conf *info, + u32 changed) { WLDBG_ENTER(DBG_LEVEL_5); - WLDBG_INFO(DBG_LEVEL_5, "change: 0x%x", changed); - - if (changed & BSS_CHANGED_ERP_PREAMBLE) { - - mwl_fwcmd_set_radio_preamble(hw, - vif->bss_conf.use_short_preamble); - } - - if (changed & BSS_CHANGED_BASIC_RATES) { - - int idx; - int rate; - - /* - * Use lowest supported basic rate for multicasts - * and management frames (such as probe responses -- - * beacons will always go out at 1 Mb/s). - */ - idx = ffs(vif->bss_conf.basic_rates); - if (idx) - idx--; - - if (hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) - rate = mwl_rates_24[idx].hw_value; - else - rate = mwl_rates_50[idx].hw_value; - - mwl_fwcmd_use_fixed_rate(hw, rate, rate); - } - - if (changed & (BSS_CHANGED_BEACON_INT | BSS_CHANGED_BEACON)) { - - struct sk_buff *skb; + WLDBG_INFO(DBG_LEVEL_5, "interface: %d, change: 0x%x", vif->type, changed); - skb = ieee80211_beacon_get(hw, vif); + if (vif->type == NL80211_IFTYPE_STATION) + mwl_mac80211_bss_info_changed_sta(hw, vif, info, changed); - if (skb != NULL) { - - mwl_fwcmd_set_beacon(hw, vif, skb->data, skb->len); - dev_kfree_skb_any(skb); - } - - if ((info->ssid[0] != '\0') && (info->ssid_len != 0)) - mwl_fwcmd_broadcast_ssid_enable(hw, vif, true); - else - mwl_fwcmd_broadcast_ssid_enable(hw, vif, false); - } - - if (changed & BSS_CHANGED_BEACON_ENABLED) { - - mwl_fwcmd_bss_start(hw, vif, info->enable_beacon); - } + if (vif->type == NL80211_IFTYPE_AP) + mwl_mac80211_bss_info_changed_ap(hw, vif, info, changed); WLDBG_EXIT(DBG_LEVEL_5); } static void mwl_mac80211_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, - unsigned int *total_flags, - u64 multicast) + unsigned int *total_flags, + u64 multicast) { WLDBG_ENTER(DBG_LEVEL_5); @@ -476,9 +466,9 @@ static void mwl_mac80211_configure_filter(struct ieee80211_hw *hw, static int mwl_mac80211_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd_param, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *key) { int rc = 0; u8 encr_type; @@ -491,19 +481,15 @@ static int mwl_mac80211_set_key(struct ieee80211_hw *hw, BUG_ON(!mwl_vif); BUG_ON(!sta_info); - if (vif->type == NL80211_IFTYPE_STATION) { - - WLDBG_EXIT_INFO(DBG_LEVEL_5, "station mode is not supported"); - return -EOPNOTSUPP; - } - - if (sta == NULL) + if (sta == NULL) { addr = vif->addr; - else + } else { addr = sta->addr; + if (mwl_vif->is_sta == true) + memcpy(mwl_vif->bssid, addr, ETH_ALEN); + } if (cmd_param == SET_KEY) { - rc = mwl_fwcmd_encryption_set_key(hw, vif, addr, key); if (rc) @@ -511,24 +497,17 @@ static int mwl_mac80211_set_key(struct ieee80211_hw *hw, if ((key->cipher == WLAN_CIPHER_SUITE_WEP40) || (key->cipher == WLAN_CIPHER_SUITE_WEP104)) { - encr_type = ENCR_TYPE_WEP; - } else if (key->cipher == WLAN_CIPHER_SUITE_CCMP) { - encr_type = ENCR_TYPE_AES; - - if ((key->flags & IEEE80211_KEY_FLAG_PAIRWISE) == 0) - mwl_vif->keyidx = key->keyidx; - + if ((key->flags & IEEE80211_KEY_FLAG_PAIRWISE) == 0) { + if (mwl_vif->is_sta == false) + mwl_vif->keyidx = key->keyidx; + } } else if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { - encr_type = ENCR_TYPE_TKIP; - } else { - encr_type = ENCR_TYPE_DISABLE; - } rc = mwl_fwcmd_update_encryption_enable(hw, vif, addr, @@ -538,14 +517,11 @@ static int mwl_mac80211_set_key(struct ieee80211_hw *hw, goto out; mwl_vif->is_hw_crypto_enabled = true; - } else { - rc = mwl_fwcmd_encryption_remove_key(hw, vif, addr, key); if (rc) goto out; - } out: @@ -571,7 +547,7 @@ static int mwl_mac80211_set_rts_threshold(struct ieee80211_hw *hw, static int mwl_mac80211_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct ieee80211_sta *sta) { struct mwl_vif *mwl_vif = MWL_VIF(vif); struct mwl_sta *sta_info = MWL_STA(sta); @@ -590,10 +566,12 @@ static int mwl_mac80211_sta_add(struct ieee80211_hw *hw, if (sta->ht_cap.ht_supported) sta_info->is_ampdu_allowed = true; + if (mwl_vif->is_sta == true) + mwl_fwcmd_set_new_stn_del(hw, vif, sta->addr); + rc = mwl_fwcmd_set_new_stn_add(hw, vif, sta); for (i = 0; i < NUM_WEP_KEYS; i++) { - key = IEEE80211_KEY_CONF(mwl_vif->wep_key_conf[i].key); if (mwl_vif->wep_key_conf[i].enabled) @@ -607,7 +585,7 @@ static int mwl_mac80211_sta_add(struct ieee80211_hw *hw, static int mwl_mac80211_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct ieee80211_sta *sta) { int rc; @@ -622,8 +600,8 @@ static int mwl_mac80211_sta_remove(struct ieee80211_hw *hw, static int mwl_mac80211_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u16 queue, - const struct ieee80211_tx_queue_params *params) + u16 queue, + const struct ieee80211_tx_queue_params *params) { struct mwl_priv *priv = hw->priv; int rc = 0; @@ -635,13 +613,11 @@ static int mwl_mac80211_conf_tx(struct ieee80211_hw *hw, memcpy(&priv->wmm_params[queue], params, sizeof(*params)); if (!priv->wmm_enabled) { - rc = mwl_fwcmd_set_wmm_mode(hw, true); priv->wmm_enabled = true; } if (!rc) { - int q = SYSADPT_TX_WMM_QUEUES - 1 - queue; rc = mwl_fwcmd_set_edca_params(hw, q, @@ -691,9 +667,9 @@ static int mwl_mac80211_get_survey(struct ieee80211_hw *hw, static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, - u16 tid, u16 *ssn, u8 buf_size) + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, + u16 tid, u16 *ssn, u8 buf_size) { int i, rc = 0; struct mwl_priv *priv = hw->priv; @@ -704,7 +680,6 @@ static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw, WLDBG_ENTER(DBG_LEVEL_5); if (!(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION)) { - WLDBG_EXIT_INFO(DBG_LEVEL_5, "no HW AMPDU"); return -ENOTSUPP; } @@ -714,11 +689,9 @@ static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw, stream = mwl_fwcmd_lookup_stream(hw, addr, tid); switch (action) { - case IEEE80211_AMPDU_RX_START: case IEEE80211_AMPDU_RX_STOP: break; - case IEEE80211_AMPDU_TX_START: /* By the time we get here the hw queues may contain outgoing * packets for this RA/TID that are not part of this BA @@ -732,7 +705,6 @@ static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw, *ssn = 0; if (stream == NULL) { - /* This means that somebody outside this driver called * ieee80211_start_tx_ba_session. This is unexpected * because we do our own rate control. Just warn and @@ -742,7 +714,6 @@ static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw, } if (stream == NULL) { - WLDBG_EXIT_INFO(DBG_LEVEL_5, "no stream found"); rc = -EBUSY; break; @@ -755,11 +726,9 @@ static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw, SPIN_UNLOCK(&priv->locks.stream_lock); for (i = 0; i < MAX_AMPDU_ATTEMPTS; i++) { - /* Check if link is still valid */ if (!sta_info->is_ampdu_allowed) { - SPIN_LOCK(&priv->locks.stream_lock); mwl_fwcmd_remove_stream(hw, stream); SPIN_UNLOCK(&priv->locks.stream_lock); @@ -778,7 +747,6 @@ static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw, SPIN_LOCK(&priv->locks.stream_lock); if (rc) { - mwl_fwcmd_remove_stream(hw, stream); WLDBG_EXIT_INFO(DBG_LEVEL_5, "error code: %d", rc); rc = -EBUSY; @@ -787,15 +755,11 @@ static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw, ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid); break; - case IEEE80211_AMPDU_TX_STOP_CONT: case IEEE80211_AMPDU_TX_STOP_FLUSH: case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: - if (stream) { - if (stream->state == AMPDU_STREAM_ACTIVE) { - idx = stream->idx; SPIN_UNLOCK(&priv->locks.stream_lock); mwl_fwcmd_destroy_ba(hw, idx); @@ -807,9 +771,7 @@ static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw, ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid); break; - case IEEE80211_AMPDU_TX_OPERATIONAL: - BUG_ON(stream == NULL); BUG_ON(stream->state != AMPDU_STREAM_IN_PROGRESS); SPIN_UNLOCK(&priv->locks.stream_lock); @@ -819,7 +781,6 @@ static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw, if (!rc) stream->state = AMPDU_STREAM_ACTIVE; else { - idx = stream->idx; SPIN_UNLOCK(&priv->locks.stream_lock); mwl_fwcmd_destroy_ba(hw, idx); @@ -827,10 +788,8 @@ static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw, mwl_fwcmd_remove_stream(hw, stream); } break; - default: rc = -ENOTSUPP; - } SPIN_UNLOCK(&priv->locks.stream_lock); @@ -848,3 +807,72 @@ static void mwl_mac80211_remove_vif(struct mwl_priv *priv, struct mwl_vif *vif) priv->macids_used &= ~(1 << vif->macid); list_del(&vif->list); } + +static void mwl_mac80211_bss_info_changed_sta(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, + u32 changed) +{ + if (changed & BSS_CHANGED_ERP_PREAMBLE) { + mwl_fwcmd_set_radio_preamble(hw, + vif->bss_conf.use_short_preamble); + } + + if ((changed & BSS_CHANGED_ASSOC) && vif->bss_conf.assoc) { + + mwl_fwcmd_set_aid(hw, vif, (u8 *) vif->bss_conf.bssid, + vif->bss_conf.aid); + } +} + +static void mwl_mac80211_bss_info_changed_ap(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info, + u32 changed) +{ + if (changed & BSS_CHANGED_ERP_PREAMBLE) { + mwl_fwcmd_set_radio_preamble(hw, + vif->bss_conf.use_short_preamble); + } + + if (changed & BSS_CHANGED_BASIC_RATES) { + int idx; + int rate; + + /* + * Use lowest supported basic rate for multicasts + * and management frames (such as probe responses -- + * beacons will always go out at 1 Mb/s). + */ + idx = ffs(vif->bss_conf.basic_rates); + if (idx) + idx--; + + if (hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) + rate = mwl_rates_24[idx].hw_value; + else + rate = mwl_rates_50[idx].hw_value; + + mwl_fwcmd_use_fixed_rate(hw, rate, rate); + } + + if (changed & (BSS_CHANGED_BEACON_INT | BSS_CHANGED_BEACON)) { + struct sk_buff *skb; + + skb = ieee80211_beacon_get(hw, vif); + + if (skb != NULL) { + + mwl_fwcmd_set_beacon(hw, vif, skb->data, skb->len); + dev_kfree_skb_any(skb); + } + + if ((info->ssid[0] != '\0') && (info->ssid_len != 0)) + mwl_fwcmd_broadcast_ssid_enable(hw, vif, true); + else + mwl_fwcmd_broadcast_ssid_enable(hw, vif, false); + } + + if (changed & BSS_CHANGED_BEACON_ENABLED) + mwl_fwcmd_bss_start(hw, vif, info->enable_beacon); +} diff --git a/mwl_mac80211.h b/mwl_mac80211.h index 1432e02..1d4b57c 100644 --- a/mwl_mac80211.h +++ b/mwl_mac80211.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2006-2014 Marvell International Ltd. +* Copyright (c) 2006-2015 Marvell International Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -1,5 +1,5 @@ /* -* Copyright (c) 2006-2014 Marvell International Ltd. +* Copyright (c) 2006-2015 Marvell International Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -38,13 +38,14 @@ #define MWL_DESC "Marvell 802.11ac Wireless Network Driver" #define MWL_DEV_NAME "Marvell 88W8864 802.11ac Adapter" #define MWL_DRV_NAME KBUILD_MODNAME -#define MWL_DRV_VERSION "10.2.6.1.p4" +#define MWL_DRV_VERSION "10.2.8.5.p0" #define FILE_PATH_LEN 64 #define CMD_BUF_SIZE 0x4000 #define INVALID_WATCHDOG 0xAA + /* PRIVATE FUNCTION DECLARATION */ @@ -53,10 +54,12 @@ static void mwl_remove(struct pci_dev *pdev); static int mwl_alloc_pci_resource(struct mwl_priv *priv); static void mwl_free_pci_resource(struct mwl_priv *priv); static int mwl_init_firmware(struct mwl_priv *priv, char *fw_image); -static int mwl_load_tx_pwr_tbl(struct mwl_priv *priv, char *pwr_tbl); -static void mwl_set_ht_caps(struct ieee80211_hw *hw, +static void mwl_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request); +static void mwl_process_of_dts(struct mwl_priv *priv); +static void mwl_set_ht_caps(struct mwl_priv *priv, struct ieee80211_supported_band *band); -static void mwl_set_vht_caps(struct ieee80211_hw *hw, +static void mwl_set_vht_caps(struct mwl_priv *priv, struct ieee80211_supported_band *band); static void mwl_set_caps(struct mwl_priv *priv); static int mwl_wl_init(struct mwl_priv *priv); @@ -64,34 +67,25 @@ static void mwl_wl_deinit(struct mwl_priv *priv); static void mwl_watchdog_ba_events(struct work_struct *work); static irqreturn_t mwl_interrupt(int irq, void *dev_id); -static int atoi(const char *num_str); -static long atohex(const char *number); -static long atohex2(const char *number); /* PRIVATE VARIABLES */ -static char fw_image_path[FILE_PATH_LEN] = "88W8864.bin"; -static char pwr_tbl_path[FILE_PATH_LEN] = "PWR_TABLE.ini"; +static char fw_image_path[FILE_PATH_LEN] = "mwlwifi/88W8864.bin"; static struct pci_device_id mwl_pci_id_tbl[SYSADPT_MAX_CARDS_SUPPORT + 1] = { - { 0x11ab, 0x2a55, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)MWL_DEV_NAME }, { 0, 0, 0, 0, 0, 0, 0 } - }; static struct pci_driver mwl_pci_driver = { - .name = MWL_DRV_NAME, .id_table = mwl_pci_id_tbl, .probe = mwl_probe, .remove = mwl_remove - }; static const struct ieee80211_channel mwl_channels_24[] = { - { .band = IEEE80211_BAND_2GHZ, .center_freq = 2412, .hw_value = 1, }, { .band = IEEE80211_BAND_2GHZ, .center_freq = 2417, .hw_value = 2, }, { .band = IEEE80211_BAND_2GHZ, .center_freq = 2422, .hw_value = 3, }, @@ -106,11 +100,9 @@ static const struct ieee80211_channel mwl_channels_24[] = { { .band = IEEE80211_BAND_2GHZ, .center_freq = 2467, .hw_value = 12, }, { .band = IEEE80211_BAND_2GHZ, .center_freq = 2472, .hw_value = 13, }, { .band = IEEE80211_BAND_2GHZ, .center_freq = 2484, .hw_value = 14, }, - }; static const struct ieee80211_rate mwl_rates_24[] = { - { .bitrate = 10, .hw_value = 2, }, { .bitrate = 20, .hw_value = 4, }, { .bitrate = 55, .hw_value = 11, }, @@ -124,11 +116,9 @@ static const struct ieee80211_rate mwl_rates_24[] = { { .bitrate = 360, .hw_value = 72, }, { .bitrate = 480, .hw_value = 96, }, { .bitrate = 540, .hw_value = 108, }, - }; static const struct ieee80211_channel mwl_channels_50[] = { - { .band = IEEE80211_BAND_5GHZ, .center_freq = 5180, .hw_value = 36, }, { .band = IEEE80211_BAND_5GHZ, .center_freq = 5200, .hw_value = 40, }, { .band = IEEE80211_BAND_5GHZ, .center_freq = 5220, .hw_value = 44, }, @@ -153,11 +143,9 @@ static const struct ieee80211_channel mwl_channels_50[] = { { .band = IEEE80211_BAND_5GHZ, .center_freq = 5765, .hw_value = 153, }, { .band = IEEE80211_BAND_5GHZ, .center_freq = 5785, .hw_value = 157, }, { .band = IEEE80211_BAND_5GHZ, .center_freq = 5805, .hw_value = 161, }, - }; static const struct ieee80211_rate mwl_rates_50[] = { - { .bitrate = 60, .hw_value = 12, }, { .bitrate = 90, .hw_value = 18, }, { .bitrate = 120, .hw_value = 24, }, @@ -166,48 +154,27 @@ static const struct ieee80211_rate mwl_rates_50[] = { { .bitrate = 360, .hw_value = 72, }, { .bitrate = 480, .hw_value = 96, }, { .bitrate = 540, .hw_value = 108, }, - }; static const struct ieee80211_iface_limit ap_if_limits[] = { - - { .max = 8, .types = BIT(NL80211_IFTYPE_AP) }, + { .max = SYSADPT_NUM_OF_AP, .types = BIT(NL80211_IFTYPE_AP) }, { .max = 1, .types = BIT(NL80211_IFTYPE_STATION) }, - }; static const struct ieee80211_iface_combination ap_if_comb = { - .limits = ap_if_limits, .n_limits = ARRAY_SIZE(ap_if_limits), - .max_interfaces = 8, + .max_interfaces = SYSADPT_NUM_OF_AP, .num_different_channels = 1, - }; -/* PUBLIC FUNCTION DEFINITION -*/ - -module_param_string(fw_name, fw_image_path, FILE_PATH_LEN, 0); -MODULE_PARM_DESC(fw_name, "Specify where to load the F/W image"); -module_param_string(pwr_tbl, pwr_tbl_path, FILE_PATH_LEN, 0); -MODULE_PARM_DESC(pwr_tbl, "Specify where to load TX power table"); - -module_pci_driver(mwl_pci_driver); - -MODULE_DESCRIPTION(MWL_DESC); -MODULE_VERSION(MWL_DRV_VERSION); -MODULE_AUTHOR("Marvell Semiconductor, Inc."); -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_SUPPORTED_DEVICE(MWL_DEV_NAME); -MODULE_DEVICE_TABLE(pci, mwl_pci_id_tbl); /* PRIVATE FUNCTION DEFINITION */ static int mwl_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - static int printed_version; + static bool printed_version = false; struct ieee80211_hw *hw; struct mwl_priv *priv; int rc = 0; @@ -215,14 +182,12 @@ static int mwl_probe(struct pci_dev *pdev, const struct pci_device_id *id) WLDBG_ENTER(DBG_LEVEL_0); if (!printed_version) { - WLDBG_PRINT("<<%s version %s>>", MWL_DESC, MWL_DRV_VERSION); - printed_version = 1; + printed_version = true; } rc = pci_enable_device(pdev); if (rc) { - WLDBG_ERROR(DBG_LEVEL_0, "%s: cannot enable new PCI device", MWL_DRV_NAME); WLDBG_EXIT_INFO(DBG_LEVEL_0, "init error"); @@ -231,7 +196,6 @@ static int mwl_probe(struct pci_dev *pdev, const struct pci_device_id *id) rc = pci_set_dma_mask(pdev, 0xffffffff); if (rc) { - WLDBG_ERROR(DBG_LEVEL_0, "%s: 32-bit PCI DMA not supported", MWL_DRV_NAME); goto err_pci_disable_device; @@ -241,13 +205,16 @@ static int mwl_probe(struct pci_dev *pdev, const struct pci_device_id *id) hw = ieee80211_alloc_hw(sizeof(*priv), mwl_mac80211_get_ops()); if (hw == NULL) { - WLDBG_ERROR(DBG_LEVEL_0, "%s: ieee80211 alloc failed", MWL_DRV_NAME); rc = -ENOMEM; goto err_pci_disable_device; } + /* hook regulatory domain change notification + */ + hw->wiphy->reg_notifier = mwl_reg_notifier; + /* set interrupt service routine to mac80211 module */ mwl_mac80211_set_isr(mwl_interrupt); @@ -265,7 +232,6 @@ static int mwl_probe(struct pci_dev *pdev, const struct pci_device_id *id) rc = mwl_init_firmware(priv, fw_image_path); if (rc) { - WLDBG_ERROR(DBG_LEVEL_0, "%s: fail to initialize firmware", MWL_DRV_NAME); goto err_init_firmware; @@ -275,16 +241,10 @@ static int mwl_probe(struct pci_dev *pdev, const struct pci_device_id *id) */ release_firmware(priv->fw_ucode); - rc = mwl_load_tx_pwr_tbl(priv, pwr_tbl_path); - if (rc) { - - WLDBG_PRINT("%s: fail to load tx power table", - MWL_DRV_NAME); - } + mwl_process_of_dts(priv); rc = mwl_wl_init(priv); if (rc) { - WLDBG_ERROR(DBG_LEVEL_0, "%s: fail to initialize wireless lan", MWL_DRV_NAME); goto err_wl_init; @@ -321,7 +281,6 @@ static void mwl_remove(struct pci_dev *pdev) WLDBG_ENTER(DBG_LEVEL_0); if (hw == NULL) { - WLDBG_EXIT_INFO(DBG_LEVEL_0, "ieee80211 hw is null"); return; } @@ -390,8 +349,7 @@ static int mwl_alloc_pci_resource(struct mwl_priv *priv) phys_addr2[1] = 0; priv->iobase1 = phys_addr2[0]; - if (!priv->iobase1) - { + if (!priv->iobase1) { WLDBG_ERROR(DBG_LEVEL_0, "%s: cannot remap PCI memory region 1", MWL_DRV_NAME); goto err_release_mem_region_bar1; @@ -400,10 +358,9 @@ static int mwl_alloc_pci_resource(struct mwl_priv *priv) WLDBG_PRINT("priv->iobase1 = %x", (unsigned int)priv->iobase1); priv->pcmd_buf = (unsigned short *) - pci_alloc_consistent(priv->pdev, CMD_BUF_SIZE, &priv->pphys_cmd_buf); + dma_alloc_coherent(&priv->pdev->dev, CMD_BUF_SIZE, &priv->pphys_cmd_buf, GFP_KERNEL); if (priv->pcmd_buf == NULL) { - WLDBG_ERROR(DBG_LEVEL_0, "%s: cannot alloc memory for command buffer", MWL_DRV_NAME); goto err_iounmap_iobase1; @@ -456,7 +413,7 @@ static void mwl_free_pci_resource(struct mwl_priv *priv) iounmap(priv->iobase1); release_mem_region(pci_resource_start(pdev, priv->next_bar_num), pci_resource_len(pdev, priv->next_bar_num)); release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); - pci_free_consistent(priv->pdev, CMD_BUF_SIZE, priv->pcmd_buf, priv->pphys_cmd_buf); + dma_free_coherent(&priv->pdev->dev, CMD_BUF_SIZE, priv->pcmd_buf, priv->pphys_cmd_buf); WLDBG_EXIT(DBG_LEVEL_0); } @@ -474,7 +431,6 @@ static int mwl_init_firmware(struct mwl_priv *priv, char *fw_name) rc = request_firmware(&priv->fw_ucode, fw_name, &priv->pdev->dev); if (rc) { - WLDBG_ERROR(DBG_LEVEL_0, "%s: cannot load firmware image <%s>", MWL_DRV_NAME, fw_name); goto err_load_fw; @@ -482,7 +438,6 @@ static int mwl_init_firmware(struct mwl_priv *priv, char *fw_name) rc = mwl_fwdl_download_firmware(priv->hw); if (rc) { - WLDBG_ERROR(DBG_LEVEL_0, "%s: cannot download firmware image <%s>", MWL_DRV_NAME, fw_name); goto err_download_fw; @@ -503,100 +458,179 @@ err_load_fw: return rc; } -static int mwl_load_tx_pwr_tbl(struct mwl_priv *priv, char *pwr_tbl) +static void mwl_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request) { - struct file *filp = NULL; - mm_segment_t oldfs; - char buff[120], *s; - int len, index = 0, i, value = 0; - char param[20][32]; - int rc = 0; + struct ieee80211_hw *hw; + struct mwl_priv *priv; + struct property *prop; + struct property *fcc_prop = NULL; + struct property *etsi_prop = NULL; + struct property *specific_prop = NULL; + u32 prop_value; + int i, j, k; WLDBG_ENTER(DBG_LEVEL_0); + BUG_ON(!wiphy); + hw = (struct ieee80211_hw *) wiphy_priv(wiphy); + BUG_ON(!hw); + priv = hw->priv; BUG_ON(!priv); - oldfs = get_fs(); - set_fs(KERNEL_DS); - - filp = filp_open(pwr_tbl, O_RDONLY, 0); - - if (!IS_ERR(filp)) { /* MUST use this one, important!!! */ - - WLDBG_PRINT("open tx power table <%s>: OK", pwr_tbl); - - /* reset the whole table */ - for (i = 0; i < SYSADPT_MAX_NUM_CHANNELS; i++) - memset(&priv->tx_pwr_tbl[i], 0, sizeof(struct mwl_tx_pwr_tbl)); + if (priv->pwr_node != NULL) { + for_each_property_of_node(priv->pwr_node, prop) { + if(strcmp(prop->name, "FCC") == 0) + fcc_prop = prop; + if (strcmp(prop->name, "ETSI") == 0) + etsi_prop = prop; + if ((prop->name[0] == request->alpha2[0]) && + (prop->name[1] == request->alpha2[1])) + specific_prop = prop; + } - while (1) { + prop = NULL; - s = buff; - while ((len = vfs_read(filp, s, 0x01, &filp->f_pos)) == 1) { + if (specific_prop != NULL) { + prop = specific_prop; + } else { + if (request->dfs_region == NL80211_DFS_ETSI) + prop = etsi_prop; + else + prop = fcc_prop; + } - if (*s == '\n') { - /* skip blank line */ - if (s == buff) - break; + if (prop != NULL) { + /* Reset the whole table + */ + for (i = 0; i < SYSADPT_MAX_NUM_CHANNELS; i++) + memset(&priv->tx_pwr_tbl[i], 0, + sizeof(struct mwl_tx_pwr_tbl)); + + /* Load related power table + */ + i = 0; + j = 0; + while (i < prop->length) { + prop_value = be32_to_cpu(*(u32 *)(prop->value + i)); + priv->tx_pwr_tbl[j].channel = prop_value; + i += 4; + prop_value = be32_to_cpu(*(u32 *)(prop->value + i)); + priv->tx_pwr_tbl[j].setcap = prop_value; + i += 4; + for (k = 0; k < SYSADPT_TX_POWER_LEVEL_TOTAL; k++) { + prop_value = be32_to_cpu(*(u32 *)(prop->value + i)); + priv->tx_pwr_tbl[j].tx_power[k] = prop_value; + i += 4; + } + prop_value = be32_to_cpu(*(u32 *)(prop->value + i)); + priv->tx_pwr_tbl[j].cdd = prop_value; + i += 4; + prop_value = be32_to_cpu(*(u32 *)(prop->value + i)); + priv->tx_pwr_tbl[j].txantenna2 = prop_value; + i += 4; + j++; + } - /* parse this line and assign value to data structure */ - *s = '\0'; - /* WLDBG_PRINT("index=<%d>: <%s>", index, buff); */ - /* 8864 total param: ch + setcap + 16 txpower + CDD + tx2 = 16 */ - sscanf(buff, "%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n", param[0], param[1], param[2], param[3], param[4], param[5] - , param[6], param[7], param[8], param[9], param[10], param[11], param[12], param[13], param[14], param[15], param[16], param[17] - , param[18], param[19]); + /* Dump loaded power tabel + */ + WLDBG_PRINT("%s: %s\n", dev_name(&wiphy->dev), prop->name); + for (i = 0; i < SYSADPT_MAX_NUM_CHANNELS; i++) { + char disp_buf[64]; + char *disp_ptr; + + if (priv->tx_pwr_tbl[i].channel == 0) + break; + WLDBG_PRINT("Channel: %d: 0x%x 0x%x 0x%x", + priv->tx_pwr_tbl[i].channel, + priv->tx_pwr_tbl[i].setcap, + priv->tx_pwr_tbl[i].cdd, + priv->tx_pwr_tbl[i].txantenna2); + disp_ptr = disp_buf; + for (j = 0; j < SYSADPT_TX_POWER_LEVEL_TOTAL; j++) { + disp_ptr += + sprintf(disp_ptr, "%x ", + priv->tx_pwr_tbl[i].tx_power[j]); + } + WLDBG_PRINT("%s", disp_buf); + } + } + } - if (strcmp(param[18], "on") == 0) - value = 1; - else if (strcmp(param[18], "off") == 0) - value = 0; - else { - WLDBG_PRINT("txpower table format error: CCD should be on|off"); - break; - } + WLDBG_EXIT(DBG_LEVEL_0); +} - priv->tx_pwr_tbl[index].cdd = value; - priv->tx_pwr_tbl[index].txantenna2 = atohex2(param[19]); - priv->tx_pwr_tbl[index].channel = atoi(param[0]); - priv->tx_pwr_tbl[index].setcap = atoi(param[1]); +static void mwl_process_of_dts(struct mwl_priv *priv) +{ + struct property *prop; + u32 prop_value; - for (i = 0; i < SYSADPT_TX_POWER_LEVEL_TOTAL; i++) - priv->tx_pwr_tbl[index].tx_power[i] = atohex2(param[i+2]); + WLDBG_ENTER(DBG_LEVEL_0); - index++; - break; + BUG_ON(!priv); - } else { + priv->disable_2g = false; + priv->disable_5g = false; + priv->antenna_tx = ANTENNA_TX_4_AUTO; + priv->antenna_rx = ANTENNA_RX_4_AUTO; - s++; + priv->dt_node = + of_find_node_by_name(pci_bus_to_OF_node(priv->pdev->bus), + "mwlwifi"); - } + /* look for all matching property names + */ + if (priv->dt_node != NULL) { + for_each_property_of_node(priv->dt_node, prop) { + if (strcmp(prop->name, "marvell,2ghz") == 0) + priv->disable_2g = true; + if (strcmp(prop->name, "marvell,5ghz") == 0) + priv->disable_5g = true; + if (strcmp(prop->name, "marvell,chainmask") == 0) { + prop_value = be32_to_cpu(*((u32 *)prop->value)); + if (prop_value == 2) + priv->antenna_tx = ANTENNA_TX_2; + + prop_value = be32_to_cpu(*((u32 *)(prop->value + 4))); + if (prop_value == 2) + priv->antenna_rx = ANTENNA_RX_2; } - - if (len <= 0) - break; } - filp_close(filp, current->files); - - } else { - - WLDBG_PRINT("open tx power table <%s>: FAIL", pwr_tbl); - rc = -EIO; - + priv->pwr_node = of_find_node_by_name(priv->dt_node, + "marvell,powertable"); } - set_fs(oldfs); + WLDBG_PRINT("2G: %s\n", priv->disable_2g ? "disable" : "enable"); + WLDBG_PRINT("5G: %s\n", priv->disable_5g ? "disable" : "enable"); - WLDBG_EXIT_INFO(DBG_LEVEL_0, "result: %d", rc); + if (priv->antenna_tx == ANTENNA_TX_4_AUTO) + WLDBG_PRINT("TX: 4 antennas\n"); + else if (priv->antenna_tx == ANTENNA_TX_2) + WLDBG_PRINT("TX: 2 antennas\n"); + else + WLDBG_PRINT("TX: unknown\n"); + if (priv->antenna_rx == ANTENNA_RX_4_AUTO) + WLDBG_PRINT("RX: 4 antennas\n"); + else if (priv->antenna_rx == ANTENNA_RX_2) + WLDBG_PRINT("RX: 2 antennas\n"); + else + WLDBG_PRINT("RX: unknown\n"); - return rc; + WLDBG_EXIT(DBG_LEVEL_0); } -static void mwl_set_ht_caps(struct ieee80211_hw *hw, +static void mwl_set_ht_caps(struct mwl_priv *priv, struct ieee80211_supported_band *band) { + struct ieee80211_hw *hw; + + WLDBG_ENTER(DBG_LEVEL_0); + + BUG_ON(!priv); + hw = priv->hw; + BUG_ON(!hw); + band->ht_cap.ht_supported = 1; band->ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; @@ -611,15 +645,20 @@ static void mwl_set_ht_caps(struct ieee80211_hw *hw, band->ht_cap.mcs.rx_mask[0] = 0xff; band->ht_cap.mcs.rx_mask[1] = 0xff; - band->ht_cap.mcs.rx_mask[2] = 0xff; + if (priv->antenna_rx == ANTENNA_RX_4_AUTO) + band->ht_cap.mcs.rx_mask[2] = 0xff; band->ht_cap.mcs.rx_mask[4] = 0x01; band->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; + + WLDBG_EXIT(DBG_LEVEL_0); } -static void mwl_set_vht_caps(struct ieee80211_hw *hw, +static void mwl_set_vht_caps(struct mwl_priv *priv, struct ieee80211_supported_band *band) { + WLDBG_ENTER(DBG_LEVEL_0); + band->vht_cap.vht_supported = 1; band->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454; @@ -634,8 +673,17 @@ static void mwl_set_vht_caps(struct ieee80211_hw *hw, band->vht_cap.cap |= IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN; band->vht_cap.cap |= IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN; - band->vht_cap.vht_mcs.rx_mcs_map = 0xffea; - band->vht_cap.vht_mcs.tx_mcs_map = 0xffea; + if (priv->antenna_rx == ANTENNA_RX_2) + band->vht_cap.vht_mcs.rx_mcs_map = 0xfffa; + else + band->vht_cap.vht_mcs.rx_mcs_map = 0xffea; + + if (priv->antenna_tx == ANTENNA_TX_2) + band->vht_cap.vht_mcs.tx_mcs_map = 0xfffa; + else + band->vht_cap.vht_mcs.tx_mcs_map = 0xffea; + + WLDBG_EXIT(DBG_LEVEL_0); } static void mwl_set_caps(struct mwl_priv *priv) @@ -650,41 +698,45 @@ static void mwl_set_caps(struct mwl_priv *priv) /* set up band information for 2.4G */ - BUILD_BUG_ON(sizeof(priv->channels_24) != sizeof(mwl_channels_24)); - memcpy(priv->channels_24, mwl_channels_24, sizeof(mwl_channels_24)); + if (priv->disable_2g == false) { + BUILD_BUG_ON(sizeof(priv->channels_24) != sizeof(mwl_channels_24)); + memcpy(priv->channels_24, mwl_channels_24, sizeof(mwl_channels_24)); - BUILD_BUG_ON(sizeof(priv->rates_24) != sizeof(mwl_rates_24)); - memcpy(priv->rates_24, mwl_rates_24, sizeof(mwl_rates_24)); + BUILD_BUG_ON(sizeof(priv->rates_24) != sizeof(mwl_rates_24)); + memcpy(priv->rates_24, mwl_rates_24, sizeof(mwl_rates_24)); - priv->band_24.band = IEEE80211_BAND_2GHZ; - priv->band_24.channels = priv->channels_24; - priv->band_24.n_channels = ARRAY_SIZE(mwl_channels_24); - priv->band_24.bitrates = priv->rates_24; - priv->band_24.n_bitrates = ARRAY_SIZE(mwl_rates_24); + priv->band_24.band = IEEE80211_BAND_2GHZ; + priv->band_24.channels = priv->channels_24; + priv->band_24.n_channels = ARRAY_SIZE(mwl_channels_24); + priv->band_24.bitrates = priv->rates_24; + priv->band_24.n_bitrates = ARRAY_SIZE(mwl_rates_24); - mwl_set_ht_caps(hw, &priv->band_24); - mwl_set_vht_caps(hw, &priv->band_24); + mwl_set_ht_caps(priv, &priv->band_24); + mwl_set_vht_caps(priv, &priv->band_24); - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band_24; + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band_24; + } /* set up band information for 5G */ - BUILD_BUG_ON(sizeof(priv->channels_50) != sizeof(mwl_channels_50)); - memcpy(priv->channels_50, mwl_channels_50, sizeof(mwl_channels_50)); + if (priv->disable_5g == false) { + BUILD_BUG_ON(sizeof(priv->channels_50) != sizeof(mwl_channels_50)); + memcpy(priv->channels_50, mwl_channels_50, sizeof(mwl_channels_50)); - BUILD_BUG_ON(sizeof(priv->rates_50) != sizeof(mwl_rates_50)); - memcpy(priv->rates_50, mwl_rates_50, sizeof(mwl_rates_50)); + BUILD_BUG_ON(sizeof(priv->rates_50) != sizeof(mwl_rates_50)); + memcpy(priv->rates_50, mwl_rates_50, sizeof(mwl_rates_50)); - priv->band_50.band = IEEE80211_BAND_5GHZ; - priv->band_50.channels = priv->channels_50; - priv->band_50.n_channels = ARRAY_SIZE(mwl_channels_50); - priv->band_50.bitrates = priv->rates_50; - priv->band_50.n_bitrates = ARRAY_SIZE(mwl_rates_50); + priv->band_50.band = IEEE80211_BAND_5GHZ; + priv->band_50.channels = priv->channels_50; + priv->band_50.n_channels = ARRAY_SIZE(mwl_channels_50); + priv->band_50.bitrates = priv->rates_50; + priv->band_50.n_bitrates = ARRAY_SIZE(mwl_rates_50); - mwl_set_ht_caps(hw, &priv->band_50); - mwl_set_vht_caps(hw, &priv->band_50); + mwl_set_ht_caps(priv, &priv->band_50); + mwl_set_vht_caps(priv, &priv->band_50); - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &priv->band_50; + hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &priv->band_50; + } WLDBG_EXIT(DBG_LEVEL_0); } @@ -722,8 +774,8 @@ static int mwl_wl_init(struct mwl_priv *priv) hw->vif_data_size = sizeof(struct mwl_vif); hw->sta_data_size = sizeof(struct mwl_sta); - priv->ap_macids_supported = 0x000000ff; - priv->sta_macids_supported = 0x00000100; + priv->ap_macids_supported = 0x0000ffff; + priv->sta_macids_supported = 0x00010000; priv->macids_used = 0; INIT_LIST_HEAD(&priv->vif_list); @@ -754,7 +806,6 @@ static int mwl_wl_init(struct mwl_priv *priv) rc = mwl_tx_init(hw); if (rc) { - WLDBG_ERROR(DBG_LEVEL_0, "%s: fail to initialize TX", MWL_DRV_NAME); goto err_mwl_tx_init; @@ -762,7 +813,6 @@ static int mwl_wl_init(struct mwl_priv *priv) rc = mwl_rx_init(hw); if (rc) { - WLDBG_ERROR(DBG_LEVEL_0, "%s: fail to initialize RX", MWL_DRV_NAME); goto err_mwl_rx_init; @@ -770,7 +820,6 @@ static int mwl_wl_init(struct mwl_priv *priv) rc = mwl_fwcmd_get_hw_specs(hw); if (rc) { - WLDBG_ERROR(DBG_LEVEL_0, "%s: fail to get HW specifications", MWL_DRV_NAME); goto err_get_hw_specs; @@ -792,17 +841,18 @@ static int mwl_wl_init(struct mwl_priv *priv) rc = mwl_fwcmd_set_hw_specs(hw); if (rc) { - WLDBG_ERROR(DBG_LEVEL_0, "%s: fail to set HW specifications", MWL_DRV_NAME); goto err_set_hw_specs; } + WLDBG_PRINT("firmware version: 0x%x", priv->hw_data.fw_release_num); + mwl_fwcmd_radio_disable(hw); - mwl_fwcmd_rf_antenna(hw, WL_ANTENNATYPE_RX, 0); + mwl_fwcmd_rf_antenna(hw, WL_ANTENNATYPE_TX, priv->antenna_tx); - mwl_fwcmd_rf_antenna(hw, WL_ANTENNATYPE_TX, 0); + mwl_fwcmd_rf_antenna(hw, WL_ANTENNATYPE_RX, priv->antenna_rx); hw->wiphy->interface_modes = 0; hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP); @@ -814,7 +864,6 @@ static int mwl_wl_init(struct mwl_priv *priv) rc = ieee80211_register_hw(hw); if (rc) { - WLDBG_ERROR(DBG_LEVEL_0, "%s: fail to register device", MWL_DRV_NAME); goto err_register_hw; @@ -881,7 +930,6 @@ static void mwl_watchdog_ba_events(struct work_struct *work) /* the bitmap is the hw queue number. Map it to the ampdu queue. */ if (bitmap != INVALID_WATCHDOG) { - if (bitmap == SYSADPT_TX_AMPDU_QUEUES) stream_index = 0; else if (bitmap > SYSADPT_TX_AMPDU_QUEUES) @@ -890,28 +938,22 @@ static void mwl_watchdog_ba_events(struct work_struct *work) stream_index = bitmap + 3; /** queue 0 is stream 3*/ if (bitmap != 0xFF) { - /* Check if the stream is in use before disabling it */ streams = &priv->ampdu[stream_index]; if (streams->state == AMPDU_STREAM_ACTIVE) { - ieee80211_stop_tx_ba_session(streams->sta, streams->tid); SPIN_UNLOCK(&priv->locks.stream_lock); mwl_fwcmd_destroy_ba(hw, stream_index); SPIN_LOCK(&priv->locks.stream_lock); } - } else { - for (stream_index = 0; stream_index < SYSADPT_TX_AMPDU_QUEUES; stream_index++) { - streams = &priv->ampdu[stream_index]; if (streams->state == AMPDU_STREAM_ACTIVE) { - ieee80211_stop_tx_ba_session(streams->sta, streams->tid); SPIN_UNLOCK(&priv->locks.stream_lock); @@ -950,19 +992,14 @@ static irqreturn_t mwl_interrupt(int irq, void *dev_id) return IRQ_NONE; if (int_status == 0xffffffff) { - WLDBG_INFO(DBG_LEVEL_0, "card plugged out???"); - } else { - clr_status = int_status; if (int_status & MACREG_A2HRIC_BIT_TX_DONE) { - int_status &= ~MACREG_A2HRIC_BIT_TX_DONE; if (priv->is_tx_schedule == false) { - status = readl(priv->iobase1 + MACREG_REG_A2H_INTERRUPT_STATUS_MASK); writel((status & ~MACREG_A2HRIC_BIT_TX_DONE), priv->iobase1 + MACREG_REG_A2H_INTERRUPT_STATUS_MASK); @@ -972,11 +1009,9 @@ static irqreturn_t mwl_interrupt(int irq, void *dev_id) } if (int_status & MACREG_A2HRIC_BIT_RX_RDY) { - int_status &= ~MACREG_A2HRIC_BIT_RX_RDY; if (priv->is_rx_schedule == false) { - status = readl(priv->iobase1 + MACREG_REG_A2H_INTERRUPT_STATUS_MASK); writel((status & ~MACREG_A2HRIC_BIT_RX_RDY), priv->iobase1 + MACREG_REG_A2H_INTERRUPT_STATUS_MASK); @@ -986,7 +1021,6 @@ static irqreturn_t mwl_interrupt(int irq, void *dev_id) } if (int_status & MACREG_A2HRIC_BA_WATCHDOG) { - status = readl(priv->iobase1 + MACREG_REG_A2H_INTERRUPT_STATUS_MASK); writel((status & ~MACREG_A2HRIC_BA_WATCHDOG), priv->iobase1 + MACREG_REG_A2H_INTERRUPT_STATUS_MASK); @@ -1001,70 +1035,12 @@ static irqreturn_t mwl_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static int atoi(const char *num_str) -{ - int val = 0; - - for (;; num_str++) { - - switch (*num_str) { - - case '0'...'9': - val = 10*val+(*num_str-'0'); - break; - - default: - return val; - } - } -} - -static long atohex(const char *number) -{ - long n = 0; - - if (*number == '0' && (*(number + 1) == 'x' || *(number + 1) == 'X')) - number += 2; - - while (*number <= ' ' && *number > 0) - ++number; - - while ((*number >= '0' && *number <= '9') || - (*number >= 'A' && *number <= 'F') || - (*number >= 'a' && *number <= 'f')) { - - if (*number >= '0' && *number <= '9') { - - n = (n * 0x10) + ((*number++) - '0'); - - } else if (*number >= 'A' && *number <= 'F') { - - n = (n * 0x10) + ((*number++) - 'A' + 10); - - } else { - - n = (n * 0x10) + ((*number++) - 'a' + 10); - - } - } - - return n; -} - -static long atohex2(const char *number) -{ - long n = 0; - - while (*number <= ' ' && *number > 0) - ++number; - if (*number == 0) - return n; - - if (*number == '0' && (*(number + 1) == 'x' || *(number + 1) == 'X')) - n = atohex(number+2); - else - n = atoi(number); +module_pci_driver(mwl_pci_driver); - return n; -} +MODULE_DESCRIPTION(MWL_DESC); +MODULE_VERSION(MWL_DRV_VERSION); +MODULE_AUTHOR("Marvell Semiconductor, Inc."); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_SUPPORTED_DEVICE(MWL_DEV_NAME); +MODULE_DEVICE_TABLE(pci, mwl_pci_id_tbl); @@ -1,5 +1,5 @@ /* -* Copyright (c) 2006-2014 Marvell International Ltd. +* Copyright (c) 2006-2015 Marvell International Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -20,6 +20,8 @@ * */ +#include <linux/skbuff.h> + #include "mwl_sysadpt.h" #include "mwl_dev.h" #include "mwl_debug.h" @@ -72,14 +74,10 @@ int mwl_rx_init(struct ieee80211_hw *hw) rc = mwl_rx_ring_alloc(priv); if (rc) { - WLDBG_ERROR(DBG_LEVEL_4, "allocating RX ring failed"); - } else { - rc = mwl_rx_ring_init(priv); if (rc) { - mwl_rx_ring_free(priv); WLDBG_ERROR(DBG_LEVEL_4, "initializing RX ring failed"); } @@ -128,7 +126,6 @@ void mwl_rx_recv(unsigned long data) curr_desc = priv->desc_data[0].pnext_rx_desc; if (curr_desc == NULL) { - status_mask = readl(priv->iobase1 + MACREG_REG_A2H_INTERRUPT_STATUS_MASK); writel(status_mask | MACREG_A2HRIC_BIT_RX_RDY, priv->iobase1 + MACREG_REG_A2H_INTERRUPT_STATUS_MASK); @@ -141,21 +138,18 @@ void mwl_rx_recv(unsigned long data) while ((curr_desc->rx_control == EAGLE_RXD_CTRL_DMA_OWN) && (work_done < priv->recv_limit)) { - prx_skb = curr_desc->psk_buff; if (prx_skb == NULL) goto out; pci_unmap_single(priv->pdev, - ENDIAN_SWAP32(curr_desc->pphys_buff_data), + ENDIAN_SWAP32(curr_desc->pphys_buff_data), priv->desc_data[0].rx_buf_size, PCI_DMA_FROMDEVICE); pkt_len = curr_desc->pkt_len; if (skb_tailroom(prx_skb) < pkt_len) { - - WLDBG_INFO(DBG_LEVEL_4, "Not enough tail room =%x pkt_len=%x, curr_desc=%x, curr_desc_data=%x", - skb_tailroom(prx_skb), pkt_len, curr_desc, curr_desc->pbuff_data); - dev_kfree_skb_any(prx_skb); + WLDBG_PRINT("Critical error: not enough tail room =%x pkt_len=%x, curr_desc=%x, curr_desc_data=%x", + skb_tailroom(prx_skb), pkt_len, curr_desc, curr_desc->pbuff_data); goto out; } @@ -166,13 +160,16 @@ void mwl_rx_recv(unsigned long data) wh = &((struct mwl_dma_data *)prx_skb->data)->wh; if (ieee80211_has_protected(wh->frame_control)) { - /* Check if hw crypto has been enabled for * this bss. If yes, set the status flags * accordingly */ - mwl_vif = mwl_rx_find_vif_bss(&priv->vif_list, - wh->addr1); + if (ieee80211_has_tods(wh->frame_control)) + mwl_vif = mwl_rx_find_vif_bss(&priv->vif_list, + wh->addr1); + else + mwl_vif = mwl_rx_find_vif_bss(&priv->vif_list, + wh->addr2); if (mwl_vif != NULL && mwl_vif->is_hw_crypto_enabled) { @@ -190,7 +187,6 @@ void mwl_rx_recv(unsigned long data) * Measure of MMIC failure. */ if (status.flag & RX_FLAG_MMIC_ERROR) { - struct mwl_dma_data *tr; tr = (struct mwl_dma_data *)prx_skb->data; @@ -199,7 +195,6 @@ void mwl_rx_recv(unsigned long data) } if (!ieee80211_is_auth(wh->frame_control)) - status.flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_DECRYPTED | RX_FLAG_MMIC_STRIPPED; @@ -242,12 +237,11 @@ static int mwl_rx_ring_alloc(struct mwl_priv *priv) BUG_ON(!priv); priv->desc_data[0].prx_ring = - (struct mwl_rx_desc *)pci_alloc_consistent(priv->pdev, + (struct mwl_rx_desc *)dma_alloc_coherent(&priv->pdev->dev, MAX_NUM_RX_RING_BYTES, - &priv->desc_data[0].pphys_rx_ring); + &priv->desc_data[0].pphys_rx_ring, GFP_KERNEL); if (priv->desc_data[0].prx_ring == NULL) { - WLDBG_ERROR(DBG_LEVEL_4, "can not alloc mem"); WLDBG_EXIT_INFO(DBG_LEVEL_4, "no memory"); return -ENOMEM; @@ -268,15 +262,12 @@ static int mwl_rx_ring_init(struct mwl_priv *priv) WLDBG_ENTER_INFO(DBG_LEVEL_4, "initializing %i descriptors", SYSADPT_MAX_NUM_RX_DESC); if (priv->desc_data[0].prx_ring != NULL) { - priv->desc_data[0].rx_buf_size = SYSADPT_MAX_AGGR_SIZE; for (curr_desc = 0; curr_desc < SYSADPT_MAX_NUM_RX_DESC; curr_desc++) { - CURR_RXD.psk_buff = dev_alloc_skb(priv->desc_data[0].rx_buf_size); if (skb_linearize(CURR_RXD.psk_buff)) { - dev_kfree_skb_any(CURR_RXD.psk_buff); WLDBG_ERROR(DBG_LEVEL_4, "need linearize memory"); WLDBG_EXIT_INFO(DBG_LEVEL_4, "no suitable memory"); @@ -289,10 +280,8 @@ static int mwl_rx_ring_init(struct mwl_priv *priv) CURR_RXD.qos_ctrl = 0x0000; CURR_RXD.channel = 0x00; CURR_RXD.rssi = 0x00; - CURR_RXD.sq2 = 0x00; if (CURR_RXD.psk_buff != NULL) { - CURR_RXD.pkt_len = SYSADPT_MAX_AGGR_SIZE; CURR_RXD.pbuff_data = CURR_RXD.psk_buff->data; CURR_RXD.pphys_buff_data = @@ -312,7 +301,6 @@ static int mwl_rx_ring_init(struct mwl_priv *priv) "rxdesc: %i vnext: 0x%p pnext: 0x%x", curr_desc, CURR_RXD.pnext, ENDIAN_SWAP32(CURR_RXD.pphys_next)); } else { - WLDBG_ERROR(DBG_LEVEL_4, "rxdesc %i: no skbuff available", curr_desc); WLDBG_EXIT_INFO(DBG_LEVEL_4, "no socket buffer"); @@ -347,11 +335,8 @@ static void mwl_rx_ring_cleanup(struct mwl_priv *priv) BUG_ON(!priv); if (priv->desc_data[0].prx_ring != NULL) { - for (curr_desc = 0; curr_desc < SYSADPT_MAX_NUM_RX_DESC; curr_desc++) { - if (CURR_RXD.psk_buff != NULL) { - if (skb_shinfo(CURR_RXD.psk_buff)->nr_frags) skb_shinfo(CURR_RXD.psk_buff)->nr_frags = 0; @@ -387,11 +372,10 @@ static void mwl_rx_ring_free(struct mwl_priv *priv) BUG_ON(!priv); if (priv->desc_data[0].prx_ring != NULL) { - mwl_rx_ring_cleanup(priv); - pci_free_consistent(priv->pdev, - MAX_NUM_RX_RING_BYTES, + dma_free_coherent(&priv->pdev->dev, + MAX_NUM_RX_RING_BYTES, priv->desc_data[0].prx_ring, priv->desc_data[0].pphys_rx_ring); @@ -415,7 +399,7 @@ static inline void mwl_rx_prepare_status(struct mwl_rx_desc *pdesc, status->signal = -(pdesc->rssi + W836X_RSSI_OFFSET); - /* TODO: rate & antenna + /* TODO: rate information report */ if (pdesc->channel > 14) @@ -429,12 +413,10 @@ static inline void mwl_rx_prepare_status(struct mwl_rx_desc *pdesc, /* check if status has a specific error bit (bit 7)set or indicates a general decrypt error */ if ((pdesc->status == GENERAL_DECRYPT_ERR) || (pdesc->status & DECRYPT_ERR_MASK)) { - /* check if status is not equal to 0xFF * the 0xFF check is for backward compatibility */ if (pdesc->status != GENERAL_DECRYPT_ERR) { - if (((pdesc->status & (~DECRYPT_ERR_MASK)) & TKIP_DECRYPT_MIC_ERR) && !((pdesc->status & (WEP_DECRYPT_ICV_ERR | TKIP_DECRYPT_ICV_ERR)))) { @@ -451,7 +433,6 @@ static inline struct mwl_vif *mwl_rx_find_vif_bss(struct list_head *vif_list, u8 struct mwl_vif *mwl_vif; list_for_each_entry(mwl_vif, vif_list, list) { - if (memcmp(bssid, mwl_vif->bssid, ETH_ALEN) == 0) return mwl_vif; } @@ -468,7 +449,6 @@ static inline void mwl_rx_remove_dma_header(struct sk_buff *skb, u16 qos) hdrlen = ieee80211_hdrlen(tr->wh.frame_control); if (hdrlen != sizeof(tr->wh)) { - if (ieee80211_is_data_qos(tr->wh.frame_control)) { memmove(tr->data - hdrlen, &tr->wh, hdrlen - 2); *((u16 *)(tr->data - 2)) = qos; @@ -494,7 +474,6 @@ static int mwl_rx_refill(struct mwl_priv *priv, struct mwl_rx_desc *pdesc) goto nomem; if (skb_linearize(pdesc->psk_buff)) { - dev_kfree_skb_any(pdesc->psk_buff); WLDBG_ERROR(DBG_LEVEL_4, "need linearize memory"); goto nomem; @@ -506,7 +485,6 @@ static int mwl_rx_refill(struct mwl_priv *priv, struct mwl_rx_desc *pdesc) pdesc->qos_ctrl = 0x0000; pdesc->channel = 0x00; pdesc->rssi = 0x00; - pdesc->sq2 = 0x00; pdesc->pkt_len = priv->desc_data[0].rx_buf_size; pdesc->pbuff_data = pdesc->psk_buff->data; @@ -1,5 +1,5 @@ /* -* Copyright (c) 2006-2014 Marvell International Ltd. +* Copyright (c) 2006-2015 Marvell International Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/mwl_sysadpt.h b/mwl_sysadpt.h index 5c509e1..1d7ac67 100644 --- a/mwl_sysadpt.h +++ b/mwl_sysadpt.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2006-2014 Marvell International Ltd. +* Copyright (c) 2006-2015 Marvell International Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -38,11 +38,13 @@ #define SYSADPT_TX_AMPDU_QUEUES 4 -#define SYSADPT_TOTAL_TX_QUEUES SYSADPT_TX_WMM_QUEUES +#define SYSADPT_NUM_OF_AP 16 + +#define SYSADPT_TOTAL_TX_QUEUES (SYSADPT_TX_WMM_QUEUES + SYSADPT_NUM_OF_AP) #define SYSADPT_TOTAL_HW_QUEUES (SYSADPT_TX_WMM_QUEUES + SYSADPT_TX_AMPDU_QUEUES) -#define SYSADPT_NUM_OF_DESC_DATA 4 +#define SYSADPT_NUM_OF_DESC_DATA (4 + SYSADPT_NUM_OF_AP) #define SYSADPT_MAX_NUM_TX_DESC 256 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2006-2014 Marvell International Ltd. +* Copyright (c) 2006-2015 Marvell International Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -21,6 +21,7 @@ */ #include <linux/etherdevice.h> +#include <linux/skbuff.h> #include "mwl_sysadpt.h" #include "mwl_dev.h" @@ -85,14 +86,10 @@ int mwl_tx_init(struct ieee80211_hw *hw) rc = mwl_tx_ring_alloc(priv); if (rc) { - WLDBG_ERROR(DBG_LEVEL_3, "allocating TX ring failed"); - } else { - rc = mwl_tx_ring_init(priv); if (rc) { - mwl_tx_ring_free(priv); WLDBG_ERROR(DBG_LEVEL_3, "initializing TX ring failed"); } @@ -158,13 +155,11 @@ void mwl_tx_xmit(struct ieee80211_hw *hw, qos = 0; if (skb->protocol == cpu_to_be16(ETH_P_PAE)) { - index = IEEE80211_AC_VO; eapol_frame = true; } if (ieee80211_is_mgmt(wh->frame_control)) { - mgmtframe = true; mgmt = (struct ieee80211_mgmt *)skb->data; } @@ -177,7 +172,6 @@ void mwl_tx_xmit(struct ieee80211_hw *hw, mwl_vif = MWL_VIF(tx_info->control.vif); if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - wh->seq_ctrl &= ENDIAN_SWAP16(IEEE80211_SCTL_FRAG); wh->seq_ctrl |= ENDIAN_SWAP16(mwl_vif->seqno); mwl_vif->seqno += 0x10; @@ -188,11 +182,8 @@ void mwl_tx_xmit(struct ieee80211_hw *hw, xmitcontrol = 0; if (mgmtframe || ieee80211_is_ctl(wh->frame_control)) { - qos = 0; - } else if (ieee80211_is_data(wh->frame_control)) { - qos &= ~MWL_QOS_ACK_POLICY_MASK; if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { @@ -204,25 +195,31 @@ void mwl_tx_xmit(struct ieee80211_hw *hw, } if (is_multicast_ether_addr(wh->addr1)) { - xmitcontrol |= EAGLE_TXD_XMITCTRL_USE_MC_RATE; if (ccmp) { - mwl_tx_insert_ccmp_hdr(((struct mwl_dma_data *)skb->data)->data, - mwl_vif->keyidx, mwl_vif->iv16, mwl_vif->iv32); + mwl_vif->keyidx, + mwl_vif->iv16, + mwl_vif->iv32); INCREASE_IV(mwl_vif->iv16, mwl_vif->iv32); } - } else { - if (ccmp) { + if (mwl_vif->is_sta == true) { + mwl_tx_insert_ccmp_hdr(((struct mwl_dma_data *)skb->data)->data, + mwl_vif->keyidx, + mwl_vif->iv16, + mwl_vif->iv32); + INCREASE_IV(mwl_vif->iv16, mwl_vif->iv32); + } else { + struct mwl_sta *sta_info = MWL_STA(sta); - struct mwl_sta *sta_info = MWL_STA(sta); - - mwl_tx_insert_ccmp_hdr(((struct mwl_dma_data *)skb->data)->data, - 0, sta_info->iv16, sta_info->iv32); - INCREASE_IV(sta_info->iv16, sta_info->iv32); + mwl_tx_insert_ccmp_hdr(((struct mwl_dma_data *)skb->data)->data, + 0, sta_info->iv16, + sta_info->iv32); + INCREASE_IV(sta_info->iv16, sta_info->iv32); + } } } } @@ -237,13 +234,10 @@ void mwl_tx_xmit(struct ieee80211_hw *hw, * been setup. */ if (mgmtframe) { - if (unlikely(ieee80211_is_action(wh->frame_control) && - mgmt->u.action.category == WLAN_CATEGORY_BACK && - mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ)) { - + mgmt->u.action.category == WLAN_CATEGORY_BACK && + mgmt->u.action.u.addba_req.action_code == WLAN_ACTION_ADDBA_REQ)) { u16 capab = ENDIAN_SWAP16(mgmt->u.action.u.addba_req.capab); - tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; index = mwl_tx_tid_queue_mapping(tid); } @@ -253,7 +247,6 @@ void mwl_tx_xmit(struct ieee80211_hw *hw, if (sta && sta->ht_cap.ht_supported && !eapol_frame && ieee80211_is_data_qos(wh->frame_control)) { - tid = qos & 0xf; mwl_tx_count_packet(sta, tid); @@ -261,14 +254,11 @@ void mwl_tx_xmit(struct ieee80211_hw *hw, stream = mwl_fwcmd_lookup_stream(hw, sta->addr, tid); if (stream != NULL) { - if (stream->state == AMPDU_STREAM_ACTIVE) { - WARN_ON(!(qos & MWL_QOS_ACK_POLICY_BLOCKACK)); txpriority = (SYSADPT_TX_WMM_QUEUES + stream->idx) % SYSADPT_TOTAL_HW_QUEUES; - } else if (stream->state == AMPDU_STREAM_NEW) { /* We get here if the driver sends us packets * after we've initiated a stream, but before @@ -297,7 +287,6 @@ void mwl_tx_xmit(struct ieee80211_hw *hw, dev_kfree_skb_any(skb); return; } - } else { /* Defer calling mwl8k_start_stream so that the current * skb can go out before the ADDBA request. This @@ -305,7 +294,6 @@ void mwl_tx_xmit(struct ieee80211_hw *hw, * as described above. */ if (mwl_fwcmd_ampdu_allowed(sta, tid)) { - stream = mwl_fwcmd_add_stream(hw, sta, tid); if (stream != NULL) @@ -314,9 +302,7 @@ void mwl_tx_xmit(struct ieee80211_hw *hw, } SPIN_UNLOCK(&priv->locks.stream_lock); - } else { - qos &= ~MWL_QOS_ACK_POLICY_MASK; qos |= MWL_QOS_ACK_POLICY_NORMAL; } @@ -330,12 +316,9 @@ void mwl_tx_xmit(struct ieee80211_hw *hw, tx_ctrl->ccmp = ccmp; if (skb_queue_len(&priv->txq[index]) > priv->txq_limit) { - dev_kfree_skb_any(skb); WLDBG_INFO(DBG_LEVEL_3, "queue len > limit"); - } else { - skb_queue_tail(&priv->txq[index], skb); } @@ -344,7 +327,6 @@ void mwl_tx_xmit(struct ieee80211_hw *hw, /* Initiate the ampdu session here */ if (start_ba_session) { - SPIN_LOCK(&priv->locks.stream_lock); if (mwl_fwcmd_start_stream(hw, stream)) mwl_fwcmd_remove_stream(hw, stream); @@ -371,13 +353,11 @@ void mwl_tx_done(unsigned long data) SPIN_LOCK_IRQSAVE(&priv->locks.xmit_lock, flags); for (num = 0; num < SYSADPT_NUM_OF_DESC_DATA; num++) { - while (STALE_TXD(num) && (STALE_TXD(num)->status & ENDIAN_SWAP32(EAGLE_TXD_STATUS_OK)) && (!(STALE_TXD(num)->status & ENDIAN_SWAP32(EAGLE_TXD_STATUS_FW_OWNED)))) { - pci_unmap_single(priv->pdev, - ENDIAN_SWAP32(STALE_TXD(num)->pkt_ptr), + ENDIAN_SWAP32(STALE_TXD(num)->pkt_ptr), STALE_TXD(num)->psk_buff->len, PCI_DMA_TODEVICE); done_skb = STALE_TXD(num)->psk_buff; @@ -395,8 +375,11 @@ void mwl_tx_done(unsigned long data) tr = (struct mwl_dma_data *)done_skb->data; - if (ieee80211_is_assoc_resp(tr->wh.frame_control)) { - + if (ieee80211_is_assoc_resp(tr->wh.frame_control) || + ieee80211_is_reassoc_resp(tr->wh.frame_control) || + ieee80211_is_auth(tr->wh.frame_control) || + ieee80211_is_nullfunc(tr->wh.frame_control) || + ieee80211_is_qos_nullfunc(tr->wh.frame_control)) { /* Remove H/W dma header */ hdrlen = ieee80211_hdrlen(tr->wh.frame_control); @@ -416,9 +399,7 @@ void mwl_tx_done(unsigned long data) info->flags |= IEEE80211_TX_STAT_ACK; ieee80211_tx_status(hw, done_skb); - } else { - /* Due to firmware does not return real tx status, * we should not ACK data frame, otherwise, hostap will * think station is always existed. @@ -432,10 +413,9 @@ void mwl_tx_done(unsigned long data) } } - SPIN_UNLOCK_IRQRESTORE(&priv->locks.xmit_lock, flags); + SPIN_UNLOCK_IRQRESTORE(&priv->locks.xmit_lock, flags); if (priv->irq != -1) { - u32 status; status = readl(priv->iobase1 + MACREG_REG_A2H_INTERRUPT_STATUS_MASK); @@ -462,19 +442,17 @@ static int mwl_tx_ring_alloc(struct mwl_priv *priv) BUG_ON(!priv); - mem = (u8 *)pci_alloc_consistent(priv->pdev, + mem = (u8 *)dma_alloc_coherent(&priv->pdev->dev, MAX_NUM_TX_RING_BYTES * SYSADPT_NUM_OF_DESC_DATA, - &priv->desc_data[0].pphys_tx_ring); + &priv->desc_data[0].pphys_tx_ring, GFP_KERNEL); if (mem == NULL) { - WLDBG_ERROR(DBG_LEVEL_3, "can not alloc mem"); WLDBG_EXIT_INFO(DBG_LEVEL_3, "no memory"); return -ENOMEM; } for (num = 0; num < SYSADPT_NUM_OF_DESC_DATA; num++) { - WLDBG_INFO(DBG_LEVEL_3, "allocating %i (0x%x) bytes", MAX_NUM_TX_RING_BYTES, MAX_NUM_TX_RING_BYTES); @@ -505,16 +483,13 @@ static int mwl_tx_ring_init(struct mwl_priv *priv) BUG_ON(!priv); for (num = 0; num < SYSADPT_NUM_OF_DESC_DATA; num++) { - skb_queue_head_init(&priv->txq[num]); priv->fw_desc_cnt[num] = 0; if (priv->desc_data[num].ptx_ring != NULL) { - WLDBG_INFO(DBG_LEVEL_3, "initializing %i descriptors", SYSADPT_MAX_NUM_TX_DESC); for (curr_desc = 0; curr_desc < SYSADPT_MAX_NUM_TX_DESC; curr_desc++) { - CURR_TXD(num).status = ENDIAN_SWAP32(EAGLE_TXD_STATUS_IDLE); CURR_TXD(num).pnext = &NEXT_TXD(num); CURR_TXD(num).pphys_next = @@ -535,8 +510,7 @@ static int mwl_tx_ring_init(struct mwl_priv *priv) "last txdesc vnext: 0x%p pnext: 0x%x pstale 0x%x vfirst 0x%x", LAST_TXD(num).pnext, ENDIAN_SWAP32(LAST_TXD(num).pphys_next), priv->desc_data[num].pstale_tx_desc, priv->desc_data[num].pnext_tx_desc); - } else - { + } else { WLDBG_ERROR(DBG_LEVEL_3, "no valid TX mem"); WLDBG_EXIT_INFO(DBG_LEVEL_3, "no valid memory"); return -ENOMEM; @@ -559,15 +533,11 @@ static void mwl_tx_ring_cleanup(struct mwl_priv *priv) BUG_ON(!priv); for (num = 0; num < SYSADPT_NUM_OF_DESC_DATA; num++) { - skb_queue_purge(&priv->txq[num]); priv->fw_desc_cnt[num] = 0; if (priv->desc_data[num].ptx_ring != NULL) { - for (curr_desc = 0; curr_desc < SYSADPT_MAX_NUM_TX_DESC; curr_desc++) { - if (CURR_TXD(num).psk_buff != NULL) { - WLDBG_INFO(DBG_LEVEL_3, "unmapped and free'd txdesc %i vaddr: 0x%p paddr: 0x%x", curr_desc, CURR_TXD(num).psk_buff->data, @@ -599,15 +569,13 @@ static void mwl_tx_ring_free(struct mwl_priv *priv) BUG_ON(!priv); if (priv->desc_data[0].ptx_ring != NULL) { - - pci_free_consistent(priv->pdev, - MAX_NUM_TX_RING_BYTES * SYSADPT_NUM_OF_DESC_DATA, + dma_free_coherent(&priv->pdev->dev, + MAX_NUM_TX_RING_BYTES * SYSADPT_NUM_OF_DESC_DATA, priv->desc_data[0].ptx_ring, priv->desc_data[0].pphys_tx_ring); } for (num = 0; num < SYSADPT_NUM_OF_DESC_DATA; num++) { - if (priv->desc_data[num].ptx_ring != NULL) priv->desc_data[num].ptx_ring = NULL; priv->desc_data[num].pstale_tx_desc = NULL; @@ -689,20 +657,16 @@ static inline void mwl_tx_encapsulate_frame(struct mwl_priv *priv, data_pad = 0; if (key_conf != NULL) { - head_pad = key_conf->iv_len; switch (key_conf->cipher) { - case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: data_pad = 4; break; - case WLAN_CIPHER_SUITE_TKIP: data_pad = 12; break; - case WLAN_CIPHER_SUITE_CCMP: data_pad = 8; *ccmp = true; @@ -770,10 +734,8 @@ static inline void mwl_tx_count_packet(struct ieee80211_sta *sta, u8 tid) * an ampdu stream to be started. */ if (jiffies - tx_stats->start_time > HZ) { - tx_stats->pkts = 0; tx_stats->start_time = 0; - } else tx_stats->pkts++; } @@ -796,9 +758,7 @@ static inline void mwl_tx_skbs(struct ieee80211_hw *hw) SPIN_LOCK_IRQSAVE(&priv->locks.xmit_lock, flags); while (num--) { - while (skb_queue_len(&priv->txq[num]) > 0) { - if (priv->desc_data[num].pnext_tx_desc == NULL) break; @@ -808,7 +768,6 @@ static inline void mwl_tx_skbs(struct ieee80211_hw *hw) * when fwDescCnt==256 and pStaleTxDesc->Status==0. */ if (priv->desc_data[num].pnext_tx_desc->status != EAGLE_TXD_STATUS_IDLE) { - /* Interrupt F/W anyway */ if (priv->desc_data[num].pnext_tx_desc->status & ENDIAN_SWAP32(EAGLE_TXD_STATUS_FW_OWNED)) @@ -816,7 +775,6 @@ static inline void mwl_tx_skbs(struct ieee80211_hw *hw) priv->iobase1 + MACREG_REG_H2A_INTERRUPT_EVENTS); break; - } tx_skb = skb_dequeue(&priv->txq[num]); @@ -830,7 +788,7 @@ static inline void mwl_tx_skbs(struct ieee80211_hw *hw) priv->desc_data[num].pnext_tx_desc->qos_ctrl = tx_ctrl->qos_ctrl; priv->desc_data[num].pnext_tx_desc->psk_buff = tx_skb; priv->desc_data[num].pnext_tx_desc->pkt_len = ENDIAN_SWAP16(tx_skb->len); - priv->desc_data[num].pnext_tx_desc->ack_wcb_addr = 0; + priv->desc_data[num].pnext_tx_desc->packet_info = 0; priv->desc_data[num].pnext_tx_desc->data_rate = 0; priv->desc_data[num].pnext_tx_desc->sta_info = tx_ctrl->sta_info; priv->desc_data[num].pnext_tx_desc->type = tx_ctrl->type; @@ -853,39 +811,3 @@ static inline void mwl_tx_skbs(struct ieee80211_hw *hw) WLDBG_EXIT(DBG_LEVEL_3); } - -#if 0 -static void mwl_tx_descriptor_dump(struct mwl_priv *priv) -{ - int curr_desc; - int num; - char *p1 = NULL; - char *p2 = NULL; - char str1[12] = " <- CURR_TXD"; - char str2[14] = " <- NEXT_TXD"; - char blank[2] = " "; - - WLDBG_ENTER(DBG_LEVEL_3); - - BUG_ON(!priv); - - for (num = 0; num < SYSADPT_NUM_OF_DESC_DATA; num++) { - - if (priv->desc_data[num].ptx_ring != NULL) { - - for (curr_desc = 0; curr_desc < SYSADPT_MAX_NUM_TX_DESC; curr_desc++) { - - p1 = blank; - p2 = blank; - if ((u32)&CURR_TXD(num) == (u32)priv->desc_data[num].pstale_tx_desc) - p1 = str1; - if ((u32)&CURR_TXD(num) == (u32)priv->desc_data[num].pnext_tx_desc) - p2 = str2; - WLDBG_PRINT("TxDescriptor(%d.%d) Status=0x%x %s %s", num, curr_desc, CURR_TXD(num).status, p1, p2); - } - } - } - - WLDBG_EXIT(DBG_LEVEL_3); -} -#endif @@ -1,5 +1,5 @@ /* -* Copyright (c) 2006-2014 Marvell International Ltd. +* Copyright (c) 2006-2015 Marvell International Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/test/README b/test/README index a59a2c4..a299f47 100644 --- a/test/README +++ b/test/README @@ -1,16 +1,16 @@ 1. Files for test: - a. 88W8864.bin: F/W binary. Please put this file under directory '/lib/firmware'. - b. Mamba_FCC_v1.2_5G4TX.ini: power table for Mamba. - c. mwlwifi.ko: 88W8864 mac80211 driver kernel module. - d. hostapd.conf: configuration file used to configure hostapd. - e. openwrt-mvebu-jffs2-128k.img: OpenWRT download image (built with kernel cfg80211/mac80211, iw and hostapd). + a. 88W8864.bin: F/W binary. Please put this file under directory '/lib/firmware/mwlwifi'. + b. mwlwifi.ko: 88W8864 mac80211 driver kernel module. + c. hostapd.conf: configuration file used to configure hostapd. + d. wpa_supplicant.conf: configuration file used to configure wpa_supplicant. + e. openwrt-mvebu-armada-xp-mamba-squashfs-factory.img: OpenWRT download image (built with kernel cfg80211/mac80211, iw, hostapd and wpa_supplicant). 2. Bring up driver: a. iw reg set US --> set regulatory domain (Note: cfg80211 will disable DFS channels). - b. insmod mwlwifi.ko fw_name=88W8864.bin pwr_tbl=Mamba_FCC_v1.2_5G4TX.ini + b. insmod mwlwifi.ko --> After module is inserted, physical interfaces phy0 and phy1 and network device wlan0 and wlan1 will be created. You can issue "iw dev" to check them. c. hostapd -B ./hostapd.conf @@ -46,7 +46,7 @@ (5490 - 5590 @ 80), (30, 0) (5650 - 5710 @ 40), (30, 0) (5735 - 5835 @ 80), (30, 0) - It allows you set use two ranges to do 80 MHz operation (100 ~ 116) and (149 ~ 161). + It allows you to use two ranges to do 80 MHz operation (100 ~ 116) and (149 ~ 161). b. After regulatory is set and make sure the channel range you want to use is allowable by the setting regulatory, you can modify hostapd.conf to run 80 Mhz as: @@ -76,3 +76,78 @@ ht_capab=[LDPC][HT40-][SHORT-GI-20][SHORT-GI-40] vht_oper_centr_freq_seg0_idx=106 +5. Station mode: + + a. Use iw utlity to set correct regulatory domain. + + b. Make sure dirver is loaded. + + c. wpa_supplicant -B -D nl80211 -i wlan1 -c wpa_supplicant.conf + --> There are few sample configuration files under this directory. Please use them to do test. + + d. There are two ways to change configuration for wpa_supplicant: + + * Kill and rerun + killall wpa_supplicant + <Modify configuration file for new setting> + wpa_supplicant -B -D nl80211 -i wlan1 -c wpa_supplicant.conf + + * Reload configuration file + <Modify configuration file for new setting> + kill -1 <PID of wpa_supplicant> + +6. Debug mode: + + a. hostapd: + + hostapd -d[dd] ./hostapd.conf + + b. wpa_supplicant: + + wpa_supplicant -ddK -D nl80211 -i wlan1 -c wpa_supplicant.conf + +7. Add/Delete interface via iw: + + iw dev <devname> del + iw dev <devname> interface add <name> type <type> + + You can omit the 'phy' or 'dev' if the identification is unique, + e.g. "iw wlan0 info" or "iw phy0 info". (Don't when scripting.) + + Example: + root@OpenWrt:/test# iw dev + phy#1 + Interface wlan1 + ifindex 6 + wdev 0x100000001 + addr 00:25:9c:13:01:9a + type managed + phy#0 + Interface wlan0 + ifindex 8 + wdev 0x3 + addr 00:25:9c:13:01:99 + type AP + root@OpenWrt:/test# iw wlan0 del + root@OpenWrt:/test# iw dev + phy#1 + Interface wlan1 + ifindex 6 + wdev 0x100000001 + addr 00:25:9c:13:01:9a + type managed + root@OpenWrt:/test# iw phy0 interface add wlan0 type managed + root@OpenWrt:/test# iw dev + phy#1 + Interface wlan1 + ifindex 6 + wdev 0x100000001 + addr 00:25:9c:13:01:9a + type managed + phy#0 + Interface wlan0 + ifindex 9 + wdev 0x4 + addr 00:25:9c:13:01:99 + type managed + root@OpenWrt:/test#
\ No newline at end of file diff --git a/test/setup.sh b/test/setup.sh index 142ec83..30fd0b3 100644 --- a/test/setup.sh +++ b/test/setup.sh @@ -1,4 +1,4 @@ iw reg set US -insmod mwlwifi.ko fw_name=88W8864.bin pwr_tbl=Mamba_FCC_v1.2_5G4TX.ini +insmod mwlwifi.ko hostapd -B ./hostapd.conf brctl addif br-lan wlan1 diff --git a/test/setup_multi_bssid.sh b/test/setup_multi_bssid.sh index 3e76607..8ca3d61 100644 --- a/test/setup_multi_bssid.sh +++ b/test/setup_multi_bssid.sh @@ -1,5 +1,5 @@ iw reg set US -insmod mwlwifi.ko fw_name=88W8864.bin pwr_tbl=Mamba_FCC_v1.2_5G4TX.ini +insmod mwlwifi.ko hostapd -B ./hostapd.conf brctl addif br-lan wlan1 brctl addif br-lan wlan1_0 diff --git a/test/wpa_supplicant.conf.open b/test/wpa_supplicant.conf.open new file mode 100755 index 0000000..d7677b9 --- /dev/null +++ b/test/wpa_supplicant.conf.open @@ -0,0 +1,8 @@ +ctrl_interface=/var/run/wpa_supplicant + +network={ + +ssid="mwlwifi_ap_test" +key_mgmt=NONE + +} diff --git a/test/wpa_supplicant.conf.psk b/test/wpa_supplicant.conf.psk new file mode 100755 index 0000000..ce154a6 --- /dev/null +++ b/test/wpa_supplicant.conf.psk @@ -0,0 +1,9 @@ +ctrl_interface=/var/run/wpa_supplicant + +network={ + +ssid="mwlwifi_ap_test" +key_mgmt=WPA-PSK +psk="12345678" + +} |