diff options
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(×tamp, &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 */ |