summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/bcma/core.c8
-rw-r--r--drivers/bcma/main.c5
-rw-r--r--drivers/net/wireless/ath/ath5k/ath5k.h3
-rw-r--r--drivers/net/wireless/ath/ath5k/eeprom.c6
-rw-r--r--drivers/net/wireless/ath/ath5k/eeprom.h3
-rw-r--r--drivers/net/wireless/ath/ath5k/phy.c20
-rw-r--r--drivers/net/wireless/ath/ath5k/reset.c4
-rw-r--r--drivers/net/wireless/ath/ath6kl/htc_pipe.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_eeprom.c17
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h49
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/common.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c188
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h1
-rw-r--r--drivers/net/wireless/ath/carl9170/tx.c69
-rw-r--r--drivers/net/wireless/ath/wil6210/Makefile4
-rw-r--r--drivers/net/wireless/ath/wil6210/debugfs.c14
-rw-r--r--drivers/net/wireless/b43/Kconfig6
-rw-r--r--drivers/net/wireless/b43/b43.h6
-rw-r--r--drivers/net/wireless/b43/main.c7
-rw-r--r--drivers/net/wireless/b43/phy_ht.c5
-rw-r--r--drivers/net/wireless/brcm80211/Kconfig5
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/Makefile3
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd.h7
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h2
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c30
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c33
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c42
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h34
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c39
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h2
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c28
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c382
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h25
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c22
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h87
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/usb.c37
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c6
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/Makefile4
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/led.c126
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/led.h36
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c4
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h4
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/main.c11
-rw-r--r--drivers/net/wireless/brcm80211/brcmutil/utils.c25
-rw-r--r--drivers/net/wireless/brcm80211/include/brcmu_utils.h27
-rw-r--r--drivers/net/wireless/mwifiex/Makefile1
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c157
-rw-r--r--drivers/net/wireless/mwifiex/cmdevt.c2
-rw-r--r--drivers/net/wireless/mwifiex/ethtool.c70
-rw-r--r--drivers/net/wireless/mwifiex/fw.h44
-rw-r--r--drivers/net/wireless/mwifiex/init.c6
-rw-r--r--drivers/net/wireless/mwifiex/ioctl.h23
-rw-r--r--drivers/net/wireless/mwifiex/main.h4
-rw-r--r--drivers/net/wireless/mwifiex/pcie.c156
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmd.c79
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmdresp.c2
-rw-r--r--drivers/net/wireless/mwifiex/sta_ioctl.c10
-rw-r--r--drivers/net/wireless/mwifiex/util.c5
-rw-r--r--drivers/net/wireless/mwl8k.c105
-rw-r--r--drivers/net/wireless/ray_cs.c6
-rw-r--r--drivers/net/wireless/rndis_wlan.c3
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00pci.c4
-rw-r--r--drivers/ssb/driver_chipcommon.c2
-rw-r--r--drivers/ssb/driver_chipcommon_pmu.c41
-rw-r--r--drivers/ssb/driver_mipscore.c25
-rw-r--r--drivers/ssb/driver_pcicore.c15
-rw-r--r--drivers/ssb/embedded.c5
-rw-r--r--drivers/ssb/main.c51
-rw-r--r--drivers/ssb/pci.c97
-rw-r--r--drivers/ssb/pcmcia.c46
-rw-r--r--drivers/ssb/scan.c31
-rw-r--r--drivers/ssb/sprom.c4
-rw-r--r--drivers/ssb/ssb_private.h19
-rw-r--r--include/linux/ssb/ssb.h6
77 files changed, 1870 insertions, 601 deletions
diff --git a/drivers/bcma/core.c b/drivers/bcma/core.c
index 03bbe104338f..17b26ce7e051 100644
--- a/drivers/bcma/core.c
+++ b/drivers/bcma/core.c
@@ -104,7 +104,13 @@ void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status, bool on)
if (i)
bcma_err(core->bus, "PLL enable timeout\n");
} else {
- bcma_warn(core->bus, "Disabling PLL not supported yet!\n");
+ /*
+ * Mask the PLL but don't wait for it to be disabled. PLL may be
+ * shared between cores and will be still up if there is another
+ * core using it.
+ */
+ bcma_mask32(core, BCMA_CLKCTLST, ~req);
+ bcma_read32(core, BCMA_CLKCTLST);
}
}
EXPORT_SYMBOL_GPL(bcma_core_pll_ctl);
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index 9a6188add590..f72f52b4b1dd 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -120,6 +120,11 @@ static int bcma_register_cores(struct bcma_bus *bus)
continue;
}
+ /* Only first GMAC core on BCM4706 is connected and working */
+ if (core->id.id == BCMA_CORE_4706_MAC_GBIT &&
+ core->core_unit > 0)
+ continue;
+
core->dev.release = bcma_release_core_dev;
core->dev.bus = &bcma_bus_type;
dev_set_name(&core->dev, "bcma%d:%d", bus->num, dev_id);
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index 3150def17193..2d691b8b95b9 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -1523,7 +1523,8 @@ int ath5k_hw_dma_stop(struct ath5k_hw *ah);
/* EEPROM access functions */
int ath5k_eeprom_init(struct ath5k_hw *ah);
void ath5k_eeprom_detach(struct ath5k_hw *ah);
-
+int ath5k_eeprom_mode_from_channel(struct ath5k_hw *ah,
+ struct ieee80211_channel *channel);
/* Protocol Control Unit Functions */
/* Helpers */
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c
index b7e0258887e7..94d34ee02265 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.c
+++ b/drivers/net/wireless/ath/ath5k/eeprom.c
@@ -1779,7 +1779,8 @@ ath5k_eeprom_detach(struct ath5k_hw *ah)
}
int
-ath5k_eeprom_mode_from_channel(struct ieee80211_channel *channel)
+ath5k_eeprom_mode_from_channel(struct ath5k_hw *ah,
+ struct ieee80211_channel *channel)
{
switch (channel->hw_value) {
case AR5K_MODE_11A:
@@ -1789,6 +1790,7 @@ ath5k_eeprom_mode_from_channel(struct ieee80211_channel *channel)
case AR5K_MODE_11B:
return AR5K_EEPROM_MODE_11B;
default:
- return -1;
+ ATH5K_WARN(ah, "channel is not A/B/G!");
+ return AR5K_EEPROM_MODE_11A;
}
}
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h
index 94a9bbea6874..693296ee9693 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.h
+++ b/drivers/net/wireless/ath/ath5k/eeprom.h
@@ -493,6 +493,3 @@ struct ath5k_eeprom_info {
/* Antenna raw switch tables */
u32 ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
};
-
-int
-ath5k_eeprom_mode_from_channel(struct ieee80211_channel *channel);
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index a78afa98c650..d6bc7cb61bfb 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -1612,11 +1612,7 @@ ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
ah->ah_cal_mask |= AR5K_CALIBRATION_NF;
- ee_mode = ath5k_eeprom_mode_from_channel(ah->ah_current_channel);
- if (WARN_ON(ee_mode < 0)) {
- ah->ah_cal_mask &= ~AR5K_CALIBRATION_NF;
- return;
- }
+ ee_mode = ath5k_eeprom_mode_from_channel(ah, ah->ah_current_channel);
/* completed NF calibration, test threshold */
nf = ath5k_hw_read_measured_noise_floor(ah);
@@ -2317,12 +2313,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode)
def_ant = ah->ah_def_ant;
- ee_mode = ath5k_eeprom_mode_from_channel(channel);
- if (ee_mode < 0) {
- ATH5K_ERR(ah,
- "invalid channel: %d\n", channel->center_freq);
- return;
- }
+ ee_mode = ath5k_eeprom_mode_from_channel(ah, channel);
switch (ant_mode) {
case AR5K_ANTMODE_DEFAULT:
@@ -3622,12 +3613,7 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
return -EINVAL;
}
- ee_mode = ath5k_eeprom_mode_from_channel(channel);
- if (ee_mode < 0) {
- ATH5K_ERR(ah,
- "invalid channel: %d\n", channel->center_freq);
- return -EINVAL;
- }
+ ee_mode = ath5k_eeprom_mode_from_channel(ah, channel);
/* Initialize TX power table */
switch (ah->ah_radio) {
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
index e2d8b2cf19eb..a3399c4f13a9 100644
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -984,9 +984,7 @@ ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
if (ah->ah_version == AR5K_AR5210)
return;
- ee_mode = ath5k_eeprom_mode_from_channel(channel);
- if (WARN_ON(ee_mode < 0))
- return;
+ ee_mode = ath5k_eeprom_mode_from_channel(ah, channel);
/* Adjust power delta for channel 14 */
if (channel->center_freq == 2484)
diff --git a/drivers/net/wireless/ath/ath6kl/htc_pipe.c b/drivers/net/wireless/ath/ath6kl/htc_pipe.c
index 281390178e3d..9adb56741bc3 100644
--- a/drivers/net/wireless/ath/ath6kl/htc_pipe.c
+++ b/drivers/net/wireless/ath/ath6kl/htc_pipe.c
@@ -988,8 +988,6 @@ static int ath6kl_htc_pipe_rx_complete(struct ath6kl *ar, struct sk_buff *skb,
htc_hdr = (struct htc_frame_hdr *) netdata;
- ep = &target->endpoint[htc_hdr->eid];
-
if (htc_hdr->eid >= ENDPOINT_MAX) {
ath6kl_dbg(ATH6KL_DBG_HTC,
"HTC Rx: invalid EndpointID=%d\n",
@@ -997,6 +995,7 @@ static int ath6kl_htc_pipe_rx_complete(struct ath6kl *ar, struct sk_buff *skb,
status = -EINVAL;
goto free_skb;
}
+ ep = &target->endpoint[htc_hdr->eid];
payload_len = le16_to_cpu(get_unaligned(&htc_hdr->payld_len));
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index 881e989ea470..e6b92ff265fd 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -3606,6 +3606,12 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz);
REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value);
+ if ((AR_SREV_9462(ah)) && (ah->rxchainmask == 0x2)) {
+ value = ar9003_hw_ant_ctrl_chain_get(ah, 1, is2ghz);
+ REG_RMW_FIELD(ah, switch_chain_reg[0],
+ AR_SWITCH_TABLE_ALL, value);
+ }
+
for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
if ((ah->rxchainmask & BIT(chain)) ||
(ah->txchainmask & BIT(chain))) {
@@ -3772,6 +3778,17 @@ static void ar9003_hw_atten_apply(struct ath_hw *ah, struct ath9k_channel *chan)
AR_PHY_EXT_ATTEN_CTL_2,
};
+ if ((AR_SREV_9462(ah)) && (ah->rxchainmask == 0x2)) {
+ value = ar9003_hw_atten_chain_get(ah, 1, chan);
+ REG_RMW_FIELD(ah, ext_atten_reg[0],
+ AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value);
+
+ value = ar9003_hw_atten_chain_get_margin(ah, 1, chan);
+ REG_RMW_FIELD(ah, ext_atten_reg[0],
+ AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN,
+ value);
+ }
+
/* Test value. if 0 then attenuation is unused. Don't load anything. */
for (i = 0; i < 3; i++) {
if (ah->txchainmask & BIT(i)) {
diff --git a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h
index ccc42a71b436..999ab08c34e6 100644
--- a/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h
@@ -37,28 +37,28 @@ static const u32 ar9462_pciephy_clkreq_enable_L1_2p0[][2] = {
/* Addr allmodes */
{0x00018c00, 0x18253ede},
{0x00018c04, 0x000801d8},
- {0x00018c08, 0x0003580c},
+ {0x00018c08, 0x0003780c},
};
static const u32 ar9462_2p0_baseband_postamble[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a800d},
{0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a01ae},
- {0x00009824, 0x5ac640de, 0x5ac640d0, 0x5ac640d0, 0x63c640da},
+ {0x00009824, 0x63c640de, 0x5ac640d0, 0x5ac640d0, 0x63c640da},
{0x00009828, 0x0796be89, 0x0696b081, 0x0696b881, 0x09143e81},
{0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
{0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
{0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
- {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
+ {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a2},
{0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020},
{0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000d8},
{0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec86d2e},
- {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3376605e, 0x32395d5e},
+ {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3236605e, 0x32365a5e},
{0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
{0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
- {0x00009e3c, 0xcf946222, 0xcf946222, 0xcfd5c782, 0xcfd5c282},
+ {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282},
{0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27},
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
@@ -82,9 +82,9 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = {
{0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982},
{0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000a3a4, 0x00000010, 0x00000010, 0x00000000, 0x00000000},
+ {0x0000a3a4, 0x00000050, 0x00000050, 0x00000000, 0x00000000},
{0x0000a3a8, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa},
- {0x0000a3ac, 0xaaaaaa00, 0xaaaaaa30, 0xaaaaaa00, 0xaaaaaa00},
+ {0x0000a3ac, 0xaaaaaa00, 0xaa30aa30, 0xaaaaaa00, 0xaaaaaa00},
{0x0000a41c, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce},
{0x0000a420, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce},
{0x0000a424, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce},
@@ -363,14 +363,14 @@ static const u32 ar9462_pciephy_clkreq_disable_L1_2p0[][2] = {
/* Addr allmodes */
{0x00018c00, 0x18213ede},
{0x00018c04, 0x000801d8},
- {0x00018c08, 0x0003580c},
+ {0x00018c08, 0x0003780c},
};
static const u32 ar9462_pciephy_pll_on_clkreq_disable_L1_2p0[][2] = {
/* Addr allmodes */
{0x00018c00, 0x18212ede},
{0x00018c04, 0x000801d8},
- {0x00018c08, 0x0003580c},
+ {0x00018c08, 0x0003780c},
};
static const u32 ar9462_2p0_radio_postamble_sys2ant[][5] = {
@@ -775,7 +775,7 @@ static const u32 ar9462_2p0_baseband_core[][2] = {
{0x00009fc0, 0x803e4788},
{0x00009fc4, 0x0001efb5},
{0x00009fcc, 0x40000014},
- {0x00009fd0, 0x01193b93},
+ {0x00009fd0, 0x0a193b93},
{0x0000a20c, 0x00000000},
{0x0000a220, 0x00000000},
{0x0000a224, 0x00000000},
@@ -850,7 +850,7 @@ static const u32 ar9462_2p0_baseband_core[][2] = {
{0x0000a7cc, 0x00000000},
{0x0000a7d0, 0x00000000},
{0x0000a7d4, 0x00000004},
- {0x0000a7dc, 0x00000001},
+ {0x0000a7dc, 0x00000000},
{0x0000a7f0, 0x80000000},
{0x0000a8d0, 0x004b6a8e},
{0x0000a8d4, 0x00000820},
@@ -886,7 +886,7 @@ static const u32 ar9462_modes_high_ob_db_tx_gain_table_2p0[][5] = {
{0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584},
{0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800},
{0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
- {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+ {0x0000a410, 0x000050da, 0x000050da, 0x000050de, 0x000050de},
{0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
{0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002},
@@ -906,20 +906,20 @@ static const u32 ar9462_modes_high_ob_db_tx_gain_table_2p0[][5] = {
{0x0000a53c, 0x41025e4a, 0x41025e4a, 0x34001640, 0x34001640},
{0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660},
{0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861},
- {0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81},
- {0x0000a54c, 0x59025eb6, 0x59025eb6, 0x42001a83, 0x42001a83},
- {0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x44001c84, 0x44001c84},
+ {0x0000a548, 0x55025eb3, 0x55025eb3, 0x3e001a81, 0x3e001a81},
+ {0x0000a54c, 0x58025ef3, 0x58025ef3, 0x42001a83, 0x42001a83},
+ {0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x44001a84, 0x44001a84},
{0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3},
{0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5},
{0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9},
{0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb},
- {0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
- {0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
- {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
- {0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
- {0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
- {0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
- {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+ {0x0000a564, 0x751ffff6, 0x751ffff6, 0x56001eec, 0x56001eec},
+ {0x0000a568, 0x751ffff6, 0x751ffff6, 0x58001ef0, 0x58001ef0},
+ {0x0000a56c, 0x751ffff6, 0x751ffff6, 0x5a001ef4, 0x5a001ef4},
+ {0x0000a570, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6},
+ {0x0000a574, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6},
+ {0x0000a578, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6},
+ {0x0000a57c, 0x751ffff6, 0x751ffff6, 0x5c001ff6, 0x5c001ff6},
{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
@@ -1053,7 +1053,6 @@ static const u32 ar9462_2p0_mac_core[][2] = {
{0x00008044, 0x00000000},
{0x00008048, 0x00000000},
{0x0000804c, 0xffffffff},
- {0x00008050, 0xffffffff},
{0x00008054, 0x00000000},
{0x00008058, 0x00000000},
{0x0000805c, 0x000fc78f},
@@ -1117,9 +1116,9 @@ static const u32 ar9462_2p0_mac_core[][2] = {
{0x000081f8, 0x00000000},
{0x000081fc, 0x00000000},
{0x00008240, 0x00100000},
- {0x00008244, 0x0010f424},
+ {0x00008244, 0x0010f400},
{0x00008248, 0x00000800},
- {0x0000824c, 0x0001e848},
+ {0x0000824c, 0x0001e800},
{0x00008250, 0x00000000},
{0x00008254, 0x00000000},
{0x00008258, 0x00000000},
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index 1e8508530e98..7bdd726c7a8f 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -369,7 +369,6 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan)
struct ieee80211_channel *c = chan->chan;
struct ath9k_hw_cal_data *caldata = ah->caldata;
- chan->channelFlags &= (~CHANNEL_CW_INT);
if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
ath_dbg(common, CALIBRATE,
"NF did not complete in calibration window\n");
@@ -384,7 +383,6 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan)
ath_dbg(common, CALIBRATE,
"noise floor failed detected; detected %d, threshold %d\n",
nf, nfThresh);
- chan->channelFlags |= CHANNEL_CW_INT;
}
if (!caldata) {
@@ -410,7 +408,7 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
int i, j;
ah->caldata->channel = chan->channel;
- ah->caldata->channelFlags = chan->channelFlags & ~CHANNEL_CW_INT;
+ ah->caldata->channelFlags = chan->channelFlags;
ah->caldata->chanmode = chan->chanmode;
h = ah->caldata->nfCalHist;
default_nf = ath9k_hw_get_default_nf(ah, chan);
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h
index 5f845beeb18b..eca95a0c3890 100644
--- a/drivers/net/wireless/ath/ath9k/common.h
+++ b/drivers/net/wireless/ath/ath9k/common.h
@@ -40,7 +40,7 @@
x = ATH_LPF_RSSI((x), ATH_RSSI_IN((y)), ATH_RSSI_LPF_LEN); \
} while (0)
#define ATH_EP_RND(x, mul) \
- ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
+ (((x) + ((mul)/2)) / (mul))
int ath9k_cmn_padpos(__le16 frame_control);
int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb);
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 3714b971d18e..67a2a4b3b883 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -537,6 +537,7 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
PR("AMPDUs Completed:", a_completed);
PR("AMPDUs Retried: ", a_retries);
PR("AMPDUs XRetried: ", a_xretries);
+ PR("TXERR Filtered: ", txerr_filtered);
PR("FIFO Underrun: ", fifo_underrun);
PR("TXOP Exceeded: ", xtxop);
PR("TXTIMER Expiry: ", timer_exp);
@@ -756,6 +757,8 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
TX_STAT_INC(qnum, completed);
}
+ if (ts->ts_status & ATH9K_TXERR_FILT)
+ TX_STAT_INC(qnum, txerr_filtered);
if (ts->ts_status & ATH9K_TXERR_FIFO)
TX_STAT_INC(qnum, fifo_underrun);
if (ts->ts_status & ATH9K_TXERR_XTXOP)
@@ -1909,6 +1912,7 @@ static const char ath9k_gstrings_stats[][ETH_GSTRING_LEN] = {
AMKSTR(d_tx_desc_cfg_err),
AMKSTR(d_tx_data_underrun),
AMKSTR(d_tx_delim_underrun),
+ "d_rx_crc_err",
"d_rx_decrypt_crc_err",
"d_rx_phy_err",
"d_rx_mic_err",
@@ -1989,6 +1993,7 @@ void ath9k_get_et_stats(struct ieee80211_hw *hw,
AWDATA(data_underrun);
AWDATA(delim_underrun);
+ AWDATA_RX(crc_err);
AWDATA_RX(decrypt_crc_err);
AWDATA_RX(phy_err);
AWDATA_RX(mic_err);
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 410d6d8f1aa7..794a7ec83a24 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -142,6 +142,7 @@ struct ath_interrupt_stats {
* @a_completed: Total AMPDUs completed
* @a_retries: No. of AMPDUs retried (SW)
* @a_xretries: No. of AMPDUs dropped due to xretries
+ * @txerr_filtered: No. of frames with TXERR_FILT flag set.
* @fifo_underrun: FIFO underrun occurrences
Valid only for:
- non-aggregate condition.
@@ -168,6 +169,7 @@ struct ath_tx_stats {
u32 a_completed;
u32 a_retries;
u32 a_xretries;
+ u32 txerr_filtered;
u32 fifo_underrun;
u32 xtxop;
u32 timer_exp;
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 2a2ae403e0e5..767222f2ba5c 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1667,6 +1667,104 @@ bool ath9k_hw_check_alive(struct ath_hw *ah)
}
EXPORT_SYMBOL(ath9k_hw_check_alive);
+static void ath9k_hw_init_mfp(struct ath_hw *ah)
+{
+ /* Setup MFP options for CCMP */
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
+ /* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt
+ * frames when constructing CCMP AAD. */
+ REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT,
+ 0xc7ff);
+ ah->sw_mgmt_crypto = false;
+ } else if (AR_SREV_9160_10_OR_LATER(ah)) {
+ /* Disable hardware crypto for management frames */
+ REG_CLR_BIT(ah, AR_PCU_MISC_MODE2,
+ AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE);
+ REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
+ AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT);
+ ah->sw_mgmt_crypto = true;
+ } else {
+ ah->sw_mgmt_crypto = true;
+ }
+}
+
+static void ath9k_hw_reset_opmode(struct ath_hw *ah,
+ u32 macStaId1, u32 saveDefAntenna)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr));
+ REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4)
+ | macStaId1
+ | AR_STA_ID1_RTS_USE_DEF
+ | (ah->config.ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0)
+ | ah->sta_id1_defaults);
+ ath_hw_setbssidmask(common);
+ REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
+ ath9k_hw_write_associd(ah);
+ REG_WRITE(ah, AR_ISR, ~0);
+ REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);
+
+ REGWRITE_BUFFER_FLUSH(ah);
+
+ ath9k_hw_set_operating_mode(ah, ah->opmode);
+}
+
+static void ath9k_hw_init_queues(struct ath_hw *ah)
+{
+ int i;
+
+ ENABLE_REGWRITE_BUFFER(ah);
+
+ for (i = 0; i < AR_NUM_DCU; i++)
+ REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);
+
+ REGWRITE_BUFFER_FLUSH(ah);
+
+ ah->intr_txqs = 0;
+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
+ ath9k_hw_resettxqueue(ah, i);
+}
+
+/*
+ * For big endian systems turn on swapping for descriptors
+ */
+static void ath9k_hw_init_desc(struct ath_hw *ah)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ if (AR_SREV_9100(ah)) {
+ u32 mask;
+ mask = REG_READ(ah, AR_CFG);
+ if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) {
+ ath_dbg(common, RESET, "CFG Byte Swap Set 0x%x\n",
+ mask);
+ } else {
+ mask = INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB;
+ REG_WRITE(ah, AR_CFG, mask);
+ ath_dbg(common, RESET, "Setting CFG 0x%x\n",
+ REG_READ(ah, AR_CFG));
+ }
+ } else {
+ if (common->bus_ops->ath_bus_type == ATH_USB) {
+ /* Configure AR9271 target WLAN */
+ if (AR_SREV_9271(ah))
+ REG_WRITE(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB);
+ else
+ REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
+ }
+#ifdef __BIG_ENDIAN
+ else if (AR_SREV_9330(ah) || AR_SREV_9340(ah) ||
+ AR_SREV_9550(ah))
+ REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0);
+ else
+ REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
+#endif
+ }
+}
+
/*
* Fast channel change:
* (Change synthesizer based on channel freq without resetting chip)
@@ -1744,7 +1842,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
u32 saveDefAntenna;
u32 macStaId1;
u64 tsf = 0;
- int i, r;
+ int r;
bool start_mci_reset = false;
bool save_fullsleep = ah->chip_fullsleep;
@@ -1761,10 +1859,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
ath9k_hw_getnf(ah, ah->curchan);
ah->caldata = caldata;
- if (caldata &&
- (chan->channel != caldata->channel ||
- (chan->channelFlags & ~CHANNEL_CW_INT) !=
- (caldata->channelFlags & ~CHANNEL_CW_INT))) {
+ if (caldata && (chan->channel != caldata->channel ||
+ chan->channelFlags != caldata->channelFlags)) {
/* Operating channel changed, reset channel calibration data */
memset(caldata, 0, sizeof(*caldata));
ath9k_init_nfcal_hist_buffer(ah, chan);
@@ -1851,22 +1947,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
ath9k_hw_settsf64(ah, tsf);
}
- /* Setup MFP options for CCMP */
- if (AR_SREV_9280_20_OR_LATER(ah)) {
- /* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt
- * frames when constructing CCMP AAD. */
- REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT,
- 0xc7ff);
- ah->sw_mgmt_crypto = false;
- } else if (AR_SREV_9160_10_OR_LATER(ah)) {
- /* Disable hardware crypto for management frames */
- REG_CLR_BIT(ah, AR_PCU_MISC_MODE2,
- AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE);
- REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
- AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT);
- ah->sw_mgmt_crypto = true;
- } else
- ah->sw_mgmt_crypto = true;
+ ath9k_hw_init_mfp(ah);
if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
ath9k_hw_set_delta_slope(ah, chan);
@@ -1874,24 +1955,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
ath9k_hw_spur_mitigate_freq(ah, chan);
ah->eep_ops->set_board_values(ah, chan);
- ENABLE_REGWRITE_BUFFER(ah);
-
- REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr));
- REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4)
- | macStaId1
- | AR_STA_ID1_RTS_USE_DEF
- | (ah->config.
- ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0)
- | ah->sta_id1_defaults);
- ath_hw_setbssidmask(common);
- REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);
- ath9k_hw_write_associd(ah);
- REG_WRITE(ah, AR_ISR, ~0);
- REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);
-
- REGWRITE_BUFFER_FLUSH(ah);
-
- ath9k_hw_set_operating_mode(ah, ah->opmode);
+ ath9k_hw_reset_opmode(ah, macStaId1, saveDefAntenna);
r = ath9k_hw_rf_set_freq(ah, chan);
if (r)
@@ -1899,17 +1963,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
ath9k_hw_set_clockrate(ah);
- ENABLE_REGWRITE_BUFFER(ah);
-
- for (i = 0; i < AR_NUM_DCU; i++)
- REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);
-
- REGWRITE_BUFFER_FLUSH(ah);
-
- ah->intr_txqs = 0;
- for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
- ath9k_hw_resettxqueue(ah, i);
-
+ ath9k_hw_init_queues(ah);
ath9k_hw_init_interrupt_masks(ah, ah->opmode);
ath9k_hw_ani_cache_ini_regs(ah);
ath9k_hw_init_qos(ah);
@@ -1964,38 +2018,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
REGWRITE_BUFFER_FLUSH(ah);
- /*
- * For big endian systems turn on swapping for descriptors
- */
- if (AR_SREV_9100(ah)) {
- u32 mask;
- mask = REG_READ(ah, AR_CFG);
- if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) {
- ath_dbg(common, RESET, "CFG Byte Swap Set 0x%x\n",
- mask);
- } else {
- mask =
- INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB;
- REG_WRITE(ah, AR_CFG, mask);
- ath_dbg(common, RESET, "Setting CFG 0x%x\n",
- REG_READ(ah, AR_CFG));
- }
- } else {
- if (common->bus_ops->ath_bus_type == ATH_USB) {
- /* Configure AR9271 target WLAN */
- if (AR_SREV_9271(ah))
- REG_WRITE(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB);
- else
- REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
- }
-#ifdef __BIG_ENDIAN
- else if (AR_SREV_9330(ah) || AR_SREV_9340(ah) ||
- AR_SREV_9550(ah))
- REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0);
- else
- REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
-#endif
- }
+ ath9k_hw_init_desc(ah);
if (ath9k_hw_btcoex_is_enabled(ah))
ath9k_hw_btcoex_enable(ah);
@@ -2008,7 +2031,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
if (AR_SREV_9300_20_OR_LATER(ah)) {
ar9003_hw_bb_watchdog_config(ah);
-
ar9003_hw_disable_phy_restart(ah);
}
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 784e81ccb903..30e62d92d46d 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -363,7 +363,6 @@ enum ath9k_int {
ATH9K_INT_NOCARD = 0xffffffff
};
-#define CHANNEL_CW_INT 0x00002
#define CHANNEL_CCK 0x00020
#define CHANNEL_OFDM 0x00040
#define CHANNEL_2GHZ 0x00080
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c
index 9c0b150d5b8e..c61cafa2665b 100644
--- a/drivers/net/wireless/ath/carl9170/tx.c
+++ b/drivers/net/wireless/ath/carl9170/tx.c
@@ -387,8 +387,7 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar,
u8 tid;
if (!(txinfo->flags & IEEE80211_TX_CTL_AMPDU) ||
- txinfo->flags & IEEE80211_TX_CTL_INJECTED ||
- (!(super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_AGGR))))
+ txinfo->flags & IEEE80211_TX_CTL_INJECTED)
return;
rcu_read_lock();
@@ -981,30 +980,6 @@ static int carl9170_tx_prepare(struct ar9170 *ar,
SET_VAL(CARL9170_TX_SUPER_AMPDU_FACTOR,
txc->s.ampdu_settings, factor);
-
- for (i = 0; i < CARL9170_TX_MAX_RATES; i++) {
- txrate = &info->control.rates[i];
- if (txrate->idx >= 0) {
- txc->s.ri[i] =
- CARL9170_TX_SUPER_RI_AMPDU;
-
- if (WARN_ON(!(txrate->flags &
- IEEE80211_TX_RC_MCS))) {
- /*
- * Not sure if it's even possible
- * to aggregate non-ht rates with
- * this HW.
- */
- goto err_out;
- }
- continue;
- }
-
- txrate->idx = 0;
- txrate->count = ar->hw->max_rate_tries;
- }
-
- mac_tmp |= cpu_to_le16(AR9170_TX_MAC_AGGR);
}
/*
@@ -1012,11 +987,31 @@ static int carl9170_tx_prepare(struct ar9170 *ar,
* taken from mac_control. For all fallback rate, the firmware
* updates the mac_control flags from the rate info field.
*/
- for (i = 1; i < CARL9170_TX_MAX_RATES; i++) {
+ for (i = 0; i < CARL9170_TX_MAX_RATES; i++) {
+ __le32 phy_set;
txrate = &info->control.rates[i];
if (txrate->idx < 0)
break;
+ phy_set = carl9170_tx_physet(ar, info, txrate);
+ if (i == 0) {
+ /* first rate - part of the hw's frame header */
+ txc->f.phy_control = phy_set;
+
+ if (ampdu && txrate->flags & IEEE80211_TX_RC_MCS)
+ mac_tmp |= cpu_to_le16(AR9170_TX_MAC_AGGR);
+ if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack))
+ mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS);
+ else if (carl9170_tx_cts_check(ar, txrate))
+ mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS);
+
+ } else {
+ /* fallback rates are stored in the firmware's
+ * retry rate set array.
+ */
+ txc->s.rr[i - 1] = phy_set;
+ }
+
SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[i],
txrate->count);
@@ -1027,21 +1022,13 @@ static int carl9170_tx_prepare(struct ar9170 *ar,
txc->s.ri[i] |= (AR9170_TX_MAC_PROT_CTS <<
CARL9170_TX_SUPER_RI_ERP_PROT_S);
- txc->s.rr[i - 1] = carl9170_tx_physet(ar, info, txrate);
+ if (ampdu && (txrate->flags & IEEE80211_TX_RC_MCS))
+ txc->s.ri[i] |= CARL9170_TX_SUPER_RI_AMPDU;
}
- txrate = &info->control.rates[0];
- SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[0], txrate->count);
-
- if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack))
- mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS);
- else if (carl9170_tx_cts_check(ar, txrate))
- mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS);
-
txc->s.len = cpu_to_le16(skb->len);
txc->f.length = cpu_to_le16(len + FCS_LEN);
txc->f.mac_control = mac_tmp;
- txc->f.phy_control = carl9170_tx_physet(ar, info, txrate);
arinfo = (void *)info->rate_driver_data;
arinfo->timeout = jiffies;
@@ -1381,9 +1368,9 @@ static void carl9170_tx(struct ar9170 *ar)
}
static bool carl9170_tx_ampdu_queue(struct ar9170 *ar,
- struct ieee80211_sta *sta, struct sk_buff *skb)
+ struct ieee80211_sta *sta, struct sk_buff *skb,
+ struct ieee80211_tx_info *txinfo)
{
- struct _carl9170_tx_superframe *super = (void *) skb->data;
struct carl9170_sta_info *sta_info;
struct carl9170_sta_tid *agg;
struct sk_buff *iter;
@@ -1450,7 +1437,7 @@ err_unlock:
err_unlock_rcu:
rcu_read_unlock();
- super->f.mac_control &= ~cpu_to_le16(AR9170_TX_MAC_AGGR);
+ txinfo->flags &= ~IEEE80211_TX_CTL_AMPDU;
carl9170_tx_status(ar, skb, false);
ar->tx_dropped++;
return false;
@@ -1492,7 +1479,7 @@ void carl9170_op_tx(struct ieee80211_hw *hw,
* sta == NULL checks are redundant in this
* special case.
*/
- run = carl9170_tx_ampdu_queue(ar, sta, skb);
+ run = carl9170_tx_ampdu_queue(ar, sta, skb, info);
if (run)
carl9170_tx_ampdu(ar);
diff --git a/drivers/net/wireless/ath/wil6210/Makefile b/drivers/net/wireless/ath/wil6210/Makefile
index 9396dc9fe3c5..d288eea0a26a 100644
--- a/drivers/net/wireless/ath/wil6210/Makefile
+++ b/drivers/net/wireless/ath/wil6210/Makefile
@@ -9,5 +9,7 @@ wil6210-objs += wmi.o
wil6210-objs += interrupt.o
wil6210-objs += txrx.o
-subdir-ccflags-y += -Werror
+ifeq (, $(findstring -W,$(EXTRA_CFLAGS)))
+ subdir-ccflags-y += -Werror
+endif
subdir-ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index 65fc9683bfd8..1e709bfb63a3 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -312,14 +312,6 @@ static const struct file_operations fops_memread = {
.llseek = seq_lseek,
};
-static int wil_default_open(struct inode *inode, struct file *file)
-{
- if (inode->i_private)
- file->private_data = inode->i_private;
-
- return 0;
-}
-
static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
@@ -361,7 +353,7 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf,
static const struct file_operations fops_ioblob = {
.read = wil_read_file_ioblob,
- .open = wil_default_open,
+ .open = simple_open,
.llseek = default_llseek,
};
@@ -396,7 +388,7 @@ static ssize_t wil_write_file_reset(struct file *file, const char __user *buf,
static const struct file_operations fops_reset = {
.write = wil_write_file_reset,
- .open = wil_default_open,
+ .open = simple_open,
};
/*---------Tx descriptor------------*/
@@ -526,7 +518,7 @@ static ssize_t wil_write_file_ssid(struct file *file, const char __user *buf,
static const struct file_operations fops_ssid = {
.read = wil_read_file_ssid,
.write = wil_write_file_ssid,
- .open = wil_default_open,
+ .open = simple_open,
};
/*----------------*/
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
index 287c6b670a36..078e6f3477a9 100644
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -131,7 +131,7 @@ config B43_PHY_LP
config B43_PHY_HT
bool "Support for HT-PHY (high throughput) devices"
- depends on B43
+ depends on B43 && B43_BCMA
---help---
Support for the HT-PHY.
@@ -166,8 +166,8 @@ config B43_DEBUG
Broadcom 43xx debugging.
This adds additional runtime sanity checks and statistics to the driver.
- These checks and statistics might me expensive and hurt runtime performance
- of your system.
+ These checks and statistics might be expensive and hurt the runtime
+ performance of your system.
This also adds the b43 debugfs interface.
Do not enable this, unless you are debugging the driver.
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index 10e288d470e7..fe4a77ee05c9 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -473,6 +473,12 @@ enum {
#define B43_MACCMD_CCA 0x00000008 /* Clear channel assessment */
#define B43_MACCMD_BGNOISE 0x00000010 /* Background noise */
+/* See BCMA_CLKCTLST_EXTRESREQ and BCMA_CLKCTLST_EXTRESST */
+#define B43_BCMA_CLKCTLST_80211_PLL_REQ 0x00000100
+#define B43_BCMA_CLKCTLST_PHY_PLL_REQ 0x00000200
+#define B43_BCMA_CLKCTLST_80211_PLL_ST 0x01000000
+#define B43_BCMA_CLKCTLST_PHY_PLL_ST 0x02000000
+
/* BCMA 802.11 core specific IO Control (BCMA_IOCTL) flags */
#define B43_BCMA_IOCTL_PHY_CLKEN 0x00000004 /* PHY Clock Enable */
#define B43_BCMA_IOCTL_PHY_RESET 0x00000008 /* PHY Reset */
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 05682736e466..c4d0cc582555 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -1189,10 +1189,15 @@ static void b43_bcma_phy_reset(struct b43_wldev *dev)
static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode)
{
+ u32 req = B43_BCMA_CLKCTLST_80211_PLL_REQ |
+ B43_BCMA_CLKCTLST_PHY_PLL_REQ;
+ u32 status = B43_BCMA_CLKCTLST_80211_PLL_ST |
+ B43_BCMA_CLKCTLST_PHY_PLL_ST;
+
b43_device_enable(dev, B43_BCMA_IOCTL_PHY_CLKEN);
bcma_core_set_clockmode(dev->dev->bdev, BCMA_CLKMODE_FAST);
b43_bcma_phy_reset(dev);
- bcma_core_pll_ctl(dev->dev->bdev, 0x300, 0x3000000, true);
+ bcma_core_pll_ctl(dev->dev->bdev, req, status, true);
}
#endif
diff --git a/drivers/net/wireless/b43/phy_ht.c b/drivers/net/wireless/b43/phy_ht.c
index 7416c5e9154d..3719a8884c1e 100644
--- a/drivers/net/wireless/b43/phy_ht.c
+++ b/drivers/net/wireless/b43/phy_ht.c
@@ -346,6 +346,11 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev)
u16 tmp;
u16 clip_state[3];
+ if (dev->dev->bus_type != B43_BUS_BCMA) {
+ b43err(dev->wl, "HT-PHY is supported only on BCMA bus!\n");
+ return -EOPNOTSUPP;
+ }
+
b43_phy_ht_tables_init(dev);
b43_phy_mask(dev, 0x0be, ~0x2);
diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig
index 1d92d874ebb6..747e9317dabd 100644
--- a/drivers/net/wireless/brcm80211/Kconfig
+++ b/drivers/net/wireless/brcm80211/Kconfig
@@ -12,8 +12,9 @@ config BRCMSMAC
select CORDIC
---help---
This module adds support for PCIe wireless adapters based on Broadcom
- IEEE802.11n SoftMAC chipsets. If you choose to build a module, it'll
- be called brcmsmac.ko.
+ IEEE802.11n SoftMAC chipsets. It also has WLAN led support, which will
+ be available if you select BCMA_DRIVER_GPIO. If you choose to build a
+ module, the driver will be called brcmsmac.ko.
config BRCMFMAC
tristate "Broadcom IEEE802.11n embedded FullMAC WLAN driver"
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
index 756e19fc2795..598c8e2f8d2b 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
@@ -26,6 +26,7 @@ brcmfmac-objs += \
wl_cfg80211.o \
fwil.o \
fweh.o \
+ fwsignal.o \
p2p.o \
dhd_cdc.o \
dhd_common.o \
@@ -39,3 +40,5 @@ brcmfmac-$(CONFIG_BRCMFMAC_USB) += \
usb.o
brcmfmac-$(CONFIG_BRCMDBG) += \
dhd_dbg.o
+brcmfmac-$(CONFIG_BRCM_TRACING) += \
+ tracepoint.o
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
index ef6f23be6d32..c7fa20846b32 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
@@ -501,6 +501,7 @@ struct brcmf_dcmd {
/* Forward decls for struct brcmf_pub (see below) */
struct brcmf_proto; /* device communication protocol info */
struct brcmf_cfg80211_dev; /* cfg80211 device info */
+struct brcmf_fws_info; /* firmware signalling info */
/* Common structure for module and instance linkage */
struct brcmf_pub {
@@ -527,6 +528,10 @@ struct brcmf_pub {
unsigned char proto_buf[BRCMF_DCMD_MAXLEN];
struct brcmf_fweh_info fweh;
+
+ bool fw_signals;
+ struct brcmf_fws_info *fws;
+ spinlock_t fws_spinlock;
#ifdef DEBUG
struct dentry *dbgfs_dir;
#endif
@@ -582,7 +587,7 @@ extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
void *buf, uint len);
/* Remove any protocol-specific data header. */
-extern int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx,
+extern int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
struct sk_buff *rxp);
extern int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
index ad25c3408b59..883ef9063e8a 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
@@ -134,7 +134,7 @@ extern void brcmf_dev_reset(struct device *dev);
/* Indication from bus module to change flow-control state */
extern void brcmf_txflowblock(struct device *dev, bool state);
-/* Notify tx completion */
+/* Notify the bus has transferred the tx packet to firmware */
extern void brcmf_txcomplete(struct device *dev, struct sk_buff *txp,
bool success);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c
index a2354d951dd7..e224bcb90024 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c
@@ -28,6 +28,7 @@
#include "dhd.h"
#include "dhd_proto.h"
#include "dhd_bus.h"
+#include "fwsignal.h"
#include "dhd_dbg.h"
struct brcmf_proto_cdc_dcmd {
@@ -71,13 +72,26 @@ struct brcmf_proto_cdc_dcmd {
((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | \
((idx) << BDC_FLAG2_IF_SHIFT)))
+/**
+ * struct brcmf_proto_bdc_header - BDC header format
+ *
+ * @flags: flags contain protocol and checksum info.
+ * @priority: 802.1d priority and USB flow control info (bit 4:7).
+ * @flags2: additional flags containing dongle interface index.
+ * @data_offset: start of packet data. header is following by firmware signals.
+ */
struct brcmf_proto_bdc_header {
u8 flags;
- u8 priority; /* 802.1d Priority, 4:7 flow control info for usb */
+ u8 priority;
u8 flags2;
u8 data_offset;
};
+/*
+ * maximum length of firmware signal data between
+ * the BDC header and packet data in the tx path.
+ */
+#define BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES 12
#define RETRIES 2 /* # of retries to retrieve matching dcmd response */
#define BUS_HEADER_LEN (16+64) /* Must be atleast SDPCM_RESERVE
@@ -258,7 +272,7 @@ static void pkt_set_sum_good(struct sk_buff *skb, bool x)
skb->ip_summed = (x ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE);
}
-void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx,
+void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, u8 offset,
struct sk_buff *pktbuf)
{
struct brcmf_proto_bdc_header *h;
@@ -266,7 +280,6 @@ void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx,
brcmf_dbg(CDC, "Enter\n");
/* Push BDC header used to convey priority for buses that don't */
-
skb_push(pktbuf, BDC_HEADER_LEN);
h = (struct brcmf_proto_bdc_header *)(pktbuf->data);
@@ -277,11 +290,11 @@ void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx,
h->priority = (pktbuf->priority & BDC_PRIORITY_MASK);
h->flags2 = 0;
- h->data_offset = 0;
+ h->data_offset = offset;
BDC_SET_IF_IDX(h, ifidx);
}
-int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx,
+int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx,
struct sk_buff *pktbuf)
{
struct brcmf_proto_bdc_header *h;
@@ -328,7 +341,10 @@ int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx,
pktbuf->priority = h->priority & BDC_PRIORITY_MASK;
skb_pull(pktbuf, BDC_HEADER_LEN);
- skb_pull(pktbuf, h->data_offset << 2);
+ if (do_fws)
+ brcmf_fws_hdrpull(drvr, *ifidx, h->data_offset << 2, pktbuf);
+ else
+ skb_pull(pktbuf, h->data_offset << 2);
if (pktbuf->len == 0)
return -ENODATA;
@@ -350,7 +366,7 @@ int brcmf_proto_attach(struct brcmf_pub *drvr)
}
drvr->prot = cdc;
- drvr->hdrlen += BDC_HEADER_LEN;
+ drvr->hdrlen += BDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES;
drvr->bus_if->maxctl = BRCMF_DCMD_MAXLEN +
sizeof(struct brcmf_proto_cdc_dcmd) + ROUND_UP_MARGIN;
return 0;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
index 4544342a0428..be0787cab24f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
@@ -24,6 +24,7 @@
#include "dhd_proto.h"
#include "dhd_dbg.h"
#include "fwil.h"
+#include "tracepoint.h"
#define PKTFILTER_BUF_SIZE 128
#define BRCMF_ARPOL_MODE 0xb /* agent|snoop|peer_autoreply */
@@ -373,3 +374,35 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
done:
return err;
}
+
+#ifdef CONFIG_BRCM_TRACING
+void __brcmf_err(const char *func, const char *fmt, ...)
+{
+ struct va_format vaf = {
+ .fmt = fmt,
+ };
+ va_list args;
+
+ va_start(args, fmt);
+ vaf.va = &args;
+ pr_err("%s: %pV", func, &vaf);
+ trace_brcmf_err(func, &vaf);
+ va_end(args);
+}
+#endif
+#if defined(CONFIG_BRCM_TRACING) || defined(CONFIG_BRCMDBG)
+void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...)
+{
+ struct va_format vaf = {
+ .fmt = fmt,
+ };
+ va_list args;
+
+ va_start(args, fmt);
+ vaf.va = &args;
+ if (brcmf_msg_level & level)
+ pr_debug("%s %pV", func, &vaf);
+ trace_brcmf_dbg(level, func, &vaf);
+ va_end(args);
+}
+#endif
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
index 57671eddf79d..ac792499b46a 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
@@ -22,6 +22,7 @@
#include "dhd.h"
#include "dhd_bus.h"
#include "dhd_dbg.h"
+#include "tracepoint.h"
static struct dentry *root_folder;
@@ -123,3 +124,44 @@ void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr,
debugfs_create_file("counters", S_IRUGO, dentry,
sdcnt, &brcmf_debugfs_sdio_counter_ops);
}
+
+static
+ssize_t brcmf_debugfs_fws_stats_read(struct file *f, char __user *data,
+ size_t count, loff_t *ppos)
+{
+ struct brcmf_fws_stats *fwstats = f->private_data;
+ char buf[100];
+ int res;
+
+ /* only allow read from start */
+ if (*ppos > 0)
+ return 0;
+
+ res = scnprintf(buf, sizeof(buf),
+ "header_pulls: %u\n"
+ "header_only_pkt: %u\n"
+ "tlv_parse_failed: %u\n"
+ "tlv_invalid_type: %u\n",
+ fwstats->header_pulls,
+ fwstats->header_only_pkt,
+ fwstats->tlv_parse_failed,
+ fwstats->tlv_invalid_type);
+
+ return simple_read_from_buffer(data, count, ppos, buf, res);
+}
+
+static const struct file_operations brcmf_debugfs_fws_stats_ops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .read = brcmf_debugfs_fws_stats_read
+};
+
+void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr,
+ struct brcmf_fws_stats *stats)
+{
+ struct dentry *dentry = drvr->dbgfs_dir;
+
+ if (!IS_ERR_OR_NULL(dentry))
+ debugfs_create_file("fws_stats", S_IRUGO, dentry,
+ stats, &brcmf_debugfs_fws_stats_ops);
+}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
index bc013cbe06f6..4bc646bde16f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
@@ -43,6 +43,7 @@
* debugging is not selected. When debugging the driver error
* messages are as important as other tracing or even more so.
*/
+#ifndef CONFIG_BRCM_TRACING
#ifdef CONFIG_BRCMDBG
#define brcmf_err(fmt, ...) pr_err("%s: " fmt, __func__, ##__VA_ARGS__)
#else
@@ -52,15 +53,21 @@
pr_err("%s: " fmt, __func__, ##__VA_ARGS__); \
} while (0)
#endif
+#else
+__printf(2, 3)
+void __brcmf_err(const char *func, const char *fmt, ...);
+#define brcmf_err(fmt, ...) \
+ __brcmf_err(__func__, fmt, ##__VA_ARGS__)
+#endif
-#if defined(DEBUG)
-
+#if defined(DEBUG) || defined(CONFIG_BRCM_TRACING)
+__printf(3, 4)
+void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...);
#define brcmf_dbg(level, fmt, ...) \
do { \
- if (brcmf_msg_level & BRCMF_##level##_VAL) \
- pr_debug("%s: " fmt, __func__, ##__VA_ARGS__); \
+ __brcmf_dbg(BRCMF_##level##_VAL, __func__, \
+ fmt, ##__VA_ARGS__); \
} while (0)
-
#define BRCMF_DATA_ON() (brcmf_msg_level & BRCMF_DATA_VAL)
#define BRCMF_CTL_ON() (brcmf_msg_level & BRCMF_CTL_VAL)
#define BRCMF_HDRS_ON() (brcmf_msg_level & BRCMF_HDRS_VAL)
@@ -69,7 +76,7 @@ do { \
#define BRCMF_EVENT_ON() (brcmf_msg_level & BRCMF_EVENT_VAL)
#define BRCMF_FIL_ON() (brcmf_msg_level & BRCMF_FIL_VAL)
-#else /* (defined DEBUG) || (defined DEBUG) */
+#else /* defined(DEBUG) || defined(CONFIG_BRCM_TRACING) */
#define brcmf_dbg(level, fmt, ...) no_printk(fmt, ##__VA_ARGS__)
@@ -81,7 +88,7 @@ do { \
#define BRCMF_EVENT_ON() 0
#define BRCMF_FIL_ON() 0
-#endif /* defined(DEBUG) */
+#endif /* defined(DEBUG) || defined(CONFIG_BRCM_TRACING) */
#define brcmf_dbg_hex_dump(test, data, len, fmt, ...) \
do { \
@@ -125,6 +132,13 @@ struct brcmf_sdio_count {
ulong rx_readahead_cnt; /* packets where header read-ahead was used */
};
+struct brcmf_fws_stats {
+ u32 tlv_parse_failed;
+ u32 tlv_invalid_type;
+ u32 header_only_pkt;
+ u32 header_pulls;
+};
+
struct brcmf_pub;
#ifdef DEBUG
void brcmf_debugfs_init(void);
@@ -134,6 +148,8 @@ void brcmf_debugfs_detach(struct brcmf_pub *drvr);
struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr);
void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr,
struct brcmf_sdio_count *sdcnt);
+void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr,
+ struct brcmf_fws_stats *stats);
#else
static inline void brcmf_debugfs_init(void)
{
@@ -148,6 +164,10 @@ static inline int brcmf_debugfs_attach(struct brcmf_pub *drvr)
static inline void brcmf_debugfs_detach(struct brcmf_pub *drvr)
{
}
+static inline void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr,
+ struct brcmf_fws_stats *stats)
+{
+}
#endif
#endif /* _BRCMF_DBG_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index c06cea88df0d..fa5a2af04d46 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -30,17 +30,18 @@
#include "p2p.h"
#include "wl_cfg80211.h"
#include "fwil.h"
+#include "fwsignal.h"
MODULE_AUTHOR("Broadcom Corporation");
MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
-MODULE_SUPPORTED_DEVICE("Broadcom 802.11 WLAN fullmac cards");
MODULE_LICENSE("Dual BSD/GPL");
#define MAX_WAIT_FOR_8021X_TX 50 /* msecs */
/* Error bits */
int brcmf_msg_level;
-module_param(brcmf_msg_level, int, 0);
+module_param_named(debug, brcmf_msg_level, int, S_IRUSR | S_IWUSR);
+MODULE_PARM_DESC(debug, "level of debug output");
/* P2P0 enable */
static int brcmf_p2p_enable;
@@ -230,7 +231,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
atomic_inc(&ifp->pend_8021x_cnt);
/* If the protocol uses a data header, apply it */
- brcmf_proto_hdrpush(drvr, ifp->ifidx, skb);
+ brcmf_proto_hdrpush(drvr, ifp->ifidx, 0, skb);
/* Use bus module to send data frame */
ret = brcmf_bus_txdata(drvr->bus_if, skb);
@@ -283,7 +284,7 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)
skb_unlink(skb, skb_list);
/* process and remove protocol-specific header */
- ret = brcmf_proto_hdrpull(drvr, &ifidx, skb);
+ ret = brcmf_proto_hdrpull(drvr, drvr->fw_signals, &ifidx, skb);
ifp = drvr->iflist[ifidx];
if (ret || !ifp || !ifp->ndev) {
@@ -357,23 +358,29 @@ void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success)
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_pub *drvr = bus_if->drvr;
struct brcmf_if *ifp;
+ int res;
- brcmf_proto_hdrpull(drvr, &ifidx, txp);
+ res = brcmf_proto_hdrpull(drvr, false, &ifidx, txp);
ifp = drvr->iflist[ifidx];
if (!ifp)
- return;
+ goto done;
- eh = (struct ethhdr *)(txp->data);
- type = ntohs(eh->h_proto);
+ if (res == 0) {
+ eh = (struct ethhdr *)(txp->data);
+ type = ntohs(eh->h_proto);
- if (type == ETH_P_PAE) {
- atomic_dec(&ifp->pend_8021x_cnt);
- if (waitqueue_active(&ifp->pend_8021x_wait))
- wake_up(&ifp->pend_8021x_wait);
+ if (type == ETH_P_PAE) {
+ atomic_dec(&ifp->pend_8021x_cnt);
+ if (waitqueue_active(&ifp->pend_8021x_wait))
+ wake_up(&ifp->pend_8021x_wait);
+ }
}
if (!success)
ifp->stats.tx_errors++;
+
+done:
+ brcmu_pkt_buf_free_skb(txp);
}
static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
@@ -873,6 +880,9 @@ int brcmf_bus_start(struct device *dev)
if (ret < 0)
goto fail;
+ drvr->fw_signals = true;
+ (void)brcmf_fws_init(drvr);
+
drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev);
if (drvr->config == NULL) {
ret = -ENOMEM;
@@ -889,6 +899,8 @@ fail:
brcmf_err("failed: %d\n", ret);
if (drvr->config)
brcmf_cfg80211_detach(drvr->config);
+ if (drvr->fws)
+ brcmf_fws_deinit(drvr);
free_netdev(ifp->ndev);
drvr->iflist[0] = NULL;
if (p2p_ifp) {
@@ -952,6 +964,9 @@ void brcmf_detach(struct device *dev)
if (drvr->prot)
brcmf_proto_detach(drvr);
+ if (drvr->fws)
+ brcmf_fws_deinit(drvr);
+
brcmf_debugfs_detach(drvr);
bus_if->drvr = NULL;
kfree(drvr);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h
index 48fa70302192..ef9179883748 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h
@@ -33,7 +33,7 @@ extern void brcmf_proto_stop(struct brcmf_pub *drvr);
/* Add any protocol-specific data header.
* Caller must reserve prot_hdrlen prepend space.
*/
-extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx,
+extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx, u8 offset,
struct sk_buff *txp);
/* Sets dongle media info (drv_version, mac address). */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 4469321c0eb3..9a2edd3f0a5c 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -1546,7 +1546,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
struct sk_buff_head pktlist; /* needed for bus interface */
u16 pad; /* Number of pad bytes to read */
uint rxleft = 0; /* Remaining number of frames allowed */
- int sdret; /* Return code from calls */
+ int ret; /* Return code from calls */
uint rxcount = 0; /* Total frames read */
struct brcmf_sdio_read *rd = &bus->cur_read, rd_new;
u8 head_read = 0;
@@ -1577,15 +1577,15 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
/* read header first for unknow frame length */
sdio_claim_host(bus->sdiodev->func[1]);
if (!rd->len) {
- sdret = brcmf_sdcard_recv_buf(bus->sdiodev,
+ ret = brcmf_sdcard_recv_buf(bus->sdiodev,
bus->sdiodev->sbwad,
SDIO_FUNC_2, F2SYNC,
bus->rxhdr,
BRCMF_FIRSTREAD);
bus->sdcnt.f2rxhdrs++;
- if (sdret < 0) {
+ if (ret < 0) {
brcmf_err("RXHEADER FAILED: %d\n",
- sdret);
+ ret);
bus->sdcnt.rx_hdrfail++;
brcmf_sdbrcm_rxfail(bus, true, true);
sdio_release_host(bus->sdiodev->func[1]);
@@ -1637,14 +1637,14 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
skb_pull(pkt, head_read);
pkt_align(pkt, rd->len_left, BRCMF_SDALIGN);
- sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad,
+ ret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad,
SDIO_FUNC_2, F2SYNC, pkt);
bus->sdcnt.f2rxdata++;
sdio_release_host(bus->sdiodev->func[1]);
- if (sdret < 0) {
+ if (ret < 0) {
brcmf_err("read %d bytes from channel %d failed: %d\n",
- rd->len, rd->channel, sdret);
+ rd->len, rd->channel, ret);
brcmu_pkt_buf_free_skb(pkt);
sdio_claim_host(bus->sdiodev->func[1]);
brcmf_sdbrcm_rxfail(bus, true,
@@ -1775,7 +1775,7 @@ brcmf_sdbrcm_wait_event_wakeup(struct brcmf_sdio *bus)
/* Writes a HW/SW header into the packet and sends it. */
/* Assumes: (a) header space already there, (b) caller holds lock */
static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
- uint chan, bool free_pkt)
+ uint chan)
{
int ret;
u8 *frame;
@@ -1805,10 +1805,7 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
pkt_align(new, pkt->len, BRCMF_SDALIGN);
memcpy(new->data, pkt->data, pkt->len);
- if (free_pkt)
- brcmu_pkt_buf_free_skb(pkt);
- /* free the pkt if canned one is not used */
- free_pkt = true;
+ brcmu_pkt_buf_free_skb(pkt);
pkt = new;
frame = (u8 *) (pkt->data);
/* precondition: (frame % BRCMF_SDALIGN) == 0) */
@@ -1901,10 +1898,6 @@ done:
/* restore pkt buffer pointer before calling tx complete routine */
skb_pull(pkt, SDPCM_HDRLEN + pad);
brcmf_txcomplete(bus->sdiodev->dev, pkt, ret != 0);
-
- if (free_pkt)
- brcmu_pkt_buf_free_skb(pkt);
-
return ret;
}
@@ -1932,7 +1925,7 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes)
spin_unlock_bh(&bus->txqlock);
datalen = pkt->len - SDPCM_HDRLEN;
- ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true);
+ ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL);
/* In poll mode, need to check for other events */
if (!bus->intr && cnt) {
@@ -2343,7 +2336,6 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
if (!brcmf_c_prec_enq(bus->sdiodev->dev, &bus->txq, pkt, prec)) {
skb_pull(pkt, SDPCM_HDRLEN);
brcmf_txcomplete(bus->sdiodev->dev, pkt, false);
- brcmu_pkt_buf_free_skb(pkt);
brcmf_err("out of bus->txq !!!\n");
ret = -ENOSR;
} else {
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
new file mode 100644
index 000000000000..071d55f9cd4d
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
@@ -0,0 +1,382 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/types.h>
+#include <linux/if_ether.h>
+#include <linux/spinlock.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/err.h>
+#include <uapi/linux/nl80211.h>
+
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+#include "dhd.h"
+#include "dhd_dbg.h"
+#include "fwil.h"
+#include "fweh.h"
+#include "fwsignal.h"
+
+/**
+ * DOC: Firmware Signalling
+ *
+ * Firmware can send signals to host and vice versa, which are passed in the
+ * data packets using TLV based header. This signalling layer is on top of the
+ * BDC bus protocol layer.
+ */
+
+/*
+ * single definition for firmware-driver flow control tlv's.
+ *
+ * each tlv is specified by BRCMF_FWS_TLV_DEF(name, ID, length).
+ * A length value 0 indicates variable length tlv.
+ */
+#define BRCMF_FWS_TLV_DEFLIST \
+ BRCMF_FWS_TLV_DEF(MAC_OPEN, 1, 1) \
+ BRCMF_FWS_TLV_DEF(MAC_CLOSE, 2, 1) \
+ BRCMF_FWS_TLV_DEF(MAC_REQUEST_CREDIT, 3, 2) \
+ BRCMF_FWS_TLV_DEF(TXSTATUS, 4, 4) \
+ BRCMF_FWS_TLV_DEF(PKTTAG, 5, 4) \
+ BRCMF_FWS_TLV_DEF(MACDESC_ADD, 6, 8) \
+ BRCMF_FWS_TLV_DEF(MACDESC_DEL, 7, 8) \
+ BRCMF_FWS_TLV_DEF(RSSI, 8, 1) \
+ BRCMF_FWS_TLV_DEF(INTERFACE_OPEN, 9, 1) \
+ BRCMF_FWS_TLV_DEF(INTERFACE_CLOSE, 10, 1) \
+ BRCMF_FWS_TLV_DEF(FIFO_CREDITBACK, 11, 8) \
+ BRCMF_FWS_TLV_DEF(PENDING_TRAFFIC_BMP, 12, 2) \
+ BRCMF_FWS_TLV_DEF(MAC_REQUEST_PACKET, 13, 3) \
+ BRCMF_FWS_TLV_DEF(HOST_REORDER_RXPKTS, 14, 10) \
+ BRCMF_FWS_TLV_DEF(TRANS_ID, 18, 6) \
+ BRCMF_FWS_TLV_DEF(COMP_TXSTATUS, 19, 1) \
+ BRCMF_FWS_TLV_DEF(FILLER, 255, 0)
+
+/**
+ * enum brcmf_fws_tlv_type - definition of tlv identifiers.
+ */
+#define BRCMF_FWS_TLV_DEF(name, id, len) \
+ BRCMF_FWS_TYPE_ ## name = id,
+enum brcmf_fws_tlv_type {
+ BRCMF_FWS_TLV_DEFLIST
+ BRCMF_FWS_TYPE_INVALID
+};
+#undef BRCMF_FWS_TLV_DEF
+
+/**
+ * enum brcmf_fws_tlv_len - length values for tlvs.
+ */
+#define BRCMF_FWS_TLV_DEF(name, id, len) \
+ BRCMF_FWS_TYPE_ ## name ## _LEN = len,
+enum brcmf_fws_tlv_len {
+ BRCMF_FWS_TLV_DEFLIST
+};
+#undef BRCMF_FWS_TLV_DEF
+
+#ifdef DEBUG
+/**
+ * brcmf_fws_tlv_names - array of tlv names.
+ */
+#define BRCMF_FWS_TLV_DEF(name, id, len) \
+ { id, #name },
+static struct {
+ enum brcmf_fws_tlv_type id;
+ const char *name;
+} brcmf_fws_tlv_names[] = {
+ BRCMF_FWS_TLV_DEFLIST
+};
+#undef BRCMF_FWS_TLV_DEF
+
+static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(brcmf_fws_tlv_names); i++)
+ if (brcmf_fws_tlv_names[i].id == id)
+ return brcmf_fws_tlv_names[i].name;
+
+ return "INVALID";
+}
+#else
+static const char *brcmf_fws_get_tlv_name(enum brcmf_fws_tlv_type id)
+{
+ return "NODEBUG";
+}
+#endif /* DEBUG */
+
+/**
+ * flags used to enable tlv signalling from firmware.
+ */
+#define BRCMF_FWS_FLAGS_RSSI_SIGNALS 0x0001
+#define BRCMF_FWS_FLAGS_XONXOFF_SIGNALS 0x0002
+#define BRCMF_FWS_FLAGS_CREDIT_STATUS_SIGNALS 0x0004
+#define BRCMF_FWS_FLAGS_HOST_PROPTXSTATUS_ACTIVE 0x0008
+#define BRCMF_FWS_FLAGS_PSQ_GENERATIONFSM_ENABLE 0x0010
+#define BRCMF_FWS_FLAGS_PSQ_ZERO_BUFFER_ENABLE 0x0020
+#define BRCMF_FWS_FLAGS_HOST_RXREORDER_ACTIVE 0x0040
+
+#define BRCMF_FWS_HANGER_MAXITEMS 1024
+#define BRCMF_FWS_HANGER_ITEM_STATE_FREE 1
+#define BRCMF_FWS_HANGER_ITEM_STATE_INUSE 2
+#define BRCMF_FWS_HANGER_ITEM_STATE_INUSE_SUPPRESSED 3
+
+#define BRCMF_FWS_STATE_OPEN 1
+#define BRCMF_FWS_STATE_CLOSE 2
+
+#define BRCMF_FWS_FCMODE_NONE 0
+#define BRCMF_FWS_FCMODE_IMPLIED_CREDIT 1
+#define BRCMF_FWS_FCMODE_EXPLICIT_CREDIT 2
+
+#define BRCMF_FWS_MAC_DESC_TABLE_SIZE 32
+#define BRCMF_FWS_MAX_IFNUM 16
+#define BRCMF_FWS_MAC_DESC_ID_INVALID 0xff
+
+#define BRCMF_FWS_HOSTIF_FLOWSTATE_OFF 0
+#define BRCMF_FWS_HOSTIF_FLOWSTATE_ON 1
+
+/**
+ * FWFC packet identifier
+ *
+ * 32-bit packet identifier used in PKTTAG tlv from host to dongle.
+ *
+ * - Generated at the host (e.g. dhd)
+ * - Seen as a generic sequence number by wlc except the flags field
+ *
+ * Generation : b[31] => generation number for this packet [host->fw]
+ * OR, current generation number [fw->host]
+ * Flags : b[30:27] => command, status flags
+ * FIFO-AC : b[26:24] => AC-FIFO id
+ * h-slot : b[23:8] => hanger-slot
+ * freerun : b[7:0] => A free running counter
+ */
+#define BRCMF_FWS_PKTTAG_GENERATION_MASK 0x80000000
+#define BRCMF_FWS_PKTTAG_GENERATION_SHIFT 31
+#define BRCMF_FWS_PKTTAG_FLAGS_MASK 0x78000000
+#define BRCMF_FWS_PKTTAG_FLAGS_SHIFT 27
+#define BRCMF_FWS_PKTTAG_FIFO_MASK 0x07000000
+#define BRCMF_FWS_PKTTAG_FIFO_SHIFT 24
+#define BRCMF_FWS_PKTTAG_HSLOT_MASK 0x00ffff00
+#define BRCMF_FWS_PKTTAG_HSLOT_SHIFT 8
+#define BRCMF_FWS_PKTTAG_FREERUN_MASK 0x000000ff
+#define BRCMF_FWS_PKTTAG_FREERUN_SHIFT 0
+
+#define brcmf_fws_pkttag_set_field(var, field, value) \
+ brcmu_maskset32((var), BRCMF_FWS_PKTTAG_ ## field ## _MASK, \
+ BRCMF_FWS_PKTTAG_ ## field ## _SHIFT, (value))
+#define brcmf_fws_pkttag_get_field(var, field) \
+ brcmu_maskget32((var), BRCMF_FWS_PKTTAG_ ## field ## _MASK, \
+ BRCMF_FWS_PKTTAG_ ## field ## _SHIFT)
+
+struct brcmf_fws_info {
+ struct brcmf_pub *drvr;
+ struct brcmf_fws_stats stats;
+};
+
+static int brcmf_fws_rssi_indicate(struct brcmf_fws_info *fws, s8 rssi)
+{
+ brcmf_dbg(CTL, "rssi %d\n", rssi);
+ return 0;
+}
+
+static int brcmf_fws_dbg_seqnum_check(struct brcmf_fws_info *fws, u8 *data)
+{
+ __le32 timestamp;
+
+ memcpy(&timestamp, &data[2], sizeof(timestamp));
+ brcmf_dbg(INFO, "received: seq %d, timestamp %d\n", data[1],
+ le32_to_cpu(timestamp));
+ return 0;
+}
+
+/* using macro so sparse checking does not complain
+ * about locking imbalance.
+ */
+#define brcmf_fws_lock(drvr, flags) \
+do { \
+ flags = 0; \
+ spin_lock_irqsave(&((drvr)->fws_spinlock), (flags)); \
+} while (0)
+
+/* using macro so sparse checking does not complain
+ * about locking imbalance.
+ */
+#define brcmf_fws_unlock(drvr, flags) \
+ spin_unlock_irqrestore(&((drvr)->fws_spinlock), (flags))
+
+int brcmf_fws_init(struct brcmf_pub *drvr)
+{
+ u32 tlv;
+ int rc;
+
+ /* enable rssi signals */
+ tlv = drvr->fw_signals ? BRCMF_FWS_FLAGS_RSSI_SIGNALS : 0;
+
+ spin_lock_init(&drvr->fws_spinlock);
+
+ drvr->fws = kzalloc(sizeof(*(drvr->fws)), GFP_KERNEL);
+ if (!drvr->fws) {
+ rc = -ENOMEM;
+ goto fail;
+ }
+
+ /* enable proptxtstatus signaling by default */
+ rc = brcmf_fil_iovar_int_set(drvr->iflist[0], "tlv", tlv);
+ if (rc < 0) {
+ brcmf_err("failed to set bdcv2 tlv signaling\n");
+ goto fail;
+ }
+ /* set linkage back */
+ drvr->fws->drvr = drvr;
+
+ /* create debugfs file for statistics */
+ brcmf_debugfs_create_fws_stats(drvr, &drvr->fws->stats);
+
+ /* TODO: remove upon feature delivery */
+ brcmf_err("%s bdcv2 tlv signaling [%x]\n",
+ drvr->fw_signals ? "enabled" : "disabled", tlv);
+ return 0;
+
+fail:
+ /* disable flow control entirely */
+ drvr->fw_signals = false;
+ brcmf_fws_deinit(drvr);
+ return rc;
+}
+
+void brcmf_fws_deinit(struct brcmf_pub *drvr)
+{
+ /* free top structure */
+ kfree(drvr->fws);
+ drvr->fws = NULL;
+}
+
+int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
+ struct sk_buff *skb)
+{
+ struct brcmf_fws_info *fws = drvr->fws;
+ ulong flags;
+ u8 *signal_data;
+ s16 data_len;
+ u8 type;
+ u8 len;
+ u8 *data;
+
+ brcmf_dbg(TRACE, "enter: ifidx %d, skblen %u, sig %d\n",
+ ifidx, skb->len, signal_len);
+
+ WARN_ON(signal_len > skb->len);
+
+ /* if flow control disabled, skip to packet data and leave */
+ if (!signal_len || !drvr->fw_signals) {
+ skb_pull(skb, signal_len);
+ return 0;
+ }
+
+ /* lock during tlv parsing */
+ brcmf_fws_lock(drvr, flags);
+
+ fws->stats.header_pulls++;
+ data_len = signal_len;
+ signal_data = skb->data;
+
+ while (data_len > 0) {
+ /* extract tlv info */
+ type = signal_data[0];
+
+ /* FILLER type is actually not a TLV, but
+ * a single byte that can be skipped.
+ */
+ if (type == BRCMF_FWS_TYPE_FILLER) {
+ signal_data += 1;
+ data_len -= 1;
+ continue;
+ }
+ len = signal_data[1];
+ data = signal_data + 2;
+
+ /* abort parsing when length invalid */
+ if (data_len < len + 2)
+ break;
+
+ brcmf_dbg(INFO, "tlv type=%d (%s), len=%d\n", type,
+ brcmf_fws_get_tlv_name(type), len);
+ switch (type) {
+ case BRCMF_FWS_TYPE_MAC_OPEN:
+ case BRCMF_FWS_TYPE_MAC_CLOSE:
+ WARN_ON(len != BRCMF_FWS_TYPE_MAC_OPEN_LEN);
+ break;
+ case BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT:
+ WARN_ON(len != BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT_LEN);
+ break;
+ case BRCMF_FWS_TYPE_TXSTATUS:
+ WARN_ON(len != BRCMF_FWS_TYPE_TXSTATUS_LEN);
+ break;
+ case BRCMF_FWS_TYPE_PKTTAG:
+ WARN_ON(len != BRCMF_FWS_TYPE_PKTTAG_LEN);
+ break;
+ case BRCMF_FWS_TYPE_MACDESC_ADD:
+ case BRCMF_FWS_TYPE_MACDESC_DEL:
+ WARN_ON(len != BRCMF_FWS_TYPE_MACDESC_ADD_LEN);
+ break;
+ case BRCMF_FWS_TYPE_RSSI:
+ WARN_ON(len != BRCMF_FWS_TYPE_RSSI_LEN);
+ brcmf_fws_rssi_indicate(fws, *(s8 *)data);
+ break;
+ case BRCMF_FWS_TYPE_INTERFACE_OPEN:
+ case BRCMF_FWS_TYPE_INTERFACE_CLOSE:
+ WARN_ON(len != BRCMF_FWS_TYPE_INTERFACE_OPEN_LEN);
+ break;
+ case BRCMF_FWS_TYPE_FIFO_CREDITBACK:
+ WARN_ON(len != BRCMF_FWS_TYPE_FIFO_CREDITBACK_LEN);
+ break;
+ case BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP:
+ WARN_ON(len != BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN);
+ break;
+ case BRCMF_FWS_TYPE_MAC_REQUEST_PACKET:
+ WARN_ON(len != BRCMF_FWS_TYPE_MAC_REQUEST_PACKET_LEN);
+ break;
+ case BRCMF_FWS_TYPE_HOST_REORDER_RXPKTS:
+ WARN_ON(len != BRCMF_FWS_TYPE_HOST_REORDER_RXPKTS_LEN);
+ break;
+ case BRCMF_FWS_TYPE_TRANS_ID:
+ WARN_ON(len != BRCMF_FWS_TYPE_TRANS_ID_LEN);
+ brcmf_fws_dbg_seqnum_check(fws, data);
+ break;
+ case BRCMF_FWS_TYPE_COMP_TXSTATUS:
+ WARN_ON(len != BRCMF_FWS_TYPE_COMP_TXSTATUS_LEN);
+ break;
+ default:
+ fws->stats.tlv_invalid_type++;
+ break;
+ }
+
+ signal_data += len + 2;
+ data_len -= len + 2;
+ }
+
+ if (data_len != 0)
+ fws->stats.tlv_parse_failed++;
+
+ /* signalling processing result does
+ * not affect the actual ethernet packet.
+ */
+ skb_pull(skb, signal_len);
+
+ /* this may be a signal-only packet
+ */
+ if (skb->len == 0)
+ fws->stats.header_only_pkt++;
+
+ brcmf_fws_unlock(drvr, flags);
+ return 0;
+}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h
new file mode 100644
index 000000000000..e728eea72bb4
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2012 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#ifndef FWSIGNAL_H_
+#define FWSIGNAL_H_
+
+int brcmf_fws_init(struct brcmf_pub *drvr);
+void brcmf_fws_deinit(struct brcmf_pub *drvr);
+int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
+ struct sk_buff *skb);
+#endif /* FWSIGNAL_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c
new file mode 100644
index 000000000000..b505db48c60d
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2012 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/module.h> /* bug in tracepoint.h, it should include this */
+
+#ifndef __CHECKER__
+#define CREATE_TRACE_POINTS
+#include "tracepoint.h"
+#endif
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h
new file mode 100644
index 000000000000..35efc7a67644
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2013 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#if !defined(BRCMF_TRACEPOINT_H_) || defined(TRACE_HEADER_MULTI_READ)
+#define BRCMF_TRACEPOINT_H_
+
+#include <linux/types.h>
+#include <linux/tracepoint.h>
+
+#ifndef CONFIG_BRCM_TRACING
+
+#undef TRACE_EVENT
+#define TRACE_EVENT(name, proto, ...) \
+static inline void trace_ ## name(proto) {}
+
+#undef DECLARE_EVENT_CLASS
+#define DECLARE_EVENT_CLASS(...)
+
+#undef DEFINE_EVENT
+#define DEFINE_EVENT(evt_class, name, proto, ...) \
+static inline void trace_ ## name(proto) {}
+
+#endif /* CONFIG_BRCM_TRACING */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM brcmfmac
+
+#define MAX_MSG_LEN 100
+
+TRACE_EVENT(brcmf_err,
+ TP_PROTO(const char *func, struct va_format *vaf),
+ TP_ARGS(func, vaf),
+ TP_STRUCT__entry(
+ __string(func, func)
+ __dynamic_array(char, msg, MAX_MSG_LEN)
+ ),
+ TP_fast_assign(
+ __assign_str(func, func);
+ WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
+ MAX_MSG_LEN, vaf->fmt,
+ *vaf->va) >= MAX_MSG_LEN);
+ ),
+ TP_printk("%s: %s", __get_str(func), __get_str(msg))
+);
+
+TRACE_EVENT(brcmf_dbg,
+ TP_PROTO(u32 level, const char *func, struct va_format *vaf),
+ TP_ARGS(level, func, vaf),
+ TP_STRUCT__entry(
+ __field(u32, level)
+ __string(func, func)
+ __dynamic_array(char, msg, MAX_MSG_LEN)
+ ),
+ TP_fast_assign(
+ __entry->level = level;
+ __assign_str(func, func);
+ WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
+ MAX_MSG_LEN, vaf->fmt,
+ *vaf->va) >= MAX_MSG_LEN);
+ ),
+ TP_printk("%s: %s", __get_str(func), __get_str(msg))
+);
+
+#ifdef CONFIG_BRCM_TRACING
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE tracepoint
+
+#include <trace/define_trace.h>
+
+#endif /* CONFIG_BRCM_TRACING */
+
+#endif /* BRCMF_TRACEPOINT_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
index 42289e9ea886..01aed7ad6bec 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
@@ -112,11 +112,6 @@ struct brcmf_usbdev_info {
static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,
struct brcmf_usbreq *req);
-MODULE_AUTHOR("Broadcom Corporation");
-MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN fullmac usb driver.");
-MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN fullmac usb cards");
-MODULE_LICENSE("Dual BSD/GPL");
-
static struct brcmf_usbdev *brcmf_usb_get_buspub(struct device *dev)
{
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
@@ -422,8 +417,6 @@ static void brcmf_usb_tx_complete(struct urb *urb)
brcmf_usb_del_fromq(devinfo, req);
brcmf_txcomplete(devinfo->dev, req->skb, urb->status == 0);
-
- brcmu_pkt_buf_free_skb(req->skb);
req->skb = NULL;
brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req, &devinfo->tx_freecount);
if (devinfo->tx_freecount > devinfo->tx_high_watermark &&
@@ -577,15 +570,17 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
int ret;
brcmf_dbg(USB, "Enter, skb=%p\n", skb);
- if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP)
- return -EIO;
+ if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP) {
+ ret = -EIO;
+ goto fail;
+ }
req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq,
&devinfo->tx_freecount);
if (!req) {
- brcmu_pkt_buf_free_skb(skb);
brcmf_err("no req to send\n");
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto fail;
}
req->skb = skb;
@@ -598,18 +593,21 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
if (ret) {
brcmf_err("brcmf_usb_tx usb_submit_urb FAILED\n");
brcmf_usb_del_fromq(devinfo, req);
- brcmu_pkt_buf_free_skb(req->skb);
req->skb = NULL;
brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req,
- &devinfo->tx_freecount);
- } else {
- if (devinfo->tx_freecount < devinfo->tx_low_watermark &&
- !devinfo->tx_flowblock) {
- brcmf_txflowblock(dev, true);
- devinfo->tx_flowblock = true;
- }
+ &devinfo->tx_freecount);
+ goto fail;
}
+ if (devinfo->tx_freecount < devinfo->tx_low_watermark &&
+ !devinfo->tx_flowblock) {
+ brcmf_txflowblock(dev, true);
+ devinfo->tx_flowblock = true;
+ }
+ return 0;
+
+fail:
+ brcmf_txcomplete(dev, skb, false);
return ret;
}
@@ -1485,6 +1483,7 @@ static struct usb_device_id brcmf_usb_devid_table[] = {
{ USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_BCMFW) },
{ }
};
+
MODULE_DEVICE_TABLE(usb, brcmf_usb_devid_table);
MODULE_FIRMWARE(BRCMF_USB_43143_FW_NAME);
MODULE_FIRMWARE(BRCMF_USB_43236_FW_NAME);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index 2af9c0f0798d..804473fc5c5e 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -3052,16 +3052,16 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
int i;
int ret = 0;
- brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n",
+ brcmf_dbg(SCAN, "Enter n_match_sets:%d n_ssids:%d\n",
request->n_match_sets, request->n_ssids);
if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status);
return -EAGAIN;
}
- if (!request || !request->n_ssids || !request->n_match_sets) {
+ if (!request->n_ssids || !request->n_match_sets) {
brcmf_err("Invalid sched scan req!! n_ssids:%d\n",
- request ? request->n_ssids : 0);
+ request->n_ssids);
return -EINVAL;
}
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/Makefile b/drivers/net/wireless/brcm80211/brcmsmac/Makefile
index d3d4151c3eda..cba19d839b77 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmsmac/Makefile
@@ -43,6 +43,10 @@ BRCMSMAC_OFILES := \
brcms_trace_events.o \
debug.o
+ifdef CONFIG_BCMA_DRIVER_GPIO
+BRCMSMAC_OFILES += led.o
+endif
+
MODULEPFX := brcmsmac
obj-$(CONFIG_BRCMSMAC) += $(MODULEPFX).o
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/led.c b/drivers/net/wireless/brcm80211/brcmsmac/led.c
new file mode 100644
index 000000000000..74b17cecb189
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmsmac/led.c
@@ -0,0 +1,126 @@
+#include <net/mac80211.h>
+#include <linux/bcma/bcma_driver_chipcommon.h>
+#include <linux/gpio.h>
+
+#include "mac80211_if.h"
+#include "pub.h"
+#include "main.h"
+#include "led.h"
+
+ /* number of leds */
+#define BRCMS_LED_NO 4
+ /* behavior mask */
+#define BRCMS_LED_BEH_MASK 0x7f
+ /* activelow (polarity) bit */
+#define BRCMS_LED_AL_MASK 0x80
+ /* radio enabled */
+#define BRCMS_LED_RADIO 3
+
+static void brcms_radio_led_ctrl(struct brcms_info *wl, bool state)
+{
+ if (wl->radio_led.gpio == -1)
+ return;
+
+ if (wl->radio_led.active_low)
+ state = !state;
+
+ if (state)
+ gpio_set_value(wl->radio_led.gpio, 1);
+ else
+ gpio_set_value(wl->radio_led.gpio, 0);
+}
+
+
+/* Callback from the LED subsystem. */
+static void brcms_led_brightness_set(struct led_classdev *led_dev,
+ enum led_brightness brightness)
+{
+ struct brcms_info *wl = container_of(led_dev,
+ struct brcms_info, led_dev);
+ brcms_radio_led_ctrl(wl, brightness);
+}
+
+void brcms_led_unregister(struct brcms_info *wl)
+{
+ if (wl->led_dev.dev)
+ led_classdev_unregister(&wl->led_dev);
+ if (wl->radio_led.gpio != -1)
+ gpio_free(wl->radio_led.gpio);
+}
+
+int brcms_led_register(struct brcms_info *wl)
+{
+ int i, err;
+ struct brcms_led *radio_led = &wl->radio_led;
+ /* get CC core */
+ struct bcma_drv_cc *cc_drv = &wl->wlc->hw->d11core->bus->drv_cc;
+ struct gpio_chip *bcma_gpio = &cc_drv->gpio;
+ struct ssb_sprom *sprom = &wl->wlc->hw->d11core->bus->sprom;
+ u8 *leds[] = { &sprom->gpio0,
+ &sprom->gpio1,
+ &sprom->gpio2,
+ &sprom->gpio3 };
+ unsigned gpio = -1;
+ bool active_low = false;
+
+ /* none by default */
+ radio_led->gpio = -1;
+ radio_led->active_low = false;
+
+ if (!bcma_gpio || !gpio_is_valid(bcma_gpio->base))
+ return -ENODEV;
+
+ /* find radio enabled LED */
+ for (i = 0; i < BRCMS_LED_NO; i++) {
+ u8 led = *leds[i];
+ if ((led & BRCMS_LED_BEH_MASK) == BRCMS_LED_RADIO) {
+ gpio = bcma_gpio->base + i;
+ if (led & BRCMS_LED_AL_MASK)
+ active_low = true;
+ break;
+ }
+ }
+
+ if (gpio == -1 || !gpio_is_valid(gpio))
+ return -ENODEV;
+
+ /* request and configure LED gpio */
+ err = gpio_request_one(gpio,
+ active_low ? GPIOF_OUT_INIT_HIGH
+ : GPIOF_OUT_INIT_LOW,
+ "radio on");
+ if (err) {
+ wiphy_err(wl->wiphy, "requesting led gpio %d failed (err: %d)\n",
+ gpio, err);
+ return err;
+ }
+ err = gpio_direction_output(gpio, 1);
+ if (err) {
+ wiphy_err(wl->wiphy, "cannot set led gpio %d to output (err: %d)\n",
+ gpio, err);
+ return err;
+ }
+
+ snprintf(wl->radio_led.name, sizeof(wl->radio_led.name),
+ "brcmsmac-%s:radio", wiphy_name(wl->wiphy));
+
+ wl->led_dev.name = wl->radio_led.name;
+ wl->led_dev.default_trigger =
+ ieee80211_get_radio_led_name(wl->pub->ieee_hw);
+ wl->led_dev.brightness_set = brcms_led_brightness_set;
+ err = led_classdev_register(wiphy_dev(wl->wiphy), &wl->led_dev);
+
+ if (err) {
+ wiphy_err(wl->wiphy, "cannot register led device: %s (err: %d)\n",
+ wl->radio_led.name, err);
+ return err;
+ }
+
+ wiphy_info(wl->wiphy, "registered radio enabled led device: %s gpio: %d\n",
+ wl->radio_led.name,
+ gpio);
+ radio_led->gpio = gpio;
+ radio_led->active_low = active_low;
+
+ return 0;
+}
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/led.h b/drivers/net/wireless/brcm80211/brcmsmac/led.h
new file mode 100644
index 000000000000..17a0b1f5dbcf
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmsmac/led.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _BRCM_LED_H_
+#define _BRCM_LED_H_
+struct brcms_led {
+ char name[32];
+ unsigned gpio;
+ bool active_low;
+};
+
+#ifdef CONFIG_BCMA_DRIVER_GPIO
+void brcms_led_unregister(struct brcms_info *wl);
+int brcms_led_register(struct brcms_info *wl);
+#else
+static inline void brcms_led_unregister(struct brcms_info *wl) {};
+static inline int brcms_led_register(struct brcms_info *wl)
+{
+ return -ENOTSUPP;
+};
+#endif
+
+#endif /* _BRCM_LED_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index c6451c61407a..c70cf7b654cd 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -34,6 +34,7 @@
#include "mac80211_if.h"
#include "main.h"
#include "debug.h"
+#include "led.h"
#define N_TX_QUEUES 4 /* #tx queues on mac80211<->driver interface */
#define BRCMS_FLUSH_TIMEOUT 500 /* msec */
@@ -904,6 +905,7 @@ static void brcms_remove(struct bcma_device *pdev)
struct brcms_info *wl = hw->priv;
if (wl->wlc) {
+ brcms_led_unregister(wl);
wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
ieee80211_unregister_hw(hw);
@@ -1151,6 +1153,8 @@ static int brcms_bcma_probe(struct bcma_device *pdev)
pr_err("%s: brcms_attach failed!\n", __func__);
return -ENODEV;
}
+ brcms_led_register(wl);
+
return 0;
}
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h
index 947ccacf43e6..4090032e81a2 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h
@@ -20,8 +20,10 @@
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
+#include <linux/leds.h>
#include "ucode_loader.h"
+#include "led.h"
/*
* Starting index for 5G rates in the
* legacy rate table.
@@ -81,6 +83,8 @@ struct brcms_info {
struct wiphy *wiphy;
struct brcms_ucode ucode;
bool mute_tx;
+ struct brcms_led radio_led;
+ struct led_classdev led_dev;
};
/* misc callbacks */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 8ef02dca8f8c..0c8e998bfb1e 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -7810,9 +7810,14 @@ void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx)
/* read the ucode version if we have not yet done so */
if (wlc->ucode_rev == 0) {
- wlc->ucode_rev =
- brcms_b_read_shm(wlc->hw, M_BOM_REV_MAJOR) << NBITS(u16);
- wlc->ucode_rev |= brcms_b_read_shm(wlc->hw, M_BOM_REV_MINOR);
+ u16 rev;
+ u16 patch;
+
+ rev = brcms_b_read_shm(wlc->hw, M_BOM_REV_MAJOR);
+ patch = brcms_b_read_shm(wlc->hw, M_BOM_REV_MINOR);
+ wlc->ucode_rev = (rev << NBITS(u16)) | patch;
+ snprintf(wlc->wiphy->fw_version,
+ sizeof(wlc->wiphy->fw_version), "%u.%u", rev, patch);
}
/* ..now really unleash hell (allow the MAC out of suspend) */
diff --git a/drivers/net/wireless/brcm80211/brcmutil/utils.c b/drivers/net/wireless/brcm80211/brcmutil/utils.c
index 3e6405e06ac0..bf5e50fc21ba 100644
--- a/drivers/net/wireless/brcm80211/brcmutil/utils.c
+++ b/drivers/net/wireless/brcm80211/brcmutil/utils.c
@@ -116,6 +116,31 @@ struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec)
}
EXPORT_SYMBOL(brcmu_pktq_pdeq);
+/*
+ * precedence based dequeue with match function. Passing a NULL pointer
+ * for the match function parameter is considered to be a wildcard so
+ * any packet on the queue is returned. In that case it is no different
+ * from brcmu_pktq_pdeq() above.
+ */
+struct sk_buff *brcmu_pktq_pdeq_match(struct pktq *pq, int prec,
+ bool (*match_fn)(struct sk_buff *skb,
+ void *arg), void *arg)
+{
+ struct sk_buff_head *q;
+ struct sk_buff *p, *next;
+
+ q = &pq->q[prec].skblist;
+ skb_queue_walk_safe(q, p, next) {
+ if (match_fn == NULL || match_fn(p, arg)) {
+ skb_unlink(p, q);
+ pq->len--;
+ return p;
+ }
+ }
+ return NULL;
+}
+EXPORT_SYMBOL(brcmu_pktq_pdeq_match);
+
struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec)
{
struct sk_buff_head *q;
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_utils.h b/drivers/net/wireless/brcm80211/include/brcmu_utils.h
index 477b92ad3d62..898cacb8d01d 100644
--- a/drivers/net/wireless/brcm80211/include/brcmu_utils.h
+++ b/drivers/net/wireless/brcm80211/include/brcmu_utils.h
@@ -120,6 +120,10 @@ extern struct sk_buff *brcmu_pktq_penq_head(struct pktq *pq, int prec,
struct sk_buff *p);
extern struct sk_buff *brcmu_pktq_pdeq(struct pktq *pq, int prec);
extern struct sk_buff *brcmu_pktq_pdeq_tail(struct pktq *pq, int prec);
+extern struct sk_buff *brcmu_pktq_pdeq_match(struct pktq *pq, int prec,
+ bool (*match_fn)(struct sk_buff *p,
+ void *arg),
+ void *arg);
/* packet primitives */
extern struct sk_buff *brcmu_pkt_buf_get_skb(uint len);
@@ -173,6 +177,29 @@ extern void brcmu_pktq_flush(struct pktq *pq, bool dir,
/* ip address */
struct ipv4_addr;
+/*
+ * bitfield macros using masking and shift
+ *
+ * remark: the mask parameter should be a shifted mask.
+ */
+static inline void brcmu_maskset32(u32 *var, u32 mask, u8 shift, u32 value)
+{
+ value = (value << shift) & mask;
+ *var = (*var & ~mask) | value;
+}
+static inline u32 brcmu_maskget32(u32 var, u32 mask, u8 shift)
+{
+ return (var & mask) >> shift;
+}
+static inline void brcmu_maskset16(u16 *var, u16 mask, u8 shift, u16 value)
+{
+ value = (value << shift) & mask;
+ *var = (*var & ~mask) | value;
+}
+static inline u16 brcmu_maskget16(u16 var, u16 mask, u8 shift)
+{
+ return (var & mask) >> shift;
+}
/* externs */
/* format/print */
diff --git a/drivers/net/wireless/mwifiex/Makefile b/drivers/net/wireless/mwifiex/Makefile
index 97b245cbafd8..ecf28464367f 100644
--- a/drivers/net/wireless/mwifiex/Makefile
+++ b/drivers/net/wireless/mwifiex/Makefile
@@ -39,6 +39,7 @@ mwifiex-y += sta_tx.o
mwifiex-y += sta_rx.o
mwifiex-y += uap_txrx.o
mwifiex-y += cfg80211.o
+mwifiex-y += ethtool.o
mwifiex-$(CONFIG_DEBUG_FS) += debugfs.o
obj-$(CONFIG_MWIFIEX) += mwifiex.o
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index a44023a7bd57..df30107225f8 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -2235,6 +2235,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT;
dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN;
+ dev->ethtool_ops = &mwifiex_ethtool_ops;
mdev_priv = netdev_priv(dev);
*((unsigned long *) mdev_priv) = (unsigned long) priv;
@@ -2293,6 +2294,149 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
}
EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf);
+#ifdef CONFIG_PM
+static bool
+mwifiex_is_pattern_supported(struct cfg80211_wowlan_trig_pkt_pattern *pat,
+ s8 *byte_seq)
+{
+ int j, k, valid_byte_cnt = 0;
+ bool dont_care_byte = false;
+
+ for (j = 0; j < DIV_ROUND_UP(pat->pattern_len, 8); j++) {
+ for (k = 0; k < 8; k++) {
+ if (pat->mask[j] & 1 << k) {
+ memcpy(byte_seq + valid_byte_cnt,
+ &pat->pattern[j * 8 + k], 1);
+ valid_byte_cnt++;
+ if (dont_care_byte)
+ return false;
+ } else {
+ if (valid_byte_cnt)
+ dont_care_byte = true;
+ }
+
+ if (valid_byte_cnt > MAX_BYTESEQ)
+ return false;
+ }
+ }
+
+ byte_seq[MAX_BYTESEQ] = valid_byte_cnt;
+
+ return true;
+}
+
+static int mwifiex_cfg80211_suspend(struct wiphy *wiphy,
+ struct cfg80211_wowlan *wowlan)
+{
+ struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
+ struct mwifiex_ds_mef_cfg mef_cfg;
+ struct mwifiex_mef_entry *mef_entry;
+ int i, filt_num = 0, ret;
+ bool first_pat = true;
+ u8 byte_seq[MAX_BYTESEQ + 1];
+ const u8 ipv4_mc_mac[] = {0x33, 0x33};
+ const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e};
+ struct mwifiex_private *priv =
+ mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);
+
+ if (!wowlan) {
+ dev_warn(adapter->dev, "None of the WOWLAN triggers enabled\n");
+ return 0;
+ }
+
+ if (!priv->media_connected) {
+ dev_warn(adapter->dev,
+ "Can not configure WOWLAN in disconnected state\n");
+ return 0;
+ }
+
+ memset(&mef_cfg, 0, sizeof(mef_cfg));
+ mef_cfg.num_entries = 1;
+ mef_entry = kzalloc(sizeof(*mef_entry), GFP_KERNEL);
+ mef_cfg.mef_entry = mef_entry;
+ mef_entry->mode = MEF_MODE_HOST_SLEEP;
+ mef_entry->action = MEF_ACTION_ALLOW_AND_WAKEUP_HOST;
+
+ for (i = 0; i < wowlan->n_patterns; i++) {
+ memset(byte_seq, 0, sizeof(byte_seq));
+ if (!mwifiex_is_pattern_supported(&wowlan->patterns[i],
+ byte_seq)) {
+ wiphy_err(wiphy, "Pattern not supported\n");
+ kfree(mef_entry);
+ return -EOPNOTSUPP;
+ }
+
+ if (!wowlan->patterns[i].pkt_offset) {
+ if (!(byte_seq[0] & 0x01) &&
+ (byte_seq[MAX_BYTESEQ] == 1)) {
+ mef_cfg.criteria |= MWIFIEX_CRITERIA_UNICAST;
+ continue;
+ } else if (is_broadcast_ether_addr(byte_seq)) {
+ mef_cfg.criteria |= MWIFIEX_CRITERIA_BROADCAST;
+ continue;
+ } else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) &&
+ (byte_seq[MAX_BYTESEQ] == 2)) ||
+ (!memcmp(byte_seq, ipv6_mc_mac, 3) &&
+ (byte_seq[MAX_BYTESEQ] == 3))) {
+ mef_cfg.criteria |= MWIFIEX_CRITERIA_MULTICAST;
+ continue;
+ }
+ }
+
+ mef_entry->filter[filt_num].repeat = 1;
+ mef_entry->filter[filt_num].offset =
+ wowlan->patterns[i].pkt_offset;
+ memcpy(mef_entry->filter[filt_num].byte_seq, byte_seq,
+ sizeof(byte_seq));
+ mef_entry->filter[filt_num].filt_type = TYPE_EQ;
+
+ if (first_pat)
+ first_pat = false;
+ else
+ mef_entry->filter[filt_num].filt_action = TYPE_AND;
+
+ filt_num++;
+ }
+
+ if (wowlan->magic_pkt) {
+ mef_cfg.criteria |= MWIFIEX_CRITERIA_UNICAST;
+ mef_entry->filter[filt_num].repeat = 16;
+ memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr,
+ ETH_ALEN);
+ mef_entry->filter[filt_num].byte_seq[MAX_BYTESEQ] = ETH_ALEN;
+ mef_entry->filter[filt_num].offset = 14;
+ mef_entry->filter[filt_num].filt_type = TYPE_EQ;
+ if (filt_num)
+ mef_entry->filter[filt_num].filt_action = TYPE_OR;
+ }
+
+ if (!mef_cfg.criteria)
+ mef_cfg.criteria = MWIFIEX_CRITERIA_BROADCAST |
+ MWIFIEX_CRITERIA_UNICAST |
+ MWIFIEX_CRITERIA_MULTICAST;
+
+ ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_MEF_CFG,
+ HostCmd_ACT_GEN_SET, 0,
+ &mef_cfg);
+
+ kfree(mef_entry);
+ return ret;
+}
+
+static int mwifiex_cfg80211_resume(struct wiphy *wiphy)
+{
+ return 0;
+}
+
+static void mwifiex_cfg80211_set_wakeup(struct wiphy *wiphy,
+ bool enabled)
+{
+ struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
+
+ device_set_wakeup_enable(adapter->dev, enabled);
+}
+#endif
+
/* station cfg80211 operations */
static struct cfg80211_ops mwifiex_cfg80211_ops = {
.add_virtual_intf = mwifiex_add_virtual_intf,
@@ -2321,6 +2465,11 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
.change_beacon = mwifiex_cfg80211_change_beacon,
.set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config,
.set_antenna = mwifiex_cfg80211_set_antenna,
+#ifdef CONFIG_PM
+ .suspend = mwifiex_cfg80211_suspend,
+ .resume = mwifiex_cfg80211_resume,
+ .set_wakeup = mwifiex_cfg80211_set_wakeup,
+#endif
};
/*
@@ -2379,6 +2528,14 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom);
+#ifdef CONFIG_PM
+ wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
+ wiphy->wowlan.n_patterns = MWIFIEX_MAX_FILTERS;
+ wiphy->wowlan.pattern_min_len = 1;
+ wiphy->wowlan.pattern_max_len = MWIFIEX_MAX_PATTERN_LEN;
+ wiphy->wowlan.max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN;
+#endif
+
wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P;
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index 20a6c5555873..d19a88c47a4d 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -1139,7 +1139,7 @@ int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv,
phs_cfg->params.hs_config.gpio,
phs_cfg->params.hs_config.gap);
}
- if (conditions != HOST_SLEEP_CFG_CANCEL) {
+ if (conditions != HS_CFG_CANCEL) {
adapter->is_hs_configured = true;
if (adapter->iface_type == MWIFIEX_USB ||
adapter->iface_type == MWIFIEX_PCIE)
diff --git a/drivers/net/wireless/mwifiex/ethtool.c b/drivers/net/wireless/mwifiex/ethtool.c
new file mode 100644
index 000000000000..bfb39908b2c6
--- /dev/null
+++ b/drivers/net/wireless/mwifiex/ethtool.c
@@ -0,0 +1,70 @@
+/*
+ * Marvell Wireless LAN device driver: ethtool
+ *
+ * Copyright (C) 2013, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License"). You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "main.h"
+
+static void mwifiex_ethtool_get_wol(struct net_device *dev,
+ struct ethtool_wolinfo *wol)
+{
+ struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+ u32 conditions = le32_to_cpu(priv->adapter->hs_cfg.conditions);
+
+ wol->supported = WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY;
+
+ if (conditions == HS_CFG_COND_DEF)
+ return;
+
+ if (conditions & HS_CFG_COND_UNICAST_DATA)
+ wol->wolopts |= WAKE_UCAST;
+ if (conditions & HS_CFG_COND_MULTICAST_DATA)
+ wol->wolopts |= WAKE_MCAST;
+ if (conditions & HS_CFG_COND_BROADCAST_DATA)
+ wol->wolopts |= WAKE_BCAST;
+ if (conditions & HS_CFG_COND_MAC_EVENT)
+ wol->wolopts |= WAKE_PHY;
+}
+
+static int mwifiex_ethtool_set_wol(struct net_device *dev,
+ struct ethtool_wolinfo *wol)
+{
+ struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+ u32 conditions = 0;
+
+ if (wol->wolopts & ~(WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY))
+ return -EOPNOTSUPP;
+
+ if (wol->wolopts & WAKE_UCAST)
+ conditions |= HS_CFG_COND_UNICAST_DATA;
+ if (wol->wolopts & WAKE_MCAST)
+ conditions |= HS_CFG_COND_MULTICAST_DATA;
+ if (wol->wolopts & WAKE_BCAST)
+ conditions |= HS_CFG_COND_BROADCAST_DATA;
+ if (wol->wolopts & WAKE_PHY)
+ conditions |= HS_CFG_COND_MAC_EVENT;
+ if (wol->wolopts == 0)
+ conditions |= HS_CFG_COND_DEF;
+ priv->adapter->hs_cfg.conditions = cpu_to_le32(conditions);
+
+ return 0;
+}
+
+const struct ethtool_ops mwifiex_ethtool_ops = {
+ .get_wol = mwifiex_ethtool_get_wol,
+ .set_wol = mwifiex_ethtool_set_wol,
+};
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index 25acb0682c56..6d6e5ae71eaa 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -300,6 +300,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define HostCmd_CMD_802_11_TX_RATE_QUERY 0x007f
#define HostCmd_CMD_802_11_IBSS_COALESCING_STATUS 0x0083
#define HostCmd_CMD_VERSION_EXT 0x0097
+#define HostCmd_CMD_MEF_CFG 0x009a
#define HostCmd_CMD_RSSI_INFO 0x00a4
#define HostCmd_CMD_FUNC_INIT 0x00a9
#define HostCmd_CMD_FUNC_SHUTDOWN 0x00aa
@@ -376,10 +377,14 @@ enum P2P_MODES {
#define HostCmd_SCAN_RADIO_TYPE_BG 0
#define HostCmd_SCAN_RADIO_TYPE_A 1
-#define HOST_SLEEP_CFG_CANCEL 0xffffffff
-#define HOST_SLEEP_CFG_COND_DEF 0x00000000
-#define HOST_SLEEP_CFG_GPIO_DEF 0xff
-#define HOST_SLEEP_CFG_GAP_DEF 0
+#define HS_CFG_CANCEL 0xffffffff
+#define HS_CFG_COND_DEF 0x00000000
+#define HS_CFG_GPIO_DEF 0xff
+#define HS_CFG_GAP_DEF 0
+#define HS_CFG_COND_BROADCAST_DATA 0x00000001
+#define HS_CFG_COND_UNICAST_DATA 0x00000002
+#define HS_CFG_COND_MAC_EVENT 0x00000004
+#define HS_CFG_COND_MULTICAST_DATA 0x00000008
#define MWIFIEX_TIMEOUT_FOR_AP_RESP 0xfffc
#define MWIFIEX_STATUS_CODE_AUTH_TIMEOUT 2
@@ -469,6 +474,23 @@ enum P2P_MODES {
#define EVENT_GET_BSS_TYPE(event_cause) \
(((event_cause) >> 24) & 0x00ff)
+#define MWIFIEX_MAX_PATTERN_LEN 20
+#define MWIFIEX_MAX_OFFSET_LEN 50
+#define STACK_NBYTES 100
+#define TYPE_DNUM 1
+#define TYPE_BYTESEQ 2
+#define MAX_OPERAND 0x40
+#define TYPE_EQ (MAX_OPERAND+1)
+#define TYPE_EQ_DNUM (MAX_OPERAND+2)
+#define TYPE_EQ_BIT (MAX_OPERAND+3)
+#define TYPE_AND (MAX_OPERAND+4)
+#define TYPE_OR (MAX_OPERAND+5)
+#define MEF_MODE_HOST_SLEEP 1
+#define MEF_ACTION_ALLOW_AND_WAKEUP_HOST 3
+#define MWIFIEX_CRITERIA_BROADCAST BIT(0)
+#define MWIFIEX_CRITERIA_UNICAST BIT(1)
+#define MWIFIEX_CRITERIA_MULTICAST BIT(3)
+
struct mwifiex_ie_types_header {
__le16 type;
__le16 len;
@@ -1499,6 +1521,19 @@ struct host_cmd_ds_802_11_ibss_status {
__le16 use_g_rate_protect;
} __packed;
+struct mwifiex_fw_mef_entry {
+ u8 mode;
+ u8 action;
+ __le16 exprsize;
+ u8 expr[0];
+} __packed;
+
+struct host_cmd_ds_mef_cfg {
+ __le32 criteria;
+ __le16 num_entries;
+ struct mwifiex_fw_mef_entry mef_entry[0];
+} __packed;
+
#define CONNECTION_TYPE_INFRA 0
#define CONNECTION_TYPE_ADHOC 1
#define CONNECTION_TYPE_AP 2
@@ -1603,6 +1638,7 @@ struct host_cmd_ds_command {
struct host_cmd_ds_remain_on_chan roc_cfg;
struct host_cmd_ds_p2p_mode_cfg mode_cfg;
struct host_cmd_ds_802_11_ibss_status ibss_coalescing;
+ struct host_cmd_ds_mef_cfg mef_cfg;
struct host_cmd_ds_mac_reg_access mac_reg;
struct host_cmd_ds_bbp_reg_access bbp_reg;
struct host_cmd_ds_rf_reg_access rf_reg;
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index e38aa9b3663d..cab3434d0d52 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -318,9 +318,9 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
adapter->curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K;
adapter->is_hs_configured = false;
- adapter->hs_cfg.conditions = cpu_to_le32(HOST_SLEEP_CFG_COND_DEF);
- adapter->hs_cfg.gpio = HOST_SLEEP_CFG_GPIO_DEF;
- adapter->hs_cfg.gap = HOST_SLEEP_CFG_GAP_DEF;
+ adapter->hs_cfg.conditions = cpu_to_le32(HS_CFG_COND_DEF);
+ adapter->hs_cfg.gpio = HS_CFG_GPIO_DEF;
+ adapter->hs_cfg.gap = HS_CFG_GAP_DEF;
adapter->hs_activated = false;
memset(adapter->event_body, 0, sizeof(adapter->event_body));
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h
index d85e6eb1f58a..91d522c746ed 100644
--- a/drivers/net/wireless/mwifiex/ioctl.h
+++ b/drivers/net/wireless/mwifiex/ioctl.h
@@ -354,6 +354,29 @@ struct mwifiex_ds_misc_subsc_evt {
struct subsc_evt_cfg bcn_h_rssi_cfg;
};
+#define MAX_BYTESEQ 6 /* non-adjustable */
+#define MWIFIEX_MAX_FILTERS 10
+
+struct mwifiex_mef_filter {
+ u16 repeat;
+ u16 offset;
+ s8 byte_seq[MAX_BYTESEQ + 1];
+ u8 filt_type;
+ u8 filt_action;
+};
+
+struct mwifiex_mef_entry {
+ u8 mode;
+ u8 action;
+ struct mwifiex_mef_filter filter[MWIFIEX_MAX_FILTERS];
+};
+
+struct mwifiex_ds_mef_cfg {
+ u32 criteria;
+ u16 num_entries;
+ struct mwifiex_mef_entry *mef_entry;
+};
+
#define MWIFIEX_MAX_VSIE_LEN (256)
#define MWIFIEX_MAX_VSIE_NUM (8)
#define MWIFIEX_VSIE_MASK_CLEAR 0x00
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 553adfb0aa81..560cf7312d08 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -1098,11 +1098,15 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev);
void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config);
+int mwifiex_add_wowlan_magic_pkt_filter(struct mwifiex_adapter *adapter);
+
int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
struct cfg80211_beacon_data *data);
int mwifiex_del_mgmt_ies(struct mwifiex_private *priv);
u8 *mwifiex_11d_code_2_region(u8 code);
+extern const struct ethtool_ops mwifiex_ethtool_ops;
+
#ifdef CONFIG_DEBUG_FS
void mwifiex_debugfs_init(void);
void mwifiex_debugfs_remove(void);
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c
index 35c79722c361..b813a27ee613 100644
--- a/drivers/net/wireless/mwifiex/pcie.c
+++ b/drivers/net/wireless/mwifiex/pcie.c
@@ -36,8 +36,6 @@ static u8 user_rmmod;
static struct mwifiex_if_ops pcie_ops;
static struct semaphore add_remove_card_sem;
-static int mwifiex_pcie_enable_host_int(struct mwifiex_adapter *adapter);
-static int mwifiex_pcie_resume(struct pci_dev *pdev);
static int
mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb,
@@ -78,6 +76,82 @@ static bool mwifiex_pcie_ok_to_access_hw(struct mwifiex_adapter *adapter)
return false;
}
+#ifdef CONFIG_PM
+/*
+ * Kernel needs to suspend all functions separately. Therefore all
+ * registered functions must have drivers with suspend and resume
+ * methods. Failing that the kernel simply removes the whole card.
+ *
+ * If already not suspended, this function allocates and sends a host
+ * sleep activate request to the firmware and turns off the traffic.
+ */
+static int mwifiex_pcie_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct mwifiex_adapter *adapter;
+ struct pcie_service_card *card;
+ int hs_actived;
+
+ if (pdev) {
+ card = (struct pcie_service_card *) pci_get_drvdata(pdev);
+ if (!card || !card->adapter) {
+ pr_err("Card or adapter structure is not valid\n");
+ return 0;
+ }
+ } else {
+ pr_err("PCIE device is not specified\n");
+ return 0;
+ }
+
+ adapter = card->adapter;
+
+ hs_actived = mwifiex_enable_hs(adapter);
+
+ /* Indicate device suspended */
+ adapter->is_suspended = true;
+
+ return 0;
+}
+
+/*
+ * Kernel needs to suspend all functions separately. Therefore all
+ * registered functions must have drivers with suspend and resume
+ * methods. Failing that the kernel simply removes the whole card.
+ *
+ * If already not resumed, this function turns on the traffic and
+ * sends a host sleep cancel request to the firmware.
+ */
+static int mwifiex_pcie_resume(struct pci_dev *pdev)
+{
+ struct mwifiex_adapter *adapter;
+ struct pcie_service_card *card;
+
+ if (pdev) {
+ card = (struct pcie_service_card *) pci_get_drvdata(pdev);
+ if (!card || !card->adapter) {
+ pr_err("Card or adapter structure is not valid\n");
+ return 0;
+ }
+ } else {
+ pr_err("PCIE device is not specified\n");
+ return 0;
+ }
+
+ adapter = card->adapter;
+
+ if (!adapter->is_suspended) {
+ dev_warn(adapter->dev, "Device already resumed\n");
+ return 0;
+ }
+
+ adapter->is_suspended = false;
+
+ mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
+ MWIFIEX_ASYNC_CMD);
+
+ return 0;
+}
+#endif
+
/*
* This function probes an mwifiex device and registers it. It allocates
* the card structure, enables PCIE function number and initiates the
@@ -159,80 +233,6 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev)
kfree(card);
}
-/*
- * Kernel needs to suspend all functions separately. Therefore all
- * registered functions must have drivers with suspend and resume
- * methods. Failing that the kernel simply removes the whole card.
- *
- * If already not suspended, this function allocates and sends a host
- * sleep activate request to the firmware and turns off the traffic.
- */
-static int mwifiex_pcie_suspend(struct pci_dev *pdev, pm_message_t state)
-{
- struct mwifiex_adapter *adapter;
- struct pcie_service_card *card;
- int hs_actived;
-
- if (pdev) {
- card = (struct pcie_service_card *) pci_get_drvdata(pdev);
- if (!card || !card->adapter) {
- pr_err("Card or adapter structure is not valid\n");
- return 0;
- }
- } else {
- pr_err("PCIE device is not specified\n");
- return 0;
- }
-
- adapter = card->adapter;
-
- hs_actived = mwifiex_enable_hs(adapter);
-
- /* Indicate device suspended */
- adapter->is_suspended = true;
-
- return 0;
-}
-
-/*
- * Kernel needs to suspend all functions separately. Therefore all
- * registered functions must have drivers with suspend and resume
- * methods. Failing that the kernel simply removes the whole card.
- *
- * If already not resumed, this function turns on the traffic and
- * sends a host sleep cancel request to the firmware.
- */
-static int mwifiex_pcie_resume(struct pci_dev *pdev)
-{
- struct mwifiex_adapter *adapter;
- struct pcie_service_card *card;
-
- if (pdev) {
- card = (struct pcie_service_card *) pci_get_drvdata(pdev);
- if (!card || !card->adapter) {
- pr_err("Card or adapter structure is not valid\n");
- return 0;
- }
- } else {
- pr_err("PCIE device is not specified\n");
- return 0;
- }
-
- adapter = card->adapter;
-
- if (!adapter->is_suspended) {
- dev_warn(adapter->dev, "Device already resumed\n");
- return 0;
- }
-
- adapter->is_suspended = false;
-
- mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
- MWIFIEX_ASYNC_CMD);
-
- return 0;
-}
-
static DEFINE_PCI_DEVICE_TABLE(mwifiex_ids) = {
{
PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8766P,
@@ -1030,8 +1030,8 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb,
u32 wrindx, num_tx_buffs, rx_val;
int ret;
dma_addr_t buf_pa;
- struct mwifiex_pcie_buf_desc *desc;
- struct mwifiex_pfu_buf_desc *desc2;
+ struct mwifiex_pcie_buf_desc *desc = NULL;
+ struct mwifiex_pfu_buf_desc *desc2 = NULL;
__le16 *tmp;
if (!(skb->data && skb->len)) {
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c
index c55c5bb93134..a2ae690a0a67 100644
--- a/drivers/net/wireless/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/mwifiex/sta_cmd.c
@@ -334,7 +334,7 @@ mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
cmd->command = cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH);
if (!hs_activate &&
- (hscfg_param->conditions != cpu_to_le32(HOST_SLEEP_CFG_CANCEL)) &&
+ (hscfg_param->conditions != cpu_to_le32(HS_CFG_CANCEL)) &&
((adapter->arp_filter_size > 0) &&
(adapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE))) {
dev_dbg(adapter->dev,
@@ -1059,6 +1059,80 @@ mwifiex_cmd_802_11_subsc_evt(struct mwifiex_private *priv,
return 0;
}
+static int
+mwifiex_cmd_append_rpn_expression(struct mwifiex_private *priv,
+ struct mwifiex_mef_entry *mef_entry,
+ u8 **buffer)
+{
+ struct mwifiex_mef_filter *filter = mef_entry->filter;
+ int i, byte_len;
+ u8 *stack_ptr = *buffer;
+
+ for (i = 0; i < MWIFIEX_MAX_FILTERS; i++) {
+ filter = &mef_entry->filter[i];
+ if (!filter->filt_type)
+ break;
+ *(__le32 *)stack_ptr = cpu_to_le32((u32)filter->repeat);
+ stack_ptr += 4;
+ *stack_ptr = TYPE_DNUM;
+ stack_ptr += 1;
+
+ byte_len = filter->byte_seq[MAX_BYTESEQ];
+ memcpy(stack_ptr, filter->byte_seq, byte_len);
+ stack_ptr += byte_len;
+ *stack_ptr = byte_len;
+ stack_ptr += 1;
+ *stack_ptr = TYPE_BYTESEQ;
+ stack_ptr += 1;
+
+ *(__le32 *)stack_ptr = cpu_to_le32((u32)filter->offset);
+ stack_ptr += 4;
+ *stack_ptr = TYPE_DNUM;
+ stack_ptr += 1;
+
+ *stack_ptr = filter->filt_type;
+ stack_ptr += 1;
+
+ if (filter->filt_action) {
+ *stack_ptr = filter->filt_action;
+ stack_ptr += 1;
+ }
+
+ if (stack_ptr - *buffer > STACK_NBYTES)
+ return -1;
+ }
+
+ *buffer = stack_ptr;
+ return 0;
+}
+
+static int
+mwifiex_cmd_mef_cfg(struct mwifiex_private *priv,
+ struct host_cmd_ds_command *cmd,
+ struct mwifiex_ds_mef_cfg *mef)
+{
+ struct host_cmd_ds_mef_cfg *mef_cfg = &cmd->params.mef_cfg;
+ u8 *pos = (u8 *)mef_cfg;
+
+ cmd->command = cpu_to_le16(HostCmd_CMD_MEF_CFG);
+
+ mef_cfg->criteria = cpu_to_le32(mef->criteria);
+ mef_cfg->num_entries = cpu_to_le16(mef->num_entries);
+ pos += sizeof(*mef_cfg);
+ mef_cfg->mef_entry->mode = mef->mef_entry->mode;
+ mef_cfg->mef_entry->action = mef->mef_entry->action;
+ pos += sizeof(*(mef_cfg->mef_entry));
+
+ if (mwifiex_cmd_append_rpn_expression(priv, mef->mef_entry, &pos))
+ return -1;
+
+ mef_cfg->mef_entry->exprsize =
+ cpu_to_le16(pos - mef_cfg->mef_entry->expr);
+ cmd->size = cpu_to_le16((u16) (pos - (u8 *)mef_cfg) + S_DS_GEN);
+
+ return 0;
+}
+
/*
* This function prepares the commands before sending them to the firmware.
*
@@ -1273,6 +1347,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
case HostCmd_CMD_802_11_SUBSCRIBE_EVENT:
ret = mwifiex_cmd_802_11_subsc_evt(priv, cmd_ptr, data_buf);
break;
+ case HostCmd_CMD_MEF_CFG:
+ ret = mwifiex_cmd_mef_cfg(priv, cmd_ptr, data_buf);
+ break;
default:
dev_err(priv->adapter->dev,
"PREP_CMD: unknown cmd- %#x\n", cmd_no);
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index 4669f8d9389f..80b9f2238001 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -976,6 +976,8 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
case HostCmd_CMD_UAP_BSS_STOP:
priv->bss_started = 0;
break;
+ case HostCmd_CMD_MEF_CFG:
+ break;
default:
dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n",
resp->command);
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index 9f33c92c90f5..76d31deb7b1b 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -388,7 +388,7 @@ static int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action,
break;
}
if (hs_cfg->is_invoke_hostcmd) {
- if (hs_cfg->conditions == HOST_SLEEP_CFG_CANCEL) {
+ if (hs_cfg->conditions == HS_CFG_CANCEL) {
if (!adapter->is_hs_configured)
/* Already cancelled */
break;
@@ -403,8 +403,8 @@ static int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action,
adapter->hs_cfg.gpio = (u8)hs_cfg->gpio;
if (hs_cfg->gap)
adapter->hs_cfg.gap = (u8)hs_cfg->gap;
- } else if (adapter->hs_cfg.conditions
- == cpu_to_le32(HOST_SLEEP_CFG_CANCEL)) {
+ } else if (adapter->hs_cfg.conditions ==
+ cpu_to_le32(HS_CFG_CANCEL)) {
/* Return failure if no parameters for HS
enable */
status = -1;
@@ -420,7 +420,7 @@ static int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action,
HostCmd_CMD_802_11_HS_CFG_ENH,
HostCmd_ACT_GEN_SET, 0,
&adapter->hs_cfg);
- if (hs_cfg->conditions == HOST_SLEEP_CFG_CANCEL)
+ if (hs_cfg->conditions == HS_CFG_CANCEL)
/* Restore previous condition */
adapter->hs_cfg.conditions =
cpu_to_le32(prev_cond);
@@ -454,7 +454,7 @@ int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type)
{
struct mwifiex_ds_hs_cfg hscfg;
- hscfg.conditions = HOST_SLEEP_CFG_CANCEL;
+ hscfg.conditions = HS_CFG_CANCEL;
hscfg.is_invoke_hostcmd = true;
return mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET,
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c
index 21553976b550..54667e65ca47 100644
--- a/drivers/net/wireless/mwifiex/util.c
+++ b/drivers/net/wireless/mwifiex/util.c
@@ -195,7 +195,7 @@ int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb)
skb->protocol = eth_type_trans(skb, priv->netdev);
skb->ip_summed = CHECKSUM_NONE;
- /* This is required only in case of 11n and USB as we alloc
+ /* This is required only in case of 11n and USB/PCIE as we alloc
* a buffer of 4K only if its 11N (to be able to receive 4K
* AMSDU packets). In case of SD we allocate buffers based
* on the size of packet and hence this is not needed.
@@ -212,7 +212,8 @@ int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb)
* fragments. Currently we fail the Filesndl-ht.scr script
* for UDP, hence this fix
*/
- if ((priv->adapter->iface_type == MWIFIEX_USB) &&
+ if ((priv->adapter->iface_type == MWIFIEX_USB ||
+ priv->adapter->iface_type == MWIFIEX_PCIE) &&
(skb->truesize > MWIFIEX_RX_DATA_BUF_SIZE))
skb->truesize += (skb->len - MWIFIEX_RX_DATA_BUF_SIZE);
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 091d9a64080a..aaaf10d48f7d 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -284,6 +284,7 @@ struct mwl8k_priv {
unsigned fw_state;
char *fw_pref;
char *fw_alt;
+ bool is_8764;
struct completion firmware_loading_complete;
/* bitmap of running BSSes */
@@ -600,13 +601,18 @@ mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length)
loops = 1000;
do {
u32 int_code;
-
- int_code = ioread32(regs + MWL8K_HIU_INT_CODE);
- if (int_code == MWL8K_INT_CODE_CMD_FINISHED) {
- iowrite32(0, regs + MWL8K_HIU_INT_CODE);
- break;
+ if (priv->is_8764) {
+ int_code = ioread32(regs +
+ MWL8K_HIU_H2A_INTERRUPT_STATUS);
+ if (int_code == 0)
+ break;
+ } else {
+ int_code = ioread32(regs + MWL8K_HIU_INT_CODE);
+ if (int_code == MWL8K_INT_CODE_CMD_FINISHED) {
+ iowrite32(0, regs + MWL8K_HIU_INT_CODE);
+ break;
+ }
}
-
cond_resched();
udelay(1);
} while (--loops);
@@ -724,7 +730,7 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw)
int rc;
int loops;
- if (!memcmp(fw->data, "\x01\x00\x00\x00", 4)) {
+ if (!memcmp(fw->data, "\x01\x00\x00\x00", 4) && !priv->is_8764) {
const struct firmware *helper = priv->fw_helper;
if (helper == NULL) {
@@ -743,7 +749,10 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw)
rc = mwl8k_feed_fw_image(priv, fw->data, fw->size);
} else {
- rc = mwl8k_load_fw_image(priv, fw->data, fw->size);
+ if (priv->is_8764)
+ rc = mwl8k_feed_fw_image(priv, fw->data, fw->size);
+ else
+ rc = mwl8k_load_fw_image(priv, fw->data, fw->size);
}
if (rc) {
@@ -908,9 +917,9 @@ static void mwl8k_encapsulate_tx_frame(struct mwl8k_priv *priv,
}
/*
- * Packet reception for 88w8366 AP firmware.
+ * Packet reception for 88w8366/88w8764 AP firmware.
*/
-struct mwl8k_rxd_8366_ap {
+struct mwl8k_rxd_ap {
__le16 pkt_len;
__u8 sq2;
__u8 rate;
@@ -928,30 +937,30 @@ struct mwl8k_rxd_8366_ap {
__u8 rx_ctrl;
} __packed;
-#define MWL8K_8366_AP_RATE_INFO_MCS_FORMAT 0x80
-#define MWL8K_8366_AP_RATE_INFO_40MHZ 0x40
-#define MWL8K_8366_AP_RATE_INFO_RATEID(x) ((x) & 0x3f)
+#define MWL8K_AP_RATE_INFO_MCS_FORMAT 0x80
+#define MWL8K_AP_RATE_INFO_40MHZ 0x40
+#define MWL8K_AP_RATE_INFO_RATEID(x) ((x) & 0x3f)
-#define MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST 0x80
+#define MWL8K_AP_RX_CTRL_OWNED_BY_HOST 0x80
-/* 8366 AP rx_status bits */
-#define MWL8K_8366_AP_RXSTAT_DECRYPT_ERR_MASK 0x80
-#define MWL8K_8366_AP_RXSTAT_GENERAL_DECRYPT_ERR 0xFF
-#define MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR 0x02
-#define MWL8K_8366_AP_RXSTAT_WEP_DECRYPT_ICV_ERR 0x04
-#define MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_ICV_ERR 0x08
+/* 8366/8764 AP rx_status bits */
+#define MWL8K_AP_RXSTAT_DECRYPT_ERR_MASK 0x80
+#define MWL8K_AP_RXSTAT_GENERAL_DECRYPT_ERR 0xFF
+#define MWL8K_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR 0x02
+#define MWL8K_AP_RXSTAT_WEP_DECRYPT_ICV_ERR 0x04
+#define MWL8K_AP_RXSTAT_TKIP_DECRYPT_ICV_ERR 0x08
-static void mwl8k_rxd_8366_ap_init(void *_rxd, dma_addr_t next_dma_addr)
+static void mwl8k_rxd_ap_init(void *_rxd, dma_addr_t next_dma_addr)
{
- struct mwl8k_rxd_8366_ap *rxd = _rxd;
+ struct mwl8k_rxd_ap *rxd = _rxd;
rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr);
- rxd->rx_ctrl = MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST;
+ rxd->rx_ctrl = MWL8K_AP_RX_CTRL_OWNED_BY_HOST;
}
-static void mwl8k_rxd_8366_ap_refill(void *_rxd, dma_addr_t addr, int len)
+static void mwl8k_rxd_ap_refill(void *_rxd, dma_addr_t addr, int len)
{
- struct mwl8k_rxd_8366_ap *rxd = _rxd;
+ struct mwl8k_rxd_ap *rxd = _rxd;
rxd->pkt_len = cpu_to_le16(len);
rxd->pkt_phys_addr = cpu_to_le32(addr);
@@ -960,12 +969,12 @@ static void mwl8k_rxd_8366_ap_refill(void *_rxd, dma_addr_t addr, int len)
}
static int
-mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status,
- __le16 *qos, s8 *noise)
+mwl8k_rxd_ap_process(void *_rxd, struct ieee80211_rx_status *status,
+ __le16 *qos, s8 *noise)
{
- struct mwl8k_rxd_8366_ap *rxd = _rxd;
+ struct mwl8k_rxd_ap *rxd = _rxd;
- if (!(rxd->rx_ctrl & MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST))
+ if (!(rxd->rx_ctrl & MWL8K_AP_RX_CTRL_OWNED_BY_HOST))
return -1;
rmb();
@@ -974,11 +983,11 @@ mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status,
status->signal = -rxd->rssi;
*noise = -rxd->noise_floor;
- if (rxd->rate & MWL8K_8366_AP_RATE_INFO_MCS_FORMAT) {
+ if (rxd->rate & MWL8K_AP_RATE_INFO_MCS_FORMAT) {
status->flag |= RX_FLAG_HT;
- if (rxd->rate & MWL8K_8366_AP_RATE_INFO_40MHZ)
+ if (rxd->rate & MWL8K_AP_RATE_INFO_40MHZ)
status->flag |= RX_FLAG_40MHZ;
- status->rate_idx = MWL8K_8366_AP_RATE_INFO_RATEID(rxd->rate);
+ status->rate_idx = MWL8K_AP_RATE_INFO_RATEID(rxd->rate);
} else {
int i;
@@ -1002,19 +1011,19 @@ mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status,
*qos = rxd->qos_control;
- if ((rxd->rx_status != MWL8K_8366_AP_RXSTAT_GENERAL_DECRYPT_ERR) &&
- (rxd->rx_status & MWL8K_8366_AP_RXSTAT_DECRYPT_ERR_MASK) &&
- (rxd->rx_status & MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR))
+ if ((rxd->rx_status != MWL8K_AP_RXSTAT_GENERAL_DECRYPT_ERR) &&
+ (rxd->rx_status & MWL8K_AP_RXSTAT_DECRYPT_ERR_MASK) &&
+ (rxd->rx_status & MWL8K_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR))
status->flag |= RX_FLAG_MMIC_ERROR;
return le16_to_cpu(rxd->pkt_len);
}
-static struct rxd_ops rxd_8366_ap_ops = {
- .rxd_size = sizeof(struct mwl8k_rxd_8366_ap),
- .rxd_init = mwl8k_rxd_8366_ap_init,
- .rxd_refill = mwl8k_rxd_8366_ap_refill,
- .rxd_process = mwl8k_rxd_8366_ap_process,
+static struct rxd_ops rxd_ap_ops = {
+ .rxd_size = sizeof(struct mwl8k_rxd_ap),
+ .rxd_init = mwl8k_rxd_ap_init,
+ .rxd_refill = mwl8k_rxd_ap_refill,
+ .rxd_process = mwl8k_rxd_ap_process,
};
/*
@@ -5429,12 +5438,17 @@ enum {
MWL8363 = 0,
MWL8687,
MWL8366,
+ MWL8764,
};
#define MWL8K_8366_AP_FW_API 3
#define _MWL8K_8366_AP_FW(api) "mwl8k/fmimage_8366_ap-" #api ".fw"
#define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api)
+#define MWL8K_8764_AP_FW_API 1
+#define _MWL8K_8764_AP_FW(api) "mwl8k/fmimage_8764_ap-" #api ".fw"
+#define MWL8K_8764_AP_FW(api) _MWL8K_8764_AP_FW(api)
+
static struct mwl8k_device_info mwl8k_info_tbl[] = {
[MWL8363] = {
.part_name = "88w8363",
@@ -5452,7 +5466,13 @@ static struct mwl8k_device_info mwl8k_info_tbl[] = {
.fw_image_sta = "mwl8k/fmimage_8366.fw",
.fw_image_ap = MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API),
.fw_api_ap = MWL8K_8366_AP_FW_API,
- .ap_rxd_ops = &rxd_8366_ap_ops,
+ .ap_rxd_ops = &rxd_ap_ops,
+ },
+ [MWL8764] = {
+ .part_name = "88w8764",
+ .fw_image_ap = MWL8K_8764_AP_FW(MWL8K_8764_AP_FW_API),
+ .fw_api_ap = MWL8K_8764_AP_FW_API,
+ .ap_rxd_ops = &rxd_ap_ops,
},
};
@@ -5474,6 +5494,7 @@ static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = {
{ PCI_VDEVICE(MARVELL, 0x2a41), .driver_data = MWL8366, },
{ PCI_VDEVICE(MARVELL, 0x2a42), .driver_data = MWL8366, },
{ PCI_VDEVICE(MARVELL, 0x2a43), .driver_data = MWL8366, },
+ { PCI_VDEVICE(MARVELL, 0x2b36), .driver_data = MWL8764, },
{ },
};
MODULE_DEVICE_TABLE(pci, mwl8k_pci_id_table);
@@ -5995,6 +6016,8 @@ static int mwl8k_probe(struct pci_dev *pdev,
priv->pdev = pdev;
priv->device_info = &mwl8k_info_tbl[id->driver_data];
+ if (id->driver_data == MWL8764)
+ priv->is_8764 = true;
priv->sram = pci_iomap(pdev, 0, 0x10000);
if (priv->sram == NULL) {
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 3109c0db66e1..4775b5d172d5 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -144,7 +144,7 @@ static int psm;
static char *essid;
/* Default to encapsulation unless translation requested */
-static int translate = 1;
+static bool translate = 1;
static int country = USA;
@@ -178,7 +178,7 @@ module_param(hop_dwell, int, 0);
module_param(beacon_period, int, 0);
module_param(psm, int, 0);
module_param(essid, charp, 0);
-module_param(translate, int, 0);
+module_param(translate, bool, 0);
module_param(country, int, 0);
module_param(sniffer, int, 0);
module_param(bc, int, 0);
@@ -1353,7 +1353,7 @@ static int ray_get_range(struct net_device *dev, struct iw_request_info *info,
static int ray_set_framing(struct net_device *dev, struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
- translate = *(extra); /* Set framing mode */
+ translate = !!*(extra); /* Set framing mode */
return 0;
}
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 525fd7521dff..5f66b4eac298 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -2839,8 +2839,7 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
} else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC)
cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL);
- if (info != NULL)
- kfree(info);
+ kfree(info);
priv->connected = true;
memcpy(priv->bssid, bssid, ETH_ALEN);
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index a0c8caef3b0a..b1c673ecada1 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -52,8 +52,8 @@ int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
udelay(REGISTER_BUSY_DELAY);
}
- ERROR(rt2x00dev, "Indirect register access failed: "
- "offset=0x%.08x, value=0x%.08x\n", offset, *reg);
+ printk_once(KERN_ERR "%s() Indirect register access failed: "
+ "offset=0x%.08x, value=0x%.08x\n", __func__, offset, *reg);
*reg = ~0;
return 0;
diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c
index 71098a7b5fed..7cb7d2c8fd86 100644
--- a/drivers/ssb/driver_chipcommon.c
+++ b/drivers/ssb/driver_chipcommon.c
@@ -354,7 +354,7 @@ void ssb_chipcommon_init(struct ssb_chipcommon *cc)
if (cc->dev->id.revision >= 11)
cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT);
- ssb_dprintk(KERN_INFO PFX "chipcommon status is 0x%x\n", cc->status);
+ ssb_dbg("chipcommon status is 0x%x\n", cc->status);
if (cc->dev->id.revision >= 20) {
chipco_write32(cc, SSB_CHIPCO_GPIOPULLUP, 0);
diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c
index 4c0f6d883dd3..791da2c0d8f6 100644
--- a/drivers/ssb/driver_chipcommon_pmu.c
+++ b/drivers/ssb/driver_chipcommon_pmu.c
@@ -110,8 +110,8 @@ static void ssb_pmu0_pllinit_r0(struct ssb_chipcommon *cc,
return;
}
- ssb_printk(KERN_INFO PFX "Programming PLL to %u.%03u MHz\n",
- (crystalfreq / 1000), (crystalfreq % 1000));
+ ssb_info("Programming PLL to %u.%03u MHz\n",
+ crystalfreq / 1000, crystalfreq % 1000);
/* First turn the PLL off. */
switch (bus->chip_id) {
@@ -138,7 +138,7 @@ static void ssb_pmu0_pllinit_r0(struct ssb_chipcommon *cc,
}
tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST);
if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT)
- ssb_printk(KERN_EMERG PFX "Failed to turn the PLL off!\n");
+ ssb_emerg("Failed to turn the PLL off!\n");
/* Set PDIV in PLL control 0. */
pllctl = ssb_chipco_pll_read(cc, SSB_PMU0_PLLCTL0);
@@ -249,8 +249,8 @@ static void ssb_pmu1_pllinit_r0(struct ssb_chipcommon *cc,
return;
}
- ssb_printk(KERN_INFO PFX "Programming PLL to %u.%03u MHz\n",
- (crystalfreq / 1000), (crystalfreq % 1000));
+ ssb_info("Programming PLL to %u.%03u MHz\n",
+ crystalfreq / 1000, crystalfreq % 1000);
/* First turn the PLL off. */
switch (bus->chip_id) {
@@ -275,7 +275,7 @@ static void ssb_pmu1_pllinit_r0(struct ssb_chipcommon *cc,
}
tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST);
if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT)
- ssb_printk(KERN_EMERG PFX "Failed to turn the PLL off!\n");
+ ssb_emerg("Failed to turn the PLL off!\n");
/* Set p1div and p2div. */
pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL0);
@@ -349,9 +349,8 @@ static void ssb_pmu_pll_init(struct ssb_chipcommon *cc)
case 43222:
break;
default:
- ssb_printk(KERN_ERR PFX
- "ERROR: PLL init unknown for device %04X\n",
- bus->chip_id);
+ ssb_err("ERROR: PLL init unknown for device %04X\n",
+ bus->chip_id);
}
}
@@ -472,9 +471,8 @@ static void ssb_pmu_resources_init(struct ssb_chipcommon *cc)
max_msk = 0xFFFFF;
break;
default:
- ssb_printk(KERN_ERR PFX
- "ERROR: PMU resource config unknown for device %04X\n",
- bus->chip_id);
+ ssb_err("ERROR: PMU resource config unknown for device %04X\n",
+ bus->chip_id);
}
if (updown_tab) {
@@ -526,8 +524,8 @@ void ssb_pmu_init(struct ssb_chipcommon *cc)
pmucap = chipco_read32(cc, SSB_CHIPCO_PMU_CAP);
cc->pmu.rev = (pmucap & SSB_CHIPCO_PMU_CAP_REVISION);
- ssb_dprintk(KERN_DEBUG PFX "Found rev %u PMU (capabilities 0x%08X)\n",
- cc->pmu.rev, pmucap);
+ ssb_dbg("Found rev %u PMU (capabilities 0x%08X)\n",
+ cc->pmu.rev, pmucap);
if (cc->pmu.rev == 1)
chipco_mask32(cc, SSB_CHIPCO_PMU_CTL,
@@ -638,9 +636,8 @@ u32 ssb_pmu_get_alp_clock(struct ssb_chipcommon *cc)
case 0x5354:
ssb_pmu_get_alp_clock_clk0(cc);
default:
- ssb_printk(KERN_ERR PFX
- "ERROR: PMU alp clock unknown for device %04X\n",
- bus->chip_id);
+ ssb_err("ERROR: PMU alp clock unknown for device %04X\n",
+ bus->chip_id);
return 0;
}
}
@@ -654,9 +651,8 @@ u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc)
/* 5354 chip uses a non programmable PLL of frequency 240MHz */
return 240000000;
default:
- ssb_printk(KERN_ERR PFX
- "ERROR: PMU cpu clock unknown for device %04X\n",
- bus->chip_id);
+ ssb_err("ERROR: PMU cpu clock unknown for device %04X\n",
+ bus->chip_id);
return 0;
}
}
@@ -669,9 +665,8 @@ u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc)
case 0x5354:
return 120000000;
default:
- ssb_printk(KERN_ERR PFX
- "ERROR: PMU controlclock unknown for device %04X\n",
- bus->chip_id);
+ ssb_err("ERROR: PMU controlclock unknown for device %04X\n",
+ bus->chip_id);
return 0;
}
}
diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c
index 33b37dac40bd..fa385a368a56 100644
--- a/drivers/ssb/driver_mipscore.c
+++ b/drivers/ssb/driver_mipscore.c
@@ -167,21 +167,22 @@ static void set_irq(struct ssb_device *dev, unsigned int irq)
irqflag |= (ipsflag & ~ipsflag_irq_mask[irq]);
ssb_write32(mdev, SSB_IPSFLAG, irqflag);
}
- ssb_dprintk(KERN_INFO PFX
- "set_irq: core 0x%04x, irq %d => %d\n",
- dev->id.coreid, oldirq+2, irq+2);
+ ssb_dbg("set_irq: core 0x%04x, irq %d => %d\n",
+ dev->id.coreid, oldirq+2, irq+2);
}
static void print_irq(struct ssb_device *dev, unsigned int irq)
{
- int i;
static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
- ssb_dprintk(KERN_INFO PFX
- "core 0x%04x, irq :", dev->id.coreid);
- for (i = 0; i <= 6; i++) {
- ssb_dprintk(" %s%s", irq_name[i], i==irq?"*":" ");
- }
- ssb_dprintk("\n");
+ ssb_dbg("core 0x%04x, irq : %s%s %s%s %s%s %s%s %s%s %s%s %s%s\n",
+ dev->id.coreid,
+ irq_name[0], irq == 0 ? "*" : " ",
+ irq_name[1], irq == 1 ? "*" : " ",
+ irq_name[2], irq == 2 ? "*" : " ",
+ irq_name[3], irq == 3 ? "*" : " ",
+ irq_name[4], irq == 4 ? "*" : " ",
+ irq_name[5], irq == 5 ? "*" : " ",
+ irq_name[6], irq == 6 ? "*" : " ");
}
static void dump_irq(struct ssb_bus *bus)
@@ -286,7 +287,7 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore)
if (!mcore->dev)
return; /* We don't have a MIPS core */
- ssb_dprintk(KERN_INFO PFX "Initializing MIPS core...\n");
+ ssb_dbg("Initializing MIPS core...\n");
bus = mcore->dev->bus;
hz = ssb_clockspeed(bus);
@@ -334,7 +335,7 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore)
break;
}
}
- ssb_dprintk(KERN_INFO PFX "after irq reconfiguration\n");
+ ssb_dbg("after irq reconfiguration\n");
dump_irq(bus);
ssb_mips_serial_init(mcore);
diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c
index 59801d23d7ec..d75b72ba2672 100644
--- a/drivers/ssb/driver_pcicore.c
+++ b/drivers/ssb/driver_pcicore.c
@@ -263,8 +263,7 @@ int ssb_pcicore_plat_dev_init(struct pci_dev *d)
return -ENODEV;
}
- ssb_printk(KERN_INFO "PCI: Fixing up device %s\n",
- pci_name(d));
+ ssb_info("PCI: Fixing up device %s\n", pci_name(d));
/* Fix up interrupt lines */
d->irq = ssb_mips_irq(extpci_core->dev) + 2;
@@ -285,12 +284,12 @@ static void ssb_pcicore_fixup_pcibridge(struct pci_dev *dev)
if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0)
return;
- ssb_printk(KERN_INFO "PCI: Fixing up bridge %s\n", pci_name(dev));
+ ssb_info("PCI: Fixing up bridge %s\n", pci_name(dev));
/* Enable PCI bridge bus mastering and memory space */
pci_set_master(dev);
if (pcibios_enable_device(dev, ~0) < 0) {
- ssb_printk(KERN_ERR "PCI: SSB bridge enable failed\n");
+ ssb_err("PCI: SSB bridge enable failed\n");
return;
}
@@ -299,8 +298,8 @@ static void ssb_pcicore_fixup_pcibridge(struct pci_dev *dev)
/* Make sure our latency is high enough to handle the devices behind us */
lat = 168;
- ssb_printk(KERN_INFO "PCI: Fixing latency timer of device %s to %u\n",
- pci_name(dev), lat);
+ ssb_info("PCI: Fixing latency timer of device %s to %u\n",
+ pci_name(dev), lat);
pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
}
DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_pcicore_fixup_pcibridge);
@@ -323,7 +322,7 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
return;
extpci_core = pc;
- ssb_dprintk(KERN_INFO PFX "PCIcore in host mode found\n");
+ ssb_dbg("PCIcore in host mode found\n");
/* Reset devices on the external PCI bus */
val = SSB_PCICORE_CTL_RST_OE;
val |= SSB_PCICORE_CTL_CLK_OE;
@@ -338,7 +337,7 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
udelay(1); /* Assertion time demanded by the PCI standard */
if (pc->dev->bus->has_cardbus_slot) {
- ssb_dprintk(KERN_INFO PFX "CardBus slot detected\n");
+ ssb_dbg("CardBus slot detected\n");
pc->cardbusmode = 1;
/* GPIO 1 resets the bridge */
ssb_gpio_out(pc->dev->bus, 1, 1);
diff --git a/drivers/ssb/embedded.c b/drivers/ssb/embedded.c
index bb18d76f9f2c..55e101115038 100644
--- a/drivers/ssb/embedded.c
+++ b/drivers/ssb/embedded.c
@@ -57,9 +57,8 @@ int ssb_watchdog_register(struct ssb_bus *bus)
bus->busnumber, &wdt,
sizeof(wdt));
if (IS_ERR(pdev)) {
- ssb_dprintk(KERN_INFO PFX
- "can not register watchdog device, err: %li\n",
- PTR_ERR(pdev));
+ ssb_dbg("can not register watchdog device, err: %li\n",
+ PTR_ERR(pdev));
return PTR_ERR(pdev);
}
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index 3b645b8a261f..812775a4bfb6 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -275,8 +275,8 @@ int ssb_devices_thaw(struct ssb_freeze_context *ctx)
err = sdrv->probe(sdev, &sdev->id);
if (err) {
- ssb_printk(KERN_ERR PFX "Failed to thaw device %s\n",
- dev_name(sdev->dev));
+ ssb_err("Failed to thaw device %s\n",
+ dev_name(sdev->dev));
result = err;
}
ssb_device_put(sdev);
@@ -447,10 +447,9 @@ void ssb_bus_unregister(struct ssb_bus *bus)
err = ssb_gpio_unregister(bus);
if (err == -EBUSY)
- ssb_dprintk(KERN_ERR PFX "Some GPIOs are still in use.\n");
+ ssb_dbg("Some GPIOs are still in use\n");
else if (err)
- ssb_dprintk(KERN_ERR PFX
- "Can not unregister GPIO driver: %i\n", err);
+ ssb_dbg("Can not unregister GPIO driver: %i\n", err);
ssb_buses_lock();
ssb_devices_unregister(bus);
@@ -497,8 +496,7 @@ static int ssb_devices_register(struct ssb_bus *bus)
devwrap = kzalloc(sizeof(*devwrap), GFP_KERNEL);
if (!devwrap) {
- ssb_printk(KERN_ERR PFX
- "Could not allocate device\n");
+ ssb_err("Could not allocate device\n");
err = -ENOMEM;
goto error;
}
@@ -537,9 +535,7 @@ static int ssb_devices_register(struct ssb_bus *bus)
sdev->dev = dev;
err = device_register(dev);
if (err) {
- ssb_printk(KERN_ERR PFX
- "Could not register %s\n",
- dev_name(dev));
+ ssb_err("Could not register %s\n", dev_name(dev));
/* Set dev to NULL to not unregister
* dev on error unwinding. */
sdev->dev = NULL;
@@ -825,10 +821,9 @@ static int ssb_bus_register(struct ssb_bus *bus,
ssb_mipscore_init(&bus->mipscore);
err = ssb_gpio_init(bus);
if (err == -ENOTSUPP)
- ssb_dprintk(KERN_DEBUG PFX "GPIO driver not activated\n");
+ ssb_dbg("GPIO driver not activated\n");
else if (err)
- ssb_dprintk(KERN_ERR PFX
- "Error registering GPIO driver: %i\n", err);
+ ssb_dbg("Error registering GPIO driver: %i\n", err);
err = ssb_fetch_invariants(bus, get_invariants);
if (err) {
ssb_bus_may_powerdown(bus);
@@ -878,11 +873,11 @@ int ssb_bus_pcibus_register(struct ssb_bus *bus, struct pci_dev *host_pci)
err = ssb_bus_register(bus, ssb_pci_get_invariants, 0);
if (!err) {
- ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on "
- "PCI device %s\n", dev_name(&host_pci->dev));
+ ssb_info("Sonics Silicon Backplane found on PCI device %s\n",
+ dev_name(&host_pci->dev));
} else {
- ssb_printk(KERN_ERR PFX "Failed to register PCI version"
- " of SSB with error %d\n", err);
+ ssb_err("Failed to register PCI version of SSB with error %d\n",
+ err);
}
return err;
@@ -903,8 +898,8 @@ int ssb_bus_pcmciabus_register(struct ssb_bus *bus,
err = ssb_bus_register(bus, ssb_pcmcia_get_invariants, baseaddr);
if (!err) {
- ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on "
- "PCMCIA device %s\n", pcmcia_dev->devname);
+ ssb_info("Sonics Silicon Backplane found on PCMCIA device %s\n",
+ pcmcia_dev->devname);
}
return err;
@@ -925,8 +920,8 @@ int ssb_bus_sdiobus_register(struct ssb_bus *bus, struct sdio_func *func,
err = ssb_bus_register(bus, ssb_sdio_get_invariants, ~0);
if (!err) {
- ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on "
- "SDIO device %s\n", sdio_func_id(func));
+ ssb_info("Sonics Silicon Backplane found on SDIO device %s\n",
+ sdio_func_id(func));
}
return err;
@@ -944,8 +939,8 @@ int ssb_bus_ssbbus_register(struct ssb_bus *bus, unsigned long baseaddr,
err = ssb_bus_register(bus, get_invariants, baseaddr);
if (!err) {
- ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found at "
- "address 0x%08lX\n", baseaddr);
+ ssb_info("Sonics Silicon Backplane found at address 0x%08lX\n",
+ baseaddr);
}
return err;
@@ -1339,7 +1334,7 @@ out:
#endif
return err;
error:
- ssb_printk(KERN_ERR PFX "Bus powerdown failed\n");
+ ssb_err("Bus powerdown failed\n");
goto out;
}
EXPORT_SYMBOL(ssb_bus_may_powerdown);
@@ -1362,7 +1357,7 @@ int ssb_bus_powerup(struct ssb_bus *bus, bool dynamic_pctl)
return 0;
error:
- ssb_printk(KERN_ERR PFX "Bus powerup failed\n");
+ ssb_err("Bus powerup failed\n");
return err;
}
EXPORT_SYMBOL(ssb_bus_powerup);
@@ -1470,15 +1465,13 @@ static int __init ssb_modinit(void)
err = b43_pci_ssb_bridge_init();
if (err) {
- ssb_printk(KERN_ERR "Broadcom 43xx PCI-SSB-bridge "
- "initialization failed\n");
+ ssb_err("Broadcom 43xx PCI-SSB-bridge initialization failed\n");
/* don't fail SSB init because of this */
err = 0;
}
err = ssb_gige_init();
if (err) {
- ssb_printk(KERN_ERR "SSB Broadcom Gigabit Ethernet "
- "driver initialization failed\n");
+ ssb_err("SSB Broadcom Gigabit Ethernet driver initialization failed\n");
/* don't fail SSB init because of this */
err = 0;
}
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
index e9d94968f394..6d6e7b926aa5 100644
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -56,7 +56,7 @@ int ssb_pci_switch_coreidx(struct ssb_bus *bus, u8 coreidx)
}
return 0;
error:
- ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx);
+ ssb_err("Failed to switch to core %u\n", coreidx);
return -ENODEV;
}
@@ -67,10 +67,9 @@ int ssb_pci_switch_core(struct ssb_bus *bus,
unsigned long flags;
#if SSB_VERBOSE_PCICORESWITCH_DEBUG
- ssb_printk(KERN_INFO PFX
- "Switching to %s core, index %d\n",
- ssb_core_name(dev->id.coreid),
- dev->core_index);
+ ssb_info("Switching to %s core, index %d\n",
+ ssb_core_name(dev->id.coreid),
+ dev->core_index);
#endif
spin_lock_irqsave(&bus->bar_lock, flags);
@@ -231,6 +230,15 @@ static inline u8 ssb_crc8(u8 crc, u8 data)
return t[crc ^ data];
}
+static void sprom_get_mac(char *mac, const u16 *in)
+{
+ int i;
+ for (i = 0; i < 3; i++) {
+ *mac++ = in[i];
+ *mac++ = in[i] >> 8;
+ }
+}
+
static u8 ssb_sprom_crc(const u16 *sprom, u16 size)
{
int word;
@@ -278,7 +286,7 @@ static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
u32 spromctl;
u16 size = bus->sprom_size;
- ssb_printk(KERN_NOTICE PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n");
+ ssb_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n");
err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
if (err)
goto err_ctlreg;
@@ -286,17 +294,17 @@ static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
if (err)
goto err_ctlreg;
- ssb_printk(KERN_NOTICE PFX "[ 0%%");
+ ssb_notice("[ 0%%");
msleep(500);
for (i = 0; i < size; i++) {
if (i == size / 4)
- ssb_printk("25%%");
+ ssb_cont("25%%");
else if (i == size / 2)
- ssb_printk("50%%");
+ ssb_cont("50%%");
else if (i == (size * 3) / 4)
- ssb_printk("75%%");
+ ssb_cont("75%%");
else if (i % 2)
- ssb_printk(".");
+ ssb_cont(".");
writew(sprom[i], bus->mmio + bus->sprom_offset + (i * 2));
mmiowb();
msleep(20);
@@ -309,12 +317,12 @@ static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
if (err)
goto err_ctlreg;
msleep(500);
- ssb_printk("100%% ]\n");
- ssb_printk(KERN_NOTICE PFX "SPROM written.\n");
+ ssb_cont("100%% ]\n");
+ ssb_notice("SPROM written\n");
return 0;
err_ctlreg:
- ssb_printk(KERN_ERR PFX "Could not access SPROM control register.\n");
+ ssb_err("Could not access SPROM control register.\n");
return err;
}
@@ -341,8 +349,6 @@ static s8 r123_extract_antgain(u8 sprom_revision, const u16 *in,
static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
{
- int i;
- u16 v;
u16 loc[3];
if (out->revision == 3) /* rev 3 moved MAC */
@@ -352,19 +358,10 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in)
loc[1] = SSB_SPROM1_ET0MAC;
loc[2] = SSB_SPROM1_ET1MAC;
}
- for (i = 0; i < 3; i++) {
- v = in[SPOFF(loc[0]) + i];
- *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
- }
+ sprom_get_mac(out->il0mac, &in[SPOFF(loc[0])]);
if (out->revision < 3) { /* only rev 1-2 have et0, et1 */
- for (i = 0; i < 3; i++) {
- v = in[SPOFF(loc[1]) + i];
- *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
- }
- for (i = 0; i < 3; i++) {
- v = in[SPOFF(loc[2]) + i];
- *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
- }
+ sprom_get_mac(out->et0mac, &in[SPOFF(loc[1])]);
+ sprom_get_mac(out->et1mac, &in[SPOFF(loc[2])]);
}
SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
@@ -454,19 +451,15 @@ static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in)
static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
{
- int i;
- u16 v;
u16 il0mac_offset;
if (out->revision == 4)
il0mac_offset = SSB_SPROM4_IL0MAC;
else
il0mac_offset = SSB_SPROM5_IL0MAC;
- /* extract the MAC address */
- for (i = 0; i < 3; i++) {
- v = in[SPOFF(il0mac_offset) + i];
- *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
- }
+
+ sprom_get_mac(out->il0mac, &in[SPOFF(il0mac_offset)]);
+
SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
SSB_SPROM4_ETHPHY_ET1A_SHIFT);
@@ -530,7 +523,7 @@ static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
{
int i;
- u16 v, o;
+ u16 o;
u16 pwr_info_offset[] = {
SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1,
SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3
@@ -539,10 +532,8 @@ static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
ARRAY_SIZE(out->core_pwr_info));
/* extract the MAC address */
- for (i = 0; i < 3; i++) {
- v = in[SPOFF(SSB_SPROM8_IL0MAC) + i];
- *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
- }
+ sprom_get_mac(out->il0mac, &in[SPOFF(SSB_SPROM8_IL0MAC)]);
+
SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0);
SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
@@ -743,7 +734,7 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
memset(out, 0, sizeof(*out));
out->revision = in[size - 1] & 0x00FF;
- ssb_dprintk(KERN_DEBUG PFX "SPROM revision %d detected.\n", out->revision);
+ ssb_dbg("SPROM revision %d detected\n", out->revision);
memset(out->et0mac, 0xFF, 6); /* preset et0 and et1 mac */
memset(out->et1mac, 0xFF, 6);
@@ -752,7 +743,7 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
* number stored in the SPROM.
* Always extract r1. */
out->revision = 1;
- ssb_dprintk(KERN_DEBUG PFX "SPROM treated as revision %d\n", out->revision);
+ ssb_dbg("SPROM treated as revision %d\n", out->revision);
}
switch (out->revision) {
@@ -769,9 +760,8 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
sprom_extract_r8(out, in);
break;
default:
- ssb_printk(KERN_WARNING PFX "Unsupported SPROM"
- " revision %d detected. Will extract"
- " v1\n", out->revision);
+ ssb_warn("Unsupported SPROM revision %d detected. Will extract v1\n",
+ out->revision);
out->revision = 1;
sprom_extract_r123(out, in);
}
@@ -791,7 +781,7 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus,
u16 *buf;
if (!ssb_is_sprom_available(bus)) {
- ssb_printk(KERN_ERR PFX "No SPROM available!\n");
+ ssb_err("No SPROM available!\n");
return -ENODEV;
}
if (bus->chipco.dev) { /* can be unavailable! */
@@ -810,7 +800,7 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus,
} else {
bus->sprom_offset = SSB_SPROM_BASE1;
}
- ssb_dprintk(KERN_INFO PFX "SPROM offset is 0x%x\n", bus->sprom_offset);
+ ssb_dbg("SPROM offset is 0x%x\n", bus->sprom_offset);
buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
if (!buf)
@@ -835,18 +825,15 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus,
* available for this device in some other storage */
err = ssb_fill_sprom_with_fallback(bus, sprom);
if (err) {
- ssb_printk(KERN_WARNING PFX "WARNING: Using"
- " fallback SPROM failed (err %d)\n",
- err);
+ ssb_warn("WARNING: Using fallback SPROM failed (err %d)\n",
+ err);
} else {
- ssb_dprintk(KERN_DEBUG PFX "Using SPROM"
- " revision %d provided by"
- " platform.\n", sprom->revision);
+ ssb_dbg("Using SPROM revision %d provided by platform\n",
+ sprom->revision);
err = 0;
goto out_free;
}
- ssb_printk(KERN_WARNING PFX "WARNING: Invalid"
- " SPROM CRC (corrupt SPROM)\n");
+ ssb_warn("WARNING: Invalid SPROM CRC (corrupt SPROM)\n");
}
}
err = sprom_extract(bus, sprom, buf, bus->sprom_size);
diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c
index fbafed5b729b..b413e0187087 100644
--- a/drivers/ssb/pcmcia.c
+++ b/drivers/ssb/pcmcia.c
@@ -143,7 +143,7 @@ int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
return 0;
error:
- ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx);
+ ssb_err("Failed to switch to core %u\n", coreidx);
return err;
}
@@ -153,10 +153,9 @@ int ssb_pcmcia_switch_core(struct ssb_bus *bus,
int err;
#if SSB_VERBOSE_PCMCIACORESWITCH_DEBUG
- ssb_printk(KERN_INFO PFX
- "Switching to %s core, index %d\n",
- ssb_core_name(dev->id.coreid),
- dev->core_index);
+ ssb_info("Switching to %s core, index %d\n",
+ ssb_core_name(dev->id.coreid),
+ dev->core_index);
#endif
err = ssb_pcmcia_switch_coreidx(bus, dev->core_index);
@@ -192,7 +191,7 @@ int ssb_pcmcia_switch_segment(struct ssb_bus *bus, u8 seg)
return 0;
error:
- ssb_printk(KERN_ERR PFX "Failed to switch pcmcia segment\n");
+ ssb_err("Failed to switch pcmcia segment\n");
return err;
}
@@ -549,44 +548,39 @@ static int ssb_pcmcia_sprom_write_all(struct ssb_bus *bus, const u16 *sprom)
bool failed = 0;
size_t size = SSB_PCMCIA_SPROM_SIZE;
- ssb_printk(KERN_NOTICE PFX
- "Writing SPROM. Do NOT turn off the power! "
- "Please stand by...\n");
+ ssb_notice("Writing SPROM. Do NOT turn off the power! Please stand by...\n");
err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEEN);
if (err) {
- ssb_printk(KERN_NOTICE PFX
- "Could not enable SPROM write access.\n");
+ ssb_notice("Could not enable SPROM write access\n");
return -EBUSY;
}
- ssb_printk(KERN_NOTICE PFX "[ 0%%");
+ ssb_notice("[ 0%%");
msleep(500);
for (i = 0; i < size; i++) {
if (i == size / 4)
- ssb_printk("25%%");
+ ssb_cont("25%%");
else if (i == size / 2)
- ssb_printk("50%%");
+ ssb_cont("50%%");
else if (i == (size * 3) / 4)
- ssb_printk("75%%");
+ ssb_cont("75%%");
else if (i % 2)
- ssb_printk(".");
+ ssb_cont(".");
err = ssb_pcmcia_sprom_write(bus, i, sprom[i]);
if (err) {
- ssb_printk(KERN_NOTICE PFX
- "Failed to write to SPROM.\n");
+ ssb_notice("Failed to write to SPROM\n");
failed = 1;
break;
}
}
err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEDIS);
if (err) {
- ssb_printk(KERN_NOTICE PFX
- "Could not disable SPROM write access.\n");
+ ssb_notice("Could not disable SPROM write access\n");
failed = 1;
}
msleep(500);
if (!failed) {
- ssb_printk("100%% ]\n");
- ssb_printk(KERN_NOTICE PFX "SPROM written.\n");
+ ssb_cont("100%% ]\n");
+ ssb_notice("SPROM written\n");
}
return failed ? -EBUSY : 0;
@@ -700,7 +694,7 @@ static int ssb_pcmcia_do_get_invariants(struct pcmcia_device *p_dev,
return -ENOSPC; /* continue with next entry */
error:
- ssb_printk(KERN_ERR PFX
+ ssb_err(
"PCMCIA: Failed to fetch device invariants: %s\n",
error_description);
return -ENODEV;
@@ -722,7 +716,7 @@ int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
res = pcmcia_loop_tuple(bus->host_pcmcia, CISTPL_FUNCE,
ssb_pcmcia_get_mac, sprom);
if (res != 0) {
- ssb_printk(KERN_ERR PFX
+ ssb_err(
"PCMCIA: Failed to fetch MAC address\n");
return -ENODEV;
}
@@ -733,7 +727,7 @@ int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
if ((res == 0) || (res == -ENOSPC))
return 0;
- ssb_printk(KERN_ERR PFX
+ ssb_err(
"PCMCIA: Failed to fetch device invariants\n");
return -ENODEV;
}
@@ -843,6 +837,6 @@ int ssb_pcmcia_init(struct ssb_bus *bus)
return 0;
error:
- ssb_printk(KERN_ERR PFX "Failed to initialize PCMCIA host device\n");
+ ssb_err("Failed to initialize PCMCIA host device\n");
return err;
}
diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c
index ab4627cf1114..b9429df583eb 100644
--- a/drivers/ssb/scan.c
+++ b/drivers/ssb/scan.c
@@ -125,8 +125,7 @@ static u16 pcidev_to_chipid(struct pci_dev *pci_dev)
chipid_fallback = 0x4401;
break;
default:
- ssb_printk(KERN_ERR PFX
- "PCI-ID not in fallback list\n");
+ ssb_err("PCI-ID not in fallback list\n");
}
return chipid_fallback;
@@ -152,8 +151,7 @@ static u8 chipid_to_nrcores(u16 chipid)
case 0x4704:
return 9;
default:
- ssb_printk(KERN_ERR PFX
- "CHIPID not in nrcores fallback list\n");
+ ssb_err("CHIPID not in nrcores fallback list\n");
}
return 1;
@@ -320,15 +318,13 @@ int ssb_bus_scan(struct ssb_bus *bus,
bus->chip_package = 0;
}
}
- ssb_printk(KERN_INFO PFX "Found chip with id 0x%04X, rev 0x%02X and "
- "package 0x%02X\n", bus->chip_id, bus->chip_rev,
- bus->chip_package);
+ ssb_info("Found chip with id 0x%04X, rev 0x%02X and package 0x%02X\n",
+ bus->chip_id, bus->chip_rev, bus->chip_package);
if (!bus->nr_devices)
bus->nr_devices = chipid_to_nrcores(bus->chip_id);
if (bus->nr_devices > ARRAY_SIZE(bus->devices)) {
- ssb_printk(KERN_ERR PFX
- "More than %d ssb cores found (%d)\n",
- SSB_MAX_NR_CORES, bus->nr_devices);
+ ssb_err("More than %d ssb cores found (%d)\n",
+ SSB_MAX_NR_CORES, bus->nr_devices);
goto err_unmap;
}
if (bus->bustype == SSB_BUSTYPE_SSB) {
@@ -370,8 +366,7 @@ int ssb_bus_scan(struct ssb_bus *bus,
nr_80211_cores++;
if (nr_80211_cores > 1) {
if (!we_support_multiple_80211_cores(bus)) {
- ssb_dprintk(KERN_INFO PFX "Ignoring additional "
- "802.11 core\n");
+ ssb_dbg("Ignoring additional 802.11 core\n");
continue;
}
}
@@ -379,8 +374,7 @@ int ssb_bus_scan(struct ssb_bus *bus,
case SSB_DEV_EXTIF:
#ifdef CONFIG_SSB_DRIVER_EXTIF
if (bus->extif.dev) {
- ssb_printk(KERN_WARNING PFX
- "WARNING: Multiple EXTIFs found\n");
+ ssb_warn("WARNING: Multiple EXTIFs found\n");
break;
}
bus->extif.dev = dev;
@@ -388,8 +382,7 @@ int ssb_bus_scan(struct ssb_bus *bus,
break;
case SSB_DEV_CHIPCOMMON:
if (bus->chipco.dev) {
- ssb_printk(KERN_WARNING PFX
- "WARNING: Multiple ChipCommon found\n");
+ ssb_warn("WARNING: Multiple ChipCommon found\n");
break;
}
bus->chipco.dev = dev;
@@ -398,8 +391,7 @@ int ssb_bus_scan(struct ssb_bus *bus,
case SSB_DEV_MIPS_3302:
#ifdef CONFIG_SSB_DRIVER_MIPS
if (bus->mipscore.dev) {
- ssb_printk(KERN_WARNING PFX
- "WARNING: Multiple MIPS cores found\n");
+ ssb_warn("WARNING: Multiple MIPS cores found\n");
break;
}
bus->mipscore.dev = dev;
@@ -420,8 +412,7 @@ int ssb_bus_scan(struct ssb_bus *bus,
}
}
if (bus->pcicore.dev) {
- ssb_printk(KERN_WARNING PFX
- "WARNING: Multiple PCI(E) cores found\n");
+ ssb_warn("WARNING: Multiple PCI(E) cores found\n");
break;
}
bus->pcicore.dev = dev;
diff --git a/drivers/ssb/sprom.c b/drivers/ssb/sprom.c
index 80d366fcf8d3..a3b23644b0fb 100644
--- a/drivers/ssb/sprom.c
+++ b/drivers/ssb/sprom.c
@@ -127,13 +127,13 @@ ssize_t ssb_attr_sprom_store(struct ssb_bus *bus,
goto out_kfree;
err = ssb_devices_freeze(bus, &freeze);
if (err) {
- ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n");
+ ssb_err("SPROM write: Could not freeze all devices\n");
goto out_unlock;
}
res = sprom_write(bus, sprom);
err = ssb_devices_thaw(&freeze);
if (err)
- ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n");
+ ssb_err("SPROM write: Could not thaw all devices\n");
out_unlock:
mutex_unlock(&bus->sprom_mutex);
out_kfree:
diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h
index 466171b77f68..4671f17f09af 100644
--- a/drivers/ssb/ssb_private.h
+++ b/drivers/ssb/ssb_private.h
@@ -9,16 +9,27 @@
#define PFX "ssb: "
#ifdef CONFIG_SSB_SILENT
-# define ssb_printk(fmt, x...) do { /* nothing */ } while (0)
+# define ssb_printk(fmt, ...) \
+ do { if (0) printk(fmt, ##__VA_ARGS__); } while (0)
#else
-# define ssb_printk printk
+# define ssb_printk(fmt, ...) \
+ printk(fmt, ##__VA_ARGS__)
#endif /* CONFIG_SSB_SILENT */
+#define ssb_emerg(fmt, ...) ssb_printk(KERN_EMERG PFX fmt, ##__VA_ARGS__)
+#define ssb_err(fmt, ...) ssb_printk(KERN_ERR PFX fmt, ##__VA_ARGS__)
+#define ssb_warn(fmt, ...) ssb_printk(KERN_WARNING PFX fmt, ##__VA_ARGS__)
+#define ssb_notice(fmt, ...) ssb_printk(KERN_NOTICE PFX fmt, ##__VA_ARGS__)
+#define ssb_info(fmt, ...) ssb_printk(KERN_INFO PFX fmt, ##__VA_ARGS__)
+#define ssb_cont(fmt, ...) ssb_printk(KERN_CONT fmt, ##__VA_ARGS__)
+
/* dprintk: Debugging printk; vanishes for non-debug compilation */
#ifdef CONFIG_SSB_DEBUG
-# define ssb_dprintk(fmt, x...) ssb_printk(fmt , ##x)
+# define ssb_dbg(fmt, ...) \
+ ssb_printk(KERN_DEBUG PFX fmt, ##__VA_ARGS__)
#else
-# define ssb_dprintk(fmt, x...) do { /* nothing */ } while (0)
+# define ssb_dbg(fmt, ...) \
+ do { if (0) printk(KERN_DEBUG PFX fmt, ##__VA_ARGS__); } while (0)
#endif
#ifdef CONFIG_SSB_DEBUG
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h
index 22958d68ecfe..8b1322296fed 100644
--- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h
@@ -26,9 +26,9 @@ struct ssb_sprom_core_pwr_info {
struct ssb_sprom {
u8 revision;
- u8 il0mac[6]; /* MAC address for 802.11b/g */
- u8 et0mac[6]; /* MAC address for Ethernet */
- u8 et1mac[6]; /* MAC address for 802.11a */
+ u8 il0mac[6] __aligned(sizeof(u16)); /* MAC address for 802.11b/g */
+ u8 et0mac[6] __aligned(sizeof(u16)); /* MAC address for Ethernet */
+ u8 et1mac[6] __aligned(sizeof(u16)); /* MAC address for 802.11a */
u8 et0phyaddr; /* MII address for enet0 */
u8 et1phyaddr; /* MII address for enet1 */
u8 et0mdcport; /* MDIO for enet0 */