Merge remote-tracking branch 'wireless-next/master' into iwlwifi-next
This commit is contained in:
commit
94d2f0ba05
|
@ -309,7 +309,7 @@ static struct omap2_hsmmc_info mmc[] = {
|
|||
.gpio_wp = 63,
|
||||
.deferred = true,
|
||||
},
|
||||
#ifdef CONFIG_WL12XX_PLATFORM_DATA
|
||||
#ifdef CONFIG_WILINK_PLATFORM_DATA
|
||||
{
|
||||
.name = "wl1271",
|
||||
.mmc = 2,
|
||||
|
@ -450,7 +450,7 @@ static struct regulator_init_data omap3evm_vio = {
|
|||
.consumer_supplies = omap3evm_vio_supply,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_WL12XX_PLATFORM_DATA
|
||||
#ifdef CONFIG_WILINK_PLATFORM_DATA
|
||||
|
||||
#define OMAP3EVM_WLAN_PMENA_GPIO (150)
|
||||
#define OMAP3EVM_WLAN_IRQ_GPIO (149)
|
||||
|
@ -563,7 +563,7 @@ static struct omap_board_mux omap35x_board_mux[] __initdata = {
|
|||
OMAP_PIN_OFF_NONE),
|
||||
OMAP3_MUX(GPMC_WAIT2, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP |
|
||||
OMAP_PIN_OFF_NONE),
|
||||
#ifdef CONFIG_WL12XX_PLATFORM_DATA
|
||||
#ifdef CONFIG_WILINK_PLATFORM_DATA
|
||||
/* WLAN IRQ - GPIO 149 */
|
||||
OMAP3_MUX(UART1_RTS, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
|
||||
|
||||
|
@ -601,7 +601,7 @@ static struct omap_board_mux omap36x_board_mux[] __initdata = {
|
|||
OMAP3_MUX(SYS_BOOT4, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
|
||||
OMAP3_MUX(SYS_BOOT5, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
|
||||
OMAP3_MUX(SYS_BOOT6, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
|
||||
#ifdef CONFIG_WL12XX_PLATFORM_DATA
|
||||
#ifdef CONFIG_WILINK_PLATFORM_DATA
|
||||
/* WLAN IRQ - GPIO 149 */
|
||||
OMAP3_MUX(UART1_RTS, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
|
||||
|
||||
|
@ -637,7 +637,7 @@ static struct gpio omap3_evm_ehci_gpios[] __initdata = {
|
|||
|
||||
static void __init omap3_evm_wl12xx_init(void)
|
||||
{
|
||||
#ifdef CONFIG_WL12XX_PLATFORM_DATA
|
||||
#ifdef CONFIG_WILINK_PLATFORM_DATA
|
||||
int ret;
|
||||
|
||||
/* WL12xx WLAN Init */
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
* Licensed under the GNU/GPL. See COPYING for details.
|
||||
*/
|
||||
|
||||
#include "bcma_private.h"
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/bcma/bcma.h>
|
||||
|
||||
#include "bcma_private.h"
|
||||
|
||||
struct platform_device bcma_nflash_dev = {
|
||||
.name = "bcma_nflash",
|
||||
.num_resources = 0,
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
* Licensed under the GNU/GPL. See COPYING for details.
|
||||
*/
|
||||
|
||||
#include "bcma_private.h"
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/bcma/bcma.h>
|
||||
|
||||
#include "bcma_private.h"
|
||||
|
||||
static struct resource bcma_sflash_resource = {
|
||||
.name = "bcma_sflash",
|
||||
.start = BCMA_SOC_FLASH2,
|
||||
|
|
|
@ -1613,6 +1613,10 @@ 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;
|
||||
}
|
||||
|
||||
/* completed NF calibration, test threshold */
|
||||
nf = ath5k_hw_read_measured_noise_floor(ah);
|
||||
|
|
|
@ -985,6 +985,8 @@ ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
|
|||
return;
|
||||
|
||||
ee_mode = ath5k_eeprom_mode_from_channel(channel);
|
||||
if (WARN_ON(ee_mode < 0))
|
||||
return;
|
||||
|
||||
/* Adjust power delta for channel 14 */
|
||||
if (channel->center_freq == 2484)
|
||||
|
|
|
@ -1778,14 +1778,14 @@ static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev,
|
|||
|
||||
if (vif->target_stats.rx_byte) {
|
||||
sinfo->rx_bytes = vif->target_stats.rx_byte;
|
||||
sinfo->filled |= STATION_INFO_RX_BYTES;
|
||||
sinfo->filled |= STATION_INFO_RX_BYTES64;
|
||||
sinfo->rx_packets = vif->target_stats.rx_pkt;
|
||||
sinfo->filled |= STATION_INFO_RX_PACKETS;
|
||||
}
|
||||
|
||||
if (vif->target_stats.tx_byte) {
|
||||
sinfo->tx_bytes = vif->target_stats.tx_byte;
|
||||
sinfo->filled |= STATION_INFO_TX_BYTES;
|
||||
sinfo->filled |= STATION_INFO_TX_BYTES64;
|
||||
sinfo->tx_packets = vif->target_stats.tx_pkt;
|
||||
sinfo->filled |= STATION_INFO_TX_PACKETS;
|
||||
}
|
||||
|
|
|
@ -58,6 +58,7 @@ config ATH9K_DEBUGFS
|
|||
bool "Atheros ath9k debugging"
|
||||
depends on ATH9K
|
||||
select MAC80211_DEBUGFS
|
||||
select RELAY
|
||||
---help---
|
||||
Say Y, if you need access to ath9k's statistics for
|
||||
interrupts, rate control, etc.
|
||||
|
|
|
@ -319,6 +319,8 @@ struct ath_rx {
|
|||
struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX];
|
||||
|
||||
struct sk_buff *frag;
|
||||
|
||||
u32 ampdu_ref;
|
||||
};
|
||||
|
||||
int ath_startrecv(struct ath_softc *sc);
|
||||
|
@ -387,6 +389,7 @@ struct ath_beacon_config {
|
|||
u16 bmiss_timeout;
|
||||
u8 dtim_count;
|
||||
bool enable_beacon;
|
||||
bool ibss_creator;
|
||||
};
|
||||
|
||||
struct ath_beacon {
|
||||
|
@ -869,7 +872,7 @@ enum ath_fft_sample_type {
|
|||
|
||||
struct fft_sample_tlv {
|
||||
u8 type; /* see ath_fft_sample */
|
||||
u16 length;
|
||||
__be16 length;
|
||||
/* type dependent data follows */
|
||||
} __packed;
|
||||
|
||||
|
@ -878,15 +881,15 @@ struct fft_sample_ht20 {
|
|||
|
||||
u8 max_exp;
|
||||
|
||||
u16 freq;
|
||||
__be16 freq;
|
||||
s8 rssi;
|
||||
s8 noise;
|
||||
|
||||
u16 max_magnitude;
|
||||
__be16 max_magnitude;
|
||||
u8 max_index;
|
||||
u8 bitmap_weight;
|
||||
|
||||
u64 tsf;
|
||||
__be64 tsf;
|
||||
|
||||
u8 data[SPECTRAL_HT20_NUM_BINS];
|
||||
} __packed;
|
||||
|
|
|
@ -407,12 +407,17 @@ void ath9k_beacon_tasklet(unsigned long data)
|
|||
}
|
||||
}
|
||||
|
||||
static void ath9k_beacon_init(struct ath_softc *sc, u32 nexttbtt, u32 intval)
|
||||
/*
|
||||
* Both nexttbtt and intval have to be in usecs.
|
||||
*/
|
||||
static void ath9k_beacon_init(struct ath_softc *sc, u32 nexttbtt,
|
||||
u32 intval, bool reset_tsf)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
|
||||
ath9k_hw_disable_interrupts(ah);
|
||||
ath9k_hw_reset_tsf(ah);
|
||||
if (reset_tsf)
|
||||
ath9k_hw_reset_tsf(ah);
|
||||
ath9k_beaconq_config(sc);
|
||||
ath9k_hw_beaconinit(ah, nexttbtt, intval);
|
||||
sc->beacon.bmisscnt = 0;
|
||||
|
@ -442,10 +447,12 @@ static void ath9k_beacon_config_ap(struct ath_softc *sc,
|
|||
else
|
||||
ah->imask &= ~ATH9K_INT_SWBA;
|
||||
|
||||
ath_dbg(common, BEACON, "AP nexttbtt: %u intval: %u conf_intval: %u\n",
|
||||
ath_dbg(common, BEACON,
|
||||
"AP (%s) nexttbtt: %u intval: %u conf_intval: %u\n",
|
||||
(conf->enable_beacon) ? "Enable" : "Disable",
|
||||
nexttbtt, intval, conf->beacon_interval);
|
||||
|
||||
ath9k_beacon_init(sc, nexttbtt, intval);
|
||||
ath9k_beacon_init(sc, nexttbtt, intval, true);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -586,17 +593,45 @@ static void ath9k_beacon_config_adhoc(struct ath_softc *sc,
|
|||
ath9k_reset_beacon_status(sc);
|
||||
|
||||
intval = TU_TO_USEC(conf->beacon_interval);
|
||||
nexttbtt = intval;
|
||||
|
||||
if (conf->ibss_creator) {
|
||||
nexttbtt = intval;
|
||||
} else {
|
||||
u32 tbtt, offset, tsftu;
|
||||
u64 tsf;
|
||||
|
||||
/*
|
||||
* Pull nexttbtt forward to reflect the current
|
||||
* sync'd TSF.
|
||||
*/
|
||||
tsf = ath9k_hw_gettsf64(ah);
|
||||
tsftu = TSF_TO_TU(tsf >> 32, tsf) + FUDGE;
|
||||
offset = tsftu % conf->beacon_interval;
|
||||
tbtt = tsftu - offset;
|
||||
if (offset)
|
||||
tbtt += conf->beacon_interval;
|
||||
|
||||
nexttbtt = TU_TO_USEC(tbtt);
|
||||
}
|
||||
|
||||
if (conf->enable_beacon)
|
||||
ah->imask |= ATH9K_INT_SWBA;
|
||||
else
|
||||
ah->imask &= ~ATH9K_INT_SWBA;
|
||||
|
||||
ath_dbg(common, BEACON, "IBSS nexttbtt: %u intval: %u conf_intval: %u\n",
|
||||
ath_dbg(common, BEACON,
|
||||
"IBSS (%s) nexttbtt: %u intval: %u conf_intval: %u\n",
|
||||
(conf->enable_beacon) ? "Enable" : "Disable",
|
||||
nexttbtt, intval, conf->beacon_interval);
|
||||
|
||||
ath9k_beacon_init(sc, nexttbtt, intval);
|
||||
ath9k_beacon_init(sc, nexttbtt, intval, conf->ibss_creator);
|
||||
|
||||
/*
|
||||
* Set the global 'beacon has been configured' flag for the
|
||||
* joiner case in IBSS mode.
|
||||
*/
|
||||
if (!conf->ibss_creator && conf->enable_beacon)
|
||||
set_bit(SC_OP_BEACONS, &sc->sc_flags);
|
||||
}
|
||||
|
||||
bool ath9k_allow_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
|
||||
|
@ -639,6 +674,7 @@ static void ath9k_cache_beacon_config(struct ath_softc *sc,
|
|||
cur_conf->dtim_period = bss_conf->dtim_period;
|
||||
cur_conf->listen_interval = 1;
|
||||
cur_conf->dtim_count = 1;
|
||||
cur_conf->ibss_creator = bss_conf->ibss_creator;
|
||||
cur_conf->bmiss_timeout =
|
||||
ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
|
||||
|
||||
|
@ -666,34 +702,59 @@ void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
|
|||
{
|
||||
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
|
||||
struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
|
||||
unsigned long flags;
|
||||
bool skip_beacon = false;
|
||||
|
||||
if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) {
|
||||
ath9k_cache_beacon_config(sc, bss_conf);
|
||||
ath9k_set_beacon(sc);
|
||||
set_bit(SC_OP_BEACONS, &sc->sc_flags);
|
||||
} else {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Take care of multiple interfaces when
|
||||
* enabling/disabling SWBA.
|
||||
*/
|
||||
if (changed & BSS_CHANGED_BEACON_ENABLED) {
|
||||
if (!bss_conf->enable_beacon &&
|
||||
(sc->nbcnvifs <= 1)) {
|
||||
cur_conf->enable_beacon = false;
|
||||
} else if (bss_conf->enable_beacon) {
|
||||
cur_conf->enable_beacon = true;
|
||||
ath9k_cache_beacon_config(sc, bss_conf);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure the HW beacon registers only when we have a valid
|
||||
* beacon interval.
|
||||
*/
|
||||
if (cur_conf->beacon_interval) {
|
||||
/*
|
||||
* Take care of multiple interfaces when
|
||||
* enabling/disabling SWBA.
|
||||
* If we are joining an existing IBSS network, start beaconing
|
||||
* only after a TSF-sync has taken place. Ensure that this
|
||||
* happens by setting the appropriate flags.
|
||||
*/
|
||||
if (changed & BSS_CHANGED_BEACON_ENABLED) {
|
||||
if (!bss_conf->enable_beacon &&
|
||||
(sc->nbcnvifs <= 1)) {
|
||||
cur_conf->enable_beacon = false;
|
||||
} else if (bss_conf->enable_beacon) {
|
||||
cur_conf->enable_beacon = true;
|
||||
ath9k_cache_beacon_config(sc, bss_conf);
|
||||
}
|
||||
}
|
||||
|
||||
if (cur_conf->beacon_interval) {
|
||||
if ((changed & BSS_CHANGED_IBSS) && !bss_conf->ibss_creator &&
|
||||
bss_conf->enable_beacon) {
|
||||
spin_lock_irqsave(&sc->sc_pm_lock, flags);
|
||||
sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
|
||||
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
|
||||
skip_beacon = true;
|
||||
} else {
|
||||
ath9k_set_beacon(sc);
|
||||
|
||||
if (cur_conf->enable_beacon)
|
||||
set_bit(SC_OP_BEACONS, &sc->sc_flags);
|
||||
else
|
||||
clear_bit(SC_OP_BEACONS, &sc->sc_flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do not set the SC_OP_BEACONS flag for IBSS joiner mode
|
||||
* here, it is done in ath9k_beacon_config_adhoc().
|
||||
*/
|
||||
if (cur_conf->enable_beacon && !skip_beacon)
|
||||
set_bit(SC_OP_BEACONS, &sc->sc_flags);
|
||||
else
|
||||
clear_bit(SC_OP_BEACONS, &sc->sc_flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -922,7 +922,7 @@ static void ath9k_deinit_softc(struct ath_softc *sc)
|
|||
|
||||
ath9k_eeprom_release(sc);
|
||||
|
||||
if (sc->rfs_chan_spec_scan) {
|
||||
if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) {
|
||||
relay_close(sc->rfs_chan_spec_scan);
|
||||
sc->rfs_chan_spec_scan = NULL;
|
||||
}
|
||||
|
|
|
@ -320,28 +320,25 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
|
|||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath_node *an;
|
||||
u8 density;
|
||||
an = (struct ath_node *)sta->drv_priv;
|
||||
|
||||
an->sc = sc;
|
||||
an->sta = sta;
|
||||
an->vif = vif;
|
||||
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
|
||||
ath_tx_node_init(sc, an);
|
||||
ath_tx_node_init(sc, an);
|
||||
|
||||
if (sta->ht_cap.ht_supported) {
|
||||
an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
|
||||
sta->ht_cap.ampdu_factor);
|
||||
density = ath9k_parse_mpdudensity(sta->ht_cap.ampdu_density);
|
||||
an->mpdudensity = density;
|
||||
an->mpdudensity = ath9k_parse_mpdudensity(sta->ht_cap.ampdu_density);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ath_node *an = (struct ath_node *)sta->drv_priv;
|
||||
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
|
||||
ath_tx_node_cleanup(sc, an);
|
||||
ath_tx_node_cleanup(sc, an);
|
||||
}
|
||||
|
||||
void ath9k_tasklet(unsigned long data)
|
||||
|
|
|
@ -474,8 +474,6 @@ void ath_mci_cleanup(struct ath_softc *sc)
|
|||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_mci_coex *mci = &sc->mci_coex;
|
||||
struct ath_mci_buf *buf = &mci->sched_buf;
|
||||
|
||||
ar9003_mci_cleanup(ah);
|
||||
|
||||
|
|
|
@ -533,7 +533,7 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
|
|||
if (sc->ps_flags & PS_BEACON_SYNC) {
|
||||
sc->ps_flags &= ~PS_BEACON_SYNC;
|
||||
ath_dbg(common, PS,
|
||||
"Reconfigure Beacon timers based on timestamp from the AP\n");
|
||||
"Reconfigure beacon timers based on synchronized timestamp\n");
|
||||
ath9k_set_beacon(sc);
|
||||
}
|
||||
|
||||
|
@ -1016,18 +1016,20 @@ static void ath9k_rx_skb_postprocess(struct ath_common *common,
|
|||
rxs->flag &= ~RX_FLAG_DECRYPTED;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ATH9K_DEBUGFS
|
||||
static s8 fix_rssi_inv_only(u8 rssi_val)
|
||||
{
|
||||
if (rssi_val == 128)
|
||||
rssi_val = 0;
|
||||
return (s8) rssi_val;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* returns 1 if this was a spectral frame, even if not handled. */
|
||||
static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
|
||||
struct ath_rx_status *rs, u64 tsf)
|
||||
{
|
||||
#ifdef CONFIG_ATH_DEBUG
|
||||
#ifdef CONFIG_ATH9K_DEBUGFS
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
u8 bins[SPECTRAL_HT20_NUM_BINS];
|
||||
u8 *vdata = (u8 *)hdr;
|
||||
|
@ -1036,6 +1038,7 @@ static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
|
|||
struct ath_ht20_mag_info *mag_info;
|
||||
int len = rs->rs_datalen;
|
||||
int dc_pos;
|
||||
u16 length, max_magnitude;
|
||||
|
||||
/* AR9280 and before report via ATH9K_PHYERR_RADAR, AR93xx and newer
|
||||
* via ATH9K_PHYERR_SPECTRAL. Haven't seen ATH9K_PHYERR_FALSE_RADAR_EXT
|
||||
|
@ -1063,8 +1066,8 @@ static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
|
|||
return 1;
|
||||
|
||||
fft_sample.tlv.type = ATH_FFT_SAMPLE_HT20;
|
||||
fft_sample.tlv.length = sizeof(fft_sample) - sizeof(fft_sample.tlv);
|
||||
fft_sample.tlv.length = __cpu_to_be16(fft_sample.tlv.length);
|
||||
length = sizeof(fft_sample) - sizeof(fft_sample.tlv);
|
||||
fft_sample.tlv.length = __cpu_to_be16(length);
|
||||
|
||||
fft_sample.freq = __cpu_to_be16(ah->curchan->chan->center_freq);
|
||||
fft_sample.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0);
|
||||
|
@ -1110,8 +1113,8 @@ static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
|
|||
memcpy(fft_sample.data, bins, SPECTRAL_HT20_NUM_BINS);
|
||||
fft_sample.max_exp = mag_info->max_exp & 0xf;
|
||||
|
||||
fft_sample.max_magnitude = spectral_max_magnitude(mag_info->all_bins);
|
||||
fft_sample.max_magnitude = __cpu_to_be16(fft_sample.max_magnitude);
|
||||
max_magnitude = spectral_max_magnitude(mag_info->all_bins);
|
||||
fft_sample.max_magnitude = __cpu_to_be16(max_magnitude);
|
||||
fft_sample.max_index = spectral_max_index(mag_info->all_bins);
|
||||
fft_sample.bitmap_weight = spectral_bitmap_weight(mag_info->all_bins);
|
||||
fft_sample.tsf = __cpu_to_be64(tsf);
|
||||
|
@ -1123,6 +1126,24 @@ static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
|
|||
#endif
|
||||
}
|
||||
|
||||
static void ath9k_apply_ampdu_details(struct ath_softc *sc,
|
||||
struct ath_rx_status *rs, struct ieee80211_rx_status *rxs)
|
||||
{
|
||||
if (rs->rs_isaggr) {
|
||||
rxs->flag |= RX_FLAG_AMPDU_DETAILS | RX_FLAG_AMPDU_LAST_KNOWN;
|
||||
|
||||
rxs->ampdu_reference = sc->rx.ampdu_ref;
|
||||
|
||||
if (!rs->rs_moreaggr) {
|
||||
rxs->flag |= RX_FLAG_AMPDU_IS_LAST;
|
||||
sc->rx.ampdu_ref++;
|
||||
}
|
||||
|
||||
if (rs->rs_flags & ATH9K_RX_DELIM_CRC_PRE)
|
||||
rxs->flag |= RX_FLAG_AMPDU_DELIM_CRC_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
||||
{
|
||||
struct ath_buf *bf;
|
||||
|
@ -1329,6 +1350,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
|||
if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx == 3)
|
||||
ath_ant_comb_scan(sc, &rs);
|
||||
|
||||
ath9k_apply_ampdu_details(sc, &rs, rxs);
|
||||
|
||||
ieee80211_rx(hw, skb);
|
||||
|
||||
requeue_drop_frag:
|
||||
|
|
|
@ -1233,7 +1233,7 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
|
|||
* in HT IBSS when a beacon with HT-info is received after the station
|
||||
* has already been added.
|
||||
*/
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
|
||||
if (sta->ht_cap.ht_supported) {
|
||||
an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
|
||||
sta->ht_cap.ampdu_factor);
|
||||
density = ath9k_parse_mpdudensity(sta->ht_cap.ampdu_density);
|
||||
|
@ -1904,8 +1904,7 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
|
|||
struct ath_buf *bf;
|
||||
u8 tidno;
|
||||
|
||||
if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) && txctl->an &&
|
||||
ieee80211_is_data_qos(hdr->frame_control)) {
|
||||
if (txctl->an && ieee80211_is_data_qos(hdr->frame_control)) {
|
||||
tidno = ieee80211_get_qos_ctl(hdr)[0] &
|
||||
IEEE80211_QOS_CTL_TID_MASK;
|
||||
tid = ATH_AN_2_TID(txctl->an, tidno);
|
||||
|
|
|
@ -1853,7 +1853,7 @@ void *carl9170_alloc(size_t priv_size)
|
|||
IEEE80211_HW_REPORTS_TX_ACK_STATUS |
|
||||
IEEE80211_HW_SUPPORTS_PS |
|
||||
IEEE80211_HW_PS_NULLFUNC_STACK |
|
||||
IEEE80211_HW_NEED_DTIM_PERIOD |
|
||||
IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC |
|
||||
IEEE80211_HW_SIGNAL_DBM;
|
||||
|
||||
if (!modparam_noht) {
|
||||
|
|
|
@ -26,6 +26,7 @@ brcmfmac-objs += \
|
|||
wl_cfg80211.o \
|
||||
fwil.o \
|
||||
fweh.o \
|
||||
p2p.o \
|
||||
dhd_cdc.o \
|
||||
dhd_common.o \
|
||||
dhd_linux.o
|
||||
|
@ -37,4 +38,4 @@ brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \
|
|||
brcmfmac-$(CONFIG_BRCMFMAC_USB) += \
|
||||
usb.o
|
||||
brcmfmac-$(CONFIG_BRCMDBG) += \
|
||||
dhd_dbg.o
|
||||
dhd_dbg.o
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
#define BRCMF_C_SET_WSEC 134
|
||||
#define BRCMF_C_GET_PHY_NOISE 135
|
||||
#define BRCMF_C_GET_BSS_INFO 136
|
||||
#define BRCMF_C_SET_SCB_TIMEOUT 158
|
||||
#define BRCMF_C_GET_PHYLIST 180
|
||||
#define BRCMF_C_SET_SCAN_CHANNEL_TIME 185
|
||||
#define BRCMF_C_SET_SCAN_UNASSOC_TIME 187
|
||||
|
@ -149,6 +150,7 @@
|
|||
#define BRCMF_E_REASON_MINTXRATE 9
|
||||
#define BRCMF_E_REASON_TXFAIL 10
|
||||
|
||||
#define BRCMF_E_REASON_LINK_BSSCFG_DIS 4
|
||||
#define BRCMF_E_REASON_FAST_ROAM_FAILED 5
|
||||
#define BRCMF_E_REASON_DIRECTED_ROAM 6
|
||||
#define BRCMF_E_REASON_TSPEC_REJECTED 7
|
||||
|
@ -375,6 +377,28 @@ struct brcmf_join_params {
|
|||
struct brcmf_assoc_params_le params_le;
|
||||
};
|
||||
|
||||
/* scan params for extended join */
|
||||
struct brcmf_join_scan_params_le {
|
||||
u8 scan_type; /* 0 use default, active or passive scan */
|
||||
__le32 nprobes; /* -1 use default, nr of probes per channel */
|
||||
__le32 active_time; /* -1 use default, dwell time per channel for
|
||||
* active scanning
|
||||
*/
|
||||
__le32 passive_time; /* -1 use default, dwell time per channel
|
||||
* for passive scanning
|
||||
*/
|
||||
__le32 home_time; /* -1 use default, dwell time for the home
|
||||
* channel between channel scans
|
||||
*/
|
||||
};
|
||||
|
||||
/* extended join params */
|
||||
struct brcmf_ext_join_params_le {
|
||||
struct brcmf_ssid_le ssid_le; /* {0, ""}: wildcard scan */
|
||||
struct brcmf_join_scan_params_le scan_le;
|
||||
struct brcmf_assoc_params_le assoc_le;
|
||||
};
|
||||
|
||||
struct brcmf_wsec_key {
|
||||
u32 index; /* key index */
|
||||
u32 len; /* key length */
|
||||
|
@ -451,6 +475,19 @@ struct brcmf_sta_info_le {
|
|||
__le32 rx_decrypt_failures; /* # of packet decrypted failed */
|
||||
};
|
||||
|
||||
/*
|
||||
* WLC_E_PROBRESP_MSG
|
||||
* WLC_E_P2P_PROBREQ_MSG
|
||||
* WLC_E_ACTION_FRAME_RX
|
||||
*/
|
||||
struct brcmf_rx_mgmt_data {
|
||||
__be16 version;
|
||||
__be16 chanspec;
|
||||
__be32 rssi;
|
||||
__be32 mactime;
|
||||
__be32 rate;
|
||||
};
|
||||
|
||||
/* Bus independent dongle command */
|
||||
struct brcmf_dcmd {
|
||||
uint cmd; /* common dongle cmd definition */
|
||||
|
@ -489,9 +526,6 @@ struct brcmf_pub {
|
|||
struct mutex proto_block;
|
||||
unsigned char proto_buf[BRCMF_DCMD_MAXLEN];
|
||||
|
||||
atomic_t pend_8021x_cnt;
|
||||
wait_queue_head_t pend_8021x_wait;
|
||||
|
||||
struct brcmf_fweh_info fweh;
|
||||
#ifdef DEBUG
|
||||
struct dentry *dbgfs_dir;
|
||||
|
@ -515,9 +549,11 @@ struct brcmf_cfg80211_vif;
|
|||
* @vif: points to cfg80211 specific interface information.
|
||||
* @ndev: associated network device.
|
||||
* @stats: interface specific network statistics.
|
||||
* @idx: interface index in device firmware.
|
||||
* @ifidx: interface index in device firmware.
|
||||
* @bssidx: index of bss associated with this interface.
|
||||
* @mac_addr: assigned mac address.
|
||||
* @pend_8021x_cnt: tracks outstanding number of 802.1x frames.
|
||||
* @pend_8021x_wait: used for signalling change in count.
|
||||
*/
|
||||
struct brcmf_if {
|
||||
struct brcmf_pub *drvr;
|
||||
|
@ -526,9 +562,11 @@ struct brcmf_if {
|
|||
struct net_device_stats stats;
|
||||
struct work_struct setmacaddr_work;
|
||||
struct work_struct multicast_work;
|
||||
int idx;
|
||||
int ifidx;
|
||||
s32 bssidx;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
atomic_t pend_8021x_cnt;
|
||||
wait_queue_head_t pend_8021x_wait;
|
||||
};
|
||||
|
||||
|
||||
|
@ -547,9 +585,10 @@ extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
|
|||
extern int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx,
|
||||
struct sk_buff *rxp);
|
||||
|
||||
extern int brcmf_net_attach(struct brcmf_if *ifp);
|
||||
extern struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx,
|
||||
s32 bssidx, char *name, u8 *mac_addr);
|
||||
extern void brcmf_del_if(struct brcmf_pub *drvr, int ifidx);
|
||||
extern int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
|
||||
extern struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx,
|
||||
s32 ifidx, char *name, u8 *mac_addr);
|
||||
extern void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx);
|
||||
extern u32 brcmf_get_chip_info(struct brcmf_if *ifp);
|
||||
|
||||
#endif /* _BRCMF_H_ */
|
||||
|
|
|
@ -24,18 +24,6 @@ enum brcmf_bus_state {
|
|||
BRCMF_BUS_DATA /* Ready for frame transfers */
|
||||
};
|
||||
|
||||
struct dngl_stats {
|
||||
unsigned long rx_packets; /* total packets received */
|
||||
unsigned long tx_packets; /* total packets transmitted */
|
||||
unsigned long rx_bytes; /* total bytes received */
|
||||
unsigned long tx_bytes; /* total bytes transmitted */
|
||||
unsigned long rx_errors; /* bad packets received */
|
||||
unsigned long tx_errors; /* packet transmit problems */
|
||||
unsigned long rx_dropped; /* packets dropped by dongle */
|
||||
unsigned long tx_dropped; /* packets dropped by dongle */
|
||||
unsigned long multicast; /* multicast packets received */
|
||||
};
|
||||
|
||||
struct brcmf_bus_dcmd {
|
||||
char *name;
|
||||
char *param;
|
||||
|
@ -72,11 +60,12 @@ struct brcmf_bus_ops {
|
|||
* @drvr: public driver information.
|
||||
* @state: operational state of the bus interface.
|
||||
* @maxctl: maximum size for rxctl request message.
|
||||
* @drvr_up: indicates driver up/down status.
|
||||
* @tx_realloc: number of tx packets realloced for headroom.
|
||||
* @dstats: dongle-based statistical data.
|
||||
* @align: alignment requirement for the bus.
|
||||
* @dcmd_list: bus/device specific dongle initialization commands.
|
||||
* @chip: device identifier of the dongle chip.
|
||||
* @chiprev: revision of the dongle chip.
|
||||
*/
|
||||
struct brcmf_bus {
|
||||
union {
|
||||
|
@ -87,10 +76,10 @@ struct brcmf_bus {
|
|||
struct brcmf_pub *drvr;
|
||||
enum brcmf_bus_state state;
|
||||
uint maxctl;
|
||||
bool drvr_up;
|
||||
unsigned long tx_realloc;
|
||||
struct dngl_stats dstats;
|
||||
u8 align;
|
||||
u32 chip;
|
||||
u32 chiprev;
|
||||
struct list_head dcmd_list;
|
||||
|
||||
struct brcmf_bus_ops *ops;
|
||||
|
|
|
@ -303,6 +303,14 @@ int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx,
|
|||
brcmf_err("rx data ifnum out of range (%d)\n", *ifidx);
|
||||
return -EBADE;
|
||||
}
|
||||
/* The ifidx is the idx to map to matching netdev/ifp. When receiving
|
||||
* events this is easy because it contains the bssidx which maps
|
||||
* 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd.
|
||||
* bssidx 1 is used for p2p0 and no data can be received or
|
||||
* transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0
|
||||
*/
|
||||
if (*ifidx)
|
||||
(*ifidx)++;
|
||||
|
||||
if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) !=
|
||||
BDC_PROTO_VER) {
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include "dhd_bus.h"
|
||||
#include "dhd_proto.h"
|
||||
#include "dhd_dbg.h"
|
||||
#include "fwil_types.h"
|
||||
#include "p2p.h"
|
||||
#include "wl_cfg80211.h"
|
||||
#include "fwil.h"
|
||||
|
||||
|
@ -40,6 +42,12 @@ MODULE_LICENSE("Dual BSD/GPL");
|
|||
int brcmf_msg_level;
|
||||
module_param(brcmf_msg_level, int, 0);
|
||||
|
||||
/* P2P0 enable */
|
||||
static int brcmf_p2p_enable;
|
||||
#ifdef CONFIG_BRCMDBG
|
||||
module_param_named(p2pon, brcmf_p2p_enable, int, 0);
|
||||
MODULE_PARM_DESC(p2pon, "enable p2p management functionality");
|
||||
#endif
|
||||
|
||||
char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx)
|
||||
{
|
||||
|
@ -70,9 +78,10 @@ static void _brcmf_set_multicast_list(struct work_struct *work)
|
|||
u32 buflen;
|
||||
s32 err;
|
||||
|
||||
brcmf_dbg(TRACE, "enter\n");
|
||||
|
||||
ifp = container_of(work, struct brcmf_if, multicast_work);
|
||||
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
|
||||
|
||||
ndev = ifp->ndev;
|
||||
|
||||
/* Determine initial value of allmulti flag */
|
||||
|
@ -129,9 +138,10 @@ _brcmf_set_mac_address(struct work_struct *work)
|
|||
struct brcmf_if *ifp;
|
||||
s32 err;
|
||||
|
||||
brcmf_dbg(TRACE, "enter\n");
|
||||
|
||||
ifp = container_of(work, struct brcmf_if, setmacaddr_work);
|
||||
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
|
||||
|
||||
err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", ifp->mac_addr,
|
||||
ETH_ALEN);
|
||||
if (err < 0) {
|
||||
|
@ -168,7 +178,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
|
|||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
struct ethhdr *eh;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
|
||||
|
||||
/* Can the device send data? */
|
||||
if (drvr->bus_if->state != BRCMF_BUS_DATA) {
|
||||
|
@ -179,8 +189,8 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (!drvr->iflist[ifp->idx]) {
|
||||
brcmf_err("bad ifidx %d\n", ifp->idx);
|
||||
if (!drvr->iflist[ifp->bssidx]) {
|
||||
brcmf_err("bad ifidx %d\n", ifp->bssidx);
|
||||
netif_stop_queue(ndev);
|
||||
dev_kfree_skb(skb);
|
||||
ret = -ENODEV;
|
||||
|
@ -192,14 +202,14 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
|
|||
struct sk_buff *skb2;
|
||||
|
||||
brcmf_dbg(INFO, "%s: insufficient headroom\n",
|
||||
brcmf_ifname(drvr, ifp->idx));
|
||||
brcmf_ifname(drvr, ifp->bssidx));
|
||||
drvr->bus_if->tx_realloc++;
|
||||
skb2 = skb_realloc_headroom(skb, drvr->hdrlen);
|
||||
dev_kfree_skb(skb);
|
||||
skb = skb2;
|
||||
if (skb == NULL) {
|
||||
brcmf_err("%s: skb_realloc_headroom failed\n",
|
||||
brcmf_ifname(drvr, ifp->idx));
|
||||
brcmf_ifname(drvr, ifp->bssidx));
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
@ -217,19 +227,21 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
|
|||
if (is_multicast_ether_addr(eh->h_dest))
|
||||
drvr->tx_multicast++;
|
||||
if (ntohs(eh->h_proto) == ETH_P_PAE)
|
||||
atomic_inc(&drvr->pend_8021x_cnt);
|
||||
atomic_inc(&ifp->pend_8021x_cnt);
|
||||
|
||||
/* If the protocol uses a data header, apply it */
|
||||
brcmf_proto_hdrpush(drvr, ifp->idx, skb);
|
||||
brcmf_proto_hdrpush(drvr, ifp->ifidx, skb);
|
||||
|
||||
/* Use bus module to send data frame */
|
||||
ret = brcmf_bus_txdata(drvr->bus_if, skb);
|
||||
|
||||
done:
|
||||
if (ret)
|
||||
drvr->bus_if->dstats.tx_dropped++;
|
||||
else
|
||||
drvr->bus_if->dstats.tx_packets++;
|
||||
if (ret) {
|
||||
ifp->stats.tx_dropped++;
|
||||
} else {
|
||||
ifp->stats.tx_packets++;
|
||||
ifp->stats.tx_bytes += skb->len;
|
||||
}
|
||||
|
||||
/* Return ok: we always eat the packet */
|
||||
return NETDEV_TX_OK;
|
||||
|
@ -270,12 +282,13 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)
|
|||
skb_queue_walk_safe(skb_list, skb, pnext) {
|
||||
skb_unlink(skb, skb_list);
|
||||
|
||||
/* process and remove protocol-specific header
|
||||
*/
|
||||
/* process and remove protocol-specific header */
|
||||
ret = brcmf_proto_hdrpull(drvr, &ifidx, skb);
|
||||
if (ret < 0) {
|
||||
if (ret != -ENODATA)
|
||||
bus_if->dstats.rx_errors++;
|
||||
ifp = drvr->iflist[ifidx];
|
||||
|
||||
if (ret || !ifp || !ifp->ndev) {
|
||||
if ((ret != -ENODATA) && ifp)
|
||||
ifp->stats.rx_errors++;
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
continue;
|
||||
}
|
||||
|
@ -295,21 +308,11 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)
|
|||
eth = skb->data;
|
||||
len = skb->len;
|
||||
|
||||
ifp = drvr->iflist[ifidx];
|
||||
if (ifp == NULL)
|
||||
ifp = drvr->iflist[0];
|
||||
|
||||
if (!ifp || !ifp->ndev ||
|
||||
ifp->ndev->reg_state != NETREG_REGISTERED) {
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
skb->dev = ifp->ndev;
|
||||
skb->protocol = eth_type_trans(skb, skb->dev);
|
||||
|
||||
if (skb->pkt_type == PACKET_MULTICAST)
|
||||
bus_if->dstats.multicast++;
|
||||
ifp->stats.multicast++;
|
||||
|
||||
skb->data = eth;
|
||||
skb->len = len;
|
||||
|
@ -325,8 +328,13 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)
|
|||
ifp->ndev->last_rx = jiffies;
|
||||
}
|
||||
|
||||
bus_if->dstats.rx_bytes += skb->len;
|
||||
bus_if->dstats.rx_packets++; /* Local count */
|
||||
if (!(ifp->ndev->flags & IFF_UP)) {
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
ifp->stats.rx_bytes += skb->len;
|
||||
ifp->stats.rx_packets++;
|
||||
|
||||
if (in_interrupt())
|
||||
netif_rx(skb);
|
||||
|
@ -348,36 +356,31 @@ void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success)
|
|||
u16 type;
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_pub *drvr = bus_if->drvr;
|
||||
struct brcmf_if *ifp;
|
||||
|
||||
brcmf_proto_hdrpull(drvr, &ifidx, txp);
|
||||
|
||||
ifp = drvr->iflist[ifidx];
|
||||
if (!ifp)
|
||||
return;
|
||||
|
||||
eh = (struct ethhdr *)(txp->data);
|
||||
type = ntohs(eh->h_proto);
|
||||
|
||||
if (type == ETH_P_PAE) {
|
||||
atomic_dec(&drvr->pend_8021x_cnt);
|
||||
if (waitqueue_active(&drvr->pend_8021x_wait))
|
||||
wake_up(&drvr->pend_8021x_wait);
|
||||
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++;
|
||||
}
|
||||
|
||||
static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_bus *bus_if = ifp->drvr->bus_if;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
/* Copy dongle stats to net device stats */
|
||||
ifp->stats.rx_packets = bus_if->dstats.rx_packets;
|
||||
ifp->stats.tx_packets = bus_if->dstats.tx_packets;
|
||||
ifp->stats.rx_bytes = bus_if->dstats.rx_bytes;
|
||||
ifp->stats.tx_bytes = bus_if->dstats.tx_bytes;
|
||||
ifp->stats.rx_errors = bus_if->dstats.rx_errors;
|
||||
ifp->stats.tx_errors = bus_if->dstats.tx_errors;
|
||||
ifp->stats.rx_dropped = bus_if->dstats.rx_dropped;
|
||||
ifp->stats.tx_dropped = bus_if->dstats.tx_dropped;
|
||||
ifp->stats.multicast = bus_if->dstats.multicast;
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
|
||||
|
||||
return &ifp->stats;
|
||||
}
|
||||
|
@ -429,7 +432,7 @@ static int brcmf_ethtool(struct brcmf_if *ifp, void __user *uaddr)
|
|||
u32 toe_cmpnt, csum_dir;
|
||||
int ret;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
|
||||
|
||||
/* all ethtool calls start with a cmd word */
|
||||
if (copy_from_user(&cmd, uaddr, sizeof(u32)))
|
||||
|
@ -452,13 +455,7 @@ static int brcmf_ethtool(struct brcmf_if *ifp, void __user *uaddr)
|
|||
sprintf(info.driver, "dhd");
|
||||
strcpy(info.version, BRCMF_VERSION_STR);
|
||||
}
|
||||
|
||||
/* otherwise, require dongle to be up */
|
||||
else if (!drvr->bus_if->drvr_up) {
|
||||
brcmf_err("dongle is not up\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
/* finally, report dongle driver type */
|
||||
/* report dongle driver type */
|
||||
else
|
||||
sprintf(info.driver, "wl");
|
||||
|
||||
|
@ -532,9 +529,9 @@ static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr,
|
|||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
|
||||
brcmf_dbg(TRACE, "ifidx %d, cmd 0x%04x\n", ifp->idx, cmd);
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d, cmd=0x%04x\n", ifp->bssidx, cmd);
|
||||
|
||||
if (!drvr->iflist[ifp->idx])
|
||||
if (!drvr->iflist[ifp->bssidx])
|
||||
return -1;
|
||||
|
||||
if (cmd == SIOCETHTOOL)
|
||||
|
@ -546,17 +543,12 @@ static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr,
|
|||
static int brcmf_netdev_stop(struct net_device *ndev)
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
if (drvr->bus_if->drvr_up == 0)
|
||||
return 0;
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
|
||||
|
||||
brcmf_cfg80211_down(ndev);
|
||||
|
||||
/* Set state and stop OS transmissions */
|
||||
drvr->bus_if->drvr_up = false;
|
||||
netif_stop_queue(ndev);
|
||||
|
||||
return 0;
|
||||
|
@ -570,7 +562,7 @@ static int brcmf_netdev_open(struct net_device *ndev)
|
|||
u32 toe_ol;
|
||||
s32 ret = 0;
|
||||
|
||||
brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx);
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
|
||||
|
||||
/* If bus is not ready, can't continue */
|
||||
if (bus_if->state != BRCMF_BUS_DATA) {
|
||||
|
@ -578,9 +570,7 @@ static int brcmf_netdev_open(struct net_device *ndev)
|
|||
return -EAGAIN;
|
||||
}
|
||||
|
||||
atomic_set(&drvr->pend_8021x_cnt, 0);
|
||||
|
||||
memcpy(ndev->dev_addr, drvr->mac, ETH_ALEN);
|
||||
atomic_set(&ifp->pend_8021x_cnt, 0);
|
||||
|
||||
/* Get current TOE mode from dongle */
|
||||
if (brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_ol) >= 0
|
||||
|
@ -591,7 +581,6 @@ static int brcmf_netdev_open(struct net_device *ndev)
|
|||
|
||||
/* Allow transmit calls */
|
||||
netif_start_queue(ndev);
|
||||
drvr->bus_if->drvr_up = true;
|
||||
if (brcmf_cfg80211_up(ndev)) {
|
||||
brcmf_err("failed to bring up cfg80211\n");
|
||||
return -1;
|
||||
|
@ -610,29 +599,18 @@ static const struct net_device_ops brcmf_netdev_ops_pri = {
|
|||
.ndo_set_rx_mode = brcmf_netdev_set_multicast_list
|
||||
};
|
||||
|
||||
static const struct net_device_ops brcmf_netdev_ops_virt = {
|
||||
.ndo_open = brcmf_cfg80211_up,
|
||||
.ndo_stop = brcmf_cfg80211_down,
|
||||
.ndo_get_stats = brcmf_netdev_get_stats,
|
||||
.ndo_do_ioctl = brcmf_netdev_ioctl_entry,
|
||||
.ndo_start_xmit = brcmf_netdev_start_xmit,
|
||||
.ndo_set_mac_address = brcmf_netdev_set_mac_address,
|
||||
.ndo_set_rx_mode = brcmf_netdev_set_multicast_list
|
||||
};
|
||||
|
||||
int brcmf_net_attach(struct brcmf_if *ifp)
|
||||
int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked)
|
||||
{
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
struct net_device *ndev;
|
||||
s32 err;
|
||||
|
||||
brcmf_dbg(TRACE, "ifidx %d mac %pM\n", ifp->idx, ifp->mac_addr);
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d mac=%pM\n", ifp->bssidx,
|
||||
ifp->mac_addr);
|
||||
ndev = ifp->ndev;
|
||||
|
||||
/* set appropriate operations */
|
||||
if (!ifp->idx)
|
||||
ndev->netdev_ops = &brcmf_netdev_ops_pri;
|
||||
else
|
||||
ndev->netdev_ops = &brcmf_netdev_ops_virt;
|
||||
ndev->netdev_ops = &brcmf_netdev_ops_pri;
|
||||
|
||||
ndev->hard_header_len = ETH_HLEN + drvr->hdrlen;
|
||||
ndev->ethtool_ops = &brcmf_ethtool_ops;
|
||||
|
@ -643,7 +621,14 @@ int brcmf_net_attach(struct brcmf_if *ifp)
|
|||
/* set the mac address */
|
||||
memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
|
||||
|
||||
if (register_netdev(ndev) != 0) {
|
||||
INIT_WORK(&ifp->setmacaddr_work, _brcmf_set_mac_address);
|
||||
INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list);
|
||||
|
||||
if (rtnl_locked)
|
||||
err = register_netdevice(ndev);
|
||||
else
|
||||
err = register_netdev(ndev);
|
||||
if (err != 0) {
|
||||
brcmf_err("couldn't register the net device\n");
|
||||
goto fail;
|
||||
}
|
||||
|
@ -657,16 +642,78 @@ fail:
|
|||
return -EBADE;
|
||||
}
|
||||
|
||||
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx, s32 bssidx,
|
||||
char *name, u8 *addr_mask)
|
||||
static int brcmf_net_p2p_open(struct net_device *ndev)
|
||||
{
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
return brcmf_cfg80211_up(ndev);
|
||||
}
|
||||
|
||||
static int brcmf_net_p2p_stop(struct net_device *ndev)
|
||||
{
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
return brcmf_cfg80211_down(ndev);
|
||||
}
|
||||
|
||||
static int brcmf_net_p2p_do_ioctl(struct net_device *ndev,
|
||||
struct ifreq *ifr, int cmd)
|
||||
{
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static netdev_tx_t brcmf_net_p2p_start_xmit(struct sk_buff *skb,
|
||||
struct net_device *ndev)
|
||||
{
|
||||
if (skb)
|
||||
dev_kfree_skb_any(skb);
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
static const struct net_device_ops brcmf_netdev_ops_p2p = {
|
||||
.ndo_open = brcmf_net_p2p_open,
|
||||
.ndo_stop = brcmf_net_p2p_stop,
|
||||
.ndo_do_ioctl = brcmf_net_p2p_do_ioctl,
|
||||
.ndo_start_xmit = brcmf_net_p2p_start_xmit
|
||||
};
|
||||
|
||||
static int brcmf_net_p2p_attach(struct brcmf_if *ifp)
|
||||
{
|
||||
struct net_device *ndev;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d mac=%pM\n", ifp->bssidx,
|
||||
ifp->mac_addr);
|
||||
ndev = ifp->ndev;
|
||||
|
||||
ndev->netdev_ops = &brcmf_netdev_ops_p2p;
|
||||
|
||||
/* set the mac address */
|
||||
memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN);
|
||||
|
||||
if (register_netdev(ndev) != 0) {
|
||||
brcmf_err("couldn't register the p2p net device\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
return -EBADE;
|
||||
}
|
||||
|
||||
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
|
||||
char *name, u8 *mac_addr)
|
||||
{
|
||||
struct brcmf_if *ifp;
|
||||
struct net_device *ndev;
|
||||
int i;
|
||||
|
||||
brcmf_dbg(TRACE, "idx %d\n", ifidx);
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifidx);
|
||||
|
||||
ifp = drvr->iflist[ifidx];
|
||||
ifp = drvr->iflist[bssidx];
|
||||
/*
|
||||
* Delete the existing interface before overwriting it
|
||||
* in case we missed the BRCMF_E_IF_DEL event.
|
||||
|
@ -678,7 +725,7 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx, s32 bssidx,
|
|||
netif_stop_queue(ifp->ndev);
|
||||
unregister_netdev(ifp->ndev);
|
||||
free_netdev(ifp->ndev);
|
||||
drvr->iflist[ifidx] = NULL;
|
||||
drvr->iflist[bssidx] = NULL;
|
||||
} else {
|
||||
brcmf_err("ignore IF event\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
@ -695,16 +742,15 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx, s32 bssidx,
|
|||
ifp = netdev_priv(ndev);
|
||||
ifp->ndev = ndev;
|
||||
ifp->drvr = drvr;
|
||||
drvr->iflist[ifidx] = ifp;
|
||||
ifp->idx = ifidx;
|
||||
drvr->iflist[bssidx] = ifp;
|
||||
ifp->ifidx = ifidx;
|
||||
ifp->bssidx = bssidx;
|
||||
|
||||
INIT_WORK(&ifp->setmacaddr_work, _brcmf_set_mac_address);
|
||||
INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list);
|
||||
|
||||
if (addr_mask != NULL)
|
||||
for (i = 0; i < ETH_ALEN; i++)
|
||||
ifp->mac_addr[i] = drvr->mac[i] ^ addr_mask[i];
|
||||
init_waitqueue_head(&ifp->pend_8021x_wait);
|
||||
|
||||
if (mac_addr != NULL)
|
||||
memcpy(ifp->mac_addr, mac_addr, ETH_ALEN);
|
||||
|
||||
brcmf_dbg(TRACE, " ==== pid:%x, if:%s (%pM) created ===\n",
|
||||
current->pid, ifp->ndev->name, ifp->mac_addr);
|
||||
|
@ -712,19 +758,18 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx, s32 bssidx,
|
|||
return ifp;
|
||||
}
|
||||
|
||||
void brcmf_del_if(struct brcmf_pub *drvr, int ifidx)
|
||||
void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
|
||||
{
|
||||
struct brcmf_if *ifp;
|
||||
|
||||
brcmf_dbg(TRACE, "idx %d\n", ifidx);
|
||||
|
||||
ifp = drvr->iflist[ifidx];
|
||||
ifp = drvr->iflist[bssidx];
|
||||
if (!ifp) {
|
||||
brcmf_err("Null interface\n");
|
||||
brcmf_err("Null interface, idx=%d\n", bssidx);
|
||||
return;
|
||||
}
|
||||
brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifp->ifidx);
|
||||
if (ifp->ndev) {
|
||||
if (ifidx == 0) {
|
||||
if (bssidx == 0) {
|
||||
if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
|
||||
rtnl_lock();
|
||||
brcmf_netdev_stop(ifp->ndev);
|
||||
|
@ -734,12 +779,14 @@ void brcmf_del_if(struct brcmf_pub *drvr, int ifidx)
|
|||
netif_stop_queue(ifp->ndev);
|
||||
}
|
||||
|
||||
cancel_work_sync(&ifp->setmacaddr_work);
|
||||
cancel_work_sync(&ifp->multicast_work);
|
||||
if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
|
||||
cancel_work_sync(&ifp->setmacaddr_work);
|
||||
cancel_work_sync(&ifp->multicast_work);
|
||||
}
|
||||
|
||||
unregister_netdev(ifp->ndev);
|
||||
drvr->iflist[ifidx] = NULL;
|
||||
if (ifidx == 0)
|
||||
drvr->iflist[bssidx] = NULL;
|
||||
if (bssidx == 0)
|
||||
brcmf_cfg80211_detach(drvr->config);
|
||||
free_netdev(ifp->ndev);
|
||||
}
|
||||
|
@ -779,8 +826,6 @@ int brcmf_attach(uint bus_hdrlen, struct device *dev)
|
|||
|
||||
INIT_LIST_HEAD(&drvr->bus_if->dcmd_list);
|
||||
|
||||
init_waitqueue_head(&drvr->pend_8021x_wait);
|
||||
|
||||
return ret;
|
||||
|
||||
fail:
|
||||
|
@ -795,6 +840,7 @@ int brcmf_bus_start(struct device *dev)
|
|||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_pub *drvr = bus_if->drvr;
|
||||
struct brcmf_if *ifp;
|
||||
struct brcmf_if *p2p_ifp;
|
||||
|
||||
brcmf_dbg(TRACE, "\n");
|
||||
|
||||
|
@ -810,6 +856,13 @@ int brcmf_bus_start(struct device *dev)
|
|||
if (IS_ERR(ifp))
|
||||
return PTR_ERR(ifp);
|
||||
|
||||
if (brcmf_p2p_enable)
|
||||
p2p_ifp = brcmf_add_if(drvr, 1, 0, "p2p%d", NULL);
|
||||
else
|
||||
p2p_ifp = NULL;
|
||||
if (IS_ERR(p2p_ifp))
|
||||
p2p_ifp = NULL;
|
||||
|
||||
/* signal bus ready */
|
||||
bus_if->state = BRCMF_BUS_DATA;
|
||||
|
||||
|
@ -828,16 +881,22 @@ int brcmf_bus_start(struct device *dev)
|
|||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
ret = brcmf_net_attach(ifp);
|
||||
ret = brcmf_net_attach(ifp, false);
|
||||
fail:
|
||||
if (ret < 0) {
|
||||
brcmf_err("failed: %d\n", ret);
|
||||
if (drvr->config)
|
||||
brcmf_cfg80211_detach(drvr->config);
|
||||
free_netdev(drvr->iflist[0]->ndev);
|
||||
free_netdev(ifp->ndev);
|
||||
drvr->iflist[0] = NULL;
|
||||
if (p2p_ifp) {
|
||||
free_netdev(p2p_ifp->ndev);
|
||||
drvr->iflist[1] = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
if ((brcmf_p2p_enable) && (p2p_ifp))
|
||||
brcmf_net_p2p_attach(p2p_ifp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -863,12 +922,13 @@ void brcmf_dev_reset(struct device *dev)
|
|||
if (drvr == NULL)
|
||||
return;
|
||||
|
||||
brcmf_fil_cmd_int_set(drvr->iflist[0], BRCMF_C_TERMINATED, 1);
|
||||
if (drvr->iflist[0])
|
||||
brcmf_fil_cmd_int_set(drvr->iflist[0], BRCMF_C_TERMINATED, 1);
|
||||
}
|
||||
|
||||
void brcmf_detach(struct device *dev)
|
||||
{
|
||||
int i;
|
||||
s32 i;
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_pub *drvr = bus_if->drvr;
|
||||
|
||||
|
@ -895,19 +955,18 @@ void brcmf_detach(struct device *dev)
|
|||
kfree(drvr);
|
||||
}
|
||||
|
||||
static int brcmf_get_pend_8021x_cnt(struct brcmf_pub *drvr)
|
||||
static int brcmf_get_pend_8021x_cnt(struct brcmf_if *ifp)
|
||||
{
|
||||
return atomic_read(&drvr->pend_8021x_cnt);
|
||||
return atomic_read(&ifp->pend_8021x_cnt);
|
||||
}
|
||||
|
||||
int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
int err;
|
||||
|
||||
err = wait_event_timeout(drvr->pend_8021x_wait,
|
||||
!brcmf_get_pend_8021x_cnt(drvr),
|
||||
err = wait_event_timeout(ifp->pend_8021x_wait,
|
||||
!brcmf_get_pend_8021x_cnt(ifp),
|
||||
msecs_to_jiffies(MAX_WAIT_FOR_8021X_TX));
|
||||
|
||||
WARN_ON(!err);
|
||||
|
@ -915,6 +974,16 @@ int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
|
|||
return !err;
|
||||
}
|
||||
|
||||
/*
|
||||
* return chip id and rev of the device encoded in u32.
|
||||
*/
|
||||
u32 brcmf_get_chip_info(struct brcmf_if *ifp)
|
||||
{
|
||||
struct brcmf_bus *bus = ifp->drvr->bus_if;
|
||||
|
||||
return bus->chip << 4 | bus->chiprev;
|
||||
}
|
||||
|
||||
static void brcmf_driver_init(struct work_struct *work)
|
||||
{
|
||||
brcmf_debugfs_init();
|
||||
|
|
|
@ -1096,7 +1096,6 @@ static int brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
|
|||
if (len > MAX_RX_DATASZ && rd->channel != SDPCM_CONTROL_CHANNEL &&
|
||||
type != BRCMF_SDIO_FT_SUPER) {
|
||||
brcmf_err("HW header length too long\n");
|
||||
bus->sdiodev->bus_if->dstats.rx_errors++;
|
||||
bus->sdcnt.rx_toolong++;
|
||||
brcmf_sdbrcm_rxfail(bus, false, false);
|
||||
rd->len = 0;
|
||||
|
@ -1298,7 +1297,6 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
|
|||
if (errcode < 0) {
|
||||
brcmf_err("glom read of %d bytes failed: %d\n",
|
||||
dlen, errcode);
|
||||
bus->sdiodev->bus_if->dstats.rx_errors++;
|
||||
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
if (bus->glomerr++ < 3) {
|
||||
|
@ -1478,7 +1476,6 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
|
|||
if ((rdlen + BRCMF_FIRSTREAD) > bus->sdiodev->bus_if->maxctl) {
|
||||
brcmf_err("%d-byte control read exceeds %d-byte buffer\n",
|
||||
rdlen, bus->sdiodev->bus_if->maxctl);
|
||||
bus->sdiodev->bus_if->dstats.rx_errors++;
|
||||
brcmf_sdbrcm_rxfail(bus, false, false);
|
||||
goto done;
|
||||
}
|
||||
|
@ -1486,7 +1483,6 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff)
|
|||
if ((len - doff) > bus->sdiodev->bus_if->maxctl) {
|
||||
brcmf_err("%d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n",
|
||||
len, len - doff, bus->sdiodev->bus_if->maxctl);
|
||||
bus->sdiodev->bus_if->dstats.rx_errors++;
|
||||
bus->sdcnt.rx_toolong++;
|
||||
brcmf_sdbrcm_rxfail(bus, false, false);
|
||||
goto done;
|
||||
|
@ -1634,7 +1630,6 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
|
|||
if (!pkt) {
|
||||
/* Give up on data, request rtx of events */
|
||||
brcmf_err("brcmu_pkt_buf_get_skb failed\n");
|
||||
bus->sdiodev->bus_if->dstats.rx_dropped++;
|
||||
brcmf_sdbrcm_rxfail(bus, false,
|
||||
RETRYCHAN(rd->channel));
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
|
@ -1652,7 +1647,6 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
|
|||
brcmf_err("read %d bytes from channel %d failed: %d\n",
|
||||
rd->len, rd->channel, sdret);
|
||||
brcmu_pkt_buf_free_skb(pkt);
|
||||
bus->sdiodev->bus_if->dstats.rx_errors++;
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
brcmf_sdbrcm_rxfail(bus, true,
|
||||
RETRYCHAN(rd->channel));
|
||||
|
@ -1940,10 +1934,6 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes)
|
|||
datalen = pkt->len - SDPCM_HDRLEN;
|
||||
|
||||
ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true);
|
||||
if (ret)
|
||||
bus->sdiodev->bus_if->dstats.tx_errors++;
|
||||
else
|
||||
bus->sdiodev->bus_if->dstats.tx_bytes += datalen;
|
||||
|
||||
/* In poll mode, need to check for other events */
|
||||
if (!bus->intr && cnt) {
|
||||
|
@ -1962,8 +1952,7 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes)
|
|||
}
|
||||
|
||||
/* Deflow-control stack if needed */
|
||||
if (bus->sdiodev->bus_if->drvr_up &&
|
||||
(bus->sdiodev->bus_if->state == BRCMF_BUS_DATA) &&
|
||||
if ((bus->sdiodev->bus_if->state == BRCMF_BUS_DATA) &&
|
||||
bus->txoff && (pktq_len(&bus->txq) < TXLOW)) {
|
||||
bus->txoff = false;
|
||||
brcmf_txflowblock(bus->sdiodev->dev, false);
|
||||
|
@ -2710,9 +2699,10 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
|
|||
* address of sdpcm_shared structure
|
||||
*/
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
|
||||
rv = brcmf_sdbrcm_membytes(bus, false, shaddr,
|
||||
(u8 *)&addr_le, 4);
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
|
@ -2731,10 +2721,8 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
|
|||
}
|
||||
|
||||
/* Read hndrte_shared structure */
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&sh_le,
|
||||
sizeof(struct sdpcm_shared_le));
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
|
@ -2836,14 +2824,12 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh,
|
|||
if ((sh->flags & SDPCM_SHARED_TRAP) == 0)
|
||||
return 0;
|
||||
|
||||
sdio_claim_host(bus->sdiodev->func[1]);
|
||||
error = brcmf_sdbrcm_membytes(bus, false, sh->trap_addr, (u8 *)&tr,
|
||||
sizeof(struct brcmf_trap_info));
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
nbytes = brcmf_sdio_dump_console(bus, sh, data, count);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
if (nbytes < 0)
|
||||
return nbytes;
|
||||
|
||||
|
@ -3308,9 +3294,6 @@ static int brcmf_sdbrcm_download_nvram(struct brcmf_sdio *bus)
|
|||
{
|
||||
int ret;
|
||||
|
||||
if (bus->sdiodev->bus_if->drvr_up)
|
||||
return -EISCONN;
|
||||
|
||||
ret = request_firmware(&bus->firmware, BRCMF_SDIO_NV_NAME,
|
||||
&bus->sdiodev->func[2]->dev);
|
||||
if (ret) {
|
||||
|
@ -3941,6 +3924,8 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
|
|||
/* Assign bus interface call back */
|
||||
bus->sdiodev->bus_if->dev = bus->sdiodev->dev;
|
||||
bus->sdiodev->bus_if->ops = &brcmf_sdio_bus_ops;
|
||||
bus->sdiodev->bus_if->chip = bus->ci->chip;
|
||||
bus->sdiodev->bus_if->chiprev = bus->ci->chiprev;
|
||||
|
||||
/* Attach to the brcmf/OS/network interface */
|
||||
ret = brcmf_attach(SDPCM_RESERVE, bus->sdiodev->dev);
|
||||
|
|
|
@ -189,24 +189,24 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
|
|||
return;
|
||||
}
|
||||
|
||||
ifp = drvr->iflist[ifevent->ifidx];
|
||||
ifp = drvr->iflist[ifevent->bssidx];
|
||||
|
||||
if (ifevent->action == BRCMF_E_IF_ADD) {
|
||||
brcmf_dbg(EVENT, "adding %s (%pM)\n", emsg->ifname,
|
||||
emsg->addr);
|
||||
ifp = brcmf_add_if(drvr, ifevent->ifidx, ifevent->bssidx,
|
||||
ifp = brcmf_add_if(drvr, ifevent->bssidx, ifevent->ifidx,
|
||||
emsg->ifname, emsg->addr);
|
||||
if (IS_ERR(ifp))
|
||||
return;
|
||||
|
||||
if (!drvr->fweh.evt_handler[BRCMF_E_IF])
|
||||
err = brcmf_net_attach(ifp);
|
||||
err = brcmf_net_attach(ifp, false);
|
||||
}
|
||||
|
||||
err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data);
|
||||
|
||||
if (ifevent->action == BRCMF_E_IF_DEL)
|
||||
brcmf_del_if(drvr, ifevent->ifidx);
|
||||
brcmf_del_if(drvr, ifevent->bssidx);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -250,8 +250,6 @@ static void brcmf_fweh_event_worker(struct work_struct *work)
|
|||
drvr = container_of(fweh, struct brcmf_pub, fweh);
|
||||
|
||||
while ((event = brcmf_fweh_dequeue_event(fweh))) {
|
||||
ifp = drvr->iflist[event->ifidx];
|
||||
|
||||
brcmf_dbg(EVENT, "event %s (%u) ifidx %u bsscfg %u addr %pM\n",
|
||||
brcmf_fweh_event_name(event->code), event->code,
|
||||
event->emsg.ifidx, event->emsg.bsscfgidx,
|
||||
|
@ -283,6 +281,7 @@ static void brcmf_fweh_event_worker(struct work_struct *work)
|
|||
goto event_free;
|
||||
}
|
||||
|
||||
ifp = drvr->iflist[emsg.bsscfgidx];
|
||||
err = brcmf_fweh_call_event_handler(ifp, event->code, &emsg,
|
||||
event->data);
|
||||
if (err) {
|
||||
|
|
|
@ -83,6 +83,7 @@ struct brcmf_event;
|
|||
BRCMF_ENUM_DEF(MULTICAST_DECODE_ERROR, 51) \
|
||||
BRCMF_ENUM_DEF(TRACE, 52) \
|
||||
BRCMF_ENUM_DEF(IF, 54) \
|
||||
BRCMF_ENUM_DEF(P2P_DISC_LISTEN_COMPLETE, 55) \
|
||||
BRCMF_ENUM_DEF(RSSI, 56) \
|
||||
BRCMF_ENUM_DEF(PFN_SCAN_COMPLETE, 57) \
|
||||
BRCMF_ENUM_DEF(EXTLOG_MSG, 58) \
|
||||
|
@ -96,8 +97,11 @@ struct brcmf_event;
|
|||
BRCMF_ENUM_DEF(DFS_AP_RESUME, 66) \
|
||||
BRCMF_ENUM_DEF(ESCAN_RESULT, 69) \
|
||||
BRCMF_ENUM_DEF(ACTION_FRAME_OFF_CHAN_COMPLETE, 70) \
|
||||
BRCMF_ENUM_DEF(PROBERESP_MSG, 71) \
|
||||
BRCMF_ENUM_DEF(P2P_PROBEREQ_MSG, 72) \
|
||||
BRCMF_ENUM_DEF(DCS_REQUEST, 73) \
|
||||
BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74)
|
||||
BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74) \
|
||||
BRCMF_ENUM_DEF(ACTION_FRAME_RX, 75)
|
||||
|
||||
#define BRCMF_ENUM_DEF(id, val) \
|
||||
BRCMF_E_##id = (val),
|
||||
|
|
|
@ -45,9 +45,10 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set)
|
|||
if (data != NULL)
|
||||
len = min_t(uint, len, BRCMF_DCMD_MAXLEN);
|
||||
if (set)
|
||||
err = brcmf_proto_cdc_set_dcmd(drvr, ifp->idx, cmd, data, len);
|
||||
err = brcmf_proto_cdc_set_dcmd(drvr, ifp->ifidx, cmd, data,
|
||||
len);
|
||||
else
|
||||
err = brcmf_proto_cdc_query_dcmd(drvr, ifp->idx, cmd, data,
|
||||
err = brcmf_proto_cdc_query_dcmd(drvr, ifp->ifidx, cmd, data,
|
||||
len);
|
||||
|
||||
if (err >= 0)
|
||||
|
@ -100,6 +101,7 @@ brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data)
|
|||
__le32 data_le = cpu_to_le32(data);
|
||||
|
||||
mutex_lock(&ifp->drvr->proto_block);
|
||||
brcmf_dbg(FIL, "cmd=%d, value=%d\n", cmd, data);
|
||||
err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), true);
|
||||
mutex_unlock(&ifp->drvr->proto_block);
|
||||
|
||||
|
@ -116,6 +118,7 @@ brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data)
|
|||
err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), false);
|
||||
mutex_unlock(&ifp->drvr->proto_block);
|
||||
*data = le32_to_cpu(data_le);
|
||||
brcmf_dbg(FIL, "cmd=%d, value=%d\n", cmd, *data);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* 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 FWIL_TYPES_H_
|
||||
#define FWIL_TYPES_H_
|
||||
|
||||
#include <linux/if_ether.h>
|
||||
|
||||
|
||||
#define BRCMF_FIL_ACTION_FRAME_SIZE 1800
|
||||
|
||||
|
||||
enum brcmf_fil_p2p_if_types {
|
||||
BRCMF_FIL_P2P_IF_CLIENT,
|
||||
BRCMF_FIL_P2P_IF_GO,
|
||||
BRCMF_FIL_P2P_IF_DYNBCN_GO,
|
||||
BRCMF_FIL_P2P_IF_DEV,
|
||||
};
|
||||
|
||||
struct brcmf_fil_p2p_if_le {
|
||||
u8 addr[ETH_ALEN];
|
||||
__le16 type;
|
||||
__le16 chspec;
|
||||
};
|
||||
|
||||
struct brcmf_fil_chan_info_le {
|
||||
__le32 hw_channel;
|
||||
__le32 target_channel;
|
||||
__le32 scan_channel;
|
||||
};
|
||||
|
||||
struct brcmf_fil_action_frame_le {
|
||||
u8 da[ETH_ALEN];
|
||||
__le16 len;
|
||||
__le32 packet_id;
|
||||
u8 data[BRCMF_FIL_ACTION_FRAME_SIZE];
|
||||
};
|
||||
|
||||
struct brcmf_fil_af_params_le {
|
||||
__le32 channel;
|
||||
__le32 dwell_time;
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 pad[2];
|
||||
struct brcmf_fil_action_frame_le action_frame;
|
||||
};
|
||||
|
||||
struct brcmf_fil_bss_enable_le {
|
||||
__le32 bsscfg_idx;
|
||||
__le32 enable;
|
||||
};
|
||||
|
||||
#endif /* FWIL_TYPES_H_ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
* 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 WL_CFGP2P_H_
|
||||
#define WL_CFGP2P_H_
|
||||
|
||||
#include <net/cfg80211.h>
|
||||
|
||||
struct brcmf_cfg80211_info;
|
||||
|
||||
/**
|
||||
* enum p2p_bss_type - different type of BSS configurations.
|
||||
*
|
||||
* @P2PAPI_BSSCFG_PRIMARY: maps to driver's primary bsscfg.
|
||||
* @P2PAPI_BSSCFG_DEVICE: maps to driver's P2P device discovery bsscfg.
|
||||
* @P2PAPI_BSSCFG_CONNECTION: maps to driver's P2P connection bsscfg.
|
||||
* @P2PAPI_BSSCFG_MAX: used for range checking.
|
||||
*/
|
||||
enum p2p_bss_type {
|
||||
P2PAPI_BSSCFG_PRIMARY, /* maps to driver's primary bsscfg */
|
||||
P2PAPI_BSSCFG_DEVICE, /* maps to driver's P2P device discovery bsscfg */
|
||||
P2PAPI_BSSCFG_CONNECTION, /* maps to driver's P2P connection bsscfg */
|
||||
P2PAPI_BSSCFG_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* struct p2p_bss - peer-to-peer bss related information.
|
||||
*
|
||||
* @vif: virtual interface of this P2P bss.
|
||||
* @private_data: TBD
|
||||
*/
|
||||
struct p2p_bss {
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
void *private_data;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum brcmf_p2p_status - P2P specific dongle status.
|
||||
*
|
||||
* @BRCMF_P2P_STATUS_IF_ADD: peer-to-peer vif add sent to dongle.
|
||||
* @BRCMF_P2P_STATUS_IF_DEL: NOT-USED?
|
||||
* @BRCMF_P2P_STATUS_IF_DELETING: peer-to-peer vif delete sent to dongle.
|
||||
* @BRCMF_P2P_STATUS_IF_CHANGING: peer-to-peer vif change sent to dongle.
|
||||
* @BRCMF_P2P_STATUS_IF_CHANGED: peer-to-peer vif change completed on dongle.
|
||||
* @BRCMF_P2P_STATUS_ACTION_TX_COMPLETED: action frame tx completed.
|
||||
* @BRCMF_P2P_STATUS_ACTION_TX_NOACK: action frame tx not acked.
|
||||
* @BRCMF_P2P_STATUS_GO_NEG_PHASE: P2P GO negotiation ongoing.
|
||||
* @BRCMF_P2P_STATUS_DISCOVER_LISTEN: P2P listen, remaining on channel.
|
||||
* @BRCMF_P2P_STATUS_SENDING_ACT_FRAME: In the process of sending action frame.
|
||||
* @BRCMF_P2P_STATUS_WAITING_NEXT_AF_LISTEN: extra listen time for af tx.
|
||||
* @BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME: waiting for action frame response.
|
||||
* @BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL: search channel for AF active.
|
||||
*/
|
||||
enum brcmf_p2p_status {
|
||||
BRCMF_P2P_STATUS_ENABLED,
|
||||
BRCMF_P2P_STATUS_IF_ADD,
|
||||
BRCMF_P2P_STATUS_IF_DEL,
|
||||
BRCMF_P2P_STATUS_IF_DELETING,
|
||||
BRCMF_P2P_STATUS_IF_CHANGING,
|
||||
BRCMF_P2P_STATUS_IF_CHANGED,
|
||||
BRCMF_P2P_STATUS_ACTION_TX_COMPLETED,
|
||||
BRCMF_P2P_STATUS_ACTION_TX_NOACK,
|
||||
BRCMF_P2P_STATUS_GO_NEG_PHASE,
|
||||
BRCMF_P2P_STATUS_DISCOVER_LISTEN,
|
||||
BRCMF_P2P_STATUS_SENDING_ACT_FRAME,
|
||||
BRCMF_P2P_STATUS_WAITING_NEXT_AF_LISTEN,
|
||||
BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME,
|
||||
BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL
|
||||
};
|
||||
|
||||
/**
|
||||
* struct afx_hdl - action frame off channel storage.
|
||||
*
|
||||
* @afx_work: worker thread for searching channel
|
||||
* @act_frm_scan: thread synchronizing struct.
|
||||
* @is_active: channel searching active.
|
||||
* @peer_chan: current channel.
|
||||
* @is_listen: sets mode for afx worker.
|
||||
* @my_listen_chan: this peers listen channel.
|
||||
* @peer_listen_chan: remote peers listen channel.
|
||||
* @tx_dst_addr: mac address where tx af should be sent to.
|
||||
*/
|
||||
struct afx_hdl {
|
||||
struct work_struct afx_work;
|
||||
struct completion act_frm_scan;
|
||||
bool is_active;
|
||||
s32 peer_chan;
|
||||
bool is_listen;
|
||||
u16 my_listen_chan;
|
||||
u16 peer_listen_chan;
|
||||
u8 tx_dst_addr[ETH_ALEN];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_p2p_info - p2p specific driver information.
|
||||
*
|
||||
* @cfg: driver private data for cfg80211 interface.
|
||||
* @status: status of P2P (see enum brcmf_p2p_status).
|
||||
* @dev_addr: P2P device address.
|
||||
* @int_addr: P2P interface address.
|
||||
* @bss_idx: informate for P2P bss types.
|
||||
* @listen_timer: timer for @WL_P2P_DISC_ST_LISTEN discover state.
|
||||
* @ssid: ssid for P2P GO.
|
||||
* @listen_channel: channel for @WL_P2P_DISC_ST_LISTEN discover state.
|
||||
* @remain_on_channel: contains copy of struct used by cfg80211.
|
||||
* @remain_on_channel_cookie: cookie counter for remain on channel cmd
|
||||
* @next_af_subtype: expected action frame subtype.
|
||||
* @send_af_done: indication that action frame tx is complete.
|
||||
* @afx_hdl: action frame search handler info.
|
||||
* @af_sent_channel: channel action frame is sent.
|
||||
* @af_tx_sent_jiffies: jiffies time when af tx was transmitted.
|
||||
* @wait_next_af: thread synchronizing struct.
|
||||
* @gon_req_action: about to send go negotiation requets frame.
|
||||
* @block_gon_req_tx: drop tx go negotiation requets frame.
|
||||
*/
|
||||
struct brcmf_p2p_info {
|
||||
struct brcmf_cfg80211_info *cfg;
|
||||
unsigned long status;
|
||||
u8 dev_addr[ETH_ALEN];
|
||||
u8 int_addr[ETH_ALEN];
|
||||
struct p2p_bss bss_idx[P2PAPI_BSSCFG_MAX];
|
||||
struct timer_list listen_timer;
|
||||
struct brcmf_ssid ssid;
|
||||
u8 listen_channel;
|
||||
struct ieee80211_channel remain_on_channel;
|
||||
u32 remain_on_channel_cookie;
|
||||
u8 next_af_subtype;
|
||||
struct completion send_af_done;
|
||||
struct afx_hdl afx_hdl;
|
||||
u32 af_sent_channel;
|
||||
unsigned long af_tx_sent_jiffies;
|
||||
struct completion wait_next_af;
|
||||
bool gon_req_action;
|
||||
bool block_gon_req_tx;
|
||||
};
|
||||
|
||||
s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg);
|
||||
void brcmf_p2p_detach(struct brcmf_p2p_info *p2p);
|
||||
struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name,
|
||||
enum nl80211_iftype type, u32 *flags,
|
||||
struct vif_params *params);
|
||||
int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev);
|
||||
int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg,
|
||||
enum brcmf_fil_p2p_if_types if_type);
|
||||
int brcmf_p2p_start_device(struct wiphy *wiphy, struct wireless_dev *wdev);
|
||||
void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev);
|
||||
int brcmf_p2p_scan_prep(struct wiphy *wiphy,
|
||||
struct cfg80211_scan_request *request,
|
||||
struct brcmf_cfg80211_vif *vif);
|
||||
int brcmf_p2p_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
struct ieee80211_channel *channel,
|
||||
unsigned int duration, u64 *cookie);
|
||||
int brcmf_p2p_notify_listen_complete(struct brcmf_if *ifp,
|
||||
const struct brcmf_event_msg *e,
|
||||
void *data);
|
||||
void brcmf_p2p_cancel_remain_on_channel(struct brcmf_if *ifp);
|
||||
int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp,
|
||||
const struct brcmf_event_msg *e,
|
||||
void *data);
|
||||
int brcmf_p2p_notify_action_tx_complete(struct brcmf_if *ifp,
|
||||
const struct brcmf_event_msg *e,
|
||||
void *data);
|
||||
bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg,
|
||||
struct net_device *ndev,
|
||||
struct brcmf_fil_af_params_le *af_params);
|
||||
bool brcmf_p2p_scan_finding_common_channel(struct brcmf_cfg80211_info *cfg,
|
||||
struct brcmf_bss_info_le *bi);
|
||||
s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
|
||||
const struct brcmf_event_msg *e,
|
||||
void *data);
|
||||
#endif /* WL_CFGP2P_H_ */
|
|
@ -421,10 +421,6 @@ static void brcmf_usb_tx_complete(struct urb *urb)
|
|||
brcmf_dbg(USB, "Enter, urb->status=%d, skb=%p\n", urb->status,
|
||||
req->skb);
|
||||
brcmf_usb_del_fromq(devinfo, req);
|
||||
if (urb->status == 0)
|
||||
devinfo->bus_pub.bus->dstats.tx_packets++;
|
||||
else
|
||||
devinfo->bus_pub.bus->dstats.tx_errors++;
|
||||
|
||||
brcmf_txcomplete(devinfo->dev, req->skb, urb->status == 0);
|
||||
|
||||
|
@ -451,10 +447,7 @@ static void brcmf_usb_rx_complete(struct urb *urb)
|
|||
req->skb = NULL;
|
||||
|
||||
/* zero lenght packets indicate usb "failure". Do not refill */
|
||||
if (urb->status == 0 && urb->actual_length) {
|
||||
devinfo->bus_pub.bus->dstats.rx_packets++;
|
||||
} else {
|
||||
devinfo->bus_pub.bus->dstats.rx_errors++;
|
||||
if (urb->status != 0 || !urb->actual_length) {
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
|
||||
return;
|
||||
|
@ -1257,6 +1250,8 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
|
|||
bus->bus_priv.usb = bus_pub;
|
||||
dev_set_drvdata(dev, bus);
|
||||
bus->ops = &brcmf_usb_bus_ops;
|
||||
bus->chip = bus_pub->devid;
|
||||
bus->chiprev = bus_pub->chiprev;
|
||||
|
||||
/* Attach to the common driver interface */
|
||||
ret = brcmf_attach(0, dev);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -41,6 +41,38 @@
|
|||
#define WL_AUTH_SHARED_KEY 1 /* d11 shared authentication */
|
||||
#define IE_MAX_LEN 512
|
||||
|
||||
/* IE TLV processing */
|
||||
#define TLV_LEN_OFF 1 /* length offset */
|
||||
#define TLV_HDR_LEN 2 /* header length */
|
||||
#define TLV_BODY_OFF 2 /* body offset */
|
||||
#define TLV_OUI_LEN 3 /* oui id length */
|
||||
|
||||
/* 802.11 Mgmt Packet flags */
|
||||
#define BRCMF_VNDR_IE_BEACON_FLAG 0x1
|
||||
#define BRCMF_VNDR_IE_PRBRSP_FLAG 0x2
|
||||
#define BRCMF_VNDR_IE_ASSOCRSP_FLAG 0x4
|
||||
#define BRCMF_VNDR_IE_AUTHRSP_FLAG 0x8
|
||||
#define BRCMF_VNDR_IE_PRBREQ_FLAG 0x10
|
||||
#define BRCMF_VNDR_IE_ASSOCREQ_FLAG 0x20
|
||||
/* vendor IE in IW advertisement protocol ID field */
|
||||
#define BRCMF_VNDR_IE_IWAPID_FLAG 0x40
|
||||
/* allow custom IE id */
|
||||
#define BRCMF_VNDR_IE_CUSTOM_FLAG 0x100
|
||||
|
||||
/* P2P Action Frames flags (spec ordered) */
|
||||
#define BRCMF_VNDR_IE_GONREQ_FLAG 0x001000
|
||||
#define BRCMF_VNDR_IE_GONRSP_FLAG 0x002000
|
||||
#define BRCMF_VNDR_IE_GONCFM_FLAG 0x004000
|
||||
#define BRCMF_VNDR_IE_INVREQ_FLAG 0x008000
|
||||
#define BRCMF_VNDR_IE_INVRSP_FLAG 0x010000
|
||||
#define BRCMF_VNDR_IE_DISREQ_FLAG 0x020000
|
||||
#define BRCMF_VNDR_IE_DISRSP_FLAG 0x040000
|
||||
#define BRCMF_VNDR_IE_PRDREQ_FLAG 0x080000
|
||||
#define BRCMF_VNDR_IE_PRDRSP_FLAG 0x100000
|
||||
|
||||
#define BRCMF_VNDR_IE_P2PAF_SHIFT 12
|
||||
|
||||
|
||||
/**
|
||||
* enum brcmf_scan_status - dongle scan status
|
||||
*
|
||||
|
@ -52,11 +84,19 @@ enum brcmf_scan_status {
|
|||
BRCMF_SCAN_STATUS_ABORT,
|
||||
};
|
||||
|
||||
/* wi-fi mode */
|
||||
/**
|
||||
* enum wl_mode - driver mode of virtual interface.
|
||||
*
|
||||
* @WL_MODE_BSS: connects to BSS.
|
||||
* @WL_MODE_IBSS: operate as ad-hoc.
|
||||
* @WL_MODE_AP: operate as access-point.
|
||||
* @WL_MODE_P2P: provide P2P discovery.
|
||||
*/
|
||||
enum wl_mode {
|
||||
WL_MODE_BSS,
|
||||
WL_MODE_IBSS,
|
||||
WL_MODE_AP
|
||||
WL_MODE_AP,
|
||||
WL_MODE_P2P
|
||||
};
|
||||
|
||||
/* dongle configuration */
|
||||
|
@ -108,6 +148,7 @@ struct brcmf_cfg80211_profile {
|
|||
* @BRCMF_VIF_STATUS_READY: ready for operation.
|
||||
* @BRCMF_VIF_STATUS_CONNECTING: connect/join in progress.
|
||||
* @BRCMF_VIF_STATUS_CONNECTED: connected/joined succesfully.
|
||||
* @BRCMF_VIF_STATUS_DISCONNECTING: disconnect/disable in progress.
|
||||
* @BRCMF_VIF_STATUS_AP_CREATING: interface configured for AP operation.
|
||||
* @BRCMF_VIF_STATUS_AP_CREATED: AP operation started.
|
||||
*/
|
||||
|
@ -115,6 +156,7 @@ enum brcmf_vif_status {
|
|||
BRCMF_VIF_STATUS_READY,
|
||||
BRCMF_VIF_STATUS_CONNECTING,
|
||||
BRCMF_VIF_STATUS_CONNECTED,
|
||||
BRCMF_VIF_STATUS_DISCONNECTING,
|
||||
BRCMF_VIF_STATUS_AP_CREATING,
|
||||
BRCMF_VIF_STATUS_AP_CREATED
|
||||
};
|
||||
|
@ -122,16 +164,22 @@ enum brcmf_vif_status {
|
|||
/**
|
||||
* struct vif_saved_ie - holds saved IEs for a virtual interface.
|
||||
*
|
||||
* @probe_req_ie: IE info for probe request.
|
||||
* @probe_res_ie: IE info for probe response.
|
||||
* @beacon_ie: IE info for beacon frame.
|
||||
* @probe_req_ie_len: IE info length for probe request.
|
||||
* @probe_res_ie_len: IE info length for probe response.
|
||||
* @beacon_ie_len: IE info length for beacon frame.
|
||||
*/
|
||||
struct vif_saved_ie {
|
||||
u8 probe_req_ie[IE_MAX_LEN];
|
||||
u8 probe_res_ie[IE_MAX_LEN];
|
||||
u8 beacon_ie[IE_MAX_LEN];
|
||||
u8 assoc_req_ie[IE_MAX_LEN];
|
||||
u32 probe_req_ie_len;
|
||||
u32 probe_res_ie_len;
|
||||
u32 beacon_ie_len;
|
||||
u32 assoc_req_ie_len;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -145,6 +193,7 @@ struct vif_saved_ie {
|
|||
* @sme_state: SME state using enum brcmf_vif_status bits.
|
||||
* @pm_block: power-management blocked.
|
||||
* @list: linked list.
|
||||
* @mgmt_rx_reg: registered rx mgmt frame types.
|
||||
*/
|
||||
struct brcmf_cfg80211_vif {
|
||||
struct brcmf_if *ifp;
|
||||
|
@ -156,6 +205,7 @@ struct brcmf_cfg80211_vif {
|
|||
bool pm_block;
|
||||
struct vif_saved_ie saved_ie;
|
||||
struct list_head list;
|
||||
u16 mgmt_rx_reg;
|
||||
};
|
||||
|
||||
/* association inform */
|
||||
|
@ -189,6 +239,9 @@ struct escan_info {
|
|||
u8 escan_buf[WL_ESCAN_BUF_SIZE];
|
||||
struct wiphy *wiphy;
|
||||
struct net_device *ndev;
|
||||
s32 (*run)(struct brcmf_cfg80211_info *cfg,
|
||||
struct net_device *ndev,
|
||||
struct cfg80211_scan_request *request, u16 action);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -272,11 +325,28 @@ struct brcmf_pno_scanresults_le {
|
|||
__le32 count;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_cfg80211_vif_event - virtual interface event information.
|
||||
*
|
||||
* @vif_wq: waitqueue awaiting interface event from firmware.
|
||||
* @vif_event_lock: protects other members in this structure.
|
||||
* @vif_complete: completion for net attach.
|
||||
* @action: either add, change, or delete.
|
||||
* @vif: virtual interface object related to the event.
|
||||
*/
|
||||
struct brcmf_cfg80211_vif_event {
|
||||
wait_queue_head_t vif_wq;
|
||||
struct mutex vif_event_lock;
|
||||
u8 action;
|
||||
struct brcmf_cfg80211_vif *vif;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_cfg80211_info - dongle private data of cfg80211 interface
|
||||
*
|
||||
* @wiphy: wiphy object for cfg80211 interface.
|
||||
* @conf: dongle configuration.
|
||||
* @p2p: peer-to-peer specific information.
|
||||
* @scan_request: cfg80211 scan request object.
|
||||
* @usr_sync: mainly for dongle up/down synchronization.
|
||||
* @bss_list: bss_list holding scanned ap information.
|
||||
|
@ -304,10 +374,12 @@ struct brcmf_pno_scanresults_le {
|
|||
* @escan_ioctl_buf: dongle command buffer for escan commands.
|
||||
* @vif_list: linked list of vif instances.
|
||||
* @vif_cnt: number of vif instances.
|
||||
* @vif_event: vif event signalling.
|
||||
*/
|
||||
struct brcmf_cfg80211_info {
|
||||
struct wiphy *wiphy;
|
||||
struct brcmf_cfg80211_conf *conf;
|
||||
struct brcmf_p2p_info p2p;
|
||||
struct cfg80211_scan_request *scan_request;
|
||||
struct mutex usr_sync;
|
||||
struct brcmf_scan_results *bss_list;
|
||||
|
@ -335,6 +407,21 @@ struct brcmf_cfg80211_info {
|
|||
u8 *escan_ioctl_buf;
|
||||
struct list_head vif_list;
|
||||
u8 vif_cnt;
|
||||
struct brcmf_cfg80211_vif_event vif_event;
|
||||
struct completion vif_disabled;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct brcmf_tlv - tag_ID/length/value_buffer tuple.
|
||||
*
|
||||
* @id: tag identifier.
|
||||
* @len: number of bytes in value buffer.
|
||||
* @data: value buffer.
|
||||
*/
|
||||
struct brcmf_tlv {
|
||||
u8 id;
|
||||
u8 len;
|
||||
u8 data[1];
|
||||
};
|
||||
|
||||
static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_info *cfg)
|
||||
|
@ -389,4 +476,26 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg);
|
|||
s32 brcmf_cfg80211_up(struct net_device *ndev);
|
||||
s32 brcmf_cfg80211_down(struct net_device *ndev);
|
||||
|
||||
struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
|
||||
enum nl80211_iftype type,
|
||||
bool pm_block);
|
||||
void brcmf_free_vif(struct brcmf_cfg80211_vif *vif);
|
||||
|
||||
s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
|
||||
const u8 *vndr_ie_buf, u32 vndr_ie_len);
|
||||
s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif);
|
||||
struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key);
|
||||
u16 channel_to_chanspec(struct ieee80211_channel *ch);
|
||||
u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state);
|
||||
void brcmf_cfg80211_arm_vif_event(struct brcmf_cfg80211_info *cfg,
|
||||
struct brcmf_cfg80211_vif *vif);
|
||||
bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg);
|
||||
int brcmf_cfg80211_wait_vif_event_timeout(struct brcmf_cfg80211_info *cfg,
|
||||
u8 action, ulong timeout);
|
||||
s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
|
||||
struct net_device *ndev,
|
||||
bool aborted, bool fw_abort);
|
||||
void brcmf_set_mpc(struct net_device *ndev, int mpc);
|
||||
void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg);
|
||||
|
||||
#endif /* _wl_cfg80211_h_ */
|
||||
|
|
|
@ -101,8 +101,6 @@
|
|||
#define DOT11_RTS_LEN 16
|
||||
#define DOT11_CTS_LEN 10
|
||||
#define DOT11_BA_BITMAP_LEN 128
|
||||
#define DOT11_MIN_BEACON_PERIOD 1
|
||||
#define DOT11_MAX_BEACON_PERIOD 0xFFFF
|
||||
#define DOT11_MAXNUMFRAGS 16
|
||||
#define DOT11_MAX_FRAG_LEN 2346
|
||||
|
||||
|
@ -5555,8 +5553,7 @@ int brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcm_rateset *rs)
|
|||
|
||||
int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period)
|
||||
{
|
||||
if (period < DOT11_MIN_BEACON_PERIOD ||
|
||||
period > DOT11_MAX_BEACON_PERIOD)
|
||||
if (period == 0)
|
||||
return -EINVAL;
|
||||
|
||||
wlc->default_bss->beacon_period = period;
|
||||
|
@ -7408,9 +7405,13 @@ brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc,
|
|||
struct brcms_bss_cfg *cfg,
|
||||
bool suspend)
|
||||
{
|
||||
u16 prb_resp[BCN_TMPL_LEN / 2];
|
||||
u16 *prb_resp;
|
||||
int len = BCN_TMPL_LEN;
|
||||
|
||||
prb_resp = kmalloc(BCN_TMPL_LEN, GFP_ATOMIC);
|
||||
if (!prb_resp)
|
||||
return;
|
||||
|
||||
/*
|
||||
* write the probe response to hardware, or save in
|
||||
* the config structure
|
||||
|
@ -7444,6 +7445,8 @@ brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc,
|
|||
|
||||
if (suspend)
|
||||
brcms_c_enable_mac(wlc);
|
||||
|
||||
kfree(prb_resp);
|
||||
}
|
||||
|
||||
void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend)
|
||||
|
|
|
@ -1001,12 +1001,12 @@ il3945_rx_allocate(struct il_priv *il, gfp_t priority)
|
|||
struct list_head *element;
|
||||
struct il_rx_buf *rxb;
|
||||
struct page *page;
|
||||
dma_addr_t page_dma;
|
||||
unsigned long flags;
|
||||
gfp_t gfp_mask = priority;
|
||||
|
||||
while (1) {
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
|
||||
if (list_empty(&rxq->rx_used)) {
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
return;
|
||||
|
@ -1035,26 +1035,34 @@ il3945_rx_allocate(struct il_priv *il, gfp_t priority)
|
|||
break;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
if (list_empty(&rxq->rx_used)) {
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
__free_pages(page, il->hw_params.rx_page_order);
|
||||
return;
|
||||
}
|
||||
element = rxq->rx_used.next;
|
||||
rxb = list_entry(element, struct il_rx_buf, list);
|
||||
list_del(element);
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
|
||||
rxb->page = page;
|
||||
/* Get physical address of RB/SKB */
|
||||
rxb->page_dma =
|
||||
page_dma =
|
||||
pci_map_page(il->pci_dev, page, 0,
|
||||
PAGE_SIZE << il->hw_params.rx_page_order,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
|
||||
if (unlikely(pci_dma_mapping_error(il->pci_dev, page_dma))) {
|
||||
__free_pages(page, il->hw_params.rx_page_order);
|
||||
break;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
|
||||
if (list_empty(&rxq->rx_used)) {
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
pci_unmap_page(il->pci_dev, page_dma,
|
||||
PAGE_SIZE << il->hw_params.rx_page_order,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
__free_pages(page, il->hw_params.rx_page_order);
|
||||
return;
|
||||
}
|
||||
|
||||
element = rxq->rx_used.next;
|
||||
rxb = list_entry(element, struct il_rx_buf, list);
|
||||
list_del(element);
|
||||
|
||||
rxb->page = page;
|
||||
rxb->page_dma = page_dma;
|
||||
list_add_tail(&rxb->list, &rxq->rx_free);
|
||||
rxq->free_count++;
|
||||
il->alloc_rxb_page++;
|
||||
|
@ -1284,8 +1292,15 @@ il3945_rx_handle(struct il_priv *il)
|
|||
pci_map_page(il->pci_dev, rxb->page, 0,
|
||||
PAGE_SIZE << il->hw_params.
|
||||
rx_page_order, PCI_DMA_FROMDEVICE);
|
||||
list_add_tail(&rxb->list, &rxq->rx_free);
|
||||
rxq->free_count++;
|
||||
if (unlikely(pci_dma_mapping_error(il->pci_dev,
|
||||
rxb->page_dma))) {
|
||||
__il_free_pages(il, rxb->page);
|
||||
rxb->page = NULL;
|
||||
list_add_tail(&rxb->list, &rxq->rx_used);
|
||||
} else {
|
||||
list_add_tail(&rxb->list, &rxq->rx_free);
|
||||
rxq->free_count++;
|
||||
}
|
||||
} else
|
||||
list_add_tail(&rxb->list, &rxq->rx_used);
|
||||
|
||||
|
|
|
@ -319,6 +319,7 @@ il4965_rx_allocate(struct il_priv *il, gfp_t priority)
|
|||
struct list_head *element;
|
||||
struct il_rx_buf *rxb;
|
||||
struct page *page;
|
||||
dma_addr_t page_dma;
|
||||
unsigned long flags;
|
||||
gfp_t gfp_mask = priority;
|
||||
|
||||
|
@ -356,33 +357,35 @@ il4965_rx_allocate(struct il_priv *il, gfp_t priority)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Get physical address of the RB */
|
||||
page_dma =
|
||||
pci_map_page(il->pci_dev, page, 0,
|
||||
PAGE_SIZE << il->hw_params.rx_page_order,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
if (unlikely(pci_dma_mapping_error(il->pci_dev, page_dma))) {
|
||||
__free_pages(page, il->hw_params.rx_page_order);
|
||||
break;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
|
||||
if (list_empty(&rxq->rx_used)) {
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
pci_unmap_page(il->pci_dev, page_dma,
|
||||
PAGE_SIZE << il->hw_params.rx_page_order,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
__free_pages(page, il->hw_params.rx_page_order);
|
||||
return;
|
||||
}
|
||||
|
||||
element = rxq->rx_used.next;
|
||||
rxb = list_entry(element, struct il_rx_buf, list);
|
||||
list_del(element);
|
||||
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
|
||||
BUG_ON(rxb->page);
|
||||
|
||||
rxb->page = page;
|
||||
/* Get physical address of the RB */
|
||||
rxb->page_dma =
|
||||
pci_map_page(il->pci_dev, page, 0,
|
||||
PAGE_SIZE << il->hw_params.rx_page_order,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
/* dma address must be no more than 36 bits */
|
||||
BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
|
||||
/* and also 256 byte aligned! */
|
||||
BUG_ON(rxb->page_dma & DMA_BIT_MASK(8));
|
||||
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
|
||||
rxb->page_dma = page_dma;
|
||||
list_add_tail(&rxb->list, &rxq->rx_free);
|
||||
rxq->free_count++;
|
||||
il->alloc_rxb_page++;
|
||||
|
@ -725,6 +728,16 @@ il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb)
|
|||
if (rate_n_flags & RATE_MCS_SGI_MSK)
|
||||
rx_status.flag |= RX_FLAG_SHORT_GI;
|
||||
|
||||
if (phy_res->phy_flags & RX_RES_PHY_FLAGS_AGG_MSK) {
|
||||
/* We know which subframes of an A-MPDU belong
|
||||
* together since we get a single PHY response
|
||||
* from the firmware for all of them.
|
||||
*/
|
||||
|
||||
rx_status.flag |= RX_FLAG_AMPDU_DETAILS;
|
||||
rx_status.ampdu_reference = il->_4965.ampdu_ref;
|
||||
}
|
||||
|
||||
il4965_pass_packet_to_mac80211(il, header, len, ampdu_status, rxb,
|
||||
&rx_status);
|
||||
}
|
||||
|
@ -736,6 +749,7 @@ il4965_hdl_rx_phy(struct il_priv *il, struct il_rx_buf *rxb)
|
|||
{
|
||||
struct il_rx_pkt *pkt = rxb_addr(rxb);
|
||||
il->_4965.last_phy_res_valid = true;
|
||||
il->_4965.ampdu_ref++;
|
||||
memcpy(&il->_4965.last_phy_res, pkt->u.raw,
|
||||
sizeof(struct il_rx_phy_res));
|
||||
}
|
||||
|
@ -4281,8 +4295,16 @@ il4965_rx_handle(struct il_priv *il)
|
|||
pci_map_page(il->pci_dev, rxb->page, 0,
|
||||
PAGE_SIZE << il->hw_params.
|
||||
rx_page_order, PCI_DMA_FROMDEVICE);
|
||||
list_add_tail(&rxb->list, &rxq->rx_free);
|
||||
rxq->free_count++;
|
||||
|
||||
if (unlikely(pci_dma_mapping_error(il->pci_dev,
|
||||
rxb->page_dma))) {
|
||||
__il_free_pages(il, rxb->page);
|
||||
rxb->page = NULL;
|
||||
list_add_tail(&rxb->list, &rxq->rx_used);
|
||||
} else {
|
||||
list_add_tail(&rxb->list, &rxq->rx_free);
|
||||
rxq->free_count++;
|
||||
}
|
||||
} else
|
||||
list_add_tail(&rxb->list, &rxq->rx_used);
|
||||
|
||||
|
@ -5711,7 +5733,7 @@ il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length)
|
|||
/* Tell mac80211 our characteristics */
|
||||
hw->flags =
|
||||
IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION |
|
||||
IEEE80211_HW_NEED_DTIM_PERIOD | IEEE80211_HW_SPECTRUM_MGMT |
|
||||
IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC | IEEE80211_HW_SPECTRUM_MGMT |
|
||||
IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_SUPPORTS_PS |
|
||||
IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
|
||||
if (il->cfg->sku & IL_SKU_N)
|
||||
|
|
|
@ -1136,6 +1136,7 @@ struct il_wep_cmd {
|
|||
#define RX_RES_PHY_FLAGS_NARROW_BAND_MSK cpu_to_le16(1 << 3)
|
||||
#define RX_RES_PHY_FLAGS_ANTENNA_MSK 0x70
|
||||
#define RX_RES_PHY_FLAGS_ANTENNA_POS 4
|
||||
#define RX_RES_PHY_FLAGS_AGG_MSK cpu_to_le16(1 << 7)
|
||||
|
||||
#define RX_RES_STATUS_SEC_TYPE_MSK (0x7 << 8)
|
||||
#define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8)
|
||||
|
|
|
@ -1356,6 +1356,7 @@ struct il_priv {
|
|||
struct {
|
||||
struct il_rx_phy_res last_phy_res;
|
||||
bool last_phy_res_valid;
|
||||
u32 ampdu_ref;
|
||||
|
||||
struct completion firmware_loading_complete;
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
|
|||
/* Tell mac80211 our characteristics */
|
||||
hw->flags = IEEE80211_HW_SIGNAL_DBM |
|
||||
IEEE80211_HW_AMPDU_AGGREGATION |
|
||||
IEEE80211_HW_NEED_DTIM_PERIOD |
|
||||
IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC |
|
||||
IEEE80211_HW_SPECTRUM_MGMT |
|
||||
IEEE80211_HW_REPORTS_TX_ACK_STATUS |
|
||||
IEEE80211_HW_QUEUE_CONTROL |
|
||||
|
|
|
@ -114,7 +114,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
|||
IEEE80211_HW_QUEUE_CONTROL |
|
||||
IEEE80211_HW_WANT_MONITOR_VIF |
|
||||
IEEE80211_HW_SCAN_WHILE_IDLE |
|
||||
IEEE80211_HW_NEED_DTIM_PERIOD |
|
||||
IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC |
|
||||
IEEE80211_HW_SUPPORTS_PS |
|
||||
IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
|
||||
IEEE80211_HW_AMPDU_AGGREGATION;
|
||||
|
|
|
@ -399,45 +399,6 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv,
|
|||
return ret_len;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function reconfigures the Tx buffer size in firmware.
|
||||
*
|
||||
* This function prepares a firmware command and issues it, if
|
||||
* the current Tx buffer size is different from the one requested.
|
||||
* Maximum configurable Tx buffer size is limited by the HT capability
|
||||
* field value.
|
||||
*/
|
||||
void
|
||||
mwifiex_cfg_tx_buf(struct mwifiex_private *priv,
|
||||
struct mwifiex_bssdescriptor *bss_desc)
|
||||
{
|
||||
u16 max_amsdu = MWIFIEX_TX_DATA_BUF_SIZE_2K;
|
||||
u16 tx_buf, curr_tx_buf_size = 0;
|
||||
|
||||
if (bss_desc->bcn_ht_cap) {
|
||||
if (le16_to_cpu(bss_desc->bcn_ht_cap->cap_info) &
|
||||
IEEE80211_HT_CAP_MAX_AMSDU)
|
||||
max_amsdu = MWIFIEX_TX_DATA_BUF_SIZE_8K;
|
||||
else
|
||||
max_amsdu = MWIFIEX_TX_DATA_BUF_SIZE_4K;
|
||||
}
|
||||
|
||||
tx_buf = min(priv->adapter->max_tx_buf_size, max_amsdu);
|
||||
|
||||
dev_dbg(priv->adapter->dev, "info: max_amsdu=%d, max_tx_buf=%d\n",
|
||||
max_amsdu, priv->adapter->max_tx_buf_size);
|
||||
|
||||
if (priv->adapter->curr_tx_buf_size <= MWIFIEX_TX_DATA_BUF_SIZE_2K)
|
||||
curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K;
|
||||
else if (priv->adapter->curr_tx_buf_size <= MWIFIEX_TX_DATA_BUF_SIZE_4K)
|
||||
curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K;
|
||||
else if (priv->adapter->curr_tx_buf_size <= MWIFIEX_TX_DATA_BUF_SIZE_8K)
|
||||
curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_8K;
|
||||
if (curr_tx_buf_size != tx_buf)
|
||||
mwifiex_send_cmd_async(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF,
|
||||
HostCmd_ACT_GEN_SET, 0, &tx_buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function checks if the given pointer is valid entry of
|
||||
* Tx BA Stream table.
|
||||
|
|
|
@ -34,8 +34,6 @@ int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, u16 cmd_action,
|
|||
int mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv,
|
||||
struct mwifiex_bssdescriptor *bss_desc,
|
||||
u8 **buffer);
|
||||
void mwifiex_cfg_tx_buf(struct mwifiex_private *priv,
|
||||
struct mwifiex_bssdescriptor *bss_desc);
|
||||
void mwifiex_fill_cap_info(struct mwifiex_private *, u8 radio_type,
|
||||
struct mwifiex_ie_types_htcap *);
|
||||
int mwifiex_set_get_11n_htcap_cfg(struct mwifiex_private *priv,
|
||||
|
|
|
@ -20,12 +20,12 @@ config MWIFIEX_SDIO
|
|||
mwifiex_sdio.
|
||||
|
||||
config MWIFIEX_PCIE
|
||||
tristate "Marvell WiFi-Ex Driver for PCIE 8766"
|
||||
tristate "Marvell WiFi-Ex Driver for PCIE 8766/8897"
|
||||
depends on MWIFIEX && PCI
|
||||
select FW_LOADER
|
||||
---help---
|
||||
This adds support for wireless adapters based on Marvell
|
||||
8766 chipset with PCIe interface.
|
||||
8766/8897 chipsets with PCIe interface.
|
||||
|
||||
If you choose to build it as a module, it will be called
|
||||
mwifiex_pcie.
|
||||
|
|
|
@ -121,7 +121,6 @@ info
|
|||
wmm_ac_vi = <number of packets sent to device from WMM AcVi queue>
|
||||
wmm_ac_be = <number of packets sent to device from WMM AcBE queue>
|
||||
wmm_ac_bk = <number of packets sent to device from WMM AcBK queue>
|
||||
max_tx_buf_size = <maximum Tx buffer size>
|
||||
tx_buf_size = <current Tx buffer size>
|
||||
curr_tx_buf_size = <current Tx buffer size>
|
||||
ps_mode = <0/1, CAM mode/PS mode>
|
||||
|
|
|
@ -58,8 +58,6 @@ static struct mwifiex_debug_data items[] = {
|
|||
item_addr(packets_out[WMM_AC_BE]), 1},
|
||||
{"wmm_ac_bk", item_size(packets_out[WMM_AC_BK]),
|
||||
item_addr(packets_out[WMM_AC_BK]), 1},
|
||||
{"max_tx_buf_size", item_size(max_tx_buf_size),
|
||||
item_addr(max_tx_buf_size), 1},
|
||||
{"tx_buf_size", item_size(tx_buf_size),
|
||||
item_addr(tx_buf_size), 1},
|
||||
{"curr_tx_buf_size", item_size(curr_tx_buf_size),
|
||||
|
|
|
@ -317,7 +317,6 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
|
|||
|
||||
adapter->pm_wakeup_fw_try = false;
|
||||
|
||||
adapter->max_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K;
|
||||
adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K;
|
||||
adapter->curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K;
|
||||
|
||||
|
|
|
@ -178,7 +178,6 @@ struct mwifiex_ds_tx_ba_stream_tbl {
|
|||
struct mwifiex_debug_info {
|
||||
u32 int_counter;
|
||||
u32 packets_out[MAX_NUM_TID];
|
||||
u32 max_tx_buf_size;
|
||||
u32 tx_buf_size;
|
||||
u32 curr_tx_buf_size;
|
||||
u32 tx_tbl_num;
|
||||
|
|
|
@ -398,8 +398,6 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
|
|||
|
||||
pos = (u8 *) assoc;
|
||||
|
||||
mwifiex_cfg_tx_buf(priv, bss_desc);
|
||||
|
||||
cmd->command = cpu_to_le16(HostCmd_CMD_802_11_ASSOCIATE);
|
||||
|
||||
/* Save so we know which BSS Desc to use in the response handler */
|
||||
|
|
|
@ -631,7 +631,6 @@ struct mwifiex_adapter {
|
|||
/* spin lock for main process */
|
||||
spinlock_t main_proc_lock;
|
||||
u32 mwifiex_processing;
|
||||
u16 max_tx_buf_size;
|
||||
u16 tx_buf_size;
|
||||
u16 curr_tx_buf_size;
|
||||
u32 ioport;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -29,6 +29,11 @@
|
|||
#include "main.h"
|
||||
|
||||
#define PCIE8766_DEFAULT_FW_NAME "mrvl/pcie8766_uapsta.bin"
|
||||
#define PCIE8897_DEFAULT_FW_NAME "mrvl/pcie8897_uapsta.bin"
|
||||
|
||||
#define PCIE_VENDOR_ID_MARVELL (0x11ab)
|
||||
#define PCIE_DEVICE_ID_MARVELL_88W8766P (0x2b30)
|
||||
#define PCIE_DEVICE_ID_MARVELL_88W8897 (0x2b38)
|
||||
|
||||
/* Constants for Buffer Descriptor (BD) rings */
|
||||
#define MWIFIEX_MAX_TXRX_BD 0x20
|
||||
|
@ -57,6 +62,8 @@
|
|||
#define PCIE_SCRATCH_10_REG 0xCE8
|
||||
#define PCIE_SCRATCH_11_REG 0xCEC
|
||||
#define PCIE_SCRATCH_12_REG 0xCF0
|
||||
#define PCIE_RD_DATA_PTR_Q0_Q1 0xC08C
|
||||
#define PCIE_WR_DATA_PTR_Q0_Q1 0xC05C
|
||||
|
||||
#define CPU_INTR_DNLD_RDY BIT(0)
|
||||
#define CPU_INTR_DOOR_BELL BIT(1)
|
||||
|
@ -75,27 +82,14 @@
|
|||
#define MWIFIEX_BD_FLAG_ROLLOVER_IND BIT(7)
|
||||
#define MWIFIEX_BD_FLAG_FIRST_DESC BIT(0)
|
||||
#define MWIFIEX_BD_FLAG_LAST_DESC BIT(1)
|
||||
#define REG_CMD_ADDR_LO PCIE_SCRATCH_0_REG
|
||||
#define REG_CMD_ADDR_HI PCIE_SCRATCH_1_REG
|
||||
#define REG_CMD_SIZE PCIE_SCRATCH_2_REG
|
||||
|
||||
#define REG_CMDRSP_ADDR_LO PCIE_SCRATCH_4_REG
|
||||
#define REG_CMDRSP_ADDR_HI PCIE_SCRATCH_5_REG
|
||||
|
||||
/* TX buffer description read pointer */
|
||||
#define REG_TXBD_RDPTR PCIE_SCRATCH_6_REG
|
||||
/* TX buffer description write pointer */
|
||||
#define REG_TXBD_WRPTR PCIE_SCRATCH_7_REG
|
||||
/* RX buffer description read pointer */
|
||||
#define REG_RXBD_RDPTR PCIE_SCRATCH_8_REG
|
||||
/* RX buffer description write pointer */
|
||||
#define REG_RXBD_WRPTR PCIE_SCRATCH_9_REG
|
||||
/* Event buffer description read pointer */
|
||||
#define REG_EVTBD_RDPTR PCIE_SCRATCH_10_REG
|
||||
/* Event buffer description write pointer */
|
||||
#define REG_EVTBD_WRPTR PCIE_SCRATCH_11_REG
|
||||
/* Driver ready signature write pointer */
|
||||
#define REG_DRV_READY PCIE_SCRATCH_12_REG
|
||||
#define MWIFIEX_BD_FLAG_SOP BIT(0)
|
||||
#define MWIFIEX_BD_FLAG_EOP BIT(1)
|
||||
#define MWIFIEX_BD_FLAG_XS_SOP BIT(2)
|
||||
#define MWIFIEX_BD_FLAG_XS_EOP BIT(3)
|
||||
#define MWIFIEX_BD_FLAG_EVT_ROLLOVER_IND BIT(7)
|
||||
#define MWIFIEX_BD_FLAG_RX_ROLLOVER_IND BIT(10)
|
||||
#define MWIFIEX_BD_FLAG_TX_START_PTR BIT(16)
|
||||
#define MWIFIEX_BD_FLAG_TX_ROLLOVER_IND BIT(26)
|
||||
|
||||
/* Max retry number of command write */
|
||||
#define MAX_WRITE_IOMEM_RETRY 2
|
||||
|
@ -104,15 +98,139 @@
|
|||
/* FW awake cookie after FW ready */
|
||||
#define FW_AWAKE_COOKIE (0xAA55AA55)
|
||||
|
||||
struct mwifiex_pcie_card_reg {
|
||||
u16 cmd_addr_lo;
|
||||
u16 cmd_addr_hi;
|
||||
u16 fw_status;
|
||||
u16 cmd_size;
|
||||
u16 cmdrsp_addr_lo;
|
||||
u16 cmdrsp_addr_hi;
|
||||
u16 tx_rdptr;
|
||||
u16 tx_wrptr;
|
||||
u16 rx_rdptr;
|
||||
u16 rx_wrptr;
|
||||
u16 evt_rdptr;
|
||||
u16 evt_wrptr;
|
||||
u16 drv_rdy;
|
||||
u16 tx_start_ptr;
|
||||
u32 tx_mask;
|
||||
u32 tx_wrap_mask;
|
||||
u32 rx_mask;
|
||||
u32 rx_wrap_mask;
|
||||
u32 tx_rollover_ind;
|
||||
u32 rx_rollover_ind;
|
||||
u32 evt_rollover_ind;
|
||||
u8 ring_flag_sop;
|
||||
u8 ring_flag_eop;
|
||||
u8 ring_flag_xs_sop;
|
||||
u8 ring_flag_xs_eop;
|
||||
u32 ring_tx_start_ptr;
|
||||
u8 pfu_enabled;
|
||||
};
|
||||
|
||||
static const struct mwifiex_pcie_card_reg mwifiex_reg_8766 = {
|
||||
.cmd_addr_lo = PCIE_SCRATCH_0_REG,
|
||||
.cmd_addr_hi = PCIE_SCRATCH_1_REG,
|
||||
.cmd_size = PCIE_SCRATCH_2_REG,
|
||||
.fw_status = PCIE_SCRATCH_3_REG,
|
||||
.cmdrsp_addr_lo = PCIE_SCRATCH_4_REG,
|
||||
.cmdrsp_addr_hi = PCIE_SCRATCH_5_REG,
|
||||
.tx_rdptr = PCIE_SCRATCH_6_REG,
|
||||
.tx_wrptr = PCIE_SCRATCH_7_REG,
|
||||
.rx_rdptr = PCIE_SCRATCH_8_REG,
|
||||
.rx_wrptr = PCIE_SCRATCH_9_REG,
|
||||
.evt_rdptr = PCIE_SCRATCH_10_REG,
|
||||
.evt_wrptr = PCIE_SCRATCH_11_REG,
|
||||
.drv_rdy = PCIE_SCRATCH_12_REG,
|
||||
.tx_start_ptr = 0,
|
||||
.tx_mask = MWIFIEX_TXBD_MASK,
|
||||
.tx_wrap_mask = 0,
|
||||
.rx_mask = MWIFIEX_RXBD_MASK,
|
||||
.rx_wrap_mask = 0,
|
||||
.tx_rollover_ind = MWIFIEX_BD_FLAG_ROLLOVER_IND,
|
||||
.rx_rollover_ind = MWIFIEX_BD_FLAG_ROLLOVER_IND,
|
||||
.evt_rollover_ind = MWIFIEX_BD_FLAG_ROLLOVER_IND,
|
||||
.ring_flag_sop = 0,
|
||||
.ring_flag_eop = 0,
|
||||
.ring_flag_xs_sop = 0,
|
||||
.ring_flag_xs_eop = 0,
|
||||
.ring_tx_start_ptr = 0,
|
||||
.pfu_enabled = 0,
|
||||
};
|
||||
|
||||
static const struct mwifiex_pcie_card_reg mwifiex_reg_8897 = {
|
||||
.cmd_addr_lo = PCIE_SCRATCH_0_REG,
|
||||
.cmd_addr_hi = PCIE_SCRATCH_1_REG,
|
||||
.cmd_size = PCIE_SCRATCH_2_REG,
|
||||
.fw_status = PCIE_SCRATCH_3_REG,
|
||||
.cmdrsp_addr_lo = PCIE_SCRATCH_4_REG,
|
||||
.cmdrsp_addr_hi = PCIE_SCRATCH_5_REG,
|
||||
.tx_rdptr = PCIE_RD_DATA_PTR_Q0_Q1,
|
||||
.tx_wrptr = PCIE_WR_DATA_PTR_Q0_Q1,
|
||||
.rx_rdptr = PCIE_WR_DATA_PTR_Q0_Q1,
|
||||
.rx_wrptr = PCIE_RD_DATA_PTR_Q0_Q1,
|
||||
.evt_rdptr = PCIE_SCRATCH_10_REG,
|
||||
.evt_wrptr = PCIE_SCRATCH_11_REG,
|
||||
.drv_rdy = PCIE_SCRATCH_12_REG,
|
||||
.tx_start_ptr = 16,
|
||||
.tx_mask = 0x03FF0000,
|
||||
.tx_wrap_mask = 0x07FF0000,
|
||||
.rx_mask = 0x000003FF,
|
||||
.rx_wrap_mask = 0x000007FF,
|
||||
.tx_rollover_ind = MWIFIEX_BD_FLAG_TX_ROLLOVER_IND,
|
||||
.rx_rollover_ind = MWIFIEX_BD_FLAG_RX_ROLLOVER_IND,
|
||||
.evt_rollover_ind = MWIFIEX_BD_FLAG_EVT_ROLLOVER_IND,
|
||||
.ring_flag_sop = MWIFIEX_BD_FLAG_SOP,
|
||||
.ring_flag_eop = MWIFIEX_BD_FLAG_EOP,
|
||||
.ring_flag_xs_sop = MWIFIEX_BD_FLAG_XS_SOP,
|
||||
.ring_flag_xs_eop = MWIFIEX_BD_FLAG_XS_EOP,
|
||||
.ring_tx_start_ptr = MWIFIEX_BD_FLAG_TX_START_PTR,
|
||||
.pfu_enabled = 1,
|
||||
};
|
||||
|
||||
struct mwifiex_pcie_device {
|
||||
const char *firmware;
|
||||
const struct mwifiex_pcie_card_reg *reg;
|
||||
u16 blksz_fw_dl;
|
||||
};
|
||||
|
||||
static const struct mwifiex_pcie_device mwifiex_pcie8766 = {
|
||||
.firmware = PCIE8766_DEFAULT_FW_NAME,
|
||||
.reg = &mwifiex_reg_8766,
|
||||
.blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD,
|
||||
};
|
||||
|
||||
static const struct mwifiex_pcie_device mwifiex_pcie8897 = {
|
||||
.firmware = PCIE8897_DEFAULT_FW_NAME,
|
||||
.reg = &mwifiex_reg_8897,
|
||||
.blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD,
|
||||
};
|
||||
|
||||
struct mwifiex_evt_buf_desc {
|
||||
u64 paddr;
|
||||
u16 len;
|
||||
u16 flags;
|
||||
} __packed;
|
||||
|
||||
struct mwifiex_pcie_buf_desc {
|
||||
u64 paddr;
|
||||
u16 len;
|
||||
u16 flags;
|
||||
} __packed;
|
||||
|
||||
struct mwifiex_pfu_buf_desc {
|
||||
u16 flags;
|
||||
u16 offset;
|
||||
u16 frag_len;
|
||||
u16 len;
|
||||
u64 paddr;
|
||||
u32 reserved;
|
||||
} __packed;
|
||||
|
||||
struct pcie_service_card {
|
||||
struct pci_dev *dev;
|
||||
struct mwifiex_adapter *adapter;
|
||||
struct mwifiex_pcie_device pcie;
|
||||
|
||||
u8 txbd_flush;
|
||||
u32 txbd_wrptr;
|
||||
|
@ -120,7 +238,7 @@ struct pcie_service_card {
|
|||
u32 txbd_ring_size;
|
||||
u8 *txbd_ring_vbase;
|
||||
dma_addr_t txbd_ring_pbase;
|
||||
struct mwifiex_pcie_buf_desc *txbd_ring[MWIFIEX_MAX_TXRX_BD];
|
||||
void *txbd_ring[MWIFIEX_MAX_TXRX_BD];
|
||||
struct sk_buff *tx_buf_list[MWIFIEX_MAX_TXRX_BD];
|
||||
|
||||
u32 rxbd_wrptr;
|
||||
|
@ -128,7 +246,7 @@ struct pcie_service_card {
|
|||
u32 rxbd_ring_size;
|
||||
u8 *rxbd_ring_vbase;
|
||||
dma_addr_t rxbd_ring_pbase;
|
||||
struct mwifiex_pcie_buf_desc *rxbd_ring[MWIFIEX_MAX_TXRX_BD];
|
||||
void *rxbd_ring[MWIFIEX_MAX_TXRX_BD];
|
||||
struct sk_buff *rx_buf_list[MWIFIEX_MAX_TXRX_BD];
|
||||
|
||||
u32 evtbd_wrptr;
|
||||
|
@ -136,7 +254,7 @@ struct pcie_service_card {
|
|||
u32 evtbd_ring_size;
|
||||
u8 *evtbd_ring_vbase;
|
||||
dma_addr_t evtbd_ring_pbase;
|
||||
struct mwifiex_pcie_buf_desc *evtbd_ring[MWIFIEX_MAX_EVT_BD];
|
||||
void *evtbd_ring[MWIFIEX_MAX_EVT_BD];
|
||||
struct sk_buff *evt_buf_list[MWIFIEX_MAX_EVT_BD];
|
||||
|
||||
struct sk_buff *cmd_buf;
|
||||
|
@ -150,11 +268,24 @@ struct pcie_service_card {
|
|||
static inline int
|
||||
mwifiex_pcie_txbd_empty(struct pcie_service_card *card, u32 rdptr)
|
||||
{
|
||||
if (((card->txbd_wrptr & MWIFIEX_TXBD_MASK) ==
|
||||
(rdptr & MWIFIEX_TXBD_MASK)) &&
|
||||
((card->txbd_wrptr & MWIFIEX_BD_FLAG_ROLLOVER_IND) !=
|
||||
(rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND)))
|
||||
return 1;
|
||||
const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
|
||||
|
||||
switch (card->dev->device) {
|
||||
case PCIE_DEVICE_ID_MARVELL_88W8766P:
|
||||
if (((card->txbd_wrptr & reg->tx_mask) ==
|
||||
(rdptr & reg->tx_mask)) &&
|
||||
((card->txbd_wrptr & reg->tx_rollover_ind) !=
|
||||
(rdptr & reg->tx_rollover_ind)))
|
||||
return 1;
|
||||
break;
|
||||
case PCIE_DEVICE_ID_MARVELL_88W8897:
|
||||
if (((card->txbd_wrptr & reg->tx_mask) ==
|
||||
(rdptr & reg->tx_mask)) &&
|
||||
((card->txbd_wrptr & reg->tx_rollover_ind) ==
|
||||
(rdptr & reg->tx_rollover_ind)))
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -162,11 +293,24 @@ mwifiex_pcie_txbd_empty(struct pcie_service_card *card, u32 rdptr)
|
|||
static inline int
|
||||
mwifiex_pcie_txbd_not_full(struct pcie_service_card *card)
|
||||
{
|
||||
if (((card->txbd_wrptr & MWIFIEX_TXBD_MASK) !=
|
||||
(card->txbd_rdptr & MWIFIEX_TXBD_MASK)) ||
|
||||
((card->txbd_wrptr & MWIFIEX_BD_FLAG_ROLLOVER_IND) !=
|
||||
(card->txbd_rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND)))
|
||||
return 1;
|
||||
const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
|
||||
|
||||
switch (card->dev->device) {
|
||||
case PCIE_DEVICE_ID_MARVELL_88W8766P:
|
||||
if (((card->txbd_wrptr & reg->tx_mask) !=
|
||||
(card->txbd_rdptr & reg->tx_mask)) ||
|
||||
((card->txbd_wrptr & reg->tx_rollover_ind) !=
|
||||
(card->txbd_rdptr & reg->tx_rollover_ind)))
|
||||
return 1;
|
||||
break;
|
||||
case PCIE_DEVICE_ID_MARVELL_88W8897:
|
||||
if (((card->txbd_wrptr & reg->tx_mask) !=
|
||||
(card->txbd_rdptr & reg->tx_mask)) ||
|
||||
((card->txbd_wrptr & reg->tx_rollover_ind) ==
|
||||
(card->txbd_rdptr & reg->tx_rollover_ind)))
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -935,9 +935,8 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
|
|||
/ MWIFIEX_SDIO_BLOCK_SIZE)
|
||||
* MWIFIEX_SDIO_BLOCK_SIZE;
|
||||
adapter->curr_tx_buf_size = adapter->tx_buf_size;
|
||||
dev_dbg(adapter->dev,
|
||||
"cmd: max_tx_buf_size=%d, tx_buf_size=%d\n",
|
||||
adapter->max_tx_buf_size, adapter->tx_buf_size);
|
||||
dev_dbg(adapter->dev, "cmd: curr_tx_buf_size=%d\n",
|
||||
adapter->curr_tx_buf_size);
|
||||
|
||||
if (adapter->if_ops.update_mp_end_port)
|
||||
adapter->if_ops.update_mp_end_port(adapter,
|
||||
|
|
|
@ -91,7 +91,7 @@ int mwifiex_get_debug_info(struct mwifiex_private *priv,
|
|||
memcpy(info->packets_out,
|
||||
priv->wmm.packets_out,
|
||||
sizeof(priv->wmm.packets_out));
|
||||
info->max_tx_buf_size = (u32) adapter->max_tx_buf_size;
|
||||
info->curr_tx_buf_size = (u32) adapter->curr_tx_buf_size;
|
||||
info->tx_buf_size = (u32) adapter->tx_buf_size;
|
||||
info->rx_tbl_num = mwifiex_get_rx_reorder_tbl(priv,
|
||||
info->rx_tbl);
|
||||
|
|
|
@ -1149,7 +1149,6 @@ static int mwl8k_rxq_init(struct ieee80211_hw *hw, int index)
|
|||
|
||||
rxq->buf = kcalloc(MWL8K_RX_DESCS, sizeof(*rxq->buf), GFP_KERNEL);
|
||||
if (rxq->buf == NULL) {
|
||||
wiphy_err(hw->wiphy, "failed to alloc RX skbuff list\n");
|
||||
pci_free_consistent(priv->pdev, size, rxq->rxd, rxq->rxd_dma);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -1442,7 +1441,6 @@ static int mwl8k_txq_init(struct ieee80211_hw *hw, int index)
|
|||
|
||||
txq->skb = kcalloc(MWL8K_TX_DESCS, sizeof(*txq->skb), GFP_KERNEL);
|
||||
if (txq->skb == NULL) {
|
||||
wiphy_err(hw->wiphy, "failed to alloc TX skbuff list\n");
|
||||
pci_free_consistent(priv->pdev, size, txq->txd, txq->txd_dma);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -5473,6 +5471,8 @@ static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = {
|
|||
{ PCI_VDEVICE(MARVELL, 0x2a2b), .driver_data = MWL8687, },
|
||||
{ PCI_VDEVICE(MARVELL, 0x2a30), .driver_data = MWL8687, },
|
||||
{ PCI_VDEVICE(MARVELL, 0x2a40), .driver_data = MWL8366, },
|
||||
{ PCI_VDEVICE(MARVELL, 0x2a41), .driver_data = MWL8366, },
|
||||
{ PCI_VDEVICE(MARVELL, 0x2a42), .driver_data = MWL8366, },
|
||||
{ PCI_VDEVICE(MARVELL, 0x2a43), .driver_data = MWL8366, },
|
||||
{ },
|
||||
};
|
||||
|
|
|
@ -84,8 +84,8 @@ static struct usb_device_id p54u_table[] = {
|
|||
{USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */
|
||||
{USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */
|
||||
{USB_DEVICE(0x0803, 0x4310)}, /* Zoom 4410a */
|
||||
{USB_DEVICE(0x083a, 0x4503)}, /* T-Com Sinus 154 data II */
|
||||
{USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */
|
||||
{USB_DEVICE(0x083a, 0x4531)}, /* T-Com Sinus 154 data II */
|
||||
{USB_DEVICE(0x083a, 0xc501)}, /* Zoom Wireless-G 4410 */
|
||||
{USB_DEVICE(0x083a, 0xf503)}, /* Accton FD7050E ver 1010ec */
|
||||
{USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */
|
||||
|
|
|
@ -1152,6 +1152,7 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
|
|||
{ PCI_DEVICE(0x1814, 0x3562) },
|
||||
{ PCI_DEVICE(0x1814, 0x3592) },
|
||||
{ PCI_DEVICE(0x1814, 0x3593) },
|
||||
{ PCI_DEVICE(0x1814, 0x359f) },
|
||||
#endif
|
||||
#ifdef CONFIG_RT2800PCI_RT53XX
|
||||
{ PCI_DEVICE(0x1814, 0x5360) },
|
||||
|
|
|
@ -968,6 +968,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
|
|||
{ USB_DEVICE(0x07d1, 0x3c13) },
|
||||
{ USB_DEVICE(0x07d1, 0x3c15) },
|
||||
{ USB_DEVICE(0x07d1, 0x3c16) },
|
||||
{ USB_DEVICE(0x07d1, 0x3c17) },
|
||||
{ USB_DEVICE(0x2001, 0x3c1b) },
|
||||
/* Draytek */
|
||||
{ USB_DEVICE(0x07fa, 0x7712) },
|
||||
|
@ -1098,9 +1099,11 @@ static struct usb_device_id rt2800usb_device_table[] = {
|
|||
{ USB_DEVICE(0x15a9, 0x0006) },
|
||||
/* Sweex */
|
||||
{ USB_DEVICE(0x177f, 0x0153) },
|
||||
{ USB_DEVICE(0x177f, 0x0164) },
|
||||
{ USB_DEVICE(0x177f, 0x0302) },
|
||||
{ USB_DEVICE(0x177f, 0x0313) },
|
||||
{ USB_DEVICE(0x177f, 0x0323) },
|
||||
{ USB_DEVICE(0x177f, 0x0324) },
|
||||
/* U-Media */
|
||||
{ USB_DEVICE(0x157e, 0x300e) },
|
||||
{ USB_DEVICE(0x157e, 0x3013) },
|
||||
|
@ -1115,6 +1118,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
|
|||
/* Zyxel */
|
||||
{ USB_DEVICE(0x0586, 0x3416) },
|
||||
{ USB_DEVICE(0x0586, 0x3418) },
|
||||
{ USB_DEVICE(0x0586, 0x341a) },
|
||||
{ USB_DEVICE(0x0586, 0x341e) },
|
||||
{ USB_DEVICE(0x0586, 0x343e) },
|
||||
#ifdef CONFIG_RT2800USB_RT33XX
|
||||
|
@ -1131,6 +1135,9 @@ static struct usb_device_id rt2800usb_device_table[] = {
|
|||
{ USB_DEVICE(0x148f, 0x8070) },
|
||||
/* Sitecom */
|
||||
{ USB_DEVICE(0x0df6, 0x0050) },
|
||||
/* Sweex */
|
||||
{ USB_DEVICE(0x177f, 0x0163) },
|
||||
{ USB_DEVICE(0x177f, 0x0165) },
|
||||
#endif
|
||||
#ifdef CONFIG_RT2800USB_RT35XX
|
||||
/* Allwin */
|
||||
|
@ -1166,6 +1173,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
|
|||
#ifdef CONFIG_RT2800USB_RT53XX
|
||||
/* Arcadyan */
|
||||
{ USB_DEVICE(0x043e, 0x7a12) },
|
||||
{ USB_DEVICE(0x043e, 0x7a32) },
|
||||
/* Azurewave */
|
||||
{ USB_DEVICE(0x13d3, 0x3329) },
|
||||
{ USB_DEVICE(0x13d3, 0x3365) },
|
||||
|
@ -1177,16 +1185,20 @@ static struct usb_device_id rt2800usb_device_table[] = {
|
|||
{ USB_DEVICE(0x2001, 0x3c1e) },
|
||||
/* LG innotek */
|
||||
{ USB_DEVICE(0x043e, 0x7a22) },
|
||||
{ USB_DEVICE(0x043e, 0x7a42) },
|
||||
/* Panasonic */
|
||||
{ USB_DEVICE(0x04da, 0x1801) },
|
||||
{ USB_DEVICE(0x04da, 0x1800) },
|
||||
{ USB_DEVICE(0x04da, 0x23f6) },
|
||||
/* Philips */
|
||||
{ USB_DEVICE(0x0471, 0x2104) },
|
||||
{ USB_DEVICE(0x0471, 0x2126) },
|
||||
{ USB_DEVICE(0x0471, 0x2180) },
|
||||
{ USB_DEVICE(0x0471, 0x2181) },
|
||||
{ USB_DEVICE(0x0471, 0x2182) },
|
||||
/* Ralink */
|
||||
{ USB_DEVICE(0x148f, 0x5370) },
|
||||
{ USB_DEVICE(0x148f, 0x5372) },
|
||||
/* Unknown */
|
||||
{ USB_DEVICE(0x04da, 0x23f6) },
|
||||
#endif
|
||||
#ifdef CONFIG_RT2800USB_UNKNOWN
|
||||
/*
|
||||
|
@ -1207,10 +1219,15 @@ static struct usb_device_id rt2800usb_device_table[] = {
|
|||
{ USB_DEVICE(0x0b05, 0x1760) },
|
||||
{ USB_DEVICE(0x0b05, 0x1761) },
|
||||
{ USB_DEVICE(0x0b05, 0x1790) },
|
||||
{ USB_DEVICE(0x0b05, 0x17a7) },
|
||||
/* AzureWave */
|
||||
{ USB_DEVICE(0x13d3, 0x3262) },
|
||||
{ USB_DEVICE(0x13d3, 0x3284) },
|
||||
{ USB_DEVICE(0x13d3, 0x3322) },
|
||||
{ USB_DEVICE(0x13d3, 0x3340) },
|
||||
{ USB_DEVICE(0x13d3, 0x3399) },
|
||||
{ USB_DEVICE(0x13d3, 0x3400) },
|
||||
{ USB_DEVICE(0x13d3, 0x3401) },
|
||||
/* Belkin */
|
||||
{ USB_DEVICE(0x050d, 0x1003) },
|
||||
/* Buffalo */
|
||||
|
@ -1223,13 +1240,17 @@ static struct usb_device_id rt2800usb_device_table[] = {
|
|||
{ USB_DEVICE(0x18c5, 0x0008) },
|
||||
/* D-Link */
|
||||
{ USB_DEVICE(0x07d1, 0x3c0b) },
|
||||
{ USB_DEVICE(0x07d1, 0x3c17) },
|
||||
/* Encore */
|
||||
{ USB_DEVICE(0x203d, 0x14a1) },
|
||||
/* EnGenius */
|
||||
{ USB_DEVICE(0x1740, 0x0600) },
|
||||
{ USB_DEVICE(0x1740, 0x0602) },
|
||||
/* Gemtek */
|
||||
{ USB_DEVICE(0x15a9, 0x0010) },
|
||||
/* Gigabyte */
|
||||
{ USB_DEVICE(0x1044, 0x800c) },
|
||||
/* Hercules */
|
||||
{ USB_DEVICE(0x06f8, 0xe036) },
|
||||
/* Huawei */
|
||||
{ USB_DEVICE(0x148f, 0xf101) },
|
||||
/* I-O DATA */
|
||||
|
@ -1256,13 +1277,17 @@ static struct usb_device_id rt2800usb_device_table[] = {
|
|||
{ USB_DEVICE(0x0df6, 0x004a) },
|
||||
{ USB_DEVICE(0x0df6, 0x004d) },
|
||||
{ USB_DEVICE(0x0df6, 0x0053) },
|
||||
{ USB_DEVICE(0x0df6, 0x0069) },
|
||||
{ USB_DEVICE(0x0df6, 0x006f) },
|
||||
/* SMC */
|
||||
{ USB_DEVICE(0x083a, 0xa512) },
|
||||
{ USB_DEVICE(0x083a, 0xc522) },
|
||||
{ USB_DEVICE(0x083a, 0xd522) },
|
||||
{ USB_DEVICE(0x083a, 0xf511) },
|
||||
/* Zyxel */
|
||||
{ USB_DEVICE(0x0586, 0x341a) },
|
||||
/* Sweex */
|
||||
{ USB_DEVICE(0x177f, 0x0254) },
|
||||
/* TP-LINK */
|
||||
{ USB_DEVICE(0xf201, 0x5370) },
|
||||
#endif
|
||||
{ 0, }
|
||||
};
|
||||
|
|
|
@ -669,7 +669,8 @@ static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw
|
|||
u8 thermalvalue, delta, delta_lck, delta_iqk;
|
||||
long ele_a, ele_d, temp_cck, val_x, value32;
|
||||
long val_y, ele_c = 0;
|
||||
u8 ofdm_index[2], cck_index = 0, ofdm_index_old[2], cck_index_old = 0;
|
||||
u8 ofdm_index[2], ofdm_index_old[2], cck_index_old = 0;
|
||||
s8 cck_index = 0;
|
||||
int i;
|
||||
bool is2t = IS_92C_SERIAL(rtlhal->version);
|
||||
s8 txpwr_level[2] = {0, 0};
|
||||
|
|
|
@ -488,7 +488,7 @@ static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw,
|
|||
u8 *praddr;
|
||||
__le16 fc;
|
||||
u16 type, c_fc;
|
||||
bool packet_matchbssid, packet_toself, packet_beacon;
|
||||
bool packet_matchbssid, packet_toself, packet_beacon = false;
|
||||
|
||||
tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift;
|
||||
|
||||
|
|
|
@ -1084,7 +1084,7 @@ void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw,
|
|||
u8 *praddr;
|
||||
__le16 fc;
|
||||
u16 type, cpu_fc;
|
||||
bool packet_matchbssid, packet_toself, packet_beacon;
|
||||
bool packet_matchbssid, packet_toself, packet_beacon = false;
|
||||
|
||||
tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift;
|
||||
hdr = (struct ieee80211_hdr *)tmp_buf;
|
||||
|
|
|
@ -76,7 +76,7 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw)
|
|||
GFP_KERNEL, hw, rtl_fw_cb);
|
||||
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
static void rtl92cu_deinit_sw_vars(struct ieee80211_hw *hw)
|
||||
|
@ -285,6 +285,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
|
|||
{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817f, rtl92cu_hal_cfg)},
|
||||
/* RTL8188CUS-VL */
|
||||
{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x818a, rtl92cu_hal_cfg)},
|
||||
{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x819a, rtl92cu_hal_cfg)},
|
||||
/* 8188 Combo for BC4 */
|
||||
{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8754, rtl92cu_hal_cfg)},
|
||||
|
||||
|
@ -363,9 +364,15 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
|
|||
|
||||
MODULE_DEVICE_TABLE(usb, rtl8192c_usb_ids);
|
||||
|
||||
static int rtl8192cu_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
return rtl_usb_probe(intf, id, &rtl92cu_hal_cfg);
|
||||
}
|
||||
|
||||
static struct usb_driver rtl8192cu_driver = {
|
||||
.name = "rtl8192cu",
|
||||
.probe = rtl_usb_probe,
|
||||
.probe = rtl8192cu_probe,
|
||||
.disconnect = rtl_usb_disconnect,
|
||||
.id_table = rtl8192c_usb_ids,
|
||||
|
||||
|
|
|
@ -841,9 +841,9 @@ static void rtl92d_dm_txpower_tracking_callback_thermalmeter(
|
|||
long ele_a = 0, ele_d, temp_cck, val_x, value32;
|
||||
long val_y, ele_c = 0;
|
||||
u8 ofdm_index[2];
|
||||
u8 cck_index = 0;
|
||||
s8 cck_index = 0;
|
||||
u8 ofdm_index_old[2];
|
||||
u8 cck_index_old = 0;
|
||||
s8 cck_index_old = 0;
|
||||
u8 index;
|
||||
int i;
|
||||
bool is2t = IS_92D_SINGLEPHY(rtlhal->version);
|
||||
|
|
|
@ -512,7 +512,6 @@ static bool _rtl8723ae_cmd_send_packet(struct ieee80211_hw *hw,
|
|||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
struct rtl8192_tx_ring *ring;
|
||||
struct rtl_tx_desc *pdesc;
|
||||
u8 own;
|
||||
unsigned long flags;
|
||||
struct sk_buff *pskb = NULL;
|
||||
|
||||
|
@ -525,7 +524,6 @@ static bool _rtl8723ae_cmd_send_packet(struct ieee80211_hw *hw,
|
|||
spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
|
||||
|
||||
pdesc = &ring->desc[0];
|
||||
own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN);
|
||||
|
||||
rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
|
||||
|
||||
|
|
|
@ -1433,7 +1433,6 @@ static void _rtl8723ae_dm_bt_coexist_2_ant(struct ieee80211_hw *hw)
|
|||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
|
||||
struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
|
||||
u8 bt_retry_cnt;
|
||||
u8 bt_info_original;
|
||||
RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
|
||||
"[BTCoex] Get bt info by fw!!\n");
|
||||
|
@ -1445,7 +1444,6 @@ static void _rtl8723ae_dm_bt_coexist_2_ant(struct ieee80211_hw *hw)
|
|||
"[BTCoex] c2h for btInfo not rcvd yet!!\n");
|
||||
}
|
||||
|
||||
bt_retry_cnt = rtlhal->hal_coex_8723.bt_retry_cnt;
|
||||
bt_info_original = rtlhal->hal_coex_8723.c2h_bt_info_original;
|
||||
|
||||
/* when bt inquiry or page scan, we have to set h2c 0x25
|
||||
|
|
|
@ -703,11 +703,9 @@ static void _rtl8723ae_hw_configure(struct ieee80211_hw *hw)
|
|||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
|
||||
u8 reg_bw_opmode;
|
||||
u32 reg_ratr, reg_prsr;
|
||||
u32 reg_prsr;
|
||||
|
||||
reg_bw_opmode = BW_OPMODE_20MHZ;
|
||||
reg_ratr = RATE_ALL_CCK | RATE_ALL_OFDM_AG |
|
||||
RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
|
||||
reg_prsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
|
||||
|
||||
rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, 0x8);
|
||||
|
@ -2030,7 +2028,7 @@ bool rtl8723ae_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)
|
|||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
|
||||
struct rtl_phy *rtlphy = &(rtlpriv->phy);
|
||||
enum rf_pwrstate e_rfpowerstate_toset, cur_rfstate;
|
||||
enum rf_pwrstate e_rfpowerstate_toset;
|
||||
u8 u1tmp;
|
||||
bool actuallyset = false;
|
||||
|
||||
|
@ -2049,8 +2047,6 @@ bool rtl8723ae_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)
|
|||
spin_unlock(&rtlpriv->locks.rf_ps_lock);
|
||||
}
|
||||
|
||||
cur_rfstate = ppsc->rfpwr_state;
|
||||
|
||||
rtl_write_byte(rtlpriv, REG_GPIO_IO_SEL_2,
|
||||
rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL_2)&~(BIT(1)));
|
||||
|
||||
|
|
|
@ -614,17 +614,11 @@ bool rtl8723ae_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
|
|||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
int i;
|
||||
bool rtstatus = true;
|
||||
u32 *radioa_array_table;
|
||||
u32 *radiob_array_table;
|
||||
u16 radioa_arraylen, radiob_arraylen;
|
||||
u16 radioa_arraylen;
|
||||
|
||||
radioa_arraylen = Rtl8723ERADIOA_1TARRAYLENGTH;
|
||||
radioa_array_table = RTL8723E_RADIOA_1TARRAY;
|
||||
radiob_arraylen = RTL8723E_RADIOB_1TARRAYLENGTH;
|
||||
radiob_array_table = RTL8723E_RADIOB_1TARRAY;
|
||||
|
||||
rtstatus = true;
|
||||
|
||||
switch (rfpath) {
|
||||
case RF90_PATH_A:
|
||||
|
@ -1531,11 +1525,8 @@ static void _rtl8723ae_phy_iq_calibrate(struct ieee80211_hw *hw,
|
|||
0x522, 0x550, 0x551, 0x040
|
||||
};
|
||||
const u32 retrycount = 2;
|
||||
u32 bbvalue;
|
||||
|
||||
if (t == 0) {
|
||||
bbvalue = rtl_get_bbreg(hw, 0x800, MASKDWORD);
|
||||
|
||||
phy_save_adda_regs(hw, adda_reg, rtlphy->adda_backup, 16);
|
||||
phy_save_mac_regs(hw, iqk_mac_reg, rtlphy->iqk_mac_backup);
|
||||
}
|
||||
|
@ -1712,8 +1703,7 @@ void rtl8723ae_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery)
|
|||
long result[4][8];
|
||||
u8 i, final_candidate;
|
||||
bool patha_ok, pathb_ok;
|
||||
long reg_e94, reg_e9c, reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4,
|
||||
reg_ecc, reg_tmp = 0;
|
||||
long reg_e94, reg_e9c, reg_ea4, reg_eb4, reg_ebc, reg_tmp = 0;
|
||||
bool is12simular, is13simular, is23simular;
|
||||
bool start_conttx = false, singletone = false;
|
||||
u32 iqk_bb_reg[10] = {
|
||||
|
@ -1780,21 +1770,15 @@ void rtl8723ae_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery)
|
|||
reg_e94 = result[i][0];
|
||||
reg_e9c = result[i][1];
|
||||
reg_ea4 = result[i][2];
|
||||
reg_eac = result[i][3];
|
||||
reg_eb4 = result[i][4];
|
||||
reg_ebc = result[i][5];
|
||||
reg_ec4 = result[i][6];
|
||||
reg_ecc = result[i][7];
|
||||
}
|
||||
if (final_candidate != 0xff) {
|
||||
rtlphy->reg_e94 = reg_e94 = result[final_candidate][0];
|
||||
rtlphy->reg_e9c = reg_e9c = result[final_candidate][1];
|
||||
reg_ea4 = result[final_candidate][2];
|
||||
reg_eac = result[final_candidate][3];
|
||||
rtlphy->reg_eb4 = reg_eb4 = result[final_candidate][4];
|
||||
rtlphy->reg_ebc = reg_ebc = result[final_candidate][5];
|
||||
reg_ec4 = result[final_candidate][6];
|
||||
reg_ecc = result[final_candidate][7];
|
||||
patha_ok = pathb_ok = true;
|
||||
} else {
|
||||
rtlphy->reg_e94 = rtlphy->reg_eb4 = 0x100;
|
||||
|
|
|
@ -244,7 +244,6 @@ static void _rtl8723ae_translate_rx_signal_stuff(struct ieee80211_hw *hw,
|
|||
struct ieee80211_hdr *hdr;
|
||||
u8 *tmp_buf;
|
||||
u8 *praddr;
|
||||
u8 *psaddr;
|
||||
__le16 fc;
|
||||
u16 type;
|
||||
bool packet_matchbssid, packet_toself, packet_beacon = false;
|
||||
|
@ -255,7 +254,6 @@ static void _rtl8723ae_translate_rx_signal_stuff(struct ieee80211_hw *hw,
|
|||
fc = hdr->frame_control;
|
||||
type = WLAN_FC_GET_TYPE(fc);
|
||||
praddr = hdr->addr1;
|
||||
psaddr = ieee80211_get_SA(hdr);
|
||||
|
||||
packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) &&
|
||||
(!compare_ether_addr(mac->bssid,
|
||||
|
|
|
@ -825,8 +825,6 @@ static void _rtl_usb_transmit(struct ieee80211_hw *hw, struct sk_buff *skb,
|
|||
u32 ep_num;
|
||||
struct urb *_urb = NULL;
|
||||
struct sk_buff *_skb = NULL;
|
||||
struct sk_buff_head *skb_list;
|
||||
struct usb_anchor *urb_list;
|
||||
|
||||
WARN_ON(NULL == rtlusb->usb_tx_aggregate_hdl);
|
||||
if (unlikely(IS_USB_STOP(rtlusb))) {
|
||||
|
@ -836,7 +834,6 @@ static void _rtl_usb_transmit(struct ieee80211_hw *hw, struct sk_buff *skb,
|
|||
return;
|
||||
}
|
||||
ep_num = rtlusb->ep_map.ep_mapping[qnum];
|
||||
skb_list = &rtlusb->tx_skb_queue[ep_num];
|
||||
_skb = skb;
|
||||
_urb = _rtl_usb_tx_urb_setup(hw, _skb, ep_num);
|
||||
if (unlikely(!_urb)) {
|
||||
|
@ -844,7 +841,6 @@ static void _rtl_usb_transmit(struct ieee80211_hw *hw, struct sk_buff *skb,
|
|||
"Can't allocate urb. Drop skb!\n");
|
||||
return;
|
||||
}
|
||||
urb_list = &rtlusb->tx_pending[ep_num];
|
||||
_rtl_submit_tx_urb(hw, _urb);
|
||||
}
|
||||
|
||||
|
@ -941,7 +937,8 @@ static struct rtl_intf_ops rtl_usb_ops = {
|
|||
};
|
||||
|
||||
int rtl_usb_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
const struct usb_device_id *id,
|
||||
struct rtl_hal_cfg *rtl_hal_cfg)
|
||||
{
|
||||
int err;
|
||||
struct ieee80211_hw *hw = NULL;
|
||||
|
@ -976,7 +973,7 @@ int rtl_usb_probe(struct usb_interface *intf,
|
|||
usb_set_intfdata(intf, hw);
|
||||
/* init cfg & intf_ops */
|
||||
rtlpriv->rtlhal.interface = INTF_USB;
|
||||
rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_info);
|
||||
rtlpriv->cfg = rtl_hal_cfg;
|
||||
rtlpriv->intf_ops = &rtl_usb_ops;
|
||||
rtl_dbgp_flag_init(hw);
|
||||
/* Init IO handler */
|
||||
|
|
|
@ -157,7 +157,8 @@ struct rtl_usb_priv {
|
|||
|
||||
|
||||
int rtl_usb_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id);
|
||||
const struct usb_device_id *id,
|
||||
struct rtl_hal_cfg *rtl92cu_hal_cfg);
|
||||
void rtl_usb_disconnect(struct usb_interface *intf);
|
||||
int rtl_usb_suspend(struct usb_interface *pusb_intf, pm_message_t message);
|
||||
int rtl_usb_resume(struct usb_interface *pusb_intf);
|
||||
|
|
|
@ -1702,7 +1702,7 @@ struct rtl_works {
|
|||
|
||||
struct rtl_debug {
|
||||
u32 dbgp_type[DBGP_TYPE_MAX];
|
||||
u32 global_debuglevel;
|
||||
int global_debuglevel;
|
||||
u64 global_debugcomponents;
|
||||
|
||||
/* add for proc debug */
|
||||
|
|
|
@ -12,4 +12,13 @@ source "drivers/net/wireless/ti/wl18xx/Kconfig"
|
|||
|
||||
# keep last for automatic dependencies
|
||||
source "drivers/net/wireless/ti/wlcore/Kconfig"
|
||||
|
||||
config WILINK_PLATFORM_DATA
|
||||
bool "TI WiLink platform data"
|
||||
depends on WLCORE_SDIO || WL1251_SDIO
|
||||
default y
|
||||
---help---
|
||||
Small platform data bit needed to pass data to the sdio modules.
|
||||
|
||||
|
||||
endif # WL_TI
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
obj-$(CONFIG_WLCORE) += wlcore/
|
||||
obj-$(CONFIG_WL12XX) += wl12xx/
|
||||
obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wlcore/
|
||||
obj-$(CONFIG_WL1251) += wl1251/
|
||||
obj-$(CONFIG_WL18XX) += wl18xx/
|
||||
|
||||
# small builtin driver bit
|
||||
obj-$(CONFIG_WILINK_PLATFORM_DATA) += wilink_platform_data.o
|
||||
|
|
|
@ -1703,7 +1703,8 @@ static struct ieee80211_sta_ht_cap wl12xx_ht_cap = {
|
|||
static int wl12xx_setup(struct wl1271 *wl)
|
||||
{
|
||||
struct wl12xx_priv *priv = wl->priv;
|
||||
struct wl12xx_platform_data *pdata = wl->pdev->dev.platform_data;
|
||||
struct wlcore_platdev_data *pdev_data = wl->pdev->dev.platform_data;
|
||||
struct wl12xx_platform_data *pdata = pdev_data->pdata;
|
||||
|
||||
wl->rtable = wl12xx_rtable;
|
||||
wl->num_tx_desc = WL12XX_NUM_TX_DESCRIPTORS;
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#define __WL18XX_CONF_H__
|
||||
|
||||
#define WL18XX_CONF_MAGIC 0x10e100ca
|
||||
#define WL18XX_CONF_VERSION (WLCORE_CONF_VERSION | 0x0005)
|
||||
#define WL18XX_CONF_VERSION (WLCORE_CONF_VERSION | 0x0006)
|
||||
#define WL18XX_CONF_MASK 0x0000ffff
|
||||
#define WL18XX_CONF_SIZE (WLCORE_CONF_SIZE + \
|
||||
sizeof(struct wl18xx_priv_conf))
|
||||
|
@ -70,8 +70,9 @@ struct wl18xx_mac_and_phy_params {
|
|||
u8 pwr_limit_reference_11_abg;
|
||||
u8 per_chan_pwr_limit_arr_11p[NUM_OF_CHANNELS_11_P];
|
||||
u8 pwr_limit_reference_11p;
|
||||
u8 spare1[9];
|
||||
u8 spare2[9];
|
||||
u8 spare1;
|
||||
u8 per_chan_bo_mode_11_abg[13];
|
||||
u8 per_chan_bo_mode_11_p[4];
|
||||
u8 primary_clock_setting_time;
|
||||
u8 clock_valid_on_wake_up;
|
||||
u8 secondary_clock_setting_time;
|
||||
|
|
|
@ -547,6 +547,11 @@ static struct wl18xx_priv_conf wl18xx_default_priv_conf = {
|
|||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
|
||||
.pwr_limit_reference_11p = 0x64,
|
||||
.per_chan_bo_mode_11_abg = { 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00 },
|
||||
.per_chan_bo_mode_11_p = { 0x00, 0x00, 0x00, 0x00 },
|
||||
.per_chan_pwr_limit_arr_11p = { 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff },
|
||||
.psat = 0,
|
||||
|
|
|
@ -33,8 +33,3 @@ config WLCORE_SDIO
|
|||
|
||||
If you choose to build a module, it'll be called wlcore_sdio.
|
||||
Say N if unsure.
|
||||
|
||||
config WL12XX_PLATFORM_DATA
|
||||
bool
|
||||
depends on WLCORE_SDIO != n || WL1251_SDIO != n
|
||||
default y
|
||||
|
|
|
@ -9,7 +9,4 @@ obj-$(CONFIG_WLCORE) += wlcore.o
|
|||
obj-$(CONFIG_WLCORE_SPI) += wlcore_spi.o
|
||||
obj-$(CONFIG_WLCORE_SDIO) += wlcore_sdio.o
|
||||
|
||||
# small builtin driver bit
|
||||
obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o
|
||||
|
||||
ccflags-y += -D__CHECK_ENDIAN__
|
||||
|
|
|
@ -84,8 +84,8 @@ out:
|
|||
static int wlcore_validate_fw_ver(struct wl1271 *wl)
|
||||
{
|
||||
unsigned int *fw_ver = wl->chip.fw_ver;
|
||||
unsigned int *min_ver = (wl->fw_type == WL12XX_FW_TYPE_NORMAL) ?
|
||||
wl->min_sr_fw_ver : wl->min_mr_fw_ver;
|
||||
unsigned int *min_ver = (wl->fw_type == WL12XX_FW_TYPE_MULTI) ?
|
||||
wl->min_mr_fw_ver : wl->min_sr_fw_ver;
|
||||
char min_fw_str[32] = "";
|
||||
int i;
|
||||
|
||||
|
|
|
@ -510,10 +510,12 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
|||
cmd->sta.hlid = wlvif->sta.hlid;
|
||||
cmd->sta.session = wl->session_ids[wlvif->sta.hlid];
|
||||
/*
|
||||
* We don't have the correct remote rates in this stage. the rates
|
||||
* will be reconfigured later, after authorization.
|
||||
* We don't have the correct remote rates in this stage. The
|
||||
* rates will be reconfigured later, after association, if the
|
||||
* firmware supports ACX_PEER_CAP. Otherwise, there's nothing
|
||||
* we can do, so use all supported_rates here.
|
||||
*/
|
||||
cmd->sta.remote_rates = cpu_to_le32(wlvif->rate_set);
|
||||
cmd->sta.remote_rates = cpu_to_le32(supported_rates);
|
||||
|
||||
wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d "
|
||||
"basic_rate_set: 0x%x, remote_rates: 0x%x",
|
||||
|
|
|
@ -2162,7 +2162,7 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool wl12xx_init_fw(struct wl1271 *wl)
|
||||
static int wl12xx_init_fw(struct wl1271 *wl)
|
||||
{
|
||||
int retries = WL1271_BOOT_RETRIES;
|
||||
bool booted = false;
|
||||
|
@ -2228,7 +2228,7 @@ power_off:
|
|||
|
||||
wl->state = WLCORE_STATE_ON;
|
||||
out:
|
||||
return booted;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool wl12xx_dev_role_started(struct wl12xx_vif *wlvif)
|
||||
|
@ -2371,7 +2371,6 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
|
|||
struct vif_counter_data vif_count;
|
||||
int ret = 0;
|
||||
u8 role_type;
|
||||
bool booted = false;
|
||||
|
||||
vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER |
|
||||
IEEE80211_VIF_SUPPORTS_CQM_RSSI;
|
||||
|
@ -2432,11 +2431,9 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
|
|||
*/
|
||||
memcpy(wl->addresses[0].addr, vif->addr, ETH_ALEN);
|
||||
|
||||
booted = wl12xx_init_fw(wl);
|
||||
if (!booted) {
|
||||
ret = -EINVAL;
|
||||
ret = wl12xx_init_fw(wl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = wl12xx_cmd_role_enable(wl, vif->addr,
|
||||
|
@ -5966,7 +5963,8 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context)
|
|||
{
|
||||
struct wl1271 *wl = context;
|
||||
struct platform_device *pdev = wl->pdev;
|
||||
struct wl12xx_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct wlcore_platdev_data *pdev_data = pdev->dev.platform_data;
|
||||
struct wl12xx_platform_data *pdata = pdev_data->pdata;
|
||||
unsigned long irqflags;
|
||||
int ret;
|
||||
|
||||
|
@ -5995,8 +5993,7 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context)
|
|||
|
||||
wl->irq = platform_get_irq(pdev, 0);
|
||||
wl->platform_quirks = pdata->platform_quirks;
|
||||
wl->set_power = pdata->set_power;
|
||||
wl->if_ops = pdata->ops;
|
||||
wl->if_ops = pdev_data->if_ops;
|
||||
|
||||
if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ)
|
||||
irqflags = IRQF_TRIGGER_RISING;
|
||||
|
|
|
@ -217,7 +217,7 @@ static struct wl1271_if_operations sdio_ops = {
|
|||
static int wl1271_probe(struct sdio_func *func,
|
||||
const struct sdio_device_id *id)
|
||||
{
|
||||
struct wl12xx_platform_data *wlan_data;
|
||||
struct wlcore_platdev_data *pdev_data;
|
||||
struct wl12xx_sdio_glue *glue;
|
||||
struct resource res[1];
|
||||
mmc_pm_flag_t mmcflags;
|
||||
|
@ -228,10 +228,16 @@ static int wl1271_probe(struct sdio_func *func,
|
|||
if (func->num != 0x02)
|
||||
return -ENODEV;
|
||||
|
||||
pdev_data = kzalloc(sizeof(*pdev_data), GFP_KERNEL);
|
||||
if (!pdev_data)
|
||||
goto out;
|
||||
|
||||
pdev_data->if_ops = &sdio_ops;
|
||||
|
||||
glue = kzalloc(sizeof(*glue), GFP_KERNEL);
|
||||
if (!glue) {
|
||||
dev_err(&func->dev, "can't allocate glue\n");
|
||||
goto out;
|
||||
goto out_free_pdev_data;
|
||||
}
|
||||
|
||||
glue->dev = &func->dev;
|
||||
|
@ -242,9 +248,9 @@ static int wl1271_probe(struct sdio_func *func,
|
|||
/* Use block mode for transferring over one block size of data */
|
||||
func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
|
||||
|
||||
wlan_data = wl12xx_get_platform_data();
|
||||
if (IS_ERR(wlan_data)) {
|
||||
ret = PTR_ERR(wlan_data);
|
||||
pdev_data->pdata = wl12xx_get_platform_data();
|
||||
if (IS_ERR(pdev_data->pdata)) {
|
||||
ret = PTR_ERR(pdev_data->pdata);
|
||||
dev_err(glue->dev, "missing wlan platform data: %d\n", ret);
|
||||
goto out_free_glue;
|
||||
}
|
||||
|
@ -254,9 +260,7 @@ static int wl1271_probe(struct sdio_func *func,
|
|||
dev_dbg(glue->dev, "sdio PM caps = 0x%x\n", mmcflags);
|
||||
|
||||
if (mmcflags & MMC_PM_KEEP_POWER)
|
||||
wlan_data->pwr_in_suspend = true;
|
||||
|
||||
wlan_data->ops = &sdio_ops;
|
||||
pdev_data->pdata->pwr_in_suspend = true;
|
||||
|
||||
sdio_set_drvdata(func, glue);
|
||||
|
||||
|
@ -274,7 +278,7 @@ static int wl1271_probe(struct sdio_func *func,
|
|||
else
|
||||
chip_family = "wl12xx";
|
||||
|
||||
glue->core = platform_device_alloc(chip_family, -1);
|
||||
glue->core = platform_device_alloc(chip_family, PLATFORM_DEVID_AUTO);
|
||||
if (!glue->core) {
|
||||
dev_err(glue->dev, "can't allocate platform_device");
|
||||
ret = -ENOMEM;
|
||||
|
@ -285,7 +289,7 @@ static int wl1271_probe(struct sdio_func *func,
|
|||
|
||||
memset(res, 0x00, sizeof(res));
|
||||
|
||||
res[0].start = wlan_data->irq;
|
||||
res[0].start = pdev_data->pdata->irq;
|
||||
res[0].flags = IORESOURCE_IRQ;
|
||||
res[0].name = "irq";
|
||||
|
||||
|
@ -295,8 +299,8 @@ static int wl1271_probe(struct sdio_func *func,
|
|||
goto out_dev_put;
|
||||
}
|
||||
|
||||
ret = platform_device_add_data(glue->core, wlan_data,
|
||||
sizeof(*wlan_data));
|
||||
ret = platform_device_add_data(glue->core, pdev_data,
|
||||
sizeof(*pdev_data));
|
||||
if (ret) {
|
||||
dev_err(glue->dev, "can't add platform data\n");
|
||||
goto out_dev_put;
|
||||
|
@ -315,6 +319,9 @@ out_dev_put:
|
|||
out_free_glue:
|
||||
kfree(glue);
|
||||
|
||||
out_free_pdev_data:
|
||||
kfree(pdev_data);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -327,22 +327,27 @@ static struct wl1271_if_operations spi_ops = {
|
|||
static int wl1271_probe(struct spi_device *spi)
|
||||
{
|
||||
struct wl12xx_spi_glue *glue;
|
||||
struct wl12xx_platform_data *pdata;
|
||||
struct wlcore_platdev_data *pdev_data;
|
||||
struct resource res[1];
|
||||
int ret = -ENOMEM;
|
||||
|
||||
pdata = spi->dev.platform_data;
|
||||
if (!pdata) {
|
||||
pdev_data = kzalloc(sizeof(*pdev_data), GFP_KERNEL);
|
||||
if (!pdev_data)
|
||||
goto out;
|
||||
|
||||
pdev_data->pdata = spi->dev.platform_data;
|
||||
if (!pdev_data->pdata) {
|
||||
dev_err(&spi->dev, "no platform data\n");
|
||||
return -ENODEV;
|
||||
ret = -ENODEV;
|
||||
goto out_free_pdev_data;
|
||||
}
|
||||
|
||||
pdata->ops = &spi_ops;
|
||||
pdev_data->if_ops = &spi_ops;
|
||||
|
||||
glue = kzalloc(sizeof(*glue), GFP_KERNEL);
|
||||
if (!glue) {
|
||||
dev_err(&spi->dev, "can't allocate glue\n");
|
||||
goto out;
|
||||
goto out_free_pdev_data;
|
||||
}
|
||||
|
||||
glue->dev = &spi->dev;
|
||||
|
@ -359,7 +364,7 @@ static int wl1271_probe(struct spi_device *spi)
|
|||
goto out_free_glue;
|
||||
}
|
||||
|
||||
glue->core = platform_device_alloc("wl12xx", -1);
|
||||
glue->core = platform_device_alloc("wl12xx", PLATFORM_DEVID_AUTO);
|
||||
if (!glue->core) {
|
||||
dev_err(glue->dev, "can't allocate platform_device\n");
|
||||
ret = -ENOMEM;
|
||||
|
@ -380,7 +385,8 @@ static int wl1271_probe(struct spi_device *spi)
|
|||
goto out_dev_put;
|
||||
}
|
||||
|
||||
ret = platform_device_add_data(glue->core, pdata, sizeof(*pdata));
|
||||
ret = platform_device_add_data(glue->core, pdev_data,
|
||||
sizeof(*pdev_data));
|
||||
if (ret) {
|
||||
dev_err(glue->dev, "can't add platform data\n");
|
||||
goto out_dev_put;
|
||||
|
@ -399,6 +405,10 @@ out_dev_put:
|
|||
|
||||
out_free_glue:
|
||||
kfree(glue);
|
||||
|
||||
out_free_pdev_data:
|
||||
kfree(pdev_data);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -183,7 +183,6 @@ struct wl1271 {
|
|||
|
||||
struct wl1271_if_operations *if_ops;
|
||||
|
||||
void (*set_power)(bool enable);
|
||||
int irq;
|
||||
|
||||
spinlock_t wl_lock;
|
||||
|
|
|
@ -206,6 +206,11 @@ struct wl1271_if_operations {
|
|||
void (*set_block_size) (struct device *child, unsigned int blksz);
|
||||
};
|
||||
|
||||
struct wlcore_platdev_data {
|
||||
struct wl12xx_platform_data *pdata;
|
||||
struct wl1271_if_operations *if_ops;
|
||||
};
|
||||
|
||||
#define MAX_NUM_KEYS 14
|
||||
#define MAX_KEY_SIZE 32
|
||||
|
||||
|
|
|
@ -27,5 +27,6 @@ config NFC_WILINK
|
|||
into the kernel or say M to compile it as module.
|
||||
|
||||
source "drivers/nfc/pn544/Kconfig"
|
||||
source "drivers/nfc/microread/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#
|
||||
|
||||
obj-$(CONFIG_NFC_PN544) += pn544/
|
||||
obj-$(CONFIG_NFC_MICROREAD) += microread/
|
||||
obj-$(CONFIG_NFC_PN533) += pn533.o
|
||||
obj-$(CONFIG_NFC_WILINK) += nfcwilink.o
|
||||
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
config NFC_MICROREAD
|
||||
tristate "Inside Secure microread NFC driver"
|
||||
depends on NFC_HCI
|
||||
select CRC_CCITT
|
||||
default n
|
||||
---help---
|
||||
This module contains the main code for Inside Secure microread
|
||||
NFC chipsets. It implements the chipset HCI logic and hooks into
|
||||
the NFC kernel APIs. Physical layers will register against it.
|
||||
|
||||
To compile this driver as a module, choose m here. The module will
|
||||
be called microread.
|
||||
Say N if unsure.
|
||||
|
||||
config NFC_MICROREAD_I2C
|
||||
tristate "NFC Microread i2c support"
|
||||
depends on NFC_MICROREAD && I2C && NFC_SHDLC
|
||||
---help---
|
||||
This module adds support for the i2c interface of adapters using
|
||||
Inside microread chipsets. Select this if your platform is using
|
||||
the i2c bus.
|
||||
|
||||
If you choose to build a module, it'll be called microread_i2c.
|
||||
Say N if unsure.
|
||||
|
||||
config NFC_MICROREAD_MEI
|
||||
tristate "NFC Microread MEI support"
|
||||
depends on NFC_MICROREAD && INTEL_MEI_BUS_NFC
|
||||
---help---
|
||||
This module adds support for the mei interface of adapters using
|
||||
Inside microread chipsets. Select this if your microread chipset
|
||||
is handled by Intel's Management Engine Interface on your platform.
|
||||
|
||||
If you choose to build a module, it'll be called microread_mei.
|
||||
Say N if unsure.
|
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
# Makefile for Microread HCI based NFC driver
|
||||
#
|
||||
|
||||
microread_i2c-objs = i2c.o
|
||||
microread_mei-objs = mei.o
|
||||
|
||||
obj-$(CONFIG_NFC_MICROREAD) += microread.o
|
||||
obj-$(CONFIG_NFC_MICROREAD_I2C) += microread_i2c.o
|
||||
obj-$(CONFIG_NFC_MICROREAD_MEI) += microread_mei.o
|
|
@ -0,0 +1,340 @@
|
|||
/*
|
||||
* HCI based Driver for Inside Secure microread NFC Chip - i2c layer
|
||||
*
|
||||
* Copyright (C) 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#include <linux/nfc.h>
|
||||
#include <net/nfc/hci.h>
|
||||
#include <net/nfc/llc.h>
|
||||
|
||||
#include "microread.h"
|
||||
|
||||
#define MICROREAD_I2C_DRIVER_NAME "microread"
|
||||
|
||||
#define MICROREAD_I2C_FRAME_HEADROOM 1
|
||||
#define MICROREAD_I2C_FRAME_TAILROOM 1
|
||||
|
||||
/* framing in HCI mode */
|
||||
#define MICROREAD_I2C_LLC_LEN 1
|
||||
#define MICROREAD_I2C_LLC_CRC 1
|
||||
#define MICROREAD_I2C_LLC_LEN_CRC (MICROREAD_I2C_LLC_LEN + \
|
||||
MICROREAD_I2C_LLC_CRC)
|
||||
#define MICROREAD_I2C_LLC_MIN_SIZE (1 + MICROREAD_I2C_LLC_LEN_CRC)
|
||||
#define MICROREAD_I2C_LLC_MAX_PAYLOAD 29
|
||||
#define MICROREAD_I2C_LLC_MAX_SIZE (MICROREAD_I2C_LLC_LEN_CRC + 1 + \
|
||||
MICROREAD_I2C_LLC_MAX_PAYLOAD)
|
||||
|
||||
struct microread_i2c_phy {
|
||||
struct i2c_client *i2c_dev;
|
||||
struct nfc_hci_dev *hdev;
|
||||
|
||||
int irq;
|
||||
|
||||
int hard_fault; /*
|
||||
* < 0 if hardware error occured (e.g. i2c err)
|
||||
* and prevents normal operation.
|
||||
*/
|
||||
};
|
||||
|
||||
#define I2C_DUMP_SKB(info, skb) \
|
||||
do { \
|
||||
pr_debug("%s:\n", info); \
|
||||
print_hex_dump(KERN_DEBUG, "i2c: ", DUMP_PREFIX_OFFSET, \
|
||||
16, 1, (skb)->data, (skb)->len, 0); \
|
||||
} while (0)
|
||||
|
||||
static void microread_i2c_add_len_crc(struct sk_buff *skb)
|
||||
{
|
||||
int i;
|
||||
u8 crc = 0;
|
||||
int len;
|
||||
|
||||
len = skb->len;
|
||||
*skb_push(skb, 1) = len;
|
||||
|
||||
for (i = 0; i < skb->len; i++)
|
||||
crc = crc ^ skb->data[i];
|
||||
|
||||
*skb_put(skb, 1) = crc;
|
||||
}
|
||||
|
||||
static void microread_i2c_remove_len_crc(struct sk_buff *skb)
|
||||
{
|
||||
skb_pull(skb, MICROREAD_I2C_FRAME_HEADROOM);
|
||||
skb_trim(skb, MICROREAD_I2C_FRAME_TAILROOM);
|
||||
}
|
||||
|
||||
static int check_crc(struct sk_buff *skb)
|
||||
{
|
||||
int i;
|
||||
u8 crc = 0;
|
||||
|
||||
for (i = 0; i < skb->len - 1; i++)
|
||||
crc = crc ^ skb->data[i];
|
||||
|
||||
if (crc != skb->data[skb->len-1]) {
|
||||
pr_err(MICROREAD_I2C_DRIVER_NAME
|
||||
": CRC error 0x%x != 0x%x\n",
|
||||
crc, skb->data[skb->len-1]);
|
||||
|
||||
pr_info(DRIVER_DESC ": %s : BAD CRC\n", __func__);
|
||||
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int microread_i2c_enable(void *phy_id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void microread_i2c_disable(void *phy_id)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static int microread_i2c_write(void *phy_id, struct sk_buff *skb)
|
||||
{
|
||||
int r;
|
||||
struct microread_i2c_phy *phy = phy_id;
|
||||
struct i2c_client *client = phy->i2c_dev;
|
||||
|
||||
if (phy->hard_fault != 0)
|
||||
return phy->hard_fault;
|
||||
|
||||
usleep_range(3000, 6000);
|
||||
|
||||
microread_i2c_add_len_crc(skb);
|
||||
|
||||
I2C_DUMP_SKB("i2c frame written", skb);
|
||||
|
||||
r = i2c_master_send(client, skb->data, skb->len);
|
||||
|
||||
if (r == -EREMOTEIO) { /* Retry, chip was in standby */
|
||||
usleep_range(6000, 10000);
|
||||
r = i2c_master_send(client, skb->data, skb->len);
|
||||
}
|
||||
|
||||
if (r >= 0) {
|
||||
if (r != skb->len)
|
||||
r = -EREMOTEIO;
|
||||
else
|
||||
r = 0;
|
||||
}
|
||||
|
||||
microread_i2c_remove_len_crc(skb);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
static int microread_i2c_read(struct microread_i2c_phy *phy,
|
||||
struct sk_buff **skb)
|
||||
{
|
||||
int r;
|
||||
u8 len;
|
||||
u8 tmp[MICROREAD_I2C_LLC_MAX_SIZE - 1];
|
||||
struct i2c_client *client = phy->i2c_dev;
|
||||
|
||||
pr_debug("%s\n", __func__);
|
||||
|
||||
r = i2c_master_recv(client, &len, 1);
|
||||
if (r != 1) {
|
||||
dev_err(&client->dev, "cannot read len byte\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
if ((len < MICROREAD_I2C_LLC_MIN_SIZE) ||
|
||||
(len > MICROREAD_I2C_LLC_MAX_SIZE)) {
|
||||
dev_err(&client->dev, "invalid len byte\n");
|
||||
pr_err("invalid len byte\n");
|
||||
r = -EBADMSG;
|
||||
goto flush;
|
||||
}
|
||||
|
||||
*skb = alloc_skb(1 + len, GFP_KERNEL);
|
||||
if (*skb == NULL) {
|
||||
r = -ENOMEM;
|
||||
goto flush;
|
||||
}
|
||||
|
||||
*skb_put(*skb, 1) = len;
|
||||
|
||||
r = i2c_master_recv(client, skb_put(*skb, len), len);
|
||||
if (r != len) {
|
||||
kfree_skb(*skb);
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
I2C_DUMP_SKB("cc frame read", *skb);
|
||||
|
||||
r = check_crc(*skb);
|
||||
if (r != 0) {
|
||||
kfree_skb(*skb);
|
||||
r = -EBADMSG;
|
||||
goto flush;
|
||||
}
|
||||
|
||||
skb_pull(*skb, 1);
|
||||
skb_trim(*skb, (*skb)->len - MICROREAD_I2C_FRAME_TAILROOM);
|
||||
|
||||
usleep_range(3000, 6000);
|
||||
|
||||
return 0;
|
||||
|
||||
flush:
|
||||
if (i2c_master_recv(client, tmp, sizeof(tmp)) < 0)
|
||||
r = -EREMOTEIO;
|
||||
|
||||
usleep_range(3000, 6000);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static irqreturn_t microread_i2c_irq_thread_fn(int irq, void *phy_id)
|
||||
{
|
||||
struct microread_i2c_phy *phy = phy_id;
|
||||
struct i2c_client *client;
|
||||
struct sk_buff *skb = NULL;
|
||||
int r;
|
||||
|
||||
if (!phy || irq != phy->i2c_dev->irq) {
|
||||
WARN_ON_ONCE(1);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
client = phy->i2c_dev;
|
||||
dev_dbg(&client->dev, "IRQ\n");
|
||||
|
||||
if (phy->hard_fault != 0)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
r = microread_i2c_read(phy, &skb);
|
||||
if (r == -EREMOTEIO) {
|
||||
phy->hard_fault = r;
|
||||
|
||||
nfc_hci_recv_frame(phy->hdev, NULL);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
} else if ((r == -ENOMEM) || (r == -EBADMSG)) {
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
nfc_hci_recv_frame(phy->hdev, skb);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct nfc_phy_ops i2c_phy_ops = {
|
||||
.write = microread_i2c_write,
|
||||
.enable = microread_i2c_enable,
|
||||
.disable = microread_i2c_disable,
|
||||
};
|
||||
|
||||
static int microread_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct microread_i2c_phy *phy;
|
||||
struct microread_nfc_platform_data *pdata =
|
||||
dev_get_platdata(&client->dev);
|
||||
int r;
|
||||
|
||||
dev_dbg(&client->dev, "client %p", client);
|
||||
|
||||
if (!pdata) {
|
||||
dev_err(&client->dev, "client %p: missing platform data",
|
||||
client);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
phy = devm_kzalloc(&client->dev, sizeof(struct microread_i2c_phy),
|
||||
GFP_KERNEL);
|
||||
if (!phy) {
|
||||
dev_err(&client->dev, "Can't allocate microread phy");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(client, phy);
|
||||
phy->i2c_dev = client;
|
||||
|
||||
r = request_threaded_irq(client->irq, NULL, microread_i2c_irq_thread_fn,
|
||||
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
||||
MICROREAD_I2C_DRIVER_NAME, phy);
|
||||
if (r) {
|
||||
dev_err(&client->dev, "Unable to register IRQ handler");
|
||||
return r;
|
||||
}
|
||||
|
||||
r = microread_probe(phy, &i2c_phy_ops, LLC_SHDLC_NAME,
|
||||
MICROREAD_I2C_FRAME_HEADROOM,
|
||||
MICROREAD_I2C_FRAME_TAILROOM,
|
||||
MICROREAD_I2C_LLC_MAX_PAYLOAD, &phy->hdev);
|
||||
if (r < 0)
|
||||
goto err_irq;
|
||||
|
||||
dev_info(&client->dev, "Probed");
|
||||
|
||||
return 0;
|
||||
|
||||
err_irq:
|
||||
free_irq(client->irq, phy);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int microread_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct microread_i2c_phy *phy = i2c_get_clientdata(client);
|
||||
|
||||
dev_dbg(&client->dev, "%s\n", __func__);
|
||||
|
||||
microread_remove(phy->hdev);
|
||||
|
||||
free_irq(client->irq, phy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct i2c_device_id microread_i2c_id[] = {
|
||||
{ MICROREAD_I2C_DRIVER_NAME, 0},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, microread_i2c_id);
|
||||
|
||||
static struct i2c_driver microread_i2c_driver = {
|
||||
.driver = {
|
||||
.name = MICROREAD_I2C_DRIVER_NAME,
|
||||
},
|
||||
.probe = microread_i2c_probe,
|
||||
.remove = microread_i2c_remove,
|
||||
.id_table = microread_i2c_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(microread_i2c_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
* HCI based Driver for Inside Secure microread NFC Chip
|
||||
*
|
||||
* Copyright (C) 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/mei_bus.h>
|
||||
|
||||
#include <linux/nfc.h>
|
||||
#include <net/nfc/hci.h>
|
||||
#include <net/nfc/llc.h>
|
||||
|
||||
#include "microread.h"
|
||||
|
||||
#define MICROREAD_DRIVER_NAME "microread"
|
||||
|
||||
#define MICROREAD_UUID UUID_LE(0x0bb17a78, 0x2a8e, 0x4c50, 0x94, \
|
||||
0xd4, 0x50, 0x26, 0x67, 0x23, 0x77, 0x5c)
|
||||
|
||||
struct mei_nfc_hdr {
|
||||
u8 cmd;
|
||||
u8 status;
|
||||
u16 req_id;
|
||||
u32 reserved;
|
||||
u16 data_size;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define MEI_NFC_HEADER_SIZE 10
|
||||
#define MEI_NFC_MAX_HCI_PAYLOAD 300
|
||||
#define MEI_NFC_MAX_READ (MEI_NFC_HEADER_SIZE + MEI_NFC_MAX_HCI_PAYLOAD)
|
||||
|
||||
struct microread_mei_phy {
|
||||
struct mei_device *mei_device;
|
||||
struct nfc_hci_dev *hdev;
|
||||
|
||||
int powered;
|
||||
|
||||
int hard_fault; /*
|
||||
* < 0 if hardware error occured (e.g. i2c err)
|
||||
* and prevents normal operation.
|
||||
*/
|
||||
};
|
||||
|
||||
#define MEI_DUMP_SKB_IN(info, skb) \
|
||||
do { \
|
||||
pr_debug("%s:\n", info); \
|
||||
print_hex_dump(KERN_DEBUG, "mei in : ", DUMP_PREFIX_OFFSET, \
|
||||
16, 1, (skb)->data, (skb)->len, 0); \
|
||||
} while (0)
|
||||
|
||||
#define MEI_DUMP_SKB_OUT(info, skb) \
|
||||
do { \
|
||||
pr_debug("%s:\n", info); \
|
||||
print_hex_dump(KERN_DEBUG, "mei out: ", DUMP_PREFIX_OFFSET, \
|
||||
16, 1, (skb)->data, (skb)->len, 0); \
|
||||
} while (0)
|
||||
|
||||
static int microread_mei_enable(void *phy_id)
|
||||
{
|
||||
struct microread_mei_phy *phy = phy_id;
|
||||
|
||||
pr_info(DRIVER_DESC ": %s\n", __func__);
|
||||
|
||||
phy->powered = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void microread_mei_disable(void *phy_id)
|
||||
{
|
||||
struct microread_mei_phy *phy = phy_id;
|
||||
|
||||
pr_info(DRIVER_DESC ": %s\n", __func__);
|
||||
|
||||
phy->powered = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Writing a frame must not return the number of written bytes.
|
||||
* It must return either zero for success, or <0 for error.
|
||||
* In addition, it must not alter the skb
|
||||
*/
|
||||
static int microread_mei_write(void *phy_id, struct sk_buff *skb)
|
||||
{
|
||||
struct microread_mei_phy *phy = phy_id;
|
||||
int r;
|
||||
|
||||
MEI_DUMP_SKB_OUT("mei frame sent", skb);
|
||||
|
||||
r = mei_send(phy->device, skb->data, skb->len);
|
||||
if (r > 0)
|
||||
r = 0;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void microread_event_cb(struct mei_device *device, u32 events,
|
||||
void *context)
|
||||
{
|
||||
struct microread_mei_phy *phy = context;
|
||||
|
||||
if (phy->hard_fault != 0)
|
||||
return;
|
||||
|
||||
if (events & BIT(MEI_EVENT_RX)) {
|
||||
struct sk_buff *skb;
|
||||
int reply_size;
|
||||
|
||||
skb = alloc_skb(MEI_NFC_MAX_READ, GFP_KERNEL);
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
reply_size = mei_recv(device, skb->data, MEI_NFC_MAX_READ);
|
||||
if (reply_size < MEI_NFC_HEADER_SIZE) {
|
||||
kfree(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
skb_put(skb, reply_size);
|
||||
skb_pull(skb, MEI_NFC_HEADER_SIZE);
|
||||
|
||||
MEI_DUMP_SKB_IN("mei frame read", skb);
|
||||
|
||||
nfc_hci_recv_frame(phy->hdev, skb);
|
||||
}
|
||||
}
|
||||
|
||||
static struct nfc_phy_ops mei_phy_ops = {
|
||||
.write = microread_mei_write,
|
||||
.enable = microread_mei_enable,
|
||||
.disable = microread_mei_disable,
|
||||
};
|
||||
|
||||
static int microread_mei_probe(struct mei_device *device,
|
||||
const struct mei_id *id)
|
||||
{
|
||||
struct microread_mei_phy *phy;
|
||||
int r;
|
||||
|
||||
pr_info("Probing NFC microread\n");
|
||||
|
||||
phy = kzalloc(sizeof(struct microread_mei_phy), GFP_KERNEL);
|
||||
if (!phy) {
|
||||
pr_err("Cannot allocate memory for microread mei phy.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
phy->device = device;
|
||||
mei_set_clientdata(device, phy);
|
||||
|
||||
r = mei_register_event_cb(device, microread_event_cb, phy);
|
||||
if (r) {
|
||||
pr_err(MICROREAD_DRIVER_NAME ": event cb registration failed\n");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
r = microread_probe(phy, &mei_phy_ops, LLC_NOP_NAME,
|
||||
MEI_NFC_HEADER_SIZE, 0, MEI_NFC_MAX_HCI_PAYLOAD,
|
||||
&phy->hdev);
|
||||
if (r < 0)
|
||||
goto err_out;
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
kfree(phy);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int microread_mei_remove(struct mei_device *device)
|
||||
{
|
||||
struct microread_mei_phy *phy = mei_get_clientdata(device);
|
||||
|
||||
pr_info("Removing microread\n");
|
||||
|
||||
microread_remove(phy->hdev);
|
||||
|
||||
if (phy->powered)
|
||||
microread_mei_disable(phy);
|
||||
|
||||
kfree(phy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct mei_id microread_mei_tbl[] = {
|
||||
{ MICROREAD_DRIVER_NAME, MICROREAD_UUID },
|
||||
|
||||
/* required last entry */
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(mei, microread_mei_tbl);
|
||||
|
||||
static struct mei_driver microread_driver = {
|
||||
.id_table = microread_mei_tbl,
|
||||
.name = MICROREAD_DRIVER_NAME,
|
||||
|
||||
.probe = microread_mei_probe,
|
||||
.remove = microread_mei_remove,
|
||||
};
|
||||
|
||||
static int microread_mei_init(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
pr_debug(DRIVER_DESC ": %s\n", __func__);
|
||||
|
||||
r = mei_driver_register(µread_driver);
|
||||
if (r) {
|
||||
pr_err(MICROREAD_DRIVER_NAME ": driver registration failed\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void microread_mei_exit(void)
|
||||
{
|
||||
mei_driver_unregister(µread_driver);
|
||||
}
|
||||
|
||||
module_init(microread_mei_init);
|
||||
module_exit(microread_mei_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
|
@ -0,0 +1,728 @@
|
|||
/*
|
||||
* HCI based Driver for Inside Secure microread NFC Chip
|
||||
*
|
||||
* Copyright (C) 2013 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/crc-ccitt.h>
|
||||
|
||||
#include <linux/nfc.h>
|
||||
#include <net/nfc/nfc.h>
|
||||
#include <net/nfc/hci.h>
|
||||
#include <net/nfc/llc.h>
|
||||
|
||||
#include "microread.h"
|
||||
|
||||
/* Proprietary gates, events, commands and registers */
|
||||
/* Admin */
|
||||
#define MICROREAD_GATE_ID_ADM NFC_HCI_ADMIN_GATE
|
||||
#define MICROREAD_GATE_ID_MGT 0x01
|
||||
#define MICROREAD_GATE_ID_OS 0x02
|
||||
#define MICROREAD_GATE_ID_TESTRF 0x03
|
||||
#define MICROREAD_GATE_ID_LOOPBACK NFC_HCI_LOOPBACK_GATE
|
||||
#define MICROREAD_GATE_ID_IDT NFC_HCI_ID_MGMT_GATE
|
||||
#define MICROREAD_GATE_ID_LMS NFC_HCI_LINK_MGMT_GATE
|
||||
|
||||
/* Reader */
|
||||
#define MICROREAD_GATE_ID_MREAD_GEN 0x10
|
||||
#define MICROREAD_GATE_ID_MREAD_ISO_B NFC_HCI_RF_READER_B_GATE
|
||||
#define MICROREAD_GATE_ID_MREAD_NFC_T1 0x12
|
||||
#define MICROREAD_GATE_ID_MREAD_ISO_A NFC_HCI_RF_READER_A_GATE
|
||||
#define MICROREAD_GATE_ID_MREAD_NFC_T3 0x14
|
||||
#define MICROREAD_GATE_ID_MREAD_ISO_15_3 0x15
|
||||
#define MICROREAD_GATE_ID_MREAD_ISO_15_2 0x16
|
||||
#define MICROREAD_GATE_ID_MREAD_ISO_B_3 0x17
|
||||
#define MICROREAD_GATE_ID_MREAD_BPRIME 0x18
|
||||
#define MICROREAD_GATE_ID_MREAD_ISO_A_3 0x19
|
||||
|
||||
/* Card */
|
||||
#define MICROREAD_GATE_ID_MCARD_GEN 0x20
|
||||
#define MICROREAD_GATE_ID_MCARD_ISO_B 0x21
|
||||
#define MICROREAD_GATE_ID_MCARD_BPRIME 0x22
|
||||
#define MICROREAD_GATE_ID_MCARD_ISO_A 0x23
|
||||
#define MICROREAD_GATE_ID_MCARD_NFC_T3 0x24
|
||||
#define MICROREAD_GATE_ID_MCARD_ISO_15_3 0x25
|
||||
#define MICROREAD_GATE_ID_MCARD_ISO_15_2 0x26
|
||||
#define MICROREAD_GATE_ID_MCARD_ISO_B_2 0x27
|
||||
#define MICROREAD_GATE_ID_MCARD_ISO_CUSTOM 0x28
|
||||
#define MICROREAD_GATE_ID_SECURE_ELEMENT 0x2F
|
||||
|
||||
/* P2P */
|
||||
#define MICROREAD_GATE_ID_P2P_GEN 0x30
|
||||
#define MICROREAD_GATE_ID_P2P_TARGET 0x31
|
||||
#define MICROREAD_PAR_P2P_TARGET_MODE 0x01
|
||||
#define MICROREAD_PAR_P2P_TARGET_GT 0x04
|
||||
#define MICROREAD_GATE_ID_P2P_INITIATOR 0x32
|
||||
#define MICROREAD_PAR_P2P_INITIATOR_GI 0x01
|
||||
#define MICROREAD_PAR_P2P_INITIATOR_GT 0x03
|
||||
|
||||
/* Those pipes are created/opened by default in the chip */
|
||||
#define MICROREAD_PIPE_ID_LMS 0x00
|
||||
#define MICROREAD_PIPE_ID_ADMIN 0x01
|
||||
#define MICROREAD_PIPE_ID_MGT 0x02
|
||||
#define MICROREAD_PIPE_ID_OS 0x03
|
||||
#define MICROREAD_PIPE_ID_HDS_LOOPBACK 0x04
|
||||
#define MICROREAD_PIPE_ID_HDS_IDT 0x05
|
||||
#define MICROREAD_PIPE_ID_HDS_MCARD_ISO_B 0x08
|
||||
#define MICROREAD_PIPE_ID_HDS_MCARD_ISO_BPRIME 0x09
|
||||
#define MICROREAD_PIPE_ID_HDS_MCARD_ISO_A 0x0A
|
||||
#define MICROREAD_PIPE_ID_HDS_MCARD_ISO_15_3 0x0B
|
||||
#define MICROREAD_PIPE_ID_HDS_MCARD_ISO_15_2 0x0C
|
||||
#define MICROREAD_PIPE_ID_HDS_MCARD_NFC_T3 0x0D
|
||||
#define MICROREAD_PIPE_ID_HDS_MCARD_ISO_B_2 0x0E
|
||||
#define MICROREAD_PIPE_ID_HDS_MCARD_CUSTOM 0x0F
|
||||
#define MICROREAD_PIPE_ID_HDS_MREAD_ISO_B 0x10
|
||||
#define MICROREAD_PIPE_ID_HDS_MREAD_NFC_T1 0x11
|
||||
#define MICROREAD_PIPE_ID_HDS_MREAD_ISO_A 0x12
|
||||
#define MICROREAD_PIPE_ID_HDS_MREAD_ISO_15_3 0x13
|
||||
#define MICROREAD_PIPE_ID_HDS_MREAD_ISO_15_2 0x14
|
||||
#define MICROREAD_PIPE_ID_HDS_MREAD_NFC_T3 0x15
|
||||
#define MICROREAD_PIPE_ID_HDS_MREAD_ISO_B_3 0x16
|
||||
#define MICROREAD_PIPE_ID_HDS_MREAD_BPRIME 0x17
|
||||
#define MICROREAD_PIPE_ID_HDS_MREAD_ISO_A_3 0x18
|
||||
#define MICROREAD_PIPE_ID_HDS_MREAD_GEN 0x1B
|
||||
#define MICROREAD_PIPE_ID_HDS_STACKED_ELEMENT 0x1C
|
||||
#define MICROREAD_PIPE_ID_HDS_INSTANCES 0x1D
|
||||
#define MICROREAD_PIPE_ID_HDS_TESTRF 0x1E
|
||||
#define MICROREAD_PIPE_ID_HDS_P2P_TARGET 0x1F
|
||||
#define MICROREAD_PIPE_ID_HDS_P2P_INITIATOR 0x20
|
||||
|
||||
/* Events */
|
||||
#define MICROREAD_EVT_MREAD_DISCOVERY_OCCURED NFC_HCI_EVT_TARGET_DISCOVERED
|
||||
#define MICROREAD_EVT_MREAD_CARD_FOUND 0x3D
|
||||
#define MICROREAD_EMCF_A_ATQA 0
|
||||
#define MICROREAD_EMCF_A_SAK 2
|
||||
#define MICROREAD_EMCF_A_LEN 3
|
||||
#define MICROREAD_EMCF_A_UID 4
|
||||
#define MICROREAD_EMCF_A3_ATQA 0
|
||||
#define MICROREAD_EMCF_A3_SAK 2
|
||||
#define MICROREAD_EMCF_A3_LEN 3
|
||||
#define MICROREAD_EMCF_A3_UID 4
|
||||
#define MICROREAD_EMCF_B_UID 0
|
||||
#define MICROREAD_EMCF_T1_ATQA 0
|
||||
#define MICROREAD_EMCF_T1_UID 4
|
||||
#define MICROREAD_EMCF_T3_UID 0
|
||||
#define MICROREAD_EVT_MREAD_DISCOVERY_START NFC_HCI_EVT_READER_REQUESTED
|
||||
#define MICROREAD_EVT_MREAD_DISCOVERY_START_SOME 0x3E
|
||||
#define MICROREAD_EVT_MREAD_DISCOVERY_STOP NFC_HCI_EVT_END_OPERATION
|
||||
#define MICROREAD_EVT_MREAD_SIM_REQUESTS 0x3F
|
||||
#define MICROREAD_EVT_MCARD_EXCHANGE NFC_HCI_EVT_TARGET_DISCOVERED
|
||||
#define MICROREAD_EVT_P2P_INITIATOR_EXCHANGE_TO_RF 0x20
|
||||
#define MICROREAD_EVT_P2P_INITIATOR_EXCHANGE_FROM_RF 0x21
|
||||
#define MICROREAD_EVT_MCARD_FIELD_ON 0x11
|
||||
#define MICROREAD_EVT_P2P_TARGET_ACTIVATED 0x13
|
||||
#define MICROREAD_EVT_P2P_TARGET_DEACTIVATED 0x12
|
||||
#define MICROREAD_EVT_MCARD_FIELD_OFF 0x14
|
||||
|
||||
/* Commands */
|
||||
#define MICROREAD_CMD_MREAD_EXCHANGE 0x10
|
||||
#define MICROREAD_CMD_MREAD_SUBSCRIBE 0x3F
|
||||
|
||||
/* Hosts IDs */
|
||||
#define MICROREAD_ELT_ID_HDS NFC_HCI_TERMINAL_HOST_ID
|
||||
#define MICROREAD_ELT_ID_SIM NFC_HCI_UICC_HOST_ID
|
||||
#define MICROREAD_ELT_ID_SE1 0x03
|
||||
#define MICROREAD_ELT_ID_SE2 0x04
|
||||
#define MICROREAD_ELT_ID_SE3 0x05
|
||||
|
||||
static struct nfc_hci_gate microread_gates[] = {
|
||||
{MICROREAD_GATE_ID_ADM, MICROREAD_PIPE_ID_ADMIN},
|
||||
{MICROREAD_GATE_ID_LOOPBACK, MICROREAD_PIPE_ID_HDS_LOOPBACK},
|
||||
{MICROREAD_GATE_ID_IDT, MICROREAD_PIPE_ID_HDS_IDT},
|
||||
{MICROREAD_GATE_ID_LMS, MICROREAD_PIPE_ID_LMS},
|
||||
{MICROREAD_GATE_ID_MREAD_ISO_B, MICROREAD_PIPE_ID_HDS_MREAD_ISO_B},
|
||||
{MICROREAD_GATE_ID_MREAD_ISO_A, MICROREAD_PIPE_ID_HDS_MREAD_ISO_A},
|
||||
{MICROREAD_GATE_ID_MREAD_ISO_A_3, MICROREAD_PIPE_ID_HDS_MREAD_ISO_A_3},
|
||||
{MICROREAD_GATE_ID_MGT, MICROREAD_PIPE_ID_MGT},
|
||||
{MICROREAD_GATE_ID_OS, MICROREAD_PIPE_ID_OS},
|
||||
{MICROREAD_GATE_ID_MREAD_NFC_T1, MICROREAD_PIPE_ID_HDS_MREAD_NFC_T1},
|
||||
{MICROREAD_GATE_ID_MREAD_NFC_T3, MICROREAD_PIPE_ID_HDS_MREAD_NFC_T3},
|
||||
{MICROREAD_GATE_ID_P2P_TARGET, MICROREAD_PIPE_ID_HDS_P2P_TARGET},
|
||||
{MICROREAD_GATE_ID_P2P_INITIATOR, MICROREAD_PIPE_ID_HDS_P2P_INITIATOR}
|
||||
};
|
||||
|
||||
/* Largest headroom needed for outgoing custom commands */
|
||||
#define MICROREAD_CMDS_HEADROOM 2
|
||||
#define MICROREAD_CMD_TAILROOM 2
|
||||
|
||||
struct microread_info {
|
||||
struct nfc_phy_ops *phy_ops;
|
||||
void *phy_id;
|
||||
|
||||
struct nfc_hci_dev *hdev;
|
||||
|
||||
int async_cb_type;
|
||||
data_exchange_cb_t async_cb;
|
||||
void *async_cb_context;
|
||||
};
|
||||
|
||||
static int microread_open(struct nfc_hci_dev *hdev)
|
||||
{
|
||||
struct microread_info *info = nfc_hci_get_clientdata(hdev);
|
||||
|
||||
return info->phy_ops->enable(info->phy_id);
|
||||
}
|
||||
|
||||
static void microread_close(struct nfc_hci_dev *hdev)
|
||||
{
|
||||
struct microread_info *info = nfc_hci_get_clientdata(hdev);
|
||||
|
||||
info->phy_ops->disable(info->phy_id);
|
||||
}
|
||||
|
||||
static int microread_hci_ready(struct nfc_hci_dev *hdev)
|
||||
{
|
||||
int r;
|
||||
u8 param[4];
|
||||
|
||||
param[0] = 0x03;
|
||||
r = nfc_hci_send_cmd(hdev, MICROREAD_GATE_ID_MREAD_ISO_A,
|
||||
MICROREAD_CMD_MREAD_SUBSCRIBE, param, 1, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = nfc_hci_send_cmd(hdev, MICROREAD_GATE_ID_MREAD_ISO_A_3,
|
||||
MICROREAD_CMD_MREAD_SUBSCRIBE, NULL, 0, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
param[0] = 0x00;
|
||||
param[1] = 0x03;
|
||||
param[2] = 0x00;
|
||||
r = nfc_hci_send_cmd(hdev, MICROREAD_GATE_ID_MREAD_ISO_B,
|
||||
MICROREAD_CMD_MREAD_SUBSCRIBE, param, 3, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = nfc_hci_send_cmd(hdev, MICROREAD_GATE_ID_MREAD_NFC_T1,
|
||||
MICROREAD_CMD_MREAD_SUBSCRIBE, NULL, 0, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
param[0] = 0xFF;
|
||||
param[1] = 0xFF;
|
||||
param[2] = 0x00;
|
||||
param[3] = 0x00;
|
||||
r = nfc_hci_send_cmd(hdev, MICROREAD_GATE_ID_MREAD_NFC_T3,
|
||||
MICROREAD_CMD_MREAD_SUBSCRIBE, param, 4, NULL);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int microread_xmit(struct nfc_hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
struct microread_info *info = nfc_hci_get_clientdata(hdev);
|
||||
|
||||
return info->phy_ops->write(info->phy_id, skb);
|
||||
}
|
||||
|
||||
static int microread_start_poll(struct nfc_hci_dev *hdev,
|
||||
u32 im_protocols, u32 tm_protocols)
|
||||
{
|
||||
int r;
|
||||
|
||||
u8 param[2];
|
||||
u8 mode;
|
||||
|
||||
param[0] = 0x00;
|
||||
param[1] = 0x00;
|
||||
|
||||
if (im_protocols & NFC_PROTO_ISO14443_MASK)
|
||||
param[0] |= (1 << 2);
|
||||
|
||||
if (im_protocols & NFC_PROTO_ISO14443_B_MASK)
|
||||
param[0] |= 1;
|
||||
|
||||
if (im_protocols & NFC_PROTO_MIFARE_MASK)
|
||||
param[1] |= 1;
|
||||
|
||||
if (im_protocols & NFC_PROTO_JEWEL_MASK)
|
||||
param[0] |= (1 << 1);
|
||||
|
||||
if (im_protocols & NFC_PROTO_FELICA_MASK)
|
||||
param[0] |= (1 << 5);
|
||||
|
||||
if (im_protocols & NFC_PROTO_NFC_DEP_MASK)
|
||||
param[1] |= (1 << 1);
|
||||
|
||||
if ((im_protocols | tm_protocols) & NFC_PROTO_NFC_DEP_MASK) {
|
||||
hdev->gb = nfc_get_local_general_bytes(hdev->ndev,
|
||||
&hdev->gb_len);
|
||||
if (hdev->gb == NULL || hdev->gb_len == 0) {
|
||||
im_protocols &= ~NFC_PROTO_NFC_DEP_MASK;
|
||||
tm_protocols &= ~NFC_PROTO_NFC_DEP_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
r = nfc_hci_send_event(hdev, MICROREAD_GATE_ID_MREAD_ISO_A,
|
||||
MICROREAD_EVT_MREAD_DISCOVERY_STOP, NULL, 0);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
mode = 0xff;
|
||||
r = nfc_hci_set_param(hdev, MICROREAD_GATE_ID_P2P_TARGET,
|
||||
MICROREAD_PAR_P2P_TARGET_MODE, &mode, 1);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (im_protocols & NFC_PROTO_NFC_DEP_MASK) {
|
||||
r = nfc_hci_set_param(hdev, MICROREAD_GATE_ID_P2P_INITIATOR,
|
||||
MICROREAD_PAR_P2P_INITIATOR_GI,
|
||||
hdev->gb, hdev->gb_len);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) {
|
||||
r = nfc_hci_set_param(hdev, MICROREAD_GATE_ID_P2P_TARGET,
|
||||
MICROREAD_PAR_P2P_TARGET_GT,
|
||||
hdev->gb, hdev->gb_len);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
mode = 0x02;
|
||||
r = nfc_hci_set_param(hdev, MICROREAD_GATE_ID_P2P_TARGET,
|
||||
MICROREAD_PAR_P2P_TARGET_MODE, &mode, 1);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return nfc_hci_send_event(hdev, MICROREAD_GATE_ID_MREAD_ISO_A,
|
||||
MICROREAD_EVT_MREAD_DISCOVERY_START_SOME,
|
||||
param, 2);
|
||||
}
|
||||
|
||||
static int microread_dep_link_up(struct nfc_hci_dev *hdev,
|
||||
struct nfc_target *target, u8 comm_mode,
|
||||
u8 *gb, size_t gb_len)
|
||||
{
|
||||
struct sk_buff *rgb_skb = NULL;
|
||||
int r;
|
||||
|
||||
r = nfc_hci_get_param(hdev, target->hci_reader_gate,
|
||||
MICROREAD_PAR_P2P_INITIATOR_GT, &rgb_skb);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (rgb_skb->len == 0 || rgb_skb->len > NFC_GB_MAXSIZE) {
|
||||
r = -EPROTO;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
r = nfc_set_remote_general_bytes(hdev->ndev, rgb_skb->data,
|
||||
rgb_skb->len);
|
||||
if (r == 0)
|
||||
r = nfc_dep_link_is_up(hdev->ndev, target->idx, comm_mode,
|
||||
NFC_RF_INITIATOR);
|
||||
exit:
|
||||
kfree_skb(rgb_skb);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int microread_dep_link_down(struct nfc_hci_dev *hdev)
|
||||
{
|
||||
return nfc_hci_send_event(hdev, MICROREAD_GATE_ID_P2P_INITIATOR,
|
||||
MICROREAD_EVT_MREAD_DISCOVERY_STOP, NULL, 0);
|
||||
}
|
||||
|
||||
static int microread_target_from_gate(struct nfc_hci_dev *hdev, u8 gate,
|
||||
struct nfc_target *target)
|
||||
{
|
||||
switch (gate) {
|
||||
case MICROREAD_GATE_ID_P2P_INITIATOR:
|
||||
target->supported_protocols = NFC_PROTO_NFC_DEP_MASK;
|
||||
break;
|
||||
default:
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int microread_complete_target_discovered(struct nfc_hci_dev *hdev,
|
||||
u8 gate,
|
||||
struct nfc_target *target)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MICROREAD_CB_TYPE_READER_ALL 1
|
||||
|
||||
static void microread_im_transceive_cb(void *context, struct sk_buff *skb,
|
||||
int err)
|
||||
{
|
||||
struct microread_info *info = context;
|
||||
|
||||
switch (info->async_cb_type) {
|
||||
case MICROREAD_CB_TYPE_READER_ALL:
|
||||
if (err == 0) {
|
||||
if (skb->len == 0) {
|
||||
err = -EPROTO;
|
||||
kfree_skb(skb);
|
||||
info->async_cb(info->async_cb_context, NULL,
|
||||
-EPROTO);
|
||||
return;
|
||||
}
|
||||
|
||||
if (skb->data[skb->len - 1] != 0) {
|
||||
err = nfc_hci_result_to_errno(
|
||||
skb->data[skb->len - 1]);
|
||||
kfree_skb(skb);
|
||||
info->async_cb(info->async_cb_context, NULL,
|
||||
err);
|
||||
return;
|
||||
}
|
||||
|
||||
skb_trim(skb, skb->len - 1); /* RF Error ind. */
|
||||
}
|
||||
info->async_cb(info->async_cb_context, skb, err);
|
||||
break;
|
||||
default:
|
||||
if (err == 0)
|
||||
kfree_skb(skb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns:
|
||||
* <= 0: driver handled the data exchange
|
||||
* 1: driver doesn't especially handle, please do standard processing
|
||||
*/
|
||||
static int microread_im_transceive(struct nfc_hci_dev *hdev,
|
||||
struct nfc_target *target,
|
||||
struct sk_buff *skb, data_exchange_cb_t cb,
|
||||
void *cb_context)
|
||||
{
|
||||
struct microread_info *info = nfc_hci_get_clientdata(hdev);
|
||||
u8 control_bits;
|
||||
u16 crc;
|
||||
|
||||
pr_info("data exchange to gate 0x%x\n", target->hci_reader_gate);
|
||||
|
||||
if (target->hci_reader_gate == MICROREAD_GATE_ID_P2P_INITIATOR) {
|
||||
*skb_push(skb, 1) = 0;
|
||||
|
||||
return nfc_hci_send_event(hdev, target->hci_reader_gate,
|
||||
MICROREAD_EVT_P2P_INITIATOR_EXCHANGE_TO_RF,
|
||||
skb->data, skb->len);
|
||||
}
|
||||
|
||||
switch (target->hci_reader_gate) {
|
||||
case MICROREAD_GATE_ID_MREAD_ISO_A:
|
||||
control_bits = 0xCB;
|
||||
break;
|
||||
case MICROREAD_GATE_ID_MREAD_ISO_A_3:
|
||||
control_bits = 0xCB;
|
||||
break;
|
||||
case MICROREAD_GATE_ID_MREAD_ISO_B:
|
||||
control_bits = 0xCB;
|
||||
break;
|
||||
case MICROREAD_GATE_ID_MREAD_NFC_T1:
|
||||
control_bits = 0x1B;
|
||||
|
||||
crc = crc_ccitt(0xffff, skb->data, skb->len);
|
||||
crc = ~crc;
|
||||
*skb_put(skb, 1) = crc & 0xff;
|
||||
*skb_put(skb, 1) = crc >> 8;
|
||||
break;
|
||||
case MICROREAD_GATE_ID_MREAD_NFC_T3:
|
||||
control_bits = 0xDB;
|
||||
break;
|
||||
default:
|
||||
pr_info("Abort im_transceive to invalid gate 0x%x\n",
|
||||
target->hci_reader_gate);
|
||||
return 1;
|
||||
}
|
||||
|
||||
*skb_push(skb, 1) = control_bits;
|
||||
|
||||
info->async_cb_type = MICROREAD_CB_TYPE_READER_ALL;
|
||||
info->async_cb = cb;
|
||||
info->async_cb_context = cb_context;
|
||||
|
||||
return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate,
|
||||
MICROREAD_CMD_MREAD_EXCHANGE,
|
||||
skb->data, skb->len,
|
||||
microread_im_transceive_cb, info);
|
||||
}
|
||||
|
||||
static int microread_tm_send(struct nfc_hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = nfc_hci_send_event(hdev, MICROREAD_GATE_ID_P2P_TARGET,
|
||||
MICROREAD_EVT_MCARD_EXCHANGE,
|
||||
skb->data, skb->len);
|
||||
|
||||
kfree_skb(skb);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void microread_target_discovered(struct nfc_hci_dev *hdev, u8 gate,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct nfc_target *targets;
|
||||
int r = 0;
|
||||
|
||||
pr_info("target discovered to gate 0x%x\n", gate);
|
||||
|
||||
targets = kzalloc(sizeof(struct nfc_target), GFP_KERNEL);
|
||||
if (targets == NULL) {
|
||||
r = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
targets->hci_reader_gate = gate;
|
||||
|
||||
switch (gate) {
|
||||
case MICROREAD_GATE_ID_MREAD_ISO_A:
|
||||
targets->supported_protocols =
|
||||
nfc_hci_sak_to_protocol(skb->data[MICROREAD_EMCF_A_SAK]);
|
||||
targets->sens_res =
|
||||
be16_to_cpu(*(u16 *)&skb->data[MICROREAD_EMCF_A_ATQA]);
|
||||
targets->sel_res = skb->data[MICROREAD_EMCF_A_SAK];
|
||||
memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_A_UID],
|
||||
skb->data[MICROREAD_EMCF_A_LEN]);
|
||||
targets->nfcid1_len = skb->data[MICROREAD_EMCF_A_LEN];
|
||||
break;
|
||||
case MICROREAD_GATE_ID_MREAD_ISO_A_3:
|
||||
targets->supported_protocols =
|
||||
nfc_hci_sak_to_protocol(skb->data[MICROREAD_EMCF_A3_SAK]);
|
||||
targets->sens_res =
|
||||
be16_to_cpu(*(u16 *)&skb->data[MICROREAD_EMCF_A3_ATQA]);
|
||||
targets->sel_res = skb->data[MICROREAD_EMCF_A3_SAK];
|
||||
memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_A3_UID],
|
||||
skb->data[MICROREAD_EMCF_A3_LEN]);
|
||||
targets->nfcid1_len = skb->data[MICROREAD_EMCF_A3_LEN];
|
||||
break;
|
||||
case MICROREAD_GATE_ID_MREAD_ISO_B:
|
||||
targets->supported_protocols = NFC_PROTO_ISO14443_B_MASK;
|
||||
memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_B_UID], 4);
|
||||
targets->nfcid1_len = 4;
|
||||
break;
|
||||
case MICROREAD_GATE_ID_MREAD_NFC_T1:
|
||||
targets->supported_protocols = NFC_PROTO_JEWEL_MASK;
|
||||
targets->sens_res =
|
||||
le16_to_cpu(*(u16 *)&skb->data[MICROREAD_EMCF_T1_ATQA]);
|
||||
memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_T1_UID], 4);
|
||||
targets->nfcid1_len = 4;
|
||||
break;
|
||||
case MICROREAD_GATE_ID_MREAD_NFC_T3:
|
||||
targets->supported_protocols = NFC_PROTO_FELICA_MASK;
|
||||
memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_T3_UID], 8);
|
||||
targets->nfcid1_len = 8;
|
||||
break;
|
||||
default:
|
||||
pr_info("discard target discovered to gate 0x%x\n", gate);
|
||||
goto exit_free;
|
||||
}
|
||||
|
||||
r = nfc_targets_found(hdev->ndev, targets, 1);
|
||||
|
||||
exit_free:
|
||||
kfree(targets);
|
||||
|
||||
exit:
|
||||
kfree_skb(skb);
|
||||
|
||||
if (r)
|
||||
pr_err("Failed to handle discovered target err=%d", r);
|
||||
}
|
||||
|
||||
static int microread_event_received(struct nfc_hci_dev *hdev, u8 gate,
|
||||
u8 event, struct sk_buff *skb)
|
||||
{
|
||||
int r;
|
||||
u8 mode;
|
||||
|
||||
pr_info("Microread received event 0x%x to gate 0x%x\n", event, gate);
|
||||
|
||||
switch (event) {
|
||||
case MICROREAD_EVT_MREAD_CARD_FOUND:
|
||||
microread_target_discovered(hdev, gate, skb);
|
||||
return 0;
|
||||
|
||||
case MICROREAD_EVT_P2P_INITIATOR_EXCHANGE_FROM_RF:
|
||||
if (skb->len < 1) {
|
||||
kfree_skb(skb);
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
if (skb->data[skb->len - 1]) {
|
||||
kfree_skb(skb);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
skb_trim(skb, skb->len - 1);
|
||||
|
||||
r = nfc_tm_data_received(hdev->ndev, skb);
|
||||
break;
|
||||
|
||||
case MICROREAD_EVT_MCARD_FIELD_ON:
|
||||
case MICROREAD_EVT_MCARD_FIELD_OFF:
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
|
||||
case MICROREAD_EVT_P2P_TARGET_ACTIVATED:
|
||||
r = nfc_tm_activated(hdev->ndev, NFC_PROTO_NFC_DEP_MASK,
|
||||
NFC_COMM_PASSIVE, skb->data,
|
||||
skb->len);
|
||||
|
||||
kfree_skb(skb);
|
||||
break;
|
||||
|
||||
case MICROREAD_EVT_MCARD_EXCHANGE:
|
||||
if (skb->len < 1) {
|
||||
kfree_skb(skb);
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
if (skb->data[skb->len-1]) {
|
||||
kfree_skb(skb);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
skb_trim(skb, skb->len - 1);
|
||||
|
||||
r = nfc_tm_data_received(hdev->ndev, skb);
|
||||
break;
|
||||
|
||||
case MICROREAD_EVT_P2P_TARGET_DEACTIVATED:
|
||||
kfree_skb(skb);
|
||||
|
||||
mode = 0xff;
|
||||
r = nfc_hci_set_param(hdev, MICROREAD_GATE_ID_P2P_TARGET,
|
||||
MICROREAD_PAR_P2P_TARGET_MODE, &mode, 1);
|
||||
if (r)
|
||||
break;
|
||||
|
||||
r = nfc_hci_send_event(hdev, gate,
|
||||
MICROREAD_EVT_MREAD_DISCOVERY_STOP, NULL,
|
||||
0);
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct nfc_hci_ops microread_hci_ops = {
|
||||
.open = microread_open,
|
||||
.close = microread_close,
|
||||
.hci_ready = microread_hci_ready,
|
||||
.xmit = microread_xmit,
|
||||
.start_poll = microread_start_poll,
|
||||
.dep_link_up = microread_dep_link_up,
|
||||
.dep_link_down = microread_dep_link_down,
|
||||
.target_from_gate = microread_target_from_gate,
|
||||
.complete_target_discovered = microread_complete_target_discovered,
|
||||
.im_transceive = microread_im_transceive,
|
||||
.tm_send = microread_tm_send,
|
||||
.check_presence = NULL,
|
||||
.event_received = microread_event_received,
|
||||
};
|
||||
|
||||
int microread_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name,
|
||||
int phy_headroom, int phy_tailroom, int phy_payload,
|
||||
struct nfc_hci_dev **hdev)
|
||||
{
|
||||
struct microread_info *info;
|
||||
unsigned long quirks = 0;
|
||||
u32 protocols, se;
|
||||
struct nfc_hci_init_data init_data;
|
||||
int r;
|
||||
|
||||
info = kzalloc(sizeof(struct microread_info), GFP_KERNEL);
|
||||
if (!info) {
|
||||
pr_err("Cannot allocate memory for microread_info.\n");
|
||||
r = -ENOMEM;
|
||||
goto err_info_alloc;
|
||||
}
|
||||
|
||||
info->phy_ops = phy_ops;
|
||||
info->phy_id = phy_id;
|
||||
|
||||
init_data.gate_count = ARRAY_SIZE(microread_gates);
|
||||
memcpy(init_data.gates, microread_gates, sizeof(microread_gates));
|
||||
|
||||
strcpy(init_data.session_id, "MICROREA");
|
||||
|
||||
set_bit(NFC_HCI_QUIRK_SHORT_CLEAR, &quirks);
|
||||
|
||||
protocols = NFC_PROTO_JEWEL_MASK |
|
||||
NFC_PROTO_MIFARE_MASK |
|
||||
NFC_PROTO_FELICA_MASK |
|
||||
NFC_PROTO_ISO14443_MASK |
|
||||
NFC_PROTO_ISO14443_B_MASK |
|
||||
NFC_PROTO_NFC_DEP_MASK;
|
||||
|
||||
se = NFC_SE_UICC | NFC_SE_EMBEDDED;
|
||||
|
||||
info->hdev = nfc_hci_allocate_device(µread_hci_ops, &init_data,
|
||||
quirks, protocols, se, llc_name,
|
||||
phy_headroom +
|
||||
MICROREAD_CMDS_HEADROOM,
|
||||
phy_tailroom +
|
||||
MICROREAD_CMD_TAILROOM,
|
||||
phy_payload);
|
||||
if (!info->hdev) {
|
||||
pr_err("Cannot allocate nfc hdev.\n");
|
||||
r = -ENOMEM;
|
||||
goto err_alloc_hdev;
|
||||
}
|
||||
|
||||
nfc_hci_set_clientdata(info->hdev, info);
|
||||
|
||||
r = nfc_hci_register_device(info->hdev);
|
||||
if (r)
|
||||
goto err_regdev;
|
||||
|
||||
*hdev = info->hdev;
|
||||
|
||||
return 0;
|
||||
|
||||
err_regdev:
|
||||
nfc_hci_free_device(info->hdev);
|
||||
|
||||
err_alloc_hdev:
|
||||
kfree(info);
|
||||
|
||||
err_info_alloc:
|
||||
return r;
|
||||
}
|
||||
EXPORT_SYMBOL(microread_probe);
|
||||
|
||||
void microread_remove(struct nfc_hci_dev *hdev)
|
||||
{
|
||||
struct microread_info *info = nfc_hci_get_clientdata(hdev);
|
||||
|
||||
nfc_hci_unregister_device(hdev);
|
||||
nfc_hci_free_device(hdev);
|
||||
kfree(info);
|
||||
}
|
||||
EXPORT_SYMBOL(microread_remove);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (C) 2011 - 2012 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc.,
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __LOCAL_MICROREAD_H_
|
||||
#define __LOCAL_MICROREAD_H_
|
||||
|
||||
#include <net/nfc/hci.h>
|
||||
|
||||
#define DRIVER_DESC "NFC driver for microread"
|
||||
|
||||
int microread_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name,
|
||||
int phy_headroom, int phy_tailroom, int phy_payload,
|
||||
struct nfc_hci_dev **hdev);
|
||||
|
||||
void microread_remove(struct nfc_hci_dev *hdev);
|
||||
|
||||
#endif /* __LOCAL_MICROREAD_H_ */
|
|
@ -219,7 +219,7 @@ struct pn533_poll_modulations {
|
|||
u8 len;
|
||||
};
|
||||
|
||||
const struct pn533_poll_modulations poll_mod[] = {
|
||||
static const struct pn533_poll_modulations poll_mod[] = {
|
||||
[PN533_POLL_MOD_106KBPS_A] = {
|
||||
.data = {
|
||||
.maxtg = 1,
|
||||
|
@ -485,7 +485,7 @@ static u8 pn533_get_cmd_code(void *frame)
|
|||
return PN533_FRAME_CMD(f);
|
||||
}
|
||||
|
||||
struct pn533_frame_ops pn533_std_frame_ops = {
|
||||
static struct pn533_frame_ops pn533_std_frame_ops = {
|
||||
.tx_frame_init = pn533_tx_frame_init,
|
||||
.tx_frame_finish = pn533_tx_frame_finish,
|
||||
.tx_update_payload_len = pn533_tx_update_payload_len,
|
||||
|
@ -532,7 +532,6 @@ static void pn533_recv_response(struct urb *urb)
|
|||
urb->status);
|
||||
dev->wq_in_error = urb->status;
|
||||
goto sched_wq;
|
||||
break;
|
||||
case -ESHUTDOWN:
|
||||
default:
|
||||
nfc_dev_err(&dev->interface->dev,
|
||||
|
@ -589,7 +588,6 @@ static void pn533_recv_ack(struct urb *urb)
|
|||
urb->status);
|
||||
dev->wq_in_error = urb->status;
|
||||
goto sched_wq;
|
||||
break;
|
||||
case -ESHUTDOWN:
|
||||
default:
|
||||
nfc_dev_err(&dev->interface->dev,
|
||||
|
@ -1380,7 +1378,7 @@ static struct sk_buff *pn533_alloc_poll_tg_frame(struct pn533 *dev)
|
|||
return NULL;
|
||||
|
||||
/* DEP support only */
|
||||
*skb_put(skb, 1) |= PN533_INIT_TARGET_DEP;
|
||||
*skb_put(skb, 1) = PN533_INIT_TARGET_DEP;
|
||||
|
||||
/* MIFARE params */
|
||||
memcpy(skb_put(skb, 6), mifare_params, 6);
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#define BCMA_CC_FLASHT_NONE 0x00000000 /* No flash */
|
||||
#define BCMA_CC_FLASHT_STSER 0x00000100 /* ST serial flash */
|
||||
#define BCMA_CC_FLASHT_ATSER 0x00000200 /* Atmel serial flash */
|
||||
#define BCMA_CC_FLASHT_NFLASH 0x00000200 /* NAND flash */
|
||||
#define BCMA_CC_FLASHT_NAND 0x00000300 /* NAND flash */
|
||||
#define BCMA_CC_FLASHT_PARA 0x00000700 /* Parallel flash */
|
||||
#define BCMA_CC_CAP_PLLT 0x00038000 /* PLL Type */
|
||||
#define BCMA_PLLTYPE_NONE 0x00000000
|
||||
|
|
|
@ -151,6 +151,11 @@
|
|||
/* Mesh Control 802.11s */
|
||||
#define IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT 0x0100
|
||||
|
||||
/* Mesh Power Save Level */
|
||||
#define IEEE80211_QOS_CTL_MESH_PS_LEVEL 0x0200
|
||||
/* Mesh Receiver Service Period Initiated */
|
||||
#define IEEE80211_QOS_CTL_RSPI 0x0400
|
||||
|
||||
/* U-APSD queue for WMM IEs sent by AP */
|
||||
#define IEEE80211_WMM_IE_AP_QOSINFO_UAPSD (1<<7)
|
||||
#define IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK 0x0f
|
||||
|
@ -675,11 +680,14 @@ struct ieee80211_meshconf_ie {
|
|||
* @IEEE80211_MESHCONF_CAPAB_FORWARDING: the STA forwards MSDUs
|
||||
* @IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING: TBTT adjustment procedure
|
||||
* is ongoing
|
||||
* @IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL: STA is in deep sleep mode or has
|
||||
* neighbors in deep sleep mode
|
||||
*/
|
||||
enum mesh_config_capab_flags {
|
||||
IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS = 0x01,
|
||||
IEEE80211_MESHCONF_CAPAB_FORWARDING = 0x08,
|
||||
IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING = 0x20,
|
||||
IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL = 0x40,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Driver include for the PN544 NFC chip.
|
||||
*
|
||||
* Copyright (C) 2011 Tieto Poland
|
||||
* Copyright (C) 2012 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _MICROREAD_H
|
||||
#define _MICROREAD_H
|
||||
|
||||
#include <linux/i2c.h>
|
||||
|
||||
#define MICROREAD_DRIVER_NAME "microread"
|
||||
|
||||
/* board config platform data for microread */
|
||||
struct microread_nfc_platform_data {
|
||||
unsigned int rst_gpio;
|
||||
unsigned int irq_gpio;
|
||||
unsigned int ioh_gpio;
|
||||
};
|
||||
|
||||
#endif /* _MICROREAD_H */
|
|
@ -24,6 +24,8 @@
|
|||
#ifndef _LINUX_WL12XX_H
|
||||
#define _LINUX_WL12XX_H
|
||||
|
||||
#include <linux/err.h>
|
||||
|
||||
/* Reference clock values */
|
||||
enum {
|
||||
WL12XX_REFCLOCK_19 = 0, /* 19.2 MHz */
|
||||
|
@ -55,17 +57,17 @@ struct wl12xx_platform_data {
|
|||
int board_tcxo_clock;
|
||||
unsigned long platform_quirks;
|
||||
bool pwr_in_suspend;
|
||||
|
||||
struct wl1271_if_operations *ops;
|
||||
};
|
||||
|
||||
/* Platform does not support level trigger interrupts */
|
||||
#define WL12XX_PLATFORM_QUIRK_EDGE_IRQ BIT(0)
|
||||
|
||||
#ifdef CONFIG_WL12XX_PLATFORM_DATA
|
||||
#ifdef CONFIG_WILINK_PLATFORM_DATA
|
||||
|
||||
int wl12xx_set_platform_data(const struct wl12xx_platform_data *data);
|
||||
|
||||
struct wl12xx_platform_data *wl12xx_get_platform_data(void);
|
||||
|
||||
#else
|
||||
|
||||
static inline
|
||||
|
@ -74,8 +76,12 @@ int wl12xx_set_platform_data(const struct wl12xx_platform_data *data)
|
|||
return -ENOSYS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
struct wl12xx_platform_data *wl12xx_get_platform_data(void);
|
||||
static inline
|
||||
struct wl12xx_platform_data *wl12xx_get_platform_data(void)
|
||||
{
|
||||
return ERR_PTR(-ENODATA);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -86,6 +86,7 @@ struct bdaddr_list {
|
|||
struct bt_uuid {
|
||||
struct list_head list;
|
||||
u8 uuid[16];
|
||||
u8 size;
|
||||
u8 svc_hint;
|
||||
};
|
||||
|
||||
|
|
|
@ -672,8 +672,10 @@ struct station_parameters {
|
|||
* @STATION_INFO_SIGNAL: @signal filled
|
||||
* @STATION_INFO_TX_BITRATE: @txrate fields are filled
|
||||
* (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
|
||||
* @STATION_INFO_RX_PACKETS: @rx_packets filled
|
||||
* @STATION_INFO_TX_PACKETS: @tx_packets filled
|
||||
* @STATION_INFO_RX_PACKETS: @rx_packets filled with 32-bit value
|
||||
* @STATION_INFO_TX_PACKETS: @tx_packets filled with 32-bit value
|
||||
* @STATION_INFO_RX_PACKETS64: @rx_packets filled with 64-bit value
|
||||
* @STATION_INFO_TX_PACKETS64: @tx_packets filled with 64-bit value
|
||||
* @STATION_INFO_TX_RETRIES: @tx_retries filled
|
||||
* @STATION_INFO_TX_FAILED: @tx_failed filled
|
||||
* @STATION_INFO_RX_DROP_MISC: @rx_dropped_misc filled
|
||||
|
@ -714,6 +716,8 @@ enum station_info_flags {
|
|||
STATION_INFO_LOCAL_PM = 1<<21,
|
||||
STATION_INFO_PEER_PM = 1<<22,
|
||||
STATION_INFO_NONPEER_PM = 1<<23,
|
||||
STATION_INFO_RX_BYTES64 = 1<<24,
|
||||
STATION_INFO_TX_BYTES64 = 1<<25,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -835,8 +839,8 @@ struct station_info {
|
|||
u32 filled;
|
||||
u32 connected_time;
|
||||
u32 inactive_time;
|
||||
u32 rx_bytes;
|
||||
u32 tx_bytes;
|
||||
u64 rx_bytes;
|
||||
u64 tx_bytes;
|
||||
u16 llid;
|
||||
u16 plid;
|
||||
u8 plink_state;
|
||||
|
@ -1289,7 +1293,6 @@ struct cfg80211_bss_ies {
|
|||
* @beacon_ies: the information elements from the last Beacon frame
|
||||
* @proberesp_ies: the information elements from the last Probe Response frame
|
||||
* @signal: signal strength value (type depends on the wiphy's signal_type)
|
||||
* @free_priv: function pointer to free private data
|
||||
* @priv: private area for driver use, has at least wiphy->bss_priv_size bytes
|
||||
*/
|
||||
struct cfg80211_bss {
|
||||
|
@ -1301,8 +1304,6 @@ struct cfg80211_bss {
|
|||
const struct cfg80211_bss_ies __rcu *beacon_ies;
|
||||
const struct cfg80211_bss_ies __rcu *proberesp_ies;
|
||||
|
||||
void (*free_priv)(struct cfg80211_bss *bss);
|
||||
|
||||
s32 signal;
|
||||
|
||||
u16 beacon_interval;
|
||||
|
@ -1596,6 +1597,32 @@ struct cfg80211_wowlan {
|
|||
int n_patterns;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cfg80211_wowlan_wakeup - wakeup report
|
||||
* @disconnect: woke up by getting disconnected
|
||||
* @magic_pkt: woke up by receiving magic packet
|
||||
* @gtk_rekey_failure: woke up by GTK rekey failure
|
||||
* @eap_identity_req: woke up by EAP identity request packet
|
||||
* @four_way_handshake: woke up by 4-way handshake
|
||||
* @rfkill_release: woke up by rfkill being released
|
||||
* @pattern_idx: pattern that caused wakeup, -1 if not due to pattern
|
||||
* @packet_present_len: copied wakeup packet data
|
||||
* @packet_len: original wakeup packet length
|
||||
* @packet: The packet causing the wakeup, if any.
|
||||
* @packet_80211: For pattern match, magic packet and other data
|
||||
* frame triggers an 802.3 frame should be reported, for
|
||||
* disconnect due to deauth 802.11 frame. This indicates which
|
||||
* it is.
|
||||
*/
|
||||
struct cfg80211_wowlan_wakeup {
|
||||
bool disconnect, magic_pkt, gtk_rekey_failure,
|
||||
eap_identity_req, four_way_handshake,
|
||||
rfkill_release, packet_80211;
|
||||
s32 pattern_idx;
|
||||
u32 packet_present_len, packet_len;
|
||||
const void *packet;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cfg80211_gtk_rekey_data - rekey data
|
||||
* @kek: key encryption key
|
||||
|
@ -3137,10 +3164,6 @@ cfg80211_get_ibss(struct wiphy *wiphy,
|
|||
WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS);
|
||||
}
|
||||
|
||||
struct cfg80211_bss *cfg80211_get_mesh(struct wiphy *wiphy,
|
||||
struct ieee80211_channel *channel,
|
||||
const u8 *meshid, size_t meshidlen,
|
||||
const u8 *meshcfg);
|
||||
/**
|
||||
* cfg80211_ref_bss - reference BSS struct
|
||||
* @bss: the BSS struct to reference
|
||||
|
@ -3852,6 +3875,21 @@ int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len,
|
|||
enum ieee80211_p2p_attr_id attr,
|
||||
u8 *buf, unsigned int bufsize);
|
||||
|
||||
/**
|
||||
* cfg80211_report_wowlan_wakeup - report wakeup from WoWLAN
|
||||
* @wdev: the wireless device reporting the wakeup
|
||||
* @wakeup: the wakeup report
|
||||
* @gfp: allocation flags
|
||||
*
|
||||
* This function reports that the given device woke up. If it
|
||||
* caused the wakeup, report the reason(s), otherwise you may
|
||||
* pass %NULL as the @wakeup parameter to advertise that something
|
||||
* else caused the wakeup.
|
||||
*/
|
||||
void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
|
||||
struct cfg80211_wowlan_wakeup *wakeup,
|
||||
gfp_t gfp);
|
||||
|
||||
/* Logging, debugging and troubleshooting/diagnostic helpers. */
|
||||
|
||||
/* wiphy_printk helpers, similar to dev_printk */
|
||||
|
|
|
@ -208,6 +208,8 @@ struct ieee80211_chanctx_conf {
|
|||
* @BSS_CHANGED_TXPOWER: TX power setting changed for this interface
|
||||
* @BSS_CHANGED_P2P_PS: P2P powersave settings (CTWindow, opportunistic PS)
|
||||
* changed (currently only in P2P client mode, GO mode will be later)
|
||||
* @BSS_CHANGED_DTIM_PERIOD: the DTIM period value was changed (set when
|
||||
* it becomes valid, managed mode only)
|
||||
*/
|
||||
enum ieee80211_bss_change {
|
||||
BSS_CHANGED_ASSOC = 1<<0,
|
||||
|
@ -230,6 +232,7 @@ enum ieee80211_bss_change {
|
|||
BSS_CHANGED_PS = 1<<17,
|
||||
BSS_CHANGED_TXPOWER = 1<<18,
|
||||
BSS_CHANGED_P2P_PS = 1<<19,
|
||||
BSS_CHANGED_DTIM_PERIOD = 1<<20,
|
||||
|
||||
/* when adding here, make sure to change ieee80211_reconfig */
|
||||
};
|
||||
|
@ -271,9 +274,8 @@ enum ieee80211_rssi_event {
|
|||
* if the hardware cannot handle this it must set the
|
||||
* IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE hardware flag
|
||||
* @dtim_period: num of beacons before the next DTIM, for beaconing,
|
||||
* valid in station mode only while @assoc is true and if also
|
||||
* requested by %IEEE80211_HW_NEED_DTIM_PERIOD (cf. also hw conf
|
||||
* @ps_dtim_period)
|
||||
* valid in station mode only if after the driver was notified
|
||||
* with the %BSS_CHANGED_DTIM_PERIOD flag, will be non-zero then.
|
||||
* @sync_tsf: last beacon's/probe response's TSF timestamp (could be old
|
||||
* as it may have been received during scanning long ago)
|
||||
* @sync_device_ts: the device timestamp corresponding to the sync_tsf,
|
||||
|
@ -406,6 +408,9 @@ struct ieee80211_bss_conf {
|
|||
* @IEEE80211_TX_INTFL_RETRANSMISSION: This frame is being retransmitted
|
||||
* after TX status because the destination was asleep, it must not
|
||||
* be modified again (no seqno assignment, crypto, etc.)
|
||||
* @IEEE80211_TX_INTFL_MLME_CONN_TX: This frame was transmitted by the MLME
|
||||
* code for connection establishment, this indicates that its status
|
||||
* should kick the MLME state machine.
|
||||
* @IEEE80211_TX_INTFL_NL80211_FRAME_TX: Frame was requested through nl80211
|
||||
* MLME command (internal to mac80211 to figure out whether to send TX
|
||||
* status to user space)
|
||||
|
@ -457,7 +462,7 @@ enum mac80211_tx_control_flags {
|
|||
IEEE80211_TX_CTL_NO_PS_BUFFER = BIT(17),
|
||||
IEEE80211_TX_CTL_MORE_FRAMES = BIT(18),
|
||||
IEEE80211_TX_INTFL_RETRANSMISSION = BIT(19),
|
||||
/* hole at 20, use later */
|
||||
IEEE80211_TX_INTFL_MLME_CONN_TX = BIT(20),
|
||||
IEEE80211_TX_INTFL_NL80211_FRAME_TX = BIT(21),
|
||||
IEEE80211_TX_CTL_LDPC = BIT(22),
|
||||
IEEE80211_TX_CTL_STBC = BIT(23) | BIT(24),
|
||||
|
@ -1328,9 +1333,9 @@ struct ieee80211_tx_control {
|
|||
* When this flag is set, signaling beacon-loss will cause an immediate
|
||||
* change to disassociated state.
|
||||
*
|
||||
* @IEEE80211_HW_NEED_DTIM_PERIOD:
|
||||
* This device needs to know the DTIM period for the BSS before
|
||||
* associating.
|
||||
* @IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC:
|
||||
* This device needs to get data from beacon before association (i.e.
|
||||
* dtim_period).
|
||||
*
|
||||
* @IEEE80211_HW_SUPPORTS_PER_STA_GTK: The device's crypto engine supports
|
||||
* per-station GTKs as used by IBSS RSN or during fast transition. If
|
||||
|
@ -1366,10 +1371,6 @@ struct ieee80211_tx_control {
|
|||
* @IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF: Use the P2P Device address for any
|
||||
* P2P Interface. This will be honoured even if more than one interface
|
||||
* is supported.
|
||||
*
|
||||
* @IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL: On this hardware TX BA session
|
||||
* should be tear down once BAR frame will not be acked.
|
||||
*
|
||||
*/
|
||||
enum ieee80211_hw_flags {
|
||||
IEEE80211_HW_HAS_RATE_CONTROL = 1<<0,
|
||||
|
@ -1379,7 +1380,7 @@ enum ieee80211_hw_flags {
|
|||
IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE = 1<<4,
|
||||
IEEE80211_HW_SIGNAL_UNSPEC = 1<<5,
|
||||
IEEE80211_HW_SIGNAL_DBM = 1<<6,
|
||||
IEEE80211_HW_NEED_DTIM_PERIOD = 1<<7,
|
||||
IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC = 1<<7,
|
||||
IEEE80211_HW_SPECTRUM_MGMT = 1<<8,
|
||||
IEEE80211_HW_AMPDU_AGGREGATION = 1<<9,
|
||||
IEEE80211_HW_SUPPORTS_PS = 1<<10,
|
||||
|
@ -1398,7 +1399,6 @@ enum ieee80211_hw_flags {
|
|||
IEEE80211_HW_TX_AMPDU_SETUP_IN_HW = 1<<23,
|
||||
IEEE80211_HW_SCAN_WHILE_IDLE = 1<<24,
|
||||
IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF = 1<<25,
|
||||
IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL = 1<<26,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -3877,6 +3877,8 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif);
|
|||
* When beacon filtering is enabled with %IEEE80211_VIF_BEACON_FILTER, and
|
||||
* %IEEE80211_CONF_PS and %IEEE80211_HW_CONNECTION_MONITOR are set, the driver
|
||||
* needs to inform if the connection to the AP has been lost.
|
||||
* The function may also be called if the connection needs to be terminated
|
||||
* for some other reason, even if %IEEE80211_HW_CONNECTION_MONITOR isn't set.
|
||||
*
|
||||
* This function will cause immediate change to disassociated state,
|
||||
* without connection recovery attempts.
|
||||
|
@ -4211,4 +4213,16 @@ void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif);
|
|||
*/
|
||||
int ieee80211_ave_rssi(struct ieee80211_vif *vif);
|
||||
|
||||
/**
|
||||
* ieee80211_report_wowlan_wakeup - report WoWLAN wakeup
|
||||
* @vif: virtual interface
|
||||
* @wakeup: wakeup reason(s)
|
||||
* @gfp: allocation flags
|
||||
*
|
||||
* See cfg80211_report_wowlan_wakeup().
|
||||
*/
|
||||
void ieee80211_report_wowlan_wakeup(struct ieee80211_vif *vif,
|
||||
struct cfg80211_wowlan_wakeup *wakeup,
|
||||
gfp_t gfp);
|
||||
|
||||
#endif /* MAC80211_H */
|
||||
|
|
|
@ -513,6 +513,12 @@
|
|||
* command with the %NL80211_ATTR_WOWLAN_TRIGGERS attribute. For
|
||||
* more background information, see
|
||||
* http://wireless.kernel.org/en/users/Documentation/WoWLAN.
|
||||
* The @NL80211_CMD_SET_WOWLAN command can also be used as a notification
|
||||
* from the driver reporting the wakeup reason. In this case, the
|
||||
* @NL80211_ATTR_WOWLAN_TRIGGERS attribute will contain the reason
|
||||
* for the wakeup, if it was caused by wireless. If it is not present
|
||||
* in the wakeup notification, the wireless device didn't cause the
|
||||
* wakeup but reports that it was woken up.
|
||||
*
|
||||
* @NL80211_CMD_SET_REKEY_OFFLOAD: This command is used give the driver
|
||||
* the necessary information for supporting GTK rekey offload. This
|
||||
|
@ -1851,6 +1857,8 @@ enum nl80211_sta_bss_param {
|
|||
* @NL80211_STA_INFO_INACTIVE_TIME: time since last activity (u32, msecs)
|
||||
* @NL80211_STA_INFO_RX_BYTES: total received bytes (u32, from this station)
|
||||
* @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
|
||||
* @NL80211_STA_INFO_RX_BYTES64: total received bytes (u64, from this station)
|
||||
* @NL80211_STA_INFO_TX_BYTES64: total transmitted bytes (u64, to this station)
|
||||
* @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm)
|
||||
* @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute
|
||||
* containing info as possible, see &enum nl80211_rate_info
|
||||
|
@ -1903,6 +1911,8 @@ enum nl80211_sta_info {
|
|||
NL80211_STA_INFO_LOCAL_PM,
|
||||
NL80211_STA_INFO_PEER_PM,
|
||||
NL80211_STA_INFO_NONPEER_PM,
|
||||
NL80211_STA_INFO_RX_BYTES64,
|
||||
NL80211_STA_INFO_TX_BYTES64,
|
||||
|
||||
/* keep last */
|
||||
__NL80211_STA_INFO_AFTER_LAST,
|
||||
|
@ -2947,6 +2957,10 @@ struct nl80211_wowlan_pattern_support {
|
|||
*
|
||||
* In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute
|
||||
* carrying a &struct nl80211_wowlan_pattern_support.
|
||||
*
|
||||
* When reporting wakeup. it is a u32 attribute containing the 0-based
|
||||
* index of the pattern that caused the wakeup, in the patterns passed
|
||||
* to the kernel when configuring.
|
||||
* @NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED: Not a real trigger, and cannot be
|
||||
* used when setting, used only to indicate that GTK rekeying is supported
|
||||
* by the device (flag)
|
||||
|
@ -2957,8 +2971,25 @@ struct nl80211_wowlan_pattern_support {
|
|||
* @NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE: wake up on 4-way handshake (flag)
|
||||
* @NL80211_WOWLAN_TRIG_RFKILL_RELEASE: wake up when rfkill is released
|
||||
* (on devices that have rfkill in the device) (flag)
|
||||
* @NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211: For wakeup reporting only, contains
|
||||
* the 802.11 packet that caused the wakeup, e.g. a deauth frame. The frame
|
||||
* may be truncated, the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN
|
||||
* attribute contains the original length.
|
||||
* @NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN: Original length of the 802.11
|
||||
* packet, may be bigger than the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211
|
||||
* attribute if the packet was truncated somewhere.
|
||||
* @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023: For wakeup reporting only, contains the
|
||||
* 802.11 packet that caused the wakeup, e.g. a magic packet. The frame may
|
||||
* be truncated, the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN attribute
|
||||
* contains the original length.
|
||||
* @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN: Original length of the 802.3
|
||||
* packet, may be bigger than the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023
|
||||
* attribute if the packet was truncated somewhere.
|
||||
* @NUM_NL80211_WOWLAN_TRIG: number of wake on wireless triggers
|
||||
* @MAX_NL80211_WOWLAN_TRIG: highest wowlan trigger attribute number
|
||||
*
|
||||
* These nested attributes are used to configure the wakeup triggers and
|
||||
* to report the wakeup reason(s).
|
||||
*/
|
||||
enum nl80211_wowlan_triggers {
|
||||
__NL80211_WOWLAN_TRIG_INVALID,
|
||||
|
@ -2971,6 +3002,10 @@ enum nl80211_wowlan_triggers {
|
|||
NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST,
|
||||
NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE,
|
||||
NL80211_WOWLAN_TRIG_RFKILL_RELEASE,
|
||||
NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211,
|
||||
NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN,
|
||||
NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023,
|
||||
NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN,
|
||||
|
||||
/* keep last */
|
||||
NUM_NL80211_WOWLAN_TRIG,
|
||||
|
|
|
@ -1183,14 +1183,10 @@ static void hci_discov_off(struct work_struct *work)
|
|||
|
||||
int hci_uuids_clear(struct hci_dev *hdev)
|
||||
{
|
||||
struct list_head *p, *n;
|
||||
struct bt_uuid *uuid, *tmp;
|
||||
|
||||
list_for_each_safe(p, n, &hdev->uuids) {
|
||||
struct bt_uuid *uuid;
|
||||
|
||||
uuid = list_entry(p, struct bt_uuid, list);
|
||||
|
||||
list_del(p);
|
||||
list_for_each_entry_safe(uuid, tmp, &hdev->uuids, list) {
|
||||
list_del(&uuid->list);
|
||||
kfree(uuid);
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue