Merge remote-tracking branch 'wireless-next/master' into iwlwifi-next

This commit is contained in:
Johannes Berg 2013-02-12 16:52:04 +01:00
commit 94d2f0ba05
134 changed files with 7974 additions and 1678 deletions

View File

@ -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 */

View File

@ -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,

View File

@ -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,

View File

@ -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);

View File

@ -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)

View File

@ -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;
}

View File

@ -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.

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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)

View File

@ -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);

View File

@ -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:

View File

@ -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);

View File

@ -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) {

View File

@ -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

View File

@ -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_ */

View File

@ -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;

View File

@ -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) {

View File

@ -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();

View File

@ -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);

View File

@ -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) {

View File

@ -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),

View File

@ -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;
}

View File

@ -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

View File

@ -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_ */

View File

@ -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

View File

@ -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_ */

View File

@ -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)

View File

@ -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);

View File

@ -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)

View File

@ -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)

View File

@ -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;

View File

@ -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 |

View File

@ -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;

View File

@ -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.

View File

@ -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,

View File

@ -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.

View File

@ -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>

View File

@ -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),

View File

@ -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;

View File

@ -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;

View File

@ -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 */

View File

@ -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

View File

@ -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;
}

View File

@ -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,

View File

@ -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);

View File

@ -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, },
{ },
};

View File

@ -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) */

View File

@ -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) },

View File

@ -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, }
};

View File

@ -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};

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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)));

View File

@ -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;

View File

@ -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,

View File

@ -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 */

View File

@ -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);

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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

View File

@ -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__

View File

@ -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;

View File

@ -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",

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -183,7 +183,6 @@ struct wl1271 {
struct wl1271_if_operations *if_ops;
void (*set_power)(bool enable);
int irq;
spinlock_t wl_lock;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

340
drivers/nfc/microread/i2c.c Normal file
View File

@ -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);

246
drivers/nfc/microread/mei.c Normal file
View File

@ -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(&microread_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(&microread_driver);
}
module_init(microread_mei_init);
module_exit(microread_mei_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION(DRIVER_DESC);

View File

@ -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(&microread_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);

View File

@ -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_ */

View File

@ -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);

View File

@ -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

View File

@ -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,
};
/**

View File

@ -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 */

View File

@ -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

View File

@ -86,6 +86,7 @@ struct bdaddr_list {
struct bt_uuid {
struct list_head list;
u8 uuid[16];
u8 size;
u8 svc_hint;
};

View File

@ -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 */

View File

@ -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 */

View File

@ -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,

View File

@ -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