Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem

This commit is contained in:
John W. Linville 2011-12-19 13:54:26 -05:00
commit 9f6e20cee6
168 changed files with 6762 additions and 3755 deletions

View File

@ -18,6 +18,9 @@ void bcma_bus_unregister(struct bcma_bus *bus);
int __init bcma_bus_early_register(struct bcma_bus *bus,
struct bcma_device *core_cc,
struct bcma_device *core_mips);
#ifdef CONFIG_PM
int bcma_bus_resume(struct bcma_bus *bus);
#endif
/* scan.c */
int bcma_bus_scan(struct bcma_bus *bus);

View File

@ -234,6 +234,41 @@ static void bcma_host_pci_remove(struct pci_dev *dev)
pci_set_drvdata(dev, NULL);
}
#ifdef CONFIG_PM
static int bcma_host_pci_suspend(struct pci_dev *dev, pm_message_t state)
{
/* Host specific */
pci_save_state(dev);
pci_disable_device(dev);
pci_set_power_state(dev, pci_choose_state(dev, state));
return 0;
}
static int bcma_host_pci_resume(struct pci_dev *dev)
{
struct bcma_bus *bus = pci_get_drvdata(dev);
int err;
/* Host specific */
pci_set_power_state(dev, 0);
err = pci_enable_device(dev);
if (err)
return err;
pci_restore_state(dev);
/* Bus specific */
err = bcma_bus_resume(bus);
if (err)
return err;
return 0;
}
#else /* CONFIG_PM */
# define bcma_host_pci_suspend NULL
# define bcma_host_pci_resume NULL
#endif /* CONFIG_PM */
static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },
@ -249,6 +284,8 @@ static struct pci_driver bcma_pci_bridge_driver = {
.id_table = bcma_pci_bridge_tbl,
.probe = bcma_host_pci_probe,
.remove = bcma_host_pci_remove,
.suspend = bcma_host_pci_suspend,
.resume = bcma_host_pci_resume,
};
int __init bcma_host_pci_init(void)

View File

@ -240,6 +240,22 @@ int __init bcma_bus_early_register(struct bcma_bus *bus,
return 0;
}
#ifdef CONFIG_PM
int bcma_bus_resume(struct bcma_bus *bus)
{
struct bcma_device *core;
/* Init CC core */
core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
if (core) {
bus->drv_cc.setup_done = false;
bcma_core_chipcommon_init(&bus->drv_cc);
}
return 0;
}
#endif
int __bcma_driver_register(struct bcma_driver *drv, struct module *owner)
{
drv->drv.name = drv->name;

View File

@ -129,6 +129,9 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
u16 v;
int i;
bus->sprom.revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] &
SSB_SPROM_REVISION_REV;
for (i = 0; i < 3; i++) {
v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i];
*(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v);
@ -136,12 +139,70 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
bus->sprom.board_rev = sprom[SPOFF(SSB_SPROM8_BOARDREV)];
bus->sprom.txpid2g[0] = (sprom[SPOFF(SSB_SPROM4_TXPID2G01)] &
SSB_SPROM4_TXPID2G0) >> SSB_SPROM4_TXPID2G0_SHIFT;
bus->sprom.txpid2g[1] = (sprom[SPOFF(SSB_SPROM4_TXPID2G01)] &
SSB_SPROM4_TXPID2G1) >> SSB_SPROM4_TXPID2G1_SHIFT;
bus->sprom.txpid2g[2] = (sprom[SPOFF(SSB_SPROM4_TXPID2G23)] &
SSB_SPROM4_TXPID2G2) >> SSB_SPROM4_TXPID2G2_SHIFT;
bus->sprom.txpid2g[3] = (sprom[SPOFF(SSB_SPROM4_TXPID2G23)] &
SSB_SPROM4_TXPID2G3) >> SSB_SPROM4_TXPID2G3_SHIFT;
bus->sprom.txpid5gl[0] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL01)] &
SSB_SPROM4_TXPID5GL0) >> SSB_SPROM4_TXPID5GL0_SHIFT;
bus->sprom.txpid5gl[1] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL01)] &
SSB_SPROM4_TXPID5GL1) >> SSB_SPROM4_TXPID5GL1_SHIFT;
bus->sprom.txpid5gl[2] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL23)] &
SSB_SPROM4_TXPID5GL2) >> SSB_SPROM4_TXPID5GL2_SHIFT;
bus->sprom.txpid5gl[3] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL23)] &
SSB_SPROM4_TXPID5GL3) >> SSB_SPROM4_TXPID5GL3_SHIFT;
bus->sprom.txpid5g[0] = (sprom[SPOFF(SSB_SPROM4_TXPID5G01)] &
SSB_SPROM4_TXPID5G0) >> SSB_SPROM4_TXPID5G0_SHIFT;
bus->sprom.txpid5g[1] = (sprom[SPOFF(SSB_SPROM4_TXPID5G01)] &
SSB_SPROM4_TXPID5G1) >> SSB_SPROM4_TXPID5G1_SHIFT;
bus->sprom.txpid5g[2] = (sprom[SPOFF(SSB_SPROM4_TXPID5G23)] &
SSB_SPROM4_TXPID5G2) >> SSB_SPROM4_TXPID5G2_SHIFT;
bus->sprom.txpid5g[3] = (sprom[SPOFF(SSB_SPROM4_TXPID5G23)] &
SSB_SPROM4_TXPID5G3) >> SSB_SPROM4_TXPID5G3_SHIFT;
bus->sprom.txpid5gh[0] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH01)] &
SSB_SPROM4_TXPID5GH0) >> SSB_SPROM4_TXPID5GH0_SHIFT;
bus->sprom.txpid5gh[1] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH01)] &
SSB_SPROM4_TXPID5GH1) >> SSB_SPROM4_TXPID5GH1_SHIFT;
bus->sprom.txpid5gh[2] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH23)] &
SSB_SPROM4_TXPID5GH2) >> SSB_SPROM4_TXPID5GH2_SHIFT;
bus->sprom.txpid5gh[3] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH23)] &
SSB_SPROM4_TXPID5GH3) >> SSB_SPROM4_TXPID5GH3_SHIFT;
bus->sprom.boardflags_lo = sprom[SPOFF(SSB_SPROM8_BFLLO)];
bus->sprom.boardflags_hi = sprom[SPOFF(SSB_SPROM8_BFLHI)];
bus->sprom.boardflags2_lo = sprom[SPOFF(SSB_SPROM8_BFL2LO)];
bus->sprom.boardflags2_hi = sprom[SPOFF(SSB_SPROM8_BFL2HI)];
bus->sprom.country_code = sprom[SPOFF(SSB_SPROM8_CCODE)];
bus->sprom.fem.ghz2.tssipos = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
SSB_SROM8_FEM_TSSIPOS) >> SSB_SROM8_FEM_TSSIPOS_SHIFT;
bus->sprom.fem.ghz2.extpa_gain = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
SSB_SROM8_FEM_EXTPA_GAIN) >> SSB_SROM8_FEM_EXTPA_GAIN_SHIFT;
bus->sprom.fem.ghz2.pdet_range = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
SSB_SROM8_FEM_PDET_RANGE) >> SSB_SROM8_FEM_PDET_RANGE_SHIFT;
bus->sprom.fem.ghz2.tr_iso = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
SSB_SROM8_FEM_TR_ISO) >> SSB_SROM8_FEM_TR_ISO_SHIFT;
bus->sprom.fem.ghz2.antswlut = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
SSB_SROM8_FEM_ANTSWLUT) >> SSB_SROM8_FEM_ANTSWLUT_SHIFT;
bus->sprom.fem.ghz5.tssipos = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
SSB_SROM8_FEM_TSSIPOS) >> SSB_SROM8_FEM_TSSIPOS_SHIFT;
bus->sprom.fem.ghz5.extpa_gain = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
SSB_SROM8_FEM_EXTPA_GAIN) >> SSB_SROM8_FEM_EXTPA_GAIN_SHIFT;
bus->sprom.fem.ghz5.pdet_range = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
SSB_SROM8_FEM_PDET_RANGE) >> SSB_SROM8_FEM_PDET_RANGE_SHIFT;
bus->sprom.fem.ghz5.tr_iso = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
SSB_SROM8_FEM_TR_ISO) >> SSB_SROM8_FEM_TR_ISO_SHIFT;
bus->sprom.fem.ghz5.antswlut = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
SSB_SROM8_FEM_ANTSWLUT) >> SSB_SROM8_FEM_ANTSWLUT_SHIFT;
}
int bcma_sprom_get(struct bcma_bus *bus)

View File

@ -152,6 +152,7 @@ struct ath_common {
struct ath_cycle_counters cc_survey;
struct ath_regulatory regulatory;
struct ath_regulatory reg_world_copy;
const struct ath_ops *ops;
const struct ath_bus_ops *bus_ops;
@ -214,6 +215,10 @@ do { \
* @ATH_DBG_HWTIMER: hardware timer handling
* @ATH_DBG_BTCOEX: bluetooth coexistance
* @ATH_DBG_BSTUCK: stuck beacons
* @ATH_DBG_MCI: Message Coexistence Interface, a private protocol
* used exclusively for WLAN-BT coexistence starting from
* AR9462.
* @ATH_DBG_DFS: radar datection
* @ATH_DBG_ANY: enable all debugging
*
* The debug level is used to control the amount and type of debugging output
@ -240,6 +245,7 @@ enum ATH_DEBUG {
ATH_DBG_WMI = 0x00004000,
ATH_DBG_BSTUCK = 0x00008000,
ATH_DBG_MCI = 0x00010000,
ATH_DBG_DFS = 0x00020000,
ATH_DBG_ANY = 0xffffffff
};

View File

@ -2,6 +2,9 @@ config ATH9K_HW
tristate
config ATH9K_COMMON
tristate
config ATH9K_DFS_DEBUGFS
def_bool y
depends on ATH9K_DEBUGFS && ATH9K_DFS_CERTIFIED
config ATH9K
tristate "Atheros 802.11n wireless cards support"
@ -51,6 +54,25 @@ config ATH9K_DEBUGFS
Also required for changing debug message flags at run time.
config ATH9K_DFS_CERTIFIED
bool "Atheros DFS support for certified platforms"
depends on ATH9K && EXPERT
default n
---help---
This option enables DFS support for initiating radiation on
ath9k. There is no way to dynamically detect if a card was DFS
certified and as such this is left as a build time option. This
option should only be enabled by system integrators that can
guarantee that all the platforms that their kernel will run on
have obtained appropriate regulatory body certification for a
respective Atheros card by using ath9k on the target shipping
platforms.
This is currently only a placeholder for future DFS support,
as DFS support requires more components that still need to be
developed. At this point enabling this option won't do anything
except increase code size.
config ATH9K_RATE_CONTROL
bool "Atheros ath9k rate control"
depends on ATH9K

View File

@ -10,6 +10,8 @@ ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o
ath9k-$(CONFIG_ATH9K_PCI) += pci.o
ath9k-$(CONFIG_ATH9K_AHB) += ahb.o
ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o
ath9k-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o
ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += dfs.o
obj-$(CONFIG_ATH9K) += ath9k.o

View File

@ -187,40 +187,12 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
isr = REG_READ(ah, AR_ISR);
}
if (async_cause & AR_INTR_ASYNC_MASK_MCI) {
u32 raw_intr, rx_msg_intr;
rx_msg_intr = REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW);
raw_intr = REG_READ(ah, AR_MCI_INTERRUPT_RAW);
if ((raw_intr == 0xdeadbeef) || (rx_msg_intr == 0xdeadbeef))
ath_dbg(common, ATH_DBG_MCI,
"MCI gets 0xdeadbeef during MCI int processing"
"new raw_intr=0x%08x, new rx_msg_raw=0x%08x, "
"raw_intr=0x%08x, rx_msg_raw=0x%08x\n",
raw_intr, rx_msg_intr, mci->raw_intr,
mci->rx_msg_intr);
else {
mci->rx_msg_intr |= rx_msg_intr;
mci->raw_intr |= raw_intr;
*masked |= ATH9K_INT_MCI;
if (rx_msg_intr & AR_MCI_INTERRUPT_RX_MSG_CONT_INFO)
mci->cont_status =
REG_READ(ah, AR_MCI_CONT_STATUS);
REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, rx_msg_intr);
REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, raw_intr);
ath_dbg(common, ATH_DBG_MCI, "AR_INTR_SYNC_MCI\n");
}
}
sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & AR_INTR_SYNC_DEFAULT;
*masked = 0;
if (!isr && !sync_cause)
if (!isr && !sync_cause && !async_cause)
return false;
if (isr) {
@ -326,6 +298,35 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
ar9003_hw_bb_watchdog_read(ah);
}
if (async_cause & AR_INTR_ASYNC_MASK_MCI) {
u32 raw_intr, rx_msg_intr;
rx_msg_intr = REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW);
raw_intr = REG_READ(ah, AR_MCI_INTERRUPT_RAW);
if ((raw_intr == 0xdeadbeef) || (rx_msg_intr == 0xdeadbeef))
ath_dbg(common, ATH_DBG_MCI,
"MCI gets 0xdeadbeef during MCI int processing"
"new raw_intr=0x%08x, new rx_msg_raw=0x%08x, "
"raw_intr=0x%08x, rx_msg_raw=0x%08x\n",
raw_intr, rx_msg_intr, mci->raw_intr,
mci->rx_msg_intr);
else {
mci->rx_msg_intr |= rx_msg_intr;
mci->raw_intr |= raw_intr;
*masked |= ATH9K_INT_MCI;
if (rx_msg_intr & AR_MCI_INTERRUPT_RX_MSG_CONT_INFO)
mci->cont_status =
REG_READ(ah, AR_MCI_CONT_STATUS);
REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, rx_msg_intr);
REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, raw_intr);
ath_dbg(common, ATH_DBG_MCI, "AR_INTR_SYNC_MCI\n");
}
}
if (sync_cause) {
if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
REG_WRITE(ah, AR_RC, AR_RC_HOSTIF);

View File

@ -159,6 +159,9 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
/* return block-ack bitmap index given sequence and starting sequence */
#define ATH_BA_INDEX(_st, _seq) (((_seq) - (_st)) & (IEEE80211_SEQ_MAX - 1))
/* return the seqno for _start + _offset */
#define ATH_BA_INDEX2SEQ(_seq, _offset) (((_seq) + (_offset)) & (IEEE80211_SEQ_MAX - 1))
/* returns delimiter padding required given the packet length */
#define ATH_AGGR_GET_NDELIM(_len) \
(((_len) >= ATH_AGGR_MINPLEN) ? 0 : \
@ -238,6 +241,7 @@ struct ath_atx_tid {
struct ath_node *an;
struct ath_atx_ac *ac;
unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
int bar_index;
u16 seq_start;
u16 seq_next;
u16 baw_size;
@ -252,9 +256,9 @@ struct ath_atx_tid {
struct ath_node {
#ifdef CONFIG_ATH9K_DEBUGFS
struct list_head list; /* for sc->nodes */
#endif
struct ieee80211_sta *sta; /* station struct we're part of */
struct ieee80211_vif *vif; /* interface with which we're associated */
#endif
struct ath_atx_tid tid[WME_NUM_TID];
struct ath_atx_ac ac[WME_NUM_AC];
int ps_key;
@ -276,7 +280,6 @@ struct ath_tx_control {
};
#define ATH_TX_ERROR 0x01
#define ATH_TX_BAR 0x02
/**
* @txq_map: Index is mac80211 queue number. This is
@ -542,7 +545,7 @@ struct ath_ant_comb {
#define DEFAULT_CACHELINE 32
#define ATH_REGCLASSIDS_MAX 10
#define ATH_CABQ_READY_TIME 80 /* % of beacon interval */
#define ATH_MAX_SW_RETRIES 10
#define ATH_MAX_SW_RETRIES 30
#define ATH_CHAN_MAX 255
#define ATH_TXPOWER_MAX 100 /* .5 dBm units */

View File

@ -856,7 +856,7 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len;
if (bf_isampdu(bf)) {
if (flags & ATH_TX_BAR)
if (flags & ATH_TX_ERROR)
TX_STAT_INC(qnum, a_xretries);
else
TX_STAT_INC(qnum, a_completed);
@ -1630,6 +1630,9 @@ int ath9k_init_debug(struct ath_hw *ah)
debugfs_create_file("debug", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
sc, &fops_debug);
#endif
ath9k_dfs_init_debug(sc);
debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_dma);
debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, sc,

View File

@ -19,6 +19,7 @@
#include "hw.h"
#include "rc.h"
#include "dfs_debug.h"
struct ath_txq;
struct ath_buf;
@ -187,6 +188,7 @@ struct ath_stats {
struct ath_interrupt_stats istats;
struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES];
struct ath_rx_stats rxstats;
struct ath_dfs_stats dfs_stats;
u32 reset[__RESET_TYPE_MAX];
};

View File

@ -0,0 +1,215 @@
/*
* Copyright (c) 2008-2011 Atheros Communications Inc.
* Copyright (c) 2011 Neratec Solutions AG
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "hw.h"
#include "hw-ops.h"
#include "ath9k.h"
#include "dfs.h"
#include "dfs_debug.h"
/*
* TODO: move into or synchronize this with generic header
* as soon as IF is defined
*/
struct dfs_radar_pulse {
u16 freq;
u64 ts;
u32 width;
u8 rssi;
};
/* internal struct to pass radar data */
struct ath_radar_data {
u8 pulse_bw_info;
u8 rssi;
u8 ext_rssi;
u8 pulse_length_ext;
u8 pulse_length_pri;
};
/* convert pulse duration to usecs, considering clock mode */
static u32 dur_to_usecs(struct ath_hw *ah, u32 dur)
{
const u32 AR93X_NSECS_PER_DUR = 800;
const u32 AR93X_NSECS_PER_DUR_FAST = (8000 / 11);
u32 nsecs;
if (IS_CHAN_A_FAST_CLOCK(ah, ah->curchan))
nsecs = dur * AR93X_NSECS_PER_DUR_FAST;
else
nsecs = dur * AR93X_NSECS_PER_DUR;
return (nsecs + 500) / 1000;
}
#define PRI_CH_RADAR_FOUND 0x01
#define EXT_CH_RADAR_FOUND 0x02
static bool
ath9k_postprocess_radar_event(struct ath_softc *sc,
struct ath_radar_data *are,
struct dfs_radar_pulse *drp)
{
u8 rssi;
u16 dur;
ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_DFS,
"pulse_bw_info=0x%x, pri,ext len/rssi=(%u/%u, %u/%u)\n",
are->pulse_bw_info,
are->pulse_length_pri, are->rssi,
are->pulse_length_ext, are->ext_rssi);
/*
* Only the last 2 bits of the BW info are relevant, they indicate
* which channel the radar was detected in.
*/
are->pulse_bw_info &= 0x03;
switch (are->pulse_bw_info) {
case PRI_CH_RADAR_FOUND:
/* radar in ctrl channel */
dur = are->pulse_length_pri;
DFS_STAT_INC(sc, pri_phy_errors);
/*
* cannot use ctrl channel RSSI
* if extension channel is stronger
*/
rssi = (are->ext_rssi >= (are->rssi + 3)) ? 0 : are->rssi;
break;
case EXT_CH_RADAR_FOUND:
/* radar in extension channel */
dur = are->pulse_length_ext;
DFS_STAT_INC(sc, ext_phy_errors);
/*
* cannot use extension channel RSSI
* if control channel is stronger
*/
rssi = (are->rssi >= (are->ext_rssi + 12)) ? 0 : are->ext_rssi;
break;
case (PRI_CH_RADAR_FOUND | EXT_CH_RADAR_FOUND):
/*
* Conducted testing, when pulse is on DC, both pri and ext
* durations are reported to be same
*
* Radiated testing, when pulse is on DC, different pri and
* ext durations are reported, so take the larger of the two
*/
if (are->pulse_length_ext >= are->pulse_length_pri)
dur = are->pulse_length_ext;
else
dur = are->pulse_length_pri;
DFS_STAT_INC(sc, dc_phy_errors);
/* when both are present use stronger one */
rssi = (are->rssi < are->ext_rssi) ? are->ext_rssi : are->rssi;
break;
default:
/*
* Bogus bandwidth info was received in descriptor,
* so ignore this PHY error
*/
DFS_STAT_INC(sc, bwinfo_discards);
return false;
}
if (rssi == 0) {
DFS_STAT_INC(sc, rssi_discards);
return false;
}
/*
* TODO: check chirping pulses
* checks for chirping are dependent on the DFS regulatory domain
* used, which is yet TBD
*/
/* convert duration to usecs */
drp->width = dur_to_usecs(sc->sc_ah, dur);
drp->rssi = rssi;
DFS_STAT_INC(sc, pulses_detected);
return true;
}
#undef PRI_CH_RADAR_FOUND
#undef EXT_CH_RADAR_FOUND
/*
* DFS: check PHY-error for radar pulse and feed the detector
*/
void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data,
struct ath_rx_status *rs, u64 mactime)
{
struct ath_radar_data ard;
u16 datalen;
char *vdata_end;
struct dfs_radar_pulse drp;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
if ((!(rs->rs_phyerr != ATH9K_PHYERR_RADAR)) &&
(!(rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT))) {
ath_dbg(common, ATH_DBG_DFS,
"Error: rs_phyer=0x%x not a radar error\n",
rs->rs_phyerr);
return;
}
datalen = rs->rs_datalen;
if (datalen == 0) {
DFS_STAT_INC(sc, datalen_discards);
return;
}
ard.rssi = rs->rs_rssi_ctl0;
ard.ext_rssi = rs->rs_rssi_ext0;
/*
* hardware stores this as 8 bit signed value.
* we will cap it at 0 if it is a negative number
*/
if (ard.rssi & 0x80)
ard.rssi = 0;
if (ard.ext_rssi & 0x80)
ard.ext_rssi = 0;
vdata_end = (char *)data + datalen;
ard.pulse_bw_info = vdata_end[-1];
ard.pulse_length_ext = vdata_end[-2];
ard.pulse_length_pri = vdata_end[-3];
ath_dbg(common, ATH_DBG_DFS,
"bw_info=%d, length_pri=%d, length_ext=%d, "
"rssi_pri=%d, rssi_ext=%d\n",
ard.pulse_bw_info, ard.pulse_length_pri, ard.pulse_length_ext,
ard.rssi, ard.ext_rssi);
drp.freq = ah->curchan->channel;
drp.ts = mactime;
if (ath9k_postprocess_radar_event(sc, &ard, &drp)) {
static u64 last_ts;
ath_dbg(common, ATH_DBG_DFS,
"ath9k_dfs_process_phyerr: channel=%d, ts=%llu, "
"width=%d, rssi=%d, delta_ts=%llu\n",
drp.freq, drp.ts, drp.width, drp.rssi, drp.ts-last_ts);
last_ts = drp.ts;
/*
* TODO: forward pulse to pattern detector
*
* ieee80211_add_radar_pulse(drp.freq, drp.ts,
* drp.width, drp.rssi);
*/
}
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2008-2011 Atheros Communications Inc.
* Copyright (c) 2011 Neratec Solutions AG
*
* 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 ATH9K_DFS_H
#define ATH9K_DFS_H
#if defined(CONFIG_ATH9K_DFS_CERTIFIED)
/**
* ath9k_dfs_process_phyerr - process radar PHY error
* @sc: ath_softc
* @data: RX payload data
* @rs: RX status after processing descriptor
* @mactime: receive time
*
* This function is called whenever the HW DFS module detects a radar
* pulse and reports it as a PHY error.
*
* The radar information provided as raw payload data is validated and
* filtered for false pulses. Events passing all tests are forwarded to
* the upper layer for pattern detection.
*/
void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data,
struct ath_rx_status *rs, u64 mactime);
#else
static inline void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data,
struct ath_rx_status *rs, u64 mactime) { }
#endif
#endif /* ATH9K_DFS_H */

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2008-2011 Atheros Communications Inc.
* Copyright (c) 2011 Neratec Solutions AG
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/debugfs.h>
#include <linux/export.h>
#include "ath9k.h"
#include "dfs_debug.h"
#define ATH9K_DFS_STAT(s, p) \
len += snprintf(buf + len, size - len, "%28s : %10u\n", s, \
sc->debug.stats.dfs_stats.p);
static ssize_t read_file_dfs(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
struct ath9k_hw_version *hw_ver = &sc->sc_ah->hw_version;
char *buf;
unsigned int len = 0, size = 8000;
ssize_t retval = 0;
buf = kzalloc(size, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
len += snprintf(buf + len, size - len, "DFS support for "
"macVersion = 0x%x, macRev = 0x%x: %s\n",
hw_ver->macVersion, hw_ver->macRev,
(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_DFS) ?
"enabled" : "disabled");
ATH9K_DFS_STAT("DFS pulses detected ", pulses_detected);
ATH9K_DFS_STAT("Datalen discards ", datalen_discards);
ATH9K_DFS_STAT("RSSI discards ", rssi_discards);
ATH9K_DFS_STAT("BW info discards ", bwinfo_discards);
ATH9K_DFS_STAT("Primary channel pulses ", pri_phy_errors);
ATH9K_DFS_STAT("Secondary channel pulses", ext_phy_errors);
ATH9K_DFS_STAT("Dual channel pulses ", dc_phy_errors);
if (len > size)
len = size;
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
kfree(buf);
return retval;
}
static int ath9k_dfs_debugfs_open(struct inode *inode, struct file *file)
{
file->private_data = inode->i_private;
return 0;
}
static const struct file_operations fops_dfs_stats = {
.read = read_file_dfs,
.open = ath9k_dfs_debugfs_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
void ath9k_dfs_init_debug(struct ath_softc *sc)
{
debugfs_create_file("dfs_stats", S_IRUSR,
sc->debug.debugfs_phy, sc, &fops_dfs_stats);
}

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2008-2011 Atheros Communications Inc.
* Copyright (c) 2011 Neratec Solutions AG
*
* 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 DFS_DEBUG_H
#define DFS_DEBUG_H
#include "hw.h"
/**
* struct ath_dfs_stats - DFS Statistics
*
* @pulses_detected: No. of pulses detected so far
* @datalen_discards: No. of pulses discarded due to invalid datalen
* @rssi_discards: No. of pulses discarded due to invalid RSSI
* @bwinfo_discards: No. of pulses discarded due to invalid BW info
* @pri_phy_errors: No. of pulses reported for primary channel
* @ext_phy_errors: No. of pulses reported for extension channel
* @dc_phy_errors: No. of pulses reported for primary + extension channel
*/
struct ath_dfs_stats {
u32 pulses_detected;
u32 datalen_discards;
u32 rssi_discards;
u32 bwinfo_discards;
u32 pri_phy_errors;
u32 ext_phy_errors;
u32 dc_phy_errors;
};
#if defined(CONFIG_ATH9K_DFS_DEBUGFS)
#define DFS_STAT_INC(sc, c) (sc->debug.stats.dfs_stats.c++)
void ath9k_dfs_init_debug(struct ath_softc *sc);
#else
#define DFS_STAT_INC(sc, c) do { } while (0)
static inline void ath9k_dfs_init_debug(struct ath_softc *sc) { }
#endif /* CONFIG_ATH9K_DFS_DEBUGFS */
#endif /* DFS_DEBUG_H */

View File

@ -212,4 +212,13 @@ static inline int ath9k_hw_fast_chan_change(struct ath_hw *ah,
return ath9k_hw_private_ops(ah)->fast_chan_change(ah, chan,
ini_reloaded);
}
static inline void ath9k_hw_set_radar_params(struct ath_hw *ah)
{
if (!ath9k_hw_private_ops(ah)->set_radar_params)
return;
ath9k_hw_private_ops(ah)->set_radar_params(ah, &ah->radar_conf);
}
#endif /* ATH9K_HW_OPS_H */

View File

@ -2277,6 +2277,30 @@ static u8 fixup_chainmask(u8 chip_chainmask, u8 eeprom_chainmask)
return chip_chainmask;
}
/**
* ath9k_hw_dfs_tested - checks if DFS has been tested with used chipset
* @ah: the atheros hardware data structure
*
* We enable DFS support upstream on chipsets which have passed a series
* of tests. The testing requirements are going to be documented. Desired
* test requirements are documented at:
*
* http://wireless.kernel.org/en/users/Drivers/ath9k/dfs
*
* Once a new chipset gets properly tested an individual commit can be used
* to document the testing for DFS for that chipset.
*/
static bool ath9k_hw_dfs_tested(struct ath_hw *ah)
{
switch (ah->hw_version.macVersion) {
/* AR9580 will likely be our first target to get testing on */
case AR_SREV_VERSION_9580:
default:
return false;
}
}
int ath9k_hw_fill_cap_info(struct ath_hw *ah)
{
struct ath9k_hw_capabilities *pCap = &ah->caps;
@ -2375,12 +2399,10 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
else
pCap->num_gpio_pins = AR_NUM_GPIO;
if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) {
pCap->hw_caps |= ATH9K_HW_CAP_CST;
if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah))
pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX;
} else {
else
pCap->rts_aggr_limit = (8 * 1024);
}
#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
ah->rfsilent = ah->eep_ops->get_eeprom(ah, EEP_RF_SILENT);
@ -2490,6 +2512,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
pCap->pcie_lcr_offset = 0x80;
}
if (ath9k_hw_dfs_tested(ah))
pCap->hw_caps |= ATH9K_HW_CAP_DFS;
tx_chainmask = pCap->tx_chainmask;
rx_chainmask = pCap->rx_chainmask;
while (tx_chainmask || rx_chainmask) {

View File

@ -196,21 +196,21 @@ enum ath_ini_subsys {
enum ath9k_hw_caps {
ATH9K_HW_CAP_HT = BIT(0),
ATH9K_HW_CAP_RFSILENT = BIT(1),
ATH9K_HW_CAP_CST = BIT(2),
ATH9K_HW_CAP_AUTOSLEEP = BIT(4),
ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(5),
ATH9K_HW_CAP_EDMA = BIT(6),
ATH9K_HW_CAP_RAC_SUPPORTED = BIT(7),
ATH9K_HW_CAP_LDPC = BIT(8),
ATH9K_HW_CAP_FASTCLOCK = BIT(9),
ATH9K_HW_CAP_SGI_20 = BIT(10),
ATH9K_HW_CAP_PAPRD = BIT(11),
ATH9K_HW_CAP_ANT_DIV_COMB = BIT(12),
ATH9K_HW_CAP_2GHZ = BIT(13),
ATH9K_HW_CAP_5GHZ = BIT(14),
ATH9K_HW_CAP_APM = BIT(15),
ATH9K_HW_CAP_RTT = BIT(16),
ATH9K_HW_CAP_MCI = BIT(17),
ATH9K_HW_CAP_AUTOSLEEP = BIT(2),
ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(3),
ATH9K_HW_CAP_EDMA = BIT(4),
ATH9K_HW_CAP_RAC_SUPPORTED = BIT(5),
ATH9K_HW_CAP_LDPC = BIT(6),
ATH9K_HW_CAP_FASTCLOCK = BIT(7),
ATH9K_HW_CAP_SGI_20 = BIT(8),
ATH9K_HW_CAP_PAPRD = BIT(9),
ATH9K_HW_CAP_ANT_DIV_COMB = BIT(10),
ATH9K_HW_CAP_2GHZ = BIT(11),
ATH9K_HW_CAP_5GHZ = BIT(12),
ATH9K_HW_CAP_APM = BIT(13),
ATH9K_HW_CAP_RTT = BIT(14),
ATH9K_HW_CAP_MCI = BIT(15),
ATH9K_HW_CAP_DFS = BIT(16),
};
struct ath9k_hw_capabilities {

View File

@ -297,9 +297,22 @@ static int ath9k_reg_notifier(struct wiphy *wiphy,
{
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct ath_softc *sc = hw->priv;
struct ath_regulatory *reg = ath9k_hw_regulatory(sc->sc_ah);
struct ath_hw *ah = sc->sc_ah;
struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
int ret;
return ath_reg_notifier_apply(wiphy, request, reg);
ret = ath_reg_notifier_apply(wiphy, request, reg);
/* Set tx power */
if (ah->curchan) {
sc->config.txpowlimit = 2 * ah->curchan->chan->max_power;
ath9k_ps_wakeup(sc);
ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false);
sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
ath9k_ps_restore(sc);
}
return ret;
}
/*

View File

@ -644,9 +644,9 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
spin_lock(&sc->nodes_lock);
list_add(&an->list, &sc->nodes);
spin_unlock(&sc->nodes_lock);
#endif
an->sta = sta;
an->vif = vif;
#endif
if (sc->sc_flags & SC_OP_TXAGGR) {
ath_tx_node_init(sc, an);
an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
@ -1873,7 +1873,8 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
if (ath9k_modparam_nohwcrypt)
return -ENOSPC;
if (vif->type == NL80211_IFTYPE_ADHOC &&
if ((vif->type == NL80211_IFTYPE_ADHOC ||
vif->type == NL80211_IFTYPE_MESH_POINT) &&
(key->cipher == WLAN_CIPHER_SUITE_TKIP ||
key->cipher == WLAN_CIPHER_SUITE_CCMP) &&
!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {

View File

@ -234,8 +234,8 @@ static void ath_mci_cal_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
}
}
void ath_mci_process_profile(struct ath_softc *sc,
struct ath_mci_profile_info *info)
static void ath_mci_process_profile(struct ath_softc *sc,
struct ath_mci_profile_info *info)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_btcoex *btcoex = &sc->btcoex;
@ -261,8 +261,8 @@ void ath_mci_process_profile(struct ath_softc *sc,
ath_mci_update_scheme(sc);
}
void ath_mci_process_status(struct ath_softc *sc,
struct ath_mci_profile_status *status)
static void ath_mci_process_status(struct ath_softc *sc,
struct ath_mci_profile_status *status)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_btcoex *btcoex = &sc->btcoex;

View File

@ -128,10 +128,6 @@ struct ath_mci_coex {
};
void ath_mci_flush_profile(struct ath_mci_profile *mci);
void ath_mci_process_profile(struct ath_softc *sc,
struct ath_mci_profile_info *info);
void ath_mci_process_status(struct ath_softc *sc,
struct ath_mci_profile_status *status);
int ath_mci_setup(struct ath_softc *sc);
void ath_mci_cleanup(struct ath_softc *sc);
void ath_mci_intr(struct ath_softc *sc);

View File

@ -1271,7 +1271,9 @@ static void ath_rc_init(struct ath_softc *sc,
ath_rc_priv->max_valid_rate = k;
ath_rc_sort_validrates(rate_table, ath_rc_priv);
ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4];
ath_rc_priv->rate_max_phy = (k > 4) ?
ath_rc_priv->valid_rate_index[k-4] :
ath_rc_priv->valid_rate_index[k-1];
ath_rc_priv->rate_table = rate_table;
ath_dbg(common, ATH_DBG_CONFIG,

View File

@ -1823,6 +1823,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len);
rxs = IEEE80211_SKB_RXCB(hdr_skb);
if (ieee80211_is_beacon(hdr->frame_control) &&
!is_zero_ether_addr(common->curbssid) &&
!compare_ether_addr(hdr->addr3, common->curbssid))
rs.is_mybeacon = true;
else

View File

@ -53,7 +53,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
int tx_flags, struct ath_txq *txq);
static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
struct ath_txq *txq, struct list_head *bf_q,
struct ath_tx_status *ts, int txok, int sendbar);
struct ath_tx_status *ts, int txok);
static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
struct list_head *head, bool internal);
static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
@ -150,6 +150,12 @@ static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
return (struct ath_frame_info *) &tx_info->rate_driver_data[0];
}
static void ath_send_bar(struct ath_atx_tid *tid, u16 seqno)
{
ieee80211_send_bar(tid->an->vif, tid->an->sta->addr, tid->tidno,
seqno << IEEE80211_SEQ_SEQ_SHIFT);
}
static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
{
struct ath_txq *txq = tid->ac->txq;
@ -158,25 +164,24 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
struct list_head bf_head;
struct ath_tx_status ts;
struct ath_frame_info *fi;
bool sendbar = false;
INIT_LIST_HEAD(&bf_head);
memset(&ts, 0, sizeof(ts));
spin_lock_bh(&txq->axq_lock);
while ((skb = __skb_dequeue(&tid->buf_q))) {
fi = get_frame_info(skb);
bf = fi->bf;
spin_unlock_bh(&txq->axq_lock);
if (bf && fi->retries) {
list_add_tail(&bf->list, &bf_head);
ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1);
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
sendbar = true;
} else {
ath_tx_send_normal(sc, txq, NULL, skb);
}
spin_lock_bh(&txq->axq_lock);
}
if (tid->baw_head == tid->baw_tail) {
@ -184,7 +189,8 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
tid->state &= ~AGGR_CLEANUP;
}
spin_unlock_bh(&txq->axq_lock);
if (sendbar)
ath_send_bar(tid, tid->seq_start);
}
static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
@ -200,6 +206,8 @@ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
while (tid->baw_head != tid->baw_tail && !test_bit(tid->baw_head, tid->tx_buf)) {
INCR(tid->seq_start, IEEE80211_SEQ_MAX);
INCR(tid->baw_head, ATH_TID_MAX_BUFS);
if (tid->bar_index >= 0)
tid->bar_index--;
}
}
@ -243,9 +251,7 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
bf = fi->bf;
if (!bf) {
spin_unlock(&txq->axq_lock);
ath_tx_complete(sc, skb, ATH_TX_ERROR, txq);
spin_lock(&txq->axq_lock);
continue;
}
@ -254,24 +260,26 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
if (fi->retries)
ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
spin_unlock(&txq->axq_lock);
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
spin_lock(&txq->axq_lock);
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
}
tid->seq_next = tid->seq_start;
tid->baw_tail = tid->baw_head;
tid->bar_index = -1;
}
static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
struct sk_buff *skb)
struct sk_buff *skb, int count)
{
struct ath_frame_info *fi = get_frame_info(skb);
struct ath_buf *bf = fi->bf;
struct ieee80211_hdr *hdr;
int prev = fi->retries;
TX_STAT_INC(txq->axq_qnum, a_retries);
if (fi->retries++ > 0)
fi->retries += count;
if (prev > 0)
return;
hdr = (struct ieee80211_hdr *)skb->data;
@ -370,7 +378,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
struct ath_buf *bf_next, *bf_last = bf->bf_lastbf;
struct list_head bf_head;
struct sk_buff_head bf_pending;
u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0;
u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0, seq_first;
u32 ba[WME_BA_BMP_SIZE >> 5];
int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
bool rc_update = true;
@ -379,6 +387,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
int nframes;
u8 tidno;
bool flush = !!(ts->ts_status & ATH9K_TX_FLUSH);
int i, retries;
int bar_index = -1;
skb = bf->bf_mpdu;
hdr = (struct ieee80211_hdr *)skb->data;
@ -387,6 +397,10 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
memcpy(rates, tx_info->control.rates, sizeof(rates));
retries = ts->ts_longretry + 1;
for (i = 0; i < ts->ts_rateindex; i++)
retries += rates[i].count;
rcu_read_lock();
sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2);
@ -400,8 +414,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
if (!bf->bf_stale || bf_next != NULL)
list_move_tail(&bf->list, &bf_head);
ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
0, 0);
ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, 0);
bf = bf_next;
}
@ -411,6 +424,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
an = (struct ath_node *)sta->drv_priv;
tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
tid = ATH_AN_2_TID(an, tidno);
seq_first = tid->seq_start;
/*
* The hardware occasionally sends a tx status for the wrong TID.
@ -460,25 +474,25 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
} else if (!isaggr && txok) {
/* transmit completion */
acked_cnt++;
} else {
if ((tid->state & AGGR_CLEANUP) || !retry) {
/*
* cleanup in progress, just fail
* the un-acked sub-frames
*/
txfail = 1;
} else if (flush) {
txpending = 1;
} else if (fi->retries < ATH_MAX_SW_RETRIES) {
if (txok || !an->sleeping)
ath_tx_set_retry(sc, txq, bf->bf_mpdu);
} else if ((tid->state & AGGR_CLEANUP) || !retry) {
/*
* cleanup in progress, just fail
* the un-acked sub-frames
*/
txfail = 1;
} else if (flush) {
txpending = 1;
} else if (fi->retries < ATH_MAX_SW_RETRIES) {
if (txok || !an->sleeping)
ath_tx_set_retry(sc, txq, bf->bf_mpdu,
retries);
txpending = 1;
} else {
txfail = 1;
sendbar = 1;
txfail_cnt++;
}
txpending = 1;
} else {
txfail = 1;
txfail_cnt++;
bar_index = max_t(int, bar_index,
ATH_BA_INDEX(seq_first, seqno));
}
/*
@ -495,9 +509,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
* complete the acked-ones/xretried ones; update
* block-ack window
*/
spin_lock_bh(&txq->axq_lock);
ath_tx_update_baw(sc, tid, seqno);
spin_unlock_bh(&txq->axq_lock);
if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
memcpy(tx_info->control.rates, rates, sizeof(rates));
@ -506,33 +518,30 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
}
ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
!txfail, sendbar);
!txfail);
} else {
/* retry the un-acked ones */
if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
if (bf->bf_next == NULL && bf_last->bf_stale) {
struct ath_buf *tbf;
if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
bf->bf_next == NULL && bf_last->bf_stale) {
struct ath_buf *tbf;
tbf = ath_clone_txbuf(sc, bf_last);
/*
* Update tx baw and complete the
* frame with failed status if we
* run out of tx buf.
*/
if (!tbf) {
spin_lock_bh(&txq->axq_lock);
ath_tx_update_baw(sc, tid, seqno);
spin_unlock_bh(&txq->axq_lock);
tbf = ath_clone_txbuf(sc, bf_last);
/*
* Update tx baw and complete the
* frame with failed status if we
* run out of tx buf.
*/
if (!tbf) {
ath_tx_update_baw(sc, tid, seqno);
ath_tx_complete_buf(sc, bf, txq,
&bf_head,
ts, 0,
!flush);
break;
}
fi->bf = tbf;
ath_tx_complete_buf(sc, bf, txq,
&bf_head, ts, 0);
bar_index = max_t(int, bar_index,
ATH_BA_INDEX(seq_first, seqno));
break;
}
fi->bf = tbf;
}
/*
@ -545,12 +554,18 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
bf = bf_next;
}
if (bar_index >= 0) {
u16 bar_seq = ATH_BA_INDEX2SEQ(seq_first, bar_index);
ath_send_bar(tid, ATH_BA_INDEX2SEQ(seq_first, bar_index + 1));
if (BAW_WITHIN(tid->seq_start, tid->baw_size, bar_seq))
tid->bar_index = ATH_BA_INDEX(tid->seq_start, bar_seq);
}
/* prepend un-acked frames to the beginning of the pending frame queue */
if (!skb_queue_empty(&bf_pending)) {
if (an->sleeping)
ieee80211_sta_set_buffered(sta, tid->tidno, true);
spin_lock_bh(&txq->axq_lock);
skb_queue_splice(&bf_pending, &tid->buf_q);
if (!an->sleeping) {
ath_tx_queue_tid(txq, tid);
@ -558,7 +573,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
if (ts->ts_status & ATH9K_TXERR_FILT)
tid->ac->clear_ps_filter = true;
}
spin_unlock_bh(&txq->axq_lock);
}
if (tid->state & AGGR_CLEANUP)
@ -617,24 +631,26 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
max_4ms_framelen = ATH_AMPDU_LIMIT_MAX;
for (i = 0; i < 4; i++) {
if (rates[i].count) {
int modeidx;
if (!(rates[i].flags & IEEE80211_TX_RC_MCS)) {
legacy = 1;
break;
}
int modeidx;
if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
modeidx = MCS_HT40;
else
modeidx = MCS_HT20;
if (!rates[i].count)
continue;
if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
modeidx++;
frmlen = ath_max_4ms_framelen[modeidx][rates[i].idx];
max_4ms_framelen = min(max_4ms_framelen, frmlen);
if (!(rates[i].flags & IEEE80211_TX_RC_MCS)) {
legacy = 1;
break;
}
if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
modeidx = MCS_HT40;
else
modeidx = MCS_HT20;
if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
modeidx++;
frmlen = ath_max_4ms_framelen[modeidx][rates[i].idx];
max_4ms_framelen = min(max_4ms_framelen, frmlen);
}
/*
@ -770,8 +786,6 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR;
seqno = bf->bf_state.seqno;
if (!bf_first)
bf_first = bf;
/* do not step over block-ack window */
if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) {
@ -779,6 +793,21 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
break;
}
if (tid->bar_index > ATH_BA_INDEX(tid->seq_start, seqno)) {
struct ath_tx_status ts = {};
struct list_head bf_head;
INIT_LIST_HEAD(&bf_head);
list_add(&bf->list, &bf_head);
__skb_unlink(skb, &tid->buf_q);
ath_tx_update_baw(sc, tid, seqno);
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
continue;
}
if (!bf_first)
bf_first = bf;
if (!rl) {
aggr_limit = ath_lookup_rate(sc, bf, tid);
rl = 1;
@ -1121,6 +1150,7 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
txtid->state |= AGGR_ADDBA_PROGRESS;
txtid->paused = true;
*ssn = txtid->seq_start = txtid->seq_next;
txtid->bar_index = -1;
memset(txtid->tx_buf, 0, sizeof(txtid->tx_buf));
txtid->baw_head = txtid->baw_tail = 0;
@ -1155,9 +1185,9 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
txtid->state |= AGGR_CLEANUP;
else
txtid->state &= ~AGGR_ADDBA_COMPLETE;
spin_unlock_bh(&txq->axq_lock);
ath_tx_flush_tid(sc, txtid);
spin_unlock_bh(&txq->axq_lock);
}
void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
@ -1399,8 +1429,6 @@ static bool bf_is_ampdu_not_probing(struct ath_buf *bf)
static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq,
struct list_head *list, bool retry_tx)
__releases(txq->axq_lock)
__acquires(txq->axq_lock)
{
struct ath_buf *bf, *lastbf;
struct list_head bf_head;
@ -1427,13 +1455,11 @@ static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq,
if (bf_is_ampdu_not_probing(bf))
txq->axq_ampdu_depth--;
spin_unlock_bh(&txq->axq_lock);
if (bf_isampdu(bf))
ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0,
retry_tx);
else
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
spin_lock_bh(&txq->axq_lock);
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
}
}
@ -1560,11 +1586,9 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
break;
}
if (!list_empty(&ac->tid_q)) {
if (!ac->sched) {
ac->sched = true;
list_add_tail(&ac->list, &txq->axq_acq);
}
if (!list_empty(&ac->tid_q) && !ac->sched) {
ac->sched = true;
list_add_tail(&ac->list, &txq->axq_acq);
}
if (ac == last_ac ||
@ -1707,10 +1731,6 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
list_add_tail(&bf->list, &bf_head);
bf->bf_state.bf_type = 0;
/* update starting sequence number for subsequent ADDBA request */
if (tid)
INCR(tid->seq_start, IEEE80211_SEQ_MAX);
bf->bf_lastbf = bf;
ath_tx_fill_desc(sc, bf, txq, fi->framelen);
ath_tx_txqaddbuf(sc, txq, &bf_head, false);
@ -1818,7 +1838,6 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
struct ath_buf *bf;
u8 tidno;
spin_lock_bh(&txctl->txq->axq_lock);
if ((sc->sc_flags & SC_OP_TXAGGR) && txctl->an &&
ieee80211_is_data_qos(hdr->frame_control)) {
tidno = ieee80211_get_qos_ctl(hdr)[0] &
@ -1837,7 +1856,7 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
} else {
bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
if (!bf)
goto out;
return;
bf->bf_state.bfs_paprd = txctl->paprd;
@ -1846,9 +1865,6 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
ath_tx_send_normal(sc, txctl->txq, tid, skb);
}
out:
spin_unlock_bh(&txctl->txq->axq_lock);
}
/* Upon failure caller should free skb */
@ -1915,9 +1931,11 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
ieee80211_stop_queue(sc->hw, q);
txq->stopped = 1;
}
spin_unlock_bh(&txq->axq_lock);
ath_tx_start_dma(sc, skb, txctl);
spin_unlock_bh(&txq->axq_lock);
return 0;
}
@ -1936,9 +1954,6 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
ath_dbg(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb);
if (tx_flags & ATH_TX_BAR)
tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
if (!(tx_flags & ATH_TX_ERROR))
/* Frame was ACKed */
tx_info->flags |= IEEE80211_TX_STAT_ACK;
@ -1966,7 +1981,6 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
q = skb_get_queue_mapping(skb);
if (txq == sc->tx.txq_map[q]) {
spin_lock_bh(&txq->axq_lock);
if (WARN_ON(--txq->pending_frames < 0))
txq->pending_frames = 0;
@ -1974,7 +1988,6 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
ieee80211_wake_queue(sc->hw, q);
txq->stopped = 0;
}
spin_unlock_bh(&txq->axq_lock);
}
ieee80211_tx_status(hw, skb);
@ -1982,16 +1995,13 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
struct ath_txq *txq, struct list_head *bf_q,
struct ath_tx_status *ts, int txok, int sendbar)
struct ath_tx_status *ts, int txok)
{
struct sk_buff *skb = bf->bf_mpdu;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
unsigned long flags;
int tx_flags = 0;
if (sendbar)
tx_flags = ATH_TX_BAR;
if (!txok)
tx_flags |= ATH_TX_ERROR;
@ -2083,8 +2093,6 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
struct ath_tx_status *ts, struct ath_buf *bf,
struct list_head *bf_head)
__releases(txq->axq_lock)
__acquires(txq->axq_lock)
{
int txok;
@ -2094,16 +2102,12 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
if (bf_is_ampdu_not_probing(bf))
txq->axq_ampdu_depth--;
spin_unlock_bh(&txq->axq_lock);
if (!bf_isampdu(bf)) {
ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok);
ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok, 0);
ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok);
} else
ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true);
spin_lock_bh(&txq->axq_lock);
if (sc->sc_flags & SC_OP_TXAGGR)
ath_txq_schedule(sc, txq);
}

View File

@ -21,6 +21,8 @@
#include "regd.h"
#include "regd_common.h"
static int __ath_regd_init(struct ath_regulatory *reg);
/*
* This is a set of common rules used by our world regulatory domains.
* We have 12 world regulatory domains. To save space we consolidate
@ -347,10 +349,26 @@ static void ath_reg_apply_world_flags(struct wiphy *wiphy,
}
}
static u16 ath_regd_find_country_by_name(char *alpha2)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
if (!memcmp(allCountries[i].isoName, alpha2, 2))
return allCountries[i].countryCode;
}
return -1;
}
int ath_reg_notifier_apply(struct wiphy *wiphy,
struct regulatory_request *request,
struct ath_regulatory *reg)
{
struct ath_common *common = container_of(reg, struct ath_common,
regulatory);
u16 country_code;
/* We always apply this */
ath_reg_apply_radar_flags(wiphy);
@ -363,14 +381,37 @@ int ath_reg_notifier_apply(struct wiphy *wiphy,
return 0;
switch (request->initiator) {
case NL80211_REGDOM_SET_BY_DRIVER:
case NL80211_REGDOM_SET_BY_CORE:
/*
* If common->reg_world_copy is world roaming it means we *were*
* world roaming... so we now have to restore that data.
*/
if (!ath_is_world_regd(&common->reg_world_copy))
break;
memcpy(reg, &common->reg_world_copy,
sizeof(struct ath_regulatory));
break;
case NL80211_REGDOM_SET_BY_DRIVER:
case NL80211_REGDOM_SET_BY_USER:
break;
case NL80211_REGDOM_SET_BY_COUNTRY_IE:
if (ath_is_world_regd(reg))
ath_reg_apply_world_flags(wiphy, request->initiator,
reg);
if (!ath_is_world_regd(reg))
break;
country_code = ath_regd_find_country_by_name(request->alpha2);
if (country_code == (u16) -1)
break;
reg->current_rd = COUNTRY_ERD_FLAG;
reg->current_rd |= country_code;
printk(KERN_DEBUG "ath: regdomain 0x%0x updated by CountryIE\n",
reg->current_rd);
__ath_regd_init(reg);
ath_reg_apply_world_flags(wiphy, request->initiator, reg);
break;
}
@ -508,11 +549,7 @@ static void ath_regd_sanitize(struct ath_regulatory *reg)
reg->current_rd = 0x64;
}
int
ath_regd_init(struct ath_regulatory *reg,
struct wiphy *wiphy,
int (*reg_notifier)(struct wiphy *wiphy,
struct regulatory_request *request))
static int __ath_regd_init(struct ath_regulatory *reg)
{
struct country_code_to_enum_rd *country = NULL;
u16 regdmn;
@ -583,7 +620,29 @@ ath_regd_init(struct ath_regulatory *reg,
printk(KERN_DEBUG "ath: Regpair used: 0x%0x\n",
reg->regpair->regDmnEnum);
return 0;
}
int
ath_regd_init(struct ath_regulatory *reg,
struct wiphy *wiphy,
int (*reg_notifier)(struct wiphy *wiphy,
struct regulatory_request *request))
{
struct ath_common *common = container_of(reg, struct ath_common,
regulatory);
int r;
r = __ath_regd_init(reg);
if (r)
return r;
if (ath_is_world_regd(reg))
memcpy(&common->reg_world_copy, reg,
sizeof(struct ath_regulatory));
ath_regd_init_wiphy(reg, wiphy, reg_notifier);
return 0;
}
EXPORT_SYMBOL(ath_regd_init);

View File

@ -228,10 +228,98 @@ static void b43_chantab_radio_2056_upload(struct b43_wldev *dev,
static void b43_radio_2056_setup(struct b43_wldev *dev,
const struct b43_nphy_channeltab_entry_rev3 *e)
{
struct ssb_sprom *sprom = dev->dev->bus_sprom;
enum ieee80211_band band = b43_current_band(dev->wl);
u16 offset;
u8 i;
u16 bias, cbias, pag_boost, pgag_boost, mixg_boost, padg_boost;
B43_WARN_ON(dev->phy.rev < 3);
b43_chantab_radio_2056_upload(dev, e);
/* TODO */
b2056_upload_syn_pll_cp2(dev, band == IEEE80211_BAND_5GHZ);
if (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1F);
b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1F);
if (dev->dev->chip_id == 0x4716) {
b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x14);
b43_radio_write(dev, B2056_SYN_PLL_CP2, 0);
} else {
b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x0B);
b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x14);
}
}
if (sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&
b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1F);
b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1F);
b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x05);
b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x0C);
}
if (dev->phy.n->ipa2g_on && band == IEEE80211_BAND_2GHZ) {
for (i = 0; i < 2; i++) {
offset = i ? B2056_TX1 : B2056_TX0;
if (dev->phy.rev >= 5) {
b43_radio_write(dev,
offset | B2056_TX_PADG_IDAC, 0xcc);
if (dev->dev->chip_id == 0x4716) {
bias = 0x40;
cbias = 0x45;
pag_boost = 0x5;
pgag_boost = 0x33;
mixg_boost = 0x55;
} else {
bias = 0x25;
cbias = 0x20;
pag_boost = 0x4;
pgag_boost = 0x03;
mixg_boost = 0x65;
}
padg_boost = 0x77;
b43_radio_write(dev,
offset | B2056_TX_INTPAG_IMAIN_STAT,
bias);
b43_radio_write(dev,
offset | B2056_TX_INTPAG_IAUX_STAT,
bias);
b43_radio_write(dev,
offset | B2056_TX_INTPAG_CASCBIAS,
cbias);
b43_radio_write(dev,
offset | B2056_TX_INTPAG_BOOST_TUNE,
pag_boost);
b43_radio_write(dev,
offset | B2056_TX_PGAG_BOOST_TUNE,
pgag_boost);
b43_radio_write(dev,
offset | B2056_TX_PADG_BOOST_TUNE,
padg_boost);
b43_radio_write(dev,
offset | B2056_TX_MIXG_BOOST_TUNE,
mixg_boost);
} else {
bias = dev->phy.is_40mhz ? 0x40 : 0x20;
b43_radio_write(dev,
offset | B2056_TX_INTPAG_IMAIN_STAT,
bias);
b43_radio_write(dev,
offset | B2056_TX_INTPAG_IAUX_STAT,
bias);
b43_radio_write(dev,
offset | B2056_TX_INTPAG_CASCBIAS,
0x30);
}
b43_radio_write(dev, offset | B2056_TX_PA_SPARE1, 0xee);
}
} else if (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ) {
/* TODO */
}
udelay(50);
/* VCO calibration */
b43_radio_write(dev, B2056_SYN_PLL_VCOCAL12, 0x00);
@ -387,7 +475,9 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
if (nphy->hang_avoid)
b43_nphy_stay_in_carrier_search(dev, 1);
if (dev->phy.rev >= 3) {
if (dev->phy.rev >= 7) {
txpi[0] = txpi[1] = 30;
} else if (dev->phy.rev >= 3) {
txpi[0] = 40;
txpi[1] = 40;
} else if (sprom->revision < 4) {
@ -411,6 +501,9 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
txpi[1] = 91;
}
}
if (dev->phy.rev < 7 &&
(txpi[0] < 40 || txpi[0] > 100 || txpi[1] < 40 || txpi[1] > 10))
txpi[0] = txpi[1] = 91;
/*
for (i = 0; i < 2; i++) {
@ -421,15 +514,31 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
for (i = 0; i < 2; i++) {
if (dev->phy.rev >= 3) {
/* FIXME: support 5GHz */
txgain = b43_ntab_tx_gain_rev3plus_2ghz[txpi[i]];
if (b43_nphy_ipa(dev)) {
txgain = *(b43_nphy_get_ipa_gain_table(dev) +
txpi[i]);
} else if (b43_current_band(dev->wl) ==
IEEE80211_BAND_5GHZ) {
/* FIXME: use 5GHz tables */
txgain =
b43_ntab_tx_gain_rev3plus_2ghz[txpi[i]];
} else {
if (dev->phy.rev >= 5 &&
sprom->fem.ghz5.extpa_gain == 3)
; /* FIXME: 5GHz_txgain_HiPwrEPA */
txgain =
b43_ntab_tx_gain_rev3plus_2ghz[txpi[i]];
}
radio_gain = (txgain >> 16) & 0x1FFFF;
} else {
txgain = b43_ntab_tx_gain_rev0_1_2[txpi[i]];
radio_gain = (txgain >> 16) & 0x1FFF;
}
dac_gain = (txgain >> 8) & 0x3F;
if (dev->phy.rev >= 7)
dac_gain = (txgain >> 8) & 0x7;
else
dac_gain = (txgain >> 8) & 0x3F;
bbmult = txgain & 0xFF;
if (dev->phy.rev >= 3) {
@ -459,7 +568,8 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
u32 tmp32;
u16 reg = (i == 0) ?
B43_NPHY_PAPD_EN0 : B43_NPHY_PAPD_EN1;
tmp32 = b43_ntab_read(dev, B43_NTAB32(26 + i, txpi[i]));
tmp32 = b43_ntab_read(dev, B43_NTAB32(26 + i,
576 + txpi[i]));
b43_phy_maskset(dev, reg, 0xE00F, (u32) tmp32 << 4);
b43_phy_set(dev, reg, 0x4);
}
@ -1493,8 +1603,8 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
struct ssb_sprom *sprom = dev->dev->bus_sprom;
/* TX to RX */
u8 tx2rx_events[9] = { 0x4, 0x3, 0x6, 0x5, 0x2, 0x1, 0x8, 0x1F };
u8 tx2rx_delays[9] = { 8, 4, 2, 2, 4, 4, 6, 1 };
u8 tx2rx_events[8] = { 0x4, 0x3, 0x6, 0x5, 0x2, 0x1, 0x8, 0x1F };
u8 tx2rx_delays[8] = { 8, 4, 2, 2, 4, 4, 6, 1 };
/* RX to TX */
u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3,
0x1F };
@ -1505,6 +1615,9 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
u16 tmp16;
u32 tmp32;
b43_phy_write(dev, 0x23f, 0x1f8);
b43_phy_write(dev, 0x240, 0x1f8);
tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
tmp32 &= 0xffffff;
b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);
@ -1520,12 +1633,13 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
b43_phy_write(dev, 0x2AE, 0x000C);
/* TX to RX */
b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays, 9);
b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays,
ARRAY_SIZE(tx2rx_events));
/* RX to TX */
if (b43_nphy_ipa(dev))
b43_nphy_set_rf_sequence(dev, 1, rx2tx_events_ipa,
rx2tx_delays_ipa, 9);
b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa,
rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa));
if (nphy->hw_phyrxchain != 3 &&
nphy->hw_phyrxchain != nphy->hw_phytxchain) {
if (b43_nphy_ipa(dev)) {
@ -1533,7 +1647,8 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
rx2tx_delays[6] = 1;
rx2tx_events[7] = 0x1F;
}
b43_nphy_set_rf_sequence(dev, 1, rx2tx_events, rx2tx_delays, 9);
b43_nphy_set_rf_sequence(dev, 1, rx2tx_events, rx2tx_delays,
ARRAY_SIZE(rx2tx_events));
}
tmp16 = (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) ?
@ -1547,8 +1662,8 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
b43_nphy_gain_ctrl_workarounds(dev);
b43_ntab_write(dev, B43_NTAB32(8, 0), 2);
b43_ntab_write(dev, B43_NTAB32(8, 16), 2);
b43_ntab_write(dev, B43_NTAB16(8, 0), 2);
b43_ntab_write(dev, B43_NTAB16(8, 16), 2);
/* TODO */
@ -1560,6 +1675,8 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_AUX, 0x07);
b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_LOB_BIAS, 0x88);
b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_LOB_BIAS, 0x88);
b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_CMFB_IDAC, 0x00);
b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_CMFB_IDAC, 0x00);
b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
@ -1584,18 +1701,18 @@ static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
0x70);
}
b43_phy_write(dev, 0x224, 0x039C);
b43_phy_write(dev, 0x225, 0x0357);
b43_phy_write(dev, 0x226, 0x0317);
b43_phy_write(dev, 0x227, 0x02D7);
b43_phy_write(dev, 0x228, 0x039C);
b43_phy_write(dev, 0x229, 0x0357);
b43_phy_write(dev, 0x22A, 0x0317);
b43_phy_write(dev, 0x22B, 0x02D7);
b43_phy_write(dev, 0x22C, 0x039C);
b43_phy_write(dev, 0x22D, 0x0357);
b43_phy_write(dev, 0x22E, 0x0317);
b43_phy_write(dev, 0x22F, 0x02D7);
b43_phy_write(dev, 0x224, 0x03eb);
b43_phy_write(dev, 0x225, 0x03eb);
b43_phy_write(dev, 0x226, 0x0341);
b43_phy_write(dev, 0x227, 0x0341);
b43_phy_write(dev, 0x228, 0x042b);
b43_phy_write(dev, 0x229, 0x042b);
b43_phy_write(dev, 0x22a, 0x0381);
b43_phy_write(dev, 0x22b, 0x0381);
b43_phy_write(dev, 0x22c, 0x042b);
b43_phy_write(dev, 0x22d, 0x042b);
b43_phy_write(dev, 0x22e, 0x0381);
b43_phy_write(dev, 0x22f, 0x0381);
}
static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev)
@ -3928,6 +4045,76 @@ int b43_phy_initn(struct b43_wldev *dev)
return 0;
}
/* http://bcm-v4.sipsolutions.net/802.11/PmuSpurAvoid */
static void b43_nphy_pmu_spur_avoid(struct b43_wldev *dev, bool avoid)
{
struct bcma_drv_cc *cc;
u32 pmu_ctl;
switch (dev->dev->bus_type) {
#ifdef CONFIG_B43_BCMA
case B43_BUS_BCMA:
cc = &dev->dev->bdev->bus->drv_cc;
if (dev->dev->chip_id == 43224 || dev->dev->chip_id == 43225) {
if (avoid) {
bcma_chipco_pll_write(cc, 0x0, 0x11500010);
bcma_chipco_pll_write(cc, 0x1, 0x000C0C06);
bcma_chipco_pll_write(cc, 0x2, 0x0F600a08);
bcma_chipco_pll_write(cc, 0x3, 0x00000000);
bcma_chipco_pll_write(cc, 0x4, 0x2001E920);
bcma_chipco_pll_write(cc, 0x5, 0x88888815);
} else {
bcma_chipco_pll_write(cc, 0x0, 0x11100010);
bcma_chipco_pll_write(cc, 0x1, 0x000c0c06);
bcma_chipco_pll_write(cc, 0x2, 0x03000a08);
bcma_chipco_pll_write(cc, 0x3, 0x00000000);
bcma_chipco_pll_write(cc, 0x4, 0x200005c0);
bcma_chipco_pll_write(cc, 0x5, 0x88888815);
}
pmu_ctl = BCMA_CC_PMU_CTL_PLL_UPD;
} else if (dev->dev->chip_id == 0x4716) {
if (avoid) {
bcma_chipco_pll_write(cc, 0x0, 0x11500060);
bcma_chipco_pll_write(cc, 0x1, 0x080C0C06);
bcma_chipco_pll_write(cc, 0x2, 0x0F600000);
bcma_chipco_pll_write(cc, 0x3, 0x00000000);
bcma_chipco_pll_write(cc, 0x4, 0x2001E924);
bcma_chipco_pll_write(cc, 0x5, 0x88888815);
} else {
bcma_chipco_pll_write(cc, 0x0, 0x11100060);
bcma_chipco_pll_write(cc, 0x1, 0x080c0c06);
bcma_chipco_pll_write(cc, 0x2, 0x03000000);
bcma_chipco_pll_write(cc, 0x3, 0x00000000);
bcma_chipco_pll_write(cc, 0x4, 0x200005c0);
bcma_chipco_pll_write(cc, 0x5, 0x88888815);
}
pmu_ctl = BCMA_CC_PMU_CTL_PLL_UPD |
BCMA_CC_PMU_CTL_NOILPONW;
} else if (dev->dev->chip_id == 0x4322 ||
dev->dev->chip_id == 0x4340 ||
dev->dev->chip_id == 0x4341) {
bcma_chipco_pll_write(cc, 0x0, 0x11100070);
bcma_chipco_pll_write(cc, 0x1, 0x1014140a);
bcma_chipco_pll_write(cc, 0x5, 0x88888854);
if (avoid)
bcma_chipco_pll_write(cc, 0x2, 0x05201828);
else
bcma_chipco_pll_write(cc, 0x2, 0x05001828);
pmu_ctl = BCMA_CC_PMU_CTL_PLL_UPD;
} else {
return;
}
bcma_cc_set32(cc, BCMA_CC_PMU_CTL, pmu_ctl);
break;
#endif
#ifdef CONFIG_B43_SSB
case B43_BUS_SSB:
/* FIXME */
break;
#endif
}
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */
static void b43_nphy_channel_setup(struct b43_wldev *dev,
const struct b43_phy_n_sfo_cfg *e,
@ -3935,6 +4122,7 @@ static void b43_nphy_channel_setup(struct b43_wldev *dev,
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_n *nphy = dev->phy.n;
int ch = new_channel->hw_value;
u16 old_band_5ghz;
u32 tmp32;
@ -3974,8 +4162,41 @@ static void b43_nphy_channel_setup(struct b43_wldev *dev,
b43_nphy_tx_lp_fbw(dev);
if (dev->phy.rev >= 3 && 0) {
/* TODO */
if (dev->phy.rev >= 3 &&
dev->phy.n->spur_avoid != B43_SPUR_AVOID_DISABLE) {
bool avoid = false;
if (dev->phy.n->spur_avoid == B43_SPUR_AVOID_FORCE) {
avoid = true;
} else if (!b43_channel_type_is_40mhz(phy->channel_type)) {
if ((ch >= 5 && ch <= 8) || ch == 13 || ch == 14)
avoid = true;
} else { /* 40MHz */
if (nphy->aband_spurwar_en &&
(ch == 38 || ch == 102 || ch == 118))
avoid = dev->dev->chip_id == 0x4716;
}
b43_nphy_pmu_spur_avoid(dev, avoid);
if (dev->dev->chip_id == 43222 || dev->dev->chip_id == 43224 ||
dev->dev->chip_id == 43225) {
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW,
avoid ? 0x5341 : 0x8889);
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
}
if (dev->phy.rev == 3 || dev->phy.rev == 4)
; /* TODO: reset PLL */
if (avoid)
b43_phy_set(dev, B43_NPHY_BBCFG, B43_NPHY_BBCFG_RSTRX);
else
b43_phy_mask(dev, B43_NPHY_BBCFG,
~B43_NPHY_BBCFG_RSTRX & 0xFFFF);
b43_nphy_reset_cca(dev);
/* wl sets useless phy_isspuravoid here */
}
b43_phy_write(dev, B43_NPHY_NDATAT_DUP40, 0x3830);
@ -4055,10 +4276,13 @@ static void b43_nphy_op_prepare_structs(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_n *nphy = phy->n;
struct ssb_sprom *sprom = dev->dev->bus_sprom;
memset(nphy, 0, sizeof(*nphy));
nphy->hang_avoid = (phy->rev == 3 || phy->rev == 4);
nphy->spur_avoid = (phy->rev >= 3) ?
B43_SPUR_AVOID_AUTO : B43_SPUR_AVOID_DISABLE;
nphy->gain_boost = true; /* this way we follow wl, assume it is true */
nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */
nphy->phyrxchain = 3; /* to avoid b43_nphy_set_rx_core_state like wl */
@ -4067,6 +4291,38 @@ static void b43_nphy_op_prepare_structs(struct b43_wldev *dev)
* 0x7f == 127 and we check for 128 when restoring TX pwr ctl. */
nphy->tx_pwr_idx[0] = 128;
nphy->tx_pwr_idx[1] = 128;
/* Hardware TX power control and 5GHz power gain */
nphy->txpwrctrl = false;
nphy->pwg_gain_5ghz = false;
if (dev->phy.rev >= 3 ||
(dev->dev->board_vendor == PCI_VENDOR_ID_APPLE &&
(dev->dev->core_rev == 11 || dev->dev->core_rev == 12))) {
nphy->txpwrctrl = true;
nphy->pwg_gain_5ghz = true;
} else if (sprom->revision >= 4) {
if (dev->phy.rev >= 2 &&
(sprom->boardflags2_lo & B43_BFL2_TXPWRCTRL_EN)) {
nphy->txpwrctrl = true;
#ifdef CONFIG_B43_SSB
if (dev->dev->bus_type == B43_BUS_SSB &&
dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI) {
struct pci_dev *pdev =
dev->dev->sdev->bus->host_pci;
if (pdev->device == 0x4328 ||
pdev->device == 0x432a)
nphy->pwg_gain_5ghz = true;
}
#endif
} else if (sprom->boardflags2_lo & B43_BFL2_5G_PWRGAIN) {
nphy->pwg_gain_5ghz = true;
}
}
if (dev->phy.rev >= 3) {
nphy->ipa2g_on = sprom->fem.ghz2.extpa_gain == 2;
nphy->ipa5g_on = sprom->fem.ghz5.extpa_gain == 2;
}
}
static void b43_nphy_op_free(struct b43_wldev *dev)

View File

@ -716,6 +716,12 @@
struct b43_wldev;
enum b43_nphy_spur_avoid {
B43_SPUR_AVOID_DISABLE,
B43_SPUR_AVOID_AUTO,
B43_SPUR_AVOID_FORCE,
};
struct b43_chanspec {
u16 center_freq;
enum nl80211_channel_type channel_type;
@ -785,6 +791,7 @@ struct b43_phy_n {
u16 mphase_txcal_bestcoeffs[11];
bool txpwrctrl;
bool pwg_gain_5ghz;
u8 tx_pwr_idx[2];
u16 adj_pwr_tbl[84];
u16 txcal_bbmult;
@ -803,6 +810,7 @@ struct b43_phy_n {
u16 classifier_state;
u16 clip_state[2];
enum b43_nphy_spur_avoid spur_avoid;
bool aband_spurwar_en;
bool gband_spurwar_en;

View File

@ -1572,14 +1572,14 @@ static const struct b2056_inittab_entry b2056_inittab_rev6_syn[] = {
[B2056_SYN_PLL_XTAL5] = { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
[B2056_SYN_PLL_XTAL6] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
[B2056_SYN_PLL_REFDIV] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
[B2056_SYN_PLL_PFD] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
[B2056_SYN_PLL_PFD] = { .ghz5 = 0x0006, .ghz2 = 0x0006, UPLOAD, },
[B2056_SYN_PLL_CP1] = { .ghz5 = 0x000f, .ghz2 = 0x000f, NOUPLOAD, },
[B2056_SYN_PLL_CP2] = { .ghz5 = 0x0030, .ghz2 = 0x0030, NOUPLOAD, },
[B2056_SYN_PLL_CP2] = { .ghz5 = 0x003f, .ghz2 = 0x003f, UPLOAD, },
[B2056_SYN_PLL_CP3] = { .ghz5 = 0x0032, .ghz2 = 0x0032, NOUPLOAD, },
[B2056_SYN_PLL_LOOPFILTER1] = { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
[B2056_SYN_PLL_LOOPFILTER2] = { .ghz5 = 0x000d, .ghz2 = 0x000d, NOUPLOAD, },
[B2056_SYN_PLL_LOOPFILTER1] = { .ghz5 = 0x0006, .ghz2 = 0x0006, UPLOAD, },
[B2056_SYN_PLL_LOOPFILTER2] = { .ghz5 = 0x0006, .ghz2 = 0x0006, UPLOAD, },
[B2056_SYN_PLL_LOOPFILTER3] = { .ghz5 = 0x0004, .ghz2 = 0x0004, NOUPLOAD, },
[B2056_SYN_PLL_LOOPFILTER4] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
[B2056_SYN_PLL_LOOPFILTER4] = { .ghz5 = 0x002b, .ghz2 = 0x002b, UPLOAD, },
[B2056_SYN_PLL_LOOPFILTER5] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
[B2056_SYN_PLL_MMD1] = { .ghz5 = 0x001c, .ghz2 = 0x001c, NOUPLOAD, },
[B2056_SYN_PLL_MMD2] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
@ -9055,6 +9055,21 @@ void b2056_upload_inittabs(struct b43_wldev *dev,
B2056_RX1, pts->rx, pts->rx_length);
}
void b2056_upload_syn_pll_cp2(struct b43_wldev *dev, bool ghz5)
{
struct b2056_inittabs_pts *pts;
const struct b2056_inittab_entry *e;
if (dev->phy.rev >= ARRAY_SIZE(b2056_inittabs)) {
B43_WARN_ON(1);
return;
}
pts = &b2056_inittabs[dev->phy.rev];
e = &pts->syn[B2056_SYN_PLL_CP2];
b43_radio_write(dev, B2056_SYN_PLL_CP2, ghz5 ? e->ghz5 : e->ghz2);
}
const struct b43_nphy_channeltab_entry_rev3 *
b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq)
{

View File

@ -1090,6 +1090,7 @@ struct b43_nphy_channeltab_entry_rev3 {
void b2056_upload_inittabs(struct b43_wldev *dev,
bool ghz5, bool ignore_uploadflag);
void b2056_upload_syn_pll_cp2(struct b43_wldev *dev, bool ghz5);
/* Get the NPHY Channel Switch Table entry for a channel.
* Returns NULL on failure to find an entry. */

View File

@ -2171,6 +2171,48 @@ static const u16 b43_ntab_loftlt1_r3[] = {
0x0000, 0x0000,
};
/* volatile tables, PHY revision >= 3 */
/* indexed by antswctl2g */
static const u16 b43_ntab_antswctl2g_r3[4][32] = {
{
0x0082, 0x0082, 0x0211, 0x0222, 0x0328,
0x0000, 0x0000, 0x0000, 0x0144, 0x0000,
0x0000, 0x0000, 0x0188, 0x0000, 0x0000,
0x0000, 0x0082, 0x0082, 0x0211, 0x0222,
0x0328, 0x0000, 0x0000, 0x0000, 0x0144,
0x0000, 0x0000, 0x0000, 0x0188, 0x0000,
0x0000, 0x0000,
},
{
0x0022, 0x0022, 0x0011, 0x0022, 0x0022,
0x0000, 0x0000, 0x0000, 0x0011, 0x0000,
0x0000, 0x0000, 0x0022, 0x0000, 0x0000,
0x0000, 0x0022, 0x0022, 0x0011, 0x0022,
0x0022, 0x0000, 0x0000, 0x0000, 0x0011,
0x0000, 0x0000, 0x0000, 0x0022, 0x0000,
0x0000, 0x0000,
},
{
0x0088, 0x0088, 0x0044, 0x0088, 0x0088,
0x0000, 0x0000, 0x0000, 0x0044, 0x0000,
0x0000, 0x0000, 0x0088, 0x0000, 0x0000,
0x0000, 0x0088, 0x0088, 0x0044, 0x0088,
0x0088, 0x0000, 0x0000, 0x0000, 0x0044,
0x0000, 0x0000, 0x0000, 0x0088, 0x0000,
0x0000, 0x0000,
},
{
0x0022, 0x0022, 0x0011, 0x0022, 0x0000,
0x0000, 0x0000, 0x0000, 0x0011, 0x0000,
0x0000, 0x0000, 0x0022, 0x0000, 0x0000,
0x03cc, 0x0022, 0x0022, 0x0011, 0x0022,
0x0000, 0x0000, 0x0000, 0x0000, 0x0011,
0x0000, 0x0000, 0x0000, 0x0022, 0x0000,
0x0000, 0x03cc,
}
};
/* TX gain tables */
const u32 b43_ntab_tx_gain_rev0_1_2[] = {
0x03cc2b44, 0x03cc2b42, 0x03cc2a44, 0x03cc2a42,
@ -2652,7 +2694,7 @@ const u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = {
const s16 tbl_tx_filter_coef_rev4[7][15] = {
{ -377, 137, -407, 208, -1527,
956, 93, 186, 93, 230,
-44, 230, 20, -191, 201 },
-44, 230, 201, -191, 201 },
{ -77, 20, -98, 49, -93,
60, 56, 111, 56, 26,
-5, 26, 34, -32, 34 },
@ -2838,9 +2880,8 @@ u32 b43_ntab_read(struct b43_wldev *dev, u32 offset)
break;
case B43_NTAB_32BIT:
b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset);
value = b43_phy_read(dev, B43_NPHY_TABLE_DATAHI);
value <<= 16;
value |= b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
value = b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
value |= b43_phy_read(dev, B43_NPHY_TABLE_DATAHI) << 16;
break;
default:
B43_WARN_ON(1);
@ -2864,6 +2905,12 @@ void b43_ntab_read_bulk(struct b43_wldev *dev, u32 offset,
b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset);
for (i = 0; i < nr_elements; i++) {
/* Auto increment broken + caching issue on BCM43224? */
if (dev->dev->chip_id == 43224 && dev->dev->chip_rev == 1) {
b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset + i);
}
switch (type) {
case B43_NTAB_8BIT:
*data = b43_phy_read(dev, B43_NPHY_TABLE_DATALO) & 0xFF;
@ -2874,9 +2921,10 @@ void b43_ntab_read_bulk(struct b43_wldev *dev, u32 offset,
data += 2;
break;
case B43_NTAB_32BIT:
*((u32 *)data) = b43_phy_read(dev, B43_NPHY_TABLE_DATAHI);
*((u32 *)data) <<= 16;
*((u32 *)data) |= b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
*((u32 *)data) =
b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
*((u32 *)data) |=
b43_phy_read(dev, B43_NPHY_TABLE_DATAHI) << 16;
data += 4;
break;
default:
@ -2932,6 +2980,13 @@ void b43_ntab_write_bulk(struct b43_wldev *dev, u32 offset,
b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset);
for (i = 0; i < nr_elements; i++) {
/* Auto increment broken + caching issue on BCM43224? */
if ((offset >> 10) == 9 && dev->dev->chip_id == 43224 &&
dev->dev->chip_rev == 1) {
b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset + i);
}
switch (type) {
case B43_NTAB_8BIT:
value = *data;
@ -2999,6 +3054,8 @@ void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev)
} while (0)
void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev)
{
struct ssb_sprom *sprom = dev->dev->bus_sprom;
/* Static tables */
ntab_upload_r3(dev, B43_NTAB_FRAMESTRUCT_R3, b43_ntab_framestruct_r3);
ntab_upload_r3(dev, B43_NTAB_PILOT_R3, b43_ntab_pilot_r3);
@ -3029,7 +3086,11 @@ void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev)
ntab_upload_r3(dev, B43_NTAB_C1_LOFEEDTH_R3, b43_ntab_loftlt1_r3);
/* Volatile tables */
/* TODO */
if (sprom->fem.ghz2.antswlut < ARRAY_SIZE(b43_ntab_antswctl2g_r3))
ntab_upload_r3(dev, B43_NTAB_ANT_SW_CTL_R3,
b43_ntab_antswctl2g_r3[sprom->fem.ghz2.antswlut]);
else
B43_WARN_ON(1);
}
struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(

View File

@ -126,26 +126,29 @@ struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
#define B43_NTAB_C1_LOFEEDTH B43_NTAB16(0x1B, 0x1C0) /* Local Oscillator Feed Through Lookup Table Core 1 */
#define B43_NTAB_C1_LOFEEDTH_SIZE 128
/* Volatile N-PHY tables, PHY revision >= 3 */
#define B43_NTAB_ANT_SW_CTL_R3 B43_NTAB16( 9, 0) /* antenna software control */
/* Static N-PHY tables, PHY revision >= 3 */
#define B43_NTAB_FRAMESTRUCT_R3 B43_NTAB32(10, 000) /* frame struct */
#define B43_NTAB_PILOT_R3 B43_NTAB16(11, 000) /* pilot */
#define B43_NTAB_TMAP_R3 B43_NTAB32(12, 000) /* TM AP */
#define B43_NTAB_INTLEVEL_R3 B43_NTAB32(13, 000) /* INT LV */
#define B43_NTAB_TDTRN_R3 B43_NTAB32(14, 000) /* TD TRN */
#define B43_NTAB_NOISEVAR0_R3 B43_NTAB32(16, 000) /* noise variance 0 */
#define B43_NTAB_FRAMESTRUCT_R3 B43_NTAB32(10, 0) /* frame struct */
#define B43_NTAB_PILOT_R3 B43_NTAB16(11, 0) /* pilot */
#define B43_NTAB_TMAP_R3 B43_NTAB32(12, 0) /* TM AP */
#define B43_NTAB_INTLEVEL_R3 B43_NTAB32(13, 0) /* INT LV */
#define B43_NTAB_TDTRN_R3 B43_NTAB32(14, 0) /* TD TRN */
#define B43_NTAB_NOISEVAR0_R3 B43_NTAB32(16, 0) /* noise variance 0 */
#define B43_NTAB_NOISEVAR1_R3 B43_NTAB32(16, 128) /* noise variance 1 */
#define B43_NTAB_MCS_R3 B43_NTAB16(18, 000) /* MCS */
#define B43_NTAB_MCS_R3 B43_NTAB16(18, 0) /* MCS */
#define B43_NTAB_TDI20A0_R3 B43_NTAB32(19, 128) /* TDI 20/0 */
#define B43_NTAB_TDI20A1_R3 B43_NTAB32(19, 256) /* TDI 20/1 */
#define B43_NTAB_TDI40A0_R3 B43_NTAB32(19, 640) /* TDI 40/0 */
#define B43_NTAB_TDI40A1_R3 B43_NTAB32(19, 768) /* TDI 40/1 */
#define B43_NTAB_PILOTLT_R3 B43_NTAB32(20, 000) /* PLT lookup */
#define B43_NTAB_CHANEST_R3 B43_NTAB32(22, 000) /* channel estimate */
#define B43_NTAB_FRAMELT_R3 B43_NTAB8 (24, 000) /* frame lookup */
#define B43_NTAB_C0_ESTPLT_R3 B43_NTAB8 (26, 000) /* estimated power lookup 0 */
#define B43_NTAB_C1_ESTPLT_R3 B43_NTAB8 (27, 000) /* estimated power lookup 1 */
#define B43_NTAB_C0_ADJPLT_R3 B43_NTAB8 (26, 064) /* adjusted power lookup 0 */
#define B43_NTAB_C1_ADJPLT_R3 B43_NTAB8 (27, 064) /* adjusted power lookup 1 */
#define B43_NTAB_PILOTLT_R3 B43_NTAB32(20, 0) /* PLT lookup */
#define B43_NTAB_CHANEST_R3 B43_NTAB32(22, 0) /* channel estimate */
#define B43_NTAB_FRAMELT_R3 B43_NTAB8(24, 0) /* frame lookup */
#define B43_NTAB_C0_ESTPLT_R3 B43_NTAB8(26, 0) /* estimated power lookup 0 */
#define B43_NTAB_C1_ESTPLT_R3 B43_NTAB8(27, 0) /* estimated power lookup 1 */
#define B43_NTAB_C0_ADJPLT_R3 B43_NTAB8(26, 64) /* adjusted power lookup 0 */
#define B43_NTAB_C1_ADJPLT_R3 B43_NTAB8(27, 64) /* adjusted power lookup 1 */
#define B43_NTAB_C0_GAINCTL_R3 B43_NTAB32(26, 192) /* gain control lookup 0 */
#define B43_NTAB_C1_GAINCTL_R3 B43_NTAB32(27, 192) /* gain control lookup 1 */
#define B43_NTAB_C0_IQLT_R3 B43_NTAB32(26, 320) /* I/Q lookup 0 */

View File

@ -3,9 +3,8 @@ config BRCMUTIL
config BRCMSMAC
tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver"
depends on PCI
depends on MAC80211
depends on BCMA=n
depends on BCMA
select BRCMUTIL
select FW_LOADER
select CRC_CCITT

View File

@ -40,8 +40,7 @@
static void brcmf_sdioh_irqhandler(struct sdio_func *func)
{
struct brcmf_bus *bus_if = dev_get_drvdata(&func->card->dev);
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv;
struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
brcmf_dbg(TRACE, "***IRQHandler\n");

View File

@ -40,6 +40,7 @@
#define DMA_ALIGN_MASK 0x03
#define SDIO_DEVICE_ID_BROADCOM_4329 0x4329
#define SDIO_DEVICE_ID_BROADCOM_4330 0x4330
#define SDIO_FUNC1_BLOCKSIZE 64
#define SDIO_FUNC2_BLOCKSIZE 512
@ -47,6 +48,7 @@
/* devices we support, null terminated */
static const struct sdio_device_id brcmf_sdmmc_ids[] = {
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)},
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)},
{ /* end: all zeroes */ },
};
MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
@ -481,12 +483,12 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
kfree(bus_if);
return -ENOMEM;
}
sdiodev->dev = &func->card->dev;
sdiodev->func[0] = func->card->sdio_func[0];
sdiodev->func[1] = func;
sdiodev->bus_if = bus_if;
bus_if->bus_priv = sdiodev;
bus_if->type = SDIO_BUS;
dev_set_drvdata(&func->card->dev, bus_if);
dev_set_drvdata(&func->card->dev, sdiodev);
atomic_set(&sdiodev->suspend, false);
init_waitqueue_head(&sdiodev->request_byte_wait);
@ -496,12 +498,15 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
}
if (func->num == 2) {
bus_if = dev_get_drvdata(&func->card->dev);
sdiodev = bus_if->bus_priv;
sdiodev = dev_get_drvdata(&func->card->dev);
if ((!sdiodev) || (sdiodev->func[1]->card != func->card))
return -ENODEV;
sdiodev->func[2] = func;
bus_if = sdiodev->bus_if;
sdiodev->dev = &func->dev;
dev_set_drvdata(&func->dev, bus_if);
brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_probe...\n");
ret = brcmf_sdio_probe(sdiodev);
}
@ -520,11 +525,12 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func)
brcmf_dbg(INFO, "Function#: 0x%04x\n", func->num);
if (func->num == 2) {
bus_if = dev_get_drvdata(&func->card->dev);
bus_if = dev_get_drvdata(&func->dev);
sdiodev = bus_if->bus_priv;
brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_remove...\n");
brcmf_sdio_remove(sdiodev);
dev_set_drvdata(&func->card->dev, NULL);
dev_set_drvdata(&func->dev, NULL);
kfree(bus_if);
kfree(sdiodev);
}
@ -534,15 +540,12 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func)
static int brcmf_sdio_suspend(struct device *dev)
{
mmc_pm_flag_t sdio_flags;
struct brcmf_sdio_dev *sdiodev;
struct sdio_func *func = dev_to_sdio_func(dev);
struct brcmf_bus *bus_if = dev_get_drvdata(&func->card->dev);
struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
int ret = 0;
brcmf_dbg(TRACE, "\n");
sdiodev = bus_if->bus_priv;
atomic_set(&sdiodev->suspend, true);
sdio_flags = sdio_get_host_pm_caps(sdiodev->func[1]);
@ -564,11 +567,9 @@ static int brcmf_sdio_suspend(struct device *dev)
static int brcmf_sdio_resume(struct device *dev)
{
struct brcmf_sdio_dev *sdiodev;
struct sdio_func *func = dev_to_sdio_func(dev);
struct brcmf_bus *bus_if = dev_get_drvdata(&func->card->dev);
struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev);
sdiodev = bus_if->bus_priv;
brcmf_sdio_wdtmr_enable(sdiodev, true);
atomic_set(&sdiodev->suspend, false);
return 0;

View File

@ -87,7 +87,7 @@
#define TOE_TX_CSUM_OL 0x00000001
#define TOE_RX_CSUM_OL 0x00000002
#define BRCMF_BSS_INFO_VERSION 108 /* curr ver of brcmf_bss_info_le struct */
#define BRCMF_BSS_INFO_VERSION 109 /* curr ver of brcmf_bss_info_le struct */
/* size of brcmf_scan_params not including variable length array */
#define BRCMF_SCAN_PARAMS_FIXED_SIZE 64

View File

@ -58,7 +58,7 @@ struct brcmf_proto_cdc_dcmd {
* Used on data packets to convey priority across USB.
*/
#define BDC_HEADER_LEN 4
#define BDC_PROTO_VER 1 /* Protocol version */
#define BDC_PROTO_VER 2 /* Protocol version */
#define BDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */
#define BDC_FLAG_VER_SHIFT 4 /* Protocol version shift */
#define BDC_FLAG_SUM_GOOD 0x04 /* Good RX checksums */
@ -77,7 +77,7 @@ struct brcmf_proto_bdc_header {
u8 flags;
u8 priority; /* 802.1d Priority, 4:7 flow control info for usb */
u8 flags2;
u8 rssi;
u8 data_offset;
};
@ -372,7 +372,7 @@ void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx,
h->priority = (pktbuf->priority & BDC_PRIORITY_MASK);
h->flags2 = 0;
h->rssi = 0;
h->data_offset = 0;
BDC_SET_IF_IDX(h, ifidx);
}

View File

@ -3636,6 +3636,8 @@ static bool brcmf_sdbrcm_chipmatch(u16 chipid)
{
if (chipid == BCM4329_CHIP_ID)
return true;
if (chipid == BCM4330_CHIP_ID)
return true;
return false;
}

View File

@ -59,37 +59,17 @@ struct sdiod_drive_str {
u8 strength; /* Pad Drive Strength in mA */
u8 sel; /* Chip-specific select value */
};
/* SDIO Drive Strength to sel value table for PMU Rev 1 */
static const struct sdiod_drive_str sdiod_drive_strength_tab1[] = {
{
4, 0x2}, {
2, 0x3}, {
1, 0x0}, {
0, 0x0}
};
/* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */
static const struct sdiod_drive_str sdiod_drive_strength_tab2[] = {
{
12, 0x7}, {
10, 0x6}, {
8, 0x5}, {
6, 0x4}, {
4, 0x2}, {
2, 0x1}, {
0, 0x0}
};
/* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */
static const struct sdiod_drive_str sdiod_drive_strength_tab3[] = {
{
32, 0x7}, {
26, 0x6}, {
22, 0x5}, {
16, 0x4}, {
12, 0x3}, {
8, 0x2}, {
4, 0x1}, {
0, 0x0}
};
/* SDIO Drive Strength to sel value table for PMU Rev 11 (1.8V) */
static const struct sdiod_drive_str sdiod_drvstr_tab1_1v8[] = {
{32, 0x6},
{26, 0x7},
{22, 0x4},
{16, 0x5},
{12, 0x2},
{8, 0x3},
{4, 0x0},
{0, 0x1}
};
u8
brcmf_sdio_chip_getinfidx(struct chip_info *ci, u16 coreid)
@ -396,6 +376,23 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev,
ci->c_inf[3].base = BCM4329_CORE_ARM_BASE;
ci->ramsize = BCM4329_RAMSIZE;
break;
case BCM4330_CHIP_ID:
ci->c_inf[0].wrapbase = 0x18100000;
ci->c_inf[0].cib = 0x27004211;
ci->c_inf[1].id = BCMA_CORE_SDIO_DEV;
ci->c_inf[1].base = 0x18002000;
ci->c_inf[1].wrapbase = 0x18102000;
ci->c_inf[1].cib = 0x07004211;
ci->c_inf[2].id = BCMA_CORE_INTERNAL_MEM;
ci->c_inf[2].base = 0x18004000;
ci->c_inf[2].wrapbase = 0x18104000;
ci->c_inf[2].cib = 0x0d080401;
ci->c_inf[3].id = BCMA_CORE_ARM_CM3;
ci->c_inf[3].base = 0x18003000;
ci->c_inf[3].wrapbase = 0x18103000;
ci->c_inf[3].cib = 0x03004211;
ci->ramsize = 0x48000;
break;
default:
brcmf_dbg(ERROR, "chipid 0x%x is not supported\n", ci->chip);
return -ENODEV;
@ -569,19 +566,8 @@ brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
return;
switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) {
case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1):
str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab1;
str_mask = 0x30000000;
str_shift = 28;
break;
case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2):
case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3):
str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab2;
str_mask = 0x00003800;
str_shift = 11;
break;
case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8):
str_tab = (struct sdiod_drive_str *)&sdiod_drive_strength_tab3;
case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12):
str_tab = (struct sdiod_drive_str *)&sdiod_drvstr_tab1_1v8;
str_mask = 0x00003800;
str_shift = 11;
break;

View File

@ -135,6 +135,7 @@ struct brcmf_sdio_dev {
wait_queue_head_t request_chain_wait;
wait_queue_head_t request_buffer_wait;
struct device *dev;
struct brcmf_bus *bus_if;
};
/* Register/deregister device interrupt handler. */

File diff suppressed because it is too large Load Diff

View File

@ -17,6 +17,8 @@
#ifndef _BRCM_AIUTILS_H_
#define _BRCM_AIUTILS_H_
#include <linux/bcma/bcma.h>
#include "types.h"
/*
@ -144,26 +146,15 @@
* public (read-only) portion of aiutils handle returned by si_attach()
*/
struct si_pub {
uint buscoretype; /* PCI_CORE_ID, PCIE_CORE_ID, PCMCIA_CORE_ID */
uint buscorerev; /* buscore rev */
uint buscoreidx; /* buscore index */
int ccrev; /* chip common core rev */
u32 cccaps; /* chip common capabilities */
u32 cccaps_ext; /* chip common capabilities extension */
int pmurev; /* pmu core rev */
u32 pmucaps; /* pmu capabilities */
uint boardtype; /* board type */
uint boardvendor; /* board vendor */
uint boardflags; /* board flags */
uint boardflags2; /* board flags2 */
uint chip; /* chip number */
uint chiprev; /* chip revision */
uint chippkg; /* chip package option */
u32 chipst; /* chip status */
bool issim; /* chip is in simulation or emulation */
uint socirev; /* SOC interconnect rev */
bool pci_pr32414;
};
struct pci_dev;
@ -179,38 +170,13 @@ struct gpioh_item {
/* misc si info needed by some of the routines */
struct si_info {
struct si_pub pub; /* back plane public state (must be first) */
struct pci_dev *pbus; /* handle to pci bus */
uint dev_coreid; /* the core provides driver functions */
void *intr_arg; /* interrupt callback function arg */
u32 (*intrsoff_fn) (void *intr_arg); /* turns chip interrupts off */
/* restore chip interrupts */
void (*intrsrestore_fn) (void *intr_arg, u32 arg);
/* check if interrupts are enabled */
bool (*intrsenabled_fn) (void *intr_arg);
struct bcma_bus *icbus; /* handle to soc interconnect bus */
struct pci_dev *pcibus; /* handle to pci bus */
struct pcicore_info *pch; /* PCI/E core handle */
struct bcma_device *buscore;
struct list_head var_list; /* list of srom variables */
void __iomem *curmap; /* current regs va */
void __iomem *regs[SI_MAXCORES]; /* other regs va */
uint curidx; /* current core index */
uint numcores; /* # discovered cores */
uint coreid[SI_MAXCORES]; /* id of each core */
u32 coresba[SI_MAXCORES]; /* backplane address of each core */
void *regs2[SI_MAXCORES]; /* 2nd virtual address per core (usbh20) */
u32 coresba2[SI_MAXCORES]; /* 2nd phys address per core (usbh20) */
u32 coresba_size[SI_MAXCORES]; /* backplane address space size */
u32 coresba2_size[SI_MAXCORES]; /* second address space size */
void *curwrap; /* current wrapper va */
void *wrappers[SI_MAXCORES]; /* other cores wrapper va */
u32 wrapba[SI_MAXCORES]; /* address of controlling wrapper */
u32 cia[SI_MAXCORES]; /* erom cia entry for each core */
u32 cib[SI_MAXCORES]; /* erom cia entry for each core */
u32 oob_router; /* oob router registers for axi */
u32 chipst; /* chip status */
};
/*
@ -223,52 +189,15 @@ struct si_info {
/* AMBA Interconnect exported externs */
extern uint ai_flag(struct si_pub *sih);
extern void ai_setint(struct si_pub *sih, int siflag);
extern uint ai_coreidx(struct si_pub *sih);
extern uint ai_corevendor(struct si_pub *sih);
extern uint ai_corerev(struct si_pub *sih);
extern bool ai_iscoreup(struct si_pub *sih);
extern u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val);
extern void ai_core_cflags_wo(struct si_pub *sih, u32 mask, u32 val);
extern u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val);
extern uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask,
uint val);
extern void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits);
extern void ai_core_disable(struct si_pub *sih, u32 bits);
extern int ai_numaddrspaces(struct si_pub *sih);
extern u32 ai_addrspace(struct si_pub *sih, uint asidx);
extern u32 ai_addrspacesize(struct si_pub *sih, uint asidx);
extern void ai_write_wrap_reg(struct si_pub *sih, u32 offset, u32 val);
extern struct bcma_device *ai_findcore(struct si_pub *sih,
u16 coreid, u16 coreunit);
extern u32 ai_core_cflags(struct bcma_device *core, u32 mask, u32 val);
/* === exported functions === */
extern struct si_pub *ai_attach(void __iomem *regs, struct pci_dev *sdh);
extern struct si_pub *ai_attach(struct bcma_bus *pbus);
extern void ai_detach(struct si_pub *sih);
extern uint ai_coreid(struct si_pub *sih);
extern uint ai_corerev(struct si_pub *sih);
extern uint ai_corereg(struct si_pub *sih, uint coreidx, uint regoff, uint mask,
uint val);
extern void ai_write_wrapperreg(struct si_pub *sih, u32 offset, u32 val);
extern u32 ai_core_cflags(struct si_pub *sih, u32 mask, u32 val);
extern u32 ai_core_sflags(struct si_pub *sih, u32 mask, u32 val);
extern bool ai_iscoreup(struct si_pub *sih);
extern uint ai_findcoreidx(struct si_pub *sih, uint coreid, uint coreunit);
extern void __iomem *ai_setcoreidx(struct si_pub *sih, uint coreidx);
extern void __iomem *ai_setcore(struct si_pub *sih, uint coreid, uint coreunit);
extern void __iomem *ai_switch_core(struct si_pub *sih, uint coreid,
uint *origidx, uint *intr_val);
extern void ai_restore_core(struct si_pub *sih, uint coreid, uint intr_val);
extern void ai_core_reset(struct si_pub *sih, u32 bits, u32 resetbits);
extern void ai_core_disable(struct si_pub *sih, u32 bits);
extern u32 ai_alp_clock(struct si_pub *sih);
extern u32 ai_ilp_clock(struct si_pub *sih);
extern uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val);
extern void ai_pci_setup(struct si_pub *sih, uint coremask);
extern void ai_setint(struct si_pub *sih, int siflag);
extern bool ai_backplane64(struct si_pub *sih);
extern void ai_register_intr_callback(struct si_pub *sih, void *intrsoff_fn,
void *intrsrestore_fn,
void *intrsenabled_fn, void *intr_arg);
extern void ai_deregister_intr_callback(struct si_pub *sih);
extern void ai_clkctl_init(struct si_pub *sih);
extern u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih);
extern bool ai_clkctl_cc(struct si_pub *sih, uint mode);
@ -283,13 +212,6 @@ extern bool ai_is_otp_disabled(struct si_pub *sih);
/* SPROM availability */
extern bool ai_is_sprom_available(struct si_pub *sih);
/*
* Build device path. Path size must be >= SI_DEVPATH_BUFSZ.
* The returned path is NULL terminated and has trailing '/'.
* Return 0 on success, nonzero otherwise.
*/
extern int ai_devpath(struct si_pub *sih, char *path, int size);
extern void ai_pci_sleep(struct si_pub *sih);
extern void ai_pci_down(struct si_pub *sih);
extern void ai_pci_up(struct si_pub *sih);
@ -299,4 +221,52 @@ extern void ai_chipcontrl_epa4331(struct si_pub *sih, bool on);
/* Enable Ex-PA for 4313 */
extern void ai_epa_4313war(struct si_pub *sih);
extern uint ai_get_buscoretype(struct si_pub *sih);
extern uint ai_get_buscorerev(struct si_pub *sih);
static inline int ai_get_ccrev(struct si_pub *sih)
{
return sih->ccrev;
}
static inline u32 ai_get_cccaps(struct si_pub *sih)
{
return sih->cccaps;
}
static inline int ai_get_pmurev(struct si_pub *sih)
{
return sih->pmurev;
}
static inline u32 ai_get_pmucaps(struct si_pub *sih)
{
return sih->pmucaps;
}
static inline uint ai_get_boardtype(struct si_pub *sih)
{
return sih->boardtype;
}
static inline uint ai_get_boardvendor(struct si_pub *sih)
{
return sih->boardvendor;
}
static inline uint ai_get_chip_id(struct si_pub *sih)
{
return sih->chip;
}
static inline uint ai_get_chiprev(struct si_pub *sih)
{
return sih->chiprev;
}
static inline uint ai_get_chippkg(struct si_pub *sih)
{
return sih->chippkg;
}
#endif /* _BRCM_AIUTILS_H_ */

View File

@ -1118,14 +1118,17 @@ brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
u8 status_delay = 0;
/* wait till the next 8 bytes of txstatus is available */
while (((s1 = R_REG(&wlc->regs->frmtxstatus)) & TXS_V) == 0) {
s1 = bcma_read32(wlc->hw->d11core, D11REGOFFS(frmtxstatus));
while ((s1 & TXS_V) == 0) {
udelay(1);
status_delay++;
if (status_delay > 10)
return; /* error condition */
s1 = bcma_read32(wlc->hw->d11core,
D11REGOFFS(frmtxstatus));
}
s2 = R_REG(&wlc->regs->frmtxstatus2);
s2 = bcma_read32(wlc->hw->d11core, D11REGOFFS(frmtxstatus2));
}
if (scb) {

View File

@ -430,6 +430,9 @@ struct d11regs {
u16 PAD[0x380]; /* 0x800 - 0xEFE */
};
/* d11 register field offset */
#define D11REGOFFS(field) offsetof(struct d11regs, field)
#define PIHR_BASE 0x0400 /* byte address of packed IHR region */
/* biststatus */

View File

@ -26,6 +26,13 @@
#include "dma.h"
#include "soc.h"
/*
* dma register field offset calculation
*/
#define DMA64REGOFFS(field) offsetof(struct dma64regs, field)
#define DMA64TXREGOFFS(di, field) (di->d64txregbase + DMA64REGOFFS(field))
#define DMA64RXREGOFFS(di, field) (di->d64rxregbase + DMA64REGOFFS(field))
/*
* DMA hardware requires each descriptor ring to be 8kB aligned, and fit within
* a contiguous 8kB physical address.
@ -220,15 +227,16 @@ struct dma_info {
uint *msg_level; /* message level pointer */
char name[MAXNAMEL]; /* callers name for diag msgs */
struct pci_dev *pbus; /* bus handle */
struct bcma_device *core;
struct device *dmadev;
bool dma64; /* this dma engine is operating in 64-bit mode */
bool addrext; /* this dma engine supports DmaExtendedAddrChanges */
/* 64-bit dma tx engine registers */
struct dma64regs __iomem *d64txregs;
uint d64txregbase;
/* 64-bit dma rx engine registers */
struct dma64regs __iomem *d64rxregs;
uint d64rxregbase;
/* pointer to dma64 tx descriptor ring */
struct dma64desc *txd64;
/* pointer to dma64 rx descriptor ring */
@ -375,15 +383,16 @@ static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags)
if (dmactrlflags & DMA_CTRL_PEN) {
u32 control;
control = R_REG(&di->d64txregs->control);
W_REG(&di->d64txregs->control,
control = bcma_read32(di->core, DMA64TXREGOFFS(di, control));
bcma_write32(di->core, DMA64TXREGOFFS(di, control),
control | D64_XC_PD);
if (R_REG(&di->d64txregs->control) & D64_XC_PD)
if (bcma_read32(di->core, DMA64TXREGOFFS(di, control)) &
D64_XC_PD)
/* We *can* disable it so it is supported,
* restore control register
*/
W_REG(&di->d64txregs->control,
control);
bcma_write32(di->core, DMA64TXREGOFFS(di, control),
control);
else
/* Not supported, don't allow it to be enabled */
dmactrlflags &= ~DMA_CTRL_PEN;
@ -394,12 +403,12 @@ static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags)
return dmactrlflags;
}
static bool _dma64_addrext(struct dma64regs __iomem *dma64regs)
static bool _dma64_addrext(struct dma_info *di, uint ctrl_offset)
{
u32 w;
OR_REG(&dma64regs->control, D64_XC_AE);
w = R_REG(&dma64regs->control);
AND_REG(&dma64regs->control, ~D64_XC_AE);
bcma_set32(di->core, ctrl_offset, D64_XC_AE);
w = bcma_read32(di->core, ctrl_offset);
bcma_mask32(di->core, ctrl_offset, ~D64_XC_AE);
return (w & D64_XC_AE) == D64_XC_AE;
}
@ -412,13 +421,13 @@ static bool _dma_isaddrext(struct dma_info *di)
/* DMA64 supports full 32- or 64-bit operation. AE is always valid */
/* not all tx or rx channel are available */
if (di->d64txregs != NULL) {
if (!_dma64_addrext(di->d64txregs))
if (di->d64txregbase != 0) {
if (!_dma64_addrext(di, DMA64TXREGOFFS(di, control)))
DMA_ERROR("%s: DMA64 tx doesn't have AE set\n",
di->name);
return true;
} else if (di->d64rxregs != NULL) {
if (!_dma64_addrext(di->d64rxregs))
} else if (di->d64rxregbase != 0) {
if (!_dma64_addrext(di, DMA64RXREGOFFS(di, control)))
DMA_ERROR("%s: DMA64 rx doesn't have AE set\n",
di->name);
return true;
@ -432,14 +441,14 @@ static bool _dma_descriptor_align(struct dma_info *di)
u32 addrl;
/* Check to see if the descriptors need to be aligned on 4K/8K or not */
if (di->d64txregs != NULL) {
W_REG(&di->d64txregs->addrlow, 0xff0);
addrl = R_REG(&di->d64txregs->addrlow);
if (di->d64txregbase != 0) {
bcma_write32(di->core, DMA64TXREGOFFS(di, addrlow), 0xff0);
addrl = bcma_read32(di->core, DMA64TXREGOFFS(di, addrlow));
if (addrl != 0)
return false;
} else if (di->d64rxregs != NULL) {
W_REG(&di->d64rxregs->addrlow, 0xff0);
addrl = R_REG(&di->d64rxregs->addrlow);
} else if (di->d64rxregbase != 0) {
bcma_write32(di->core, DMA64RXREGOFFS(di, addrlow), 0xff0);
addrl = bcma_read32(di->core, DMA64RXREGOFFS(di, addrlow));
if (addrl != 0)
return false;
}
@ -450,7 +459,7 @@ static bool _dma_descriptor_align(struct dma_info *di)
* Descriptor table must start at the DMA hardware dictated alignment, so
* allocated memory must be large enough to support this requirement.
*/
static void *dma_alloc_consistent(struct pci_dev *pdev, uint size,
static void *dma_alloc_consistent(struct dma_info *di, uint size,
u16 align_bits, uint *alloced,
dma_addr_t *pap)
{
@ -460,7 +469,7 @@ static void *dma_alloc_consistent(struct pci_dev *pdev, uint size,
size += align;
*alloced = size;
}
return pci_alloc_consistent(pdev, size, pap);
return dma_alloc_coherent(di->dmadev, size, pap, GFP_ATOMIC);
}
static
@ -486,7 +495,7 @@ static void *dma_ringalloc(struct dma_info *di, u32 boundary, uint size,
u32 desc_strtaddr;
u32 alignbytes = 1 << *alignbits;
va = dma_alloc_consistent(di->pbus, size, *alignbits, alloced, descpa);
va = dma_alloc_consistent(di, size, *alignbits, alloced, descpa);
if (NULL == va)
return NULL;
@ -495,8 +504,8 @@ static void *dma_ringalloc(struct dma_info *di, u32 boundary, uint size,
if (((desc_strtaddr + size - 1) & boundary) != (desc_strtaddr
& boundary)) {
*alignbits = dma_align_sizetobits(size);
pci_free_consistent(di->pbus, size, va, *descpa);
va = dma_alloc_consistent(di->pbus, size, *alignbits,
dma_free_coherent(di->dmadev, size, va, *descpa);
va = dma_alloc_consistent(di, size, *alignbits,
alloced, descpa);
}
return va;
@ -556,12 +565,13 @@ static bool _dma_alloc(struct dma_info *di, uint direction)
}
struct dma_pub *dma_attach(char *name, struct si_pub *sih,
void __iomem *dmaregstx, void __iomem *dmaregsrx,
uint ntxd, uint nrxd,
uint rxbufsize, int rxextheadroom,
uint nrxpost, uint rxoffset, uint *msg_level)
struct bcma_device *core,
uint txregbase, uint rxregbase, uint ntxd, uint nrxd,
uint rxbufsize, int rxextheadroom,
uint nrxpost, uint rxoffset, uint *msg_level)
{
struct dma_info *di;
u8 rev = core->id.rev;
uint size;
/* allocate private info structure */
@ -572,11 +582,13 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
di->msg_level = msg_level ? msg_level : &dma_msg_level;
di->dma64 = ((ai_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64);
di->dma64 =
((bcma_aread32(core, BCMA_IOST) & SISF_DMA64) == SISF_DMA64);
/* init dma reg pointer */
di->d64txregs = (struct dma64regs __iomem *) dmaregstx;
di->d64rxregs = (struct dma64regs __iomem *) dmaregsrx;
/* init dma reg info */
di->core = core;
di->d64txregbase = txregbase;
di->d64rxregbase = rxregbase;
/*
* Default flags (which can be changed by the driver calling
@ -585,16 +597,17 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
*/
_dma_ctrlflags(di, DMA_CTRL_ROC | DMA_CTRL_PEN, 0);
DMA_TRACE("%s: %s flags 0x%x ntxd %d nrxd %d rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d dmaregstx %p dmaregsrx %p\n",
name, "DMA64",
DMA_TRACE("%s: %s flags 0x%x ntxd %d nrxd %d "
"rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d "
"txregbase %u rxregbase %u\n", name, "DMA64",
di->dma.dmactrlflags, ntxd, nrxd, rxbufsize,
rxextheadroom, nrxpost, rxoffset, dmaregstx, dmaregsrx);
rxextheadroom, nrxpost, rxoffset, txregbase, rxregbase);
/* make a private copy of our callers name */
strncpy(di->name, name, MAXNAMEL);
di->name[MAXNAMEL - 1] = '\0';
di->pbus = ((struct si_info *)sih)->pbus;
di->dmadev = core->dma_dev;
/* save tunables */
di->ntxd = (u16) ntxd;
@ -626,11 +639,11 @@ struct dma_pub *dma_attach(char *name, struct si_pub *sih,
di->dataoffsetlow = di->ddoffsetlow;
di->dataoffsethigh = di->ddoffsethigh;
/* WAR64450 : DMACtl.Addr ext fields are not supported in SDIOD core. */
if ((ai_coreid(sih) == SDIOD_CORE_ID)
&& ((ai_corerev(sih) > 0) && (ai_corerev(sih) <= 2)))
if ((core->id.id == SDIOD_CORE_ID)
&& ((rev > 0) && (rev <= 2)))
di->addrext = 0;
else if ((ai_coreid(sih) == I2S_CORE_ID) &&
((ai_corerev(sih) == 0) || (ai_corerev(sih) == 1)))
else if ((core->id.id == I2S_CORE_ID) &&
((rev == 0) || (rev == 1)))
di->addrext = 0;
else
di->addrext = _dma_isaddrext(di);
@ -749,13 +762,13 @@ void dma_detach(struct dma_pub *pub)
/* free dma descriptor rings */
if (di->txd64)
pci_free_consistent(di->pbus, di->txdalloc,
((s8 *)di->txd64 - di->txdalign),
(di->txdpaorig));
dma_free_coherent(di->dmadev, di->txdalloc,
((s8 *)di->txd64 - di->txdalign),
(di->txdpaorig));
if (di->rxd64)
pci_free_consistent(di->pbus, di->rxdalloc,
((s8 *)di->rxd64 - di->rxdalign),
(di->rxdpaorig));
dma_free_coherent(di->dmadev, di->rxdalloc,
((s8 *)di->rxd64 - di->rxdalign),
(di->rxdpaorig));
/* free packet pointer vectors */
kfree(di->txp);
@ -780,11 +793,15 @@ _dma_ddtable_init(struct dma_info *di, uint direction, dma_addr_t pa)
if ((di->ddoffsetlow == 0)
|| !(pa & PCI32ADDR_HIGH)) {
if (direction == DMA_TX) {
W_REG(&di->d64txregs->addrlow, pa + di->ddoffsetlow);
W_REG(&di->d64txregs->addrhigh, di->ddoffsethigh);
bcma_write32(di->core, DMA64TXREGOFFS(di, addrlow),
pa + di->ddoffsetlow);
bcma_write32(di->core, DMA64TXREGOFFS(di, addrhigh),
di->ddoffsethigh);
} else {
W_REG(&di->d64rxregs->addrlow, pa + di->ddoffsetlow);
W_REG(&di->d64rxregs->addrhigh, di->ddoffsethigh);
bcma_write32(di->core, DMA64RXREGOFFS(di, addrlow),
pa + di->ddoffsetlow);
bcma_write32(di->core, DMA64RXREGOFFS(di, addrhigh),
di->ddoffsethigh);
}
} else {
/* DMA64 32bits address extension */
@ -795,15 +812,19 @@ _dma_ddtable_init(struct dma_info *di, uint direction, dma_addr_t pa)
pa &= ~PCI32ADDR_HIGH;
if (direction == DMA_TX) {
W_REG(&di->d64txregs->addrlow, pa + di->ddoffsetlow);
W_REG(&di->d64txregs->addrhigh, di->ddoffsethigh);
SET_REG(&di->d64txregs->control,
D64_XC_AE, (ae << D64_XC_AE_SHIFT));
bcma_write32(di->core, DMA64TXREGOFFS(di, addrlow),
pa + di->ddoffsetlow);
bcma_write32(di->core, DMA64TXREGOFFS(di, addrhigh),
di->ddoffsethigh);
bcma_maskset32(di->core, DMA64TXREGOFFS(di, control),
D64_XC_AE, (ae << D64_XC_AE_SHIFT));
} else {
W_REG(&di->d64rxregs->addrlow, pa + di->ddoffsetlow);
W_REG(&di->d64rxregs->addrhigh, di->ddoffsethigh);
SET_REG(&di->d64rxregs->control,
D64_RC_AE, (ae << D64_RC_AE_SHIFT));
bcma_write32(di->core, DMA64RXREGOFFS(di, addrlow),
pa + di->ddoffsetlow);
bcma_write32(di->core, DMA64RXREGOFFS(di, addrhigh),
di->ddoffsethigh);
bcma_maskset32(di->core, DMA64RXREGOFFS(di, control),
D64_RC_AE, (ae << D64_RC_AE_SHIFT));
}
}
}
@ -815,9 +836,9 @@ static void _dma_rxenable(struct dma_info *di)
DMA_TRACE("%s:\n", di->name);
control =
(R_REG(&di->d64rxregs->control) & D64_RC_AE) |
D64_RC_RE;
control = D64_RC_RE | (bcma_read32(di->core,
DMA64RXREGOFFS(di, control)) &
D64_RC_AE);
if ((dmactrlflags & DMA_CTRL_PEN) == 0)
control |= D64_RC_PD;
@ -825,7 +846,7 @@ static void _dma_rxenable(struct dma_info *di)
if (dmactrlflags & DMA_CTRL_ROC)
control |= D64_RC_OC;
W_REG(&di->d64rxregs->control,
bcma_write32(di->core, DMA64RXREGOFFS(di, control),
((di->rxoffset << D64_RC_RO_SHIFT) | control));
}
@ -868,7 +889,8 @@ static struct sk_buff *dma64_getnextrxp(struct dma_info *di, bool forceall)
return NULL;
curr =
B2I(((R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK) -
B2I(((bcma_read32(di->core,
DMA64RXREGOFFS(di, status0)) & D64_RS0_CD_MASK) -
di->rcvptrbase) & D64_RS0_CD_MASK, struct dma64desc);
/* ignore curr if forceall */
@ -882,7 +904,7 @@ static struct sk_buff *dma64_getnextrxp(struct dma_info *di, bool forceall)
pa = le32_to_cpu(di->rxd64[i].addrlow) - di->dataoffsetlow;
/* clear this packet from the descriptor ring */
pci_unmap_single(di->pbus, pa, di->rxbufsize, PCI_DMA_FROMDEVICE);
dma_unmap_single(di->dmadev, pa, di->rxbufsize, DMA_FROM_DEVICE);
di->rxd64[i].addrlow = cpu_to_le32(0xdeadbeef);
di->rxd64[i].addrhigh = cpu_to_le32(0xdeadbeef);
@ -950,12 +972,12 @@ int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list)
if (resid > 0) {
uint cur;
cur =
B2I(((R_REG(&di->d64rxregs->status0) &
D64_RS0_CD_MASK) -
di->rcvptrbase) & D64_RS0_CD_MASK,
struct dma64desc);
B2I(((bcma_read32(di->core,
DMA64RXREGOFFS(di, status0)) &
D64_RS0_CD_MASK) - di->rcvptrbase) &
D64_RS0_CD_MASK, struct dma64desc);
DMA_ERROR("rxin %d rxout %d, hw_curr %d\n",
di->rxin, di->rxout, cur);
di->rxin, di->rxout, cur);
}
#endif /* BCMDBG */
@ -983,8 +1005,10 @@ static bool dma64_rxidle(struct dma_info *di)
if (di->nrxd == 0)
return true;
return ((R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK) ==
(R_REG(&di->d64rxregs->ptr) & D64_RS0_CD_MASK));
return ((bcma_read32(di->core,
DMA64RXREGOFFS(di, status0)) & D64_RS0_CD_MASK) ==
(bcma_read32(di->core, DMA64RXREGOFFS(di, ptr)) &
D64_RS0_CD_MASK));
}
/*
@ -1048,8 +1072,8 @@ bool dma_rxfill(struct dma_pub *pub)
*/
*(u32 *) (p->data) = 0;
pa = pci_map_single(di->pbus, p->data,
di->rxbufsize, PCI_DMA_FROMDEVICE);
pa = dma_map_single(di->dmadev, p->data, di->rxbufsize,
DMA_FROM_DEVICE);
/* save the free packet pointer */
di->rxp[rxout] = p;
@ -1067,7 +1091,7 @@ bool dma_rxfill(struct dma_pub *pub)
di->rxout = rxout;
/* update the chip lastdscr pointer */
W_REG(&di->d64rxregs->ptr,
bcma_write32(di->core, DMA64RXREGOFFS(di, ptr),
di->rcvptrbase + I2B(rxout, struct dma64desc));
return ring_empty;
@ -1128,7 +1152,7 @@ void dma_txinit(struct dma_pub *pub)
if ((di->dma.dmactrlflags & DMA_CTRL_PEN) == 0)
control |= D64_XC_PD;
OR_REG(&di->d64txregs->control, control);
bcma_set32(di->core, DMA64TXREGOFFS(di, control), control);
/* DMA engine with alignment requirement requires table to be inited
* before enabling the engine
@ -1146,7 +1170,7 @@ void dma_txsuspend(struct dma_pub *pub)
if (di->ntxd == 0)
return;
OR_REG(&di->d64txregs->control, D64_XC_SE);
bcma_set32(di->core, DMA64TXREGOFFS(di, control), D64_XC_SE);
}
void dma_txresume(struct dma_pub *pub)
@ -1158,7 +1182,7 @@ void dma_txresume(struct dma_pub *pub)
if (di->ntxd == 0)
return;
AND_REG(&di->d64txregs->control, ~D64_XC_SE);
bcma_mask32(di->core, DMA64TXREGOFFS(di, control), ~D64_XC_SE);
}
bool dma_txsuspended(struct dma_pub *pub)
@ -1166,8 +1190,9 @@ bool dma_txsuspended(struct dma_pub *pub)
struct dma_info *di = (struct dma_info *)pub;
return (di->ntxd == 0) ||
((R_REG(&di->d64txregs->control) & D64_XC_SE) ==
D64_XC_SE);
((bcma_read32(di->core,
DMA64TXREGOFFS(di, control)) & D64_XC_SE) ==
D64_XC_SE);
}
void dma_txreclaim(struct dma_pub *pub, enum txd_range range)
@ -1200,16 +1225,17 @@ bool dma_txreset(struct dma_pub *pub)
return true;
/* suspend tx DMA first */
W_REG(&di->d64txregs->control, D64_XC_SE);
bcma_write32(di->core, DMA64TXREGOFFS(di, control), D64_XC_SE);
SPINWAIT(((status =
(R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK))
!= D64_XS0_XS_DISABLED) && (status != D64_XS0_XS_IDLE)
&& (status != D64_XS0_XS_STOPPED), 10000);
(bcma_read32(di->core, DMA64TXREGOFFS(di, status0)) &
D64_XS0_XS_MASK)) != D64_XS0_XS_DISABLED) &&
(status != D64_XS0_XS_IDLE) && (status != D64_XS0_XS_STOPPED),
10000);
W_REG(&di->d64txregs->control, 0);
bcma_write32(di->core, DMA64TXREGOFFS(di, control), 0);
SPINWAIT(((status =
(R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK))
!= D64_XS0_XS_DISABLED), 10000);
(bcma_read32(di->core, DMA64TXREGOFFS(di, status0)) &
D64_XS0_XS_MASK)) != D64_XS0_XS_DISABLED), 10000);
/* wait for the last transaction to complete */
udelay(300);
@ -1225,10 +1251,10 @@ bool dma_rxreset(struct dma_pub *pub)
if (di->nrxd == 0)
return true;
W_REG(&di->d64rxregs->control, 0);
bcma_write32(di->core, DMA64RXREGOFFS(di, control), 0);
SPINWAIT(((status =
(R_REG(&di->d64rxregs->status0) & D64_RS0_RS_MASK))
!= D64_RS0_RS_DISABLED), 10000);
(bcma_read32(di->core, DMA64RXREGOFFS(di, status0)) &
D64_RS0_RS_MASK)) != D64_RS0_RS_DISABLED), 10000);
return status == D64_RS0_RS_DISABLED;
}
@ -1267,7 +1293,7 @@ int dma_txfast(struct dma_pub *pub, struct sk_buff *p, bool commit)
goto outoftxd;
/* get physical address of buffer start */
pa = pci_map_single(di->pbus, data, len, PCI_DMA_TODEVICE);
pa = dma_map_single(di->dmadev, data, len, DMA_TO_DEVICE);
/* With a DMA segment list, Descriptor table is filled
* using the segment list instead of looping over
@ -1290,7 +1316,7 @@ int dma_txfast(struct dma_pub *pub, struct sk_buff *p, bool commit)
/* kick the chip */
if (commit)
W_REG(&di->d64txregs->ptr,
bcma_write32(di->core, DMA64TXREGOFFS(di, ptr),
di->xmtptrbase + I2B(txout, struct dma64desc));
/* tx flow control */
@ -1338,16 +1364,15 @@ struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range)
if (range == DMA_RANGE_ALL)
end = di->txout;
else {
struct dma64regs __iomem *dregs = di->d64txregs;
end = (u16) (B2I(((R_REG(&dregs->status0) &
D64_XS0_CD_MASK) -
di->xmtptrbase) & D64_XS0_CD_MASK,
struct dma64desc));
end = (u16) (B2I(((bcma_read32(di->core,
DMA64TXREGOFFS(di, status0)) &
D64_XS0_CD_MASK) - di->xmtptrbase) &
D64_XS0_CD_MASK, struct dma64desc));
if (range == DMA_RANGE_TRANSFERED) {
active_desc =
(u16) (R_REG(&dregs->status1) &
(u16)(bcma_read32(di->core,
DMA64TXREGOFFS(di, status1)) &
D64_XS1_AD_MASK);
active_desc =
(active_desc - di->xmtptrbase) & D64_XS0_CD_MASK;
@ -1376,7 +1401,7 @@ struct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range)
txp = di->txp[i];
di->txp[i] = NULL;
pci_unmap_single(di->pbus, pa, size, PCI_DMA_TODEVICE);
dma_unmap_single(di->dmadev, pa, size, DMA_TO_DEVICE);
}
di->txin = i;

View File

@ -75,10 +75,11 @@ struct dma_pub {
};
extern struct dma_pub *dma_attach(char *name, struct si_pub *sih,
void __iomem *dmaregstx, void __iomem *dmaregsrx,
uint ntxd, uint nrxd,
uint rxbufsize, int rxextheadroom,
uint nrxpost, uint rxoffset, uint *msg_level);
struct bcma_device *d11core,
uint txregbase, uint rxregbase,
uint ntxd, uint nrxd,
uint rxbufsize, int rxextheadroom,
uint nrxpost, uint rxoffset, uint *msg_level);
void dma_rxinit(struct dma_pub *pub);
int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list);

View File

@ -17,11 +17,11 @@
#define __UNDEF_NO_VERSION__
#include <linux/etherdevice.h>
#include <linux/pci.h>
#include <linux/sched.h>
#include <linux/firmware.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/bcma/bcma.h>
#include <net/mac80211.h>
#include <defs.h>
#include "nicpci.h"
@ -87,16 +87,14 @@ MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver.");
MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards");
MODULE_LICENSE("Dual BSD/GPL");
/* recognized PCI IDs */
static DEFINE_PCI_DEVICE_TABLE(brcms_pci_id_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) }, /* 43225 2G */
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, /* 43224 DUAL */
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, /* 4313 DUAL */
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, /* 43224 Ven */
{0}
};
MODULE_DEVICE_TABLE(pci, brcms_pci_id_table);
/* recognized BCMA Core IDs */
static struct bcma_device_id brcms_coreid_table[] = {
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 23, BCMA_ANY_CLASS),
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 24, BCMA_ANY_CLASS),
BCMA_CORETABLE_END
};
MODULE_DEVICE_TABLE(bcma, brcms_coreid_table);
#ifdef BCMDBG
static int msglevel = 0xdeadbeef;
@ -724,7 +722,7 @@ static const struct ieee80211_ops brcms_ops = {
};
/*
* is called in brcms_pci_probe() context, therefore no locking required.
* is called in brcms_bcma_probe() context, therefore no locking required.
*/
static int brcms_set_hint(struct brcms_info *wl, char *abbrev)
{
@ -864,25 +862,15 @@ static void brcms_free(struct brcms_info *wl)
#endif
kfree(t);
}
/*
* unregister_netdev() calls get_stats() which may read chip
* registers so we cannot unmap the chip registers until
* after calling unregister_netdev() .
*/
if (wl->regsva)
iounmap(wl->regsva);
wl->regsva = NULL;
}
/*
* called from both kernel as from this kernel module (error flow on attach)
* precondition: perimeter lock is not acquired.
*/
static void brcms_remove(struct pci_dev *pdev)
static void brcms_remove(struct bcma_device *pdev)
{
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
struct ieee80211_hw *hw = bcma_get_drvdata(pdev);
struct brcms_info *wl = hw->priv;
if (wl->wlc) {
@ -890,11 +878,10 @@ static void brcms_remove(struct pci_dev *pdev)
wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
ieee80211_unregister_hw(hw);
}
pci_disable_device(pdev);
brcms_free(wl);
pci_set_drvdata(pdev, NULL);
bcma_set_drvdata(pdev, NULL);
ieee80211_free_hw(hw);
}
@ -1002,11 +989,9 @@ static int ieee_hw_init(struct ieee80211_hw *hw)
* it as static.
*
*
* is called in brcms_pci_probe() context, therefore no locking required.
* is called in brcms_bcma_probe() context, therefore no locking required.
*/
static struct brcms_info *brcms_attach(u16 vendor, u16 device,
resource_size_t regs,
struct pci_dev *btparam, uint irq)
static struct brcms_info *brcms_attach(struct bcma_device *pdev)
{
struct brcms_info *wl = NULL;
int unit, err;
@ -1020,7 +1005,7 @@ static struct brcms_info *brcms_attach(u16 vendor, u16 device,
return NULL;
/* allocate private info */
hw = pci_get_drvdata(btparam); /* btparam == pdev */
hw = bcma_get_drvdata(pdev);
if (hw != NULL)
wl = hw->priv;
if (WARN_ON(hw == NULL) || WARN_ON(wl == NULL))
@ -1032,26 +1017,20 @@ static struct brcms_info *brcms_attach(u16 vendor, u16 device,
/* setup the bottom half handler */
tasklet_init(&wl->tasklet, brcms_dpc, (unsigned long) wl);
wl->regsva = ioremap_nocache(regs, PCI_BAR0_WINSZ);
if (wl->regsva == NULL) {
wiphy_err(wl->wiphy, "wl%d: ioremap() failed\n", unit);
goto fail;
}
spin_lock_init(&wl->lock);
spin_lock_init(&wl->isr_lock);
/* prepare ucode */
if (brcms_request_fw(wl, btparam) < 0) {
if (brcms_request_fw(wl, pdev->bus->host_pci) < 0) {
wiphy_err(wl->wiphy, "%s: Failed to find firmware usually in "
"%s\n", KBUILD_MODNAME, "/lib/firmware/brcm");
brcms_release_fw(wl);
brcms_remove(btparam);
brcms_remove(pdev);
return NULL;
}
/* common load-time initialization */
wl->wlc = brcms_c_attach(wl, vendor, device, unit, false,
wl->regsva, btparam, &err);
wl->wlc = brcms_c_attach((void *)wl, pdev, unit, false, &err);
brcms_release_fw(wl);
if (!wl->wlc) {
wiphy_err(wl->wiphy, "%s: attach() failed with code %d\n",
@ -1063,11 +1042,12 @@ static struct brcms_info *brcms_attach(u16 vendor, u16 device,
wl->pub->ieee_hw = hw;
/* register our interrupt handler */
if (request_irq(irq, brcms_isr, IRQF_SHARED, KBUILD_MODNAME, wl)) {
if (request_irq(pdev->bus->host_pci->irq, brcms_isr,
IRQF_SHARED, KBUILD_MODNAME, wl)) {
wiphy_err(wl->wiphy, "wl%d: request_irq() failed\n", unit);
goto fail;
}
wl->irq = irq;
wl->irq = pdev->bus->host_pci->irq;
/* register module */
brcms_c_module_register(wl->pub, "linux", wl, NULL);
@ -1114,38 +1094,19 @@ fail:
*
* Perimeter lock is initialized in the course of this function.
*/
static int __devinit
brcms_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
static int __devinit brcms_bcma_probe(struct bcma_device *pdev)
{
int rc;
struct brcms_info *wl;
struct ieee80211_hw *hw;
u32 val;
dev_info(&pdev->dev, "bus %d slot %d func %d irq %d\n",
pdev->bus->number, PCI_SLOT(pdev->devfn),
PCI_FUNC(pdev->devfn), pdev->irq);
dev_info(&pdev->dev, "mfg %x core %x rev %d class %d irq %d\n",
pdev->id.manuf, pdev->id.id, pdev->id.rev, pdev->id.class,
pdev->bus->host_pci->irq);
if ((pdev->vendor != PCI_VENDOR_ID_BROADCOM) ||
((pdev->device != 0x0576) &&
((pdev->device & 0xff00) != 0x4300) &&
((pdev->device & 0xff00) != 0x4700) &&
((pdev->device < 43000) || (pdev->device > 43999))))
if ((pdev->id.manuf != BCMA_MANUF_BCM) ||
(pdev->id.id != BCMA_CORE_80211))
return -ENODEV;
rc = pci_enable_device(pdev);
if (rc) {
pr_err("%s: Cannot enable device %d-%d_%d\n",
__func__, pdev->bus->number, PCI_SLOT(pdev->devfn),
PCI_FUNC(pdev->devfn));
return -ENODEV;
}
pci_set_master(pdev);
pci_read_config_dword(pdev, 0x40, &val);
if ((val & 0x0000ff00) != 0)
pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
hw = ieee80211_alloc_hw(sizeof(struct brcms_info), &brcms_ops);
if (!hw) {
pr_err("%s: ieee80211_alloc_hw failed\n", __func__);
@ -1154,14 +1115,11 @@ brcms_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
SET_IEEE80211_DEV(hw, &pdev->dev);
pci_set_drvdata(pdev, hw);
bcma_set_drvdata(pdev, hw);
memset(hw->priv, 0, sizeof(*wl));
wl = brcms_attach(pdev->vendor, pdev->device,
pci_resource_start(pdev, 0), pdev,
pdev->irq);
wl = brcms_attach(pdev);
if (!wl) {
pr_err("%s: %s: brcms_attach failed!\n", KBUILD_MODNAME,
__func__);
@ -1170,16 +1128,23 @@ brcms_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return 0;
}
static int brcms_suspend(struct pci_dev *pdev, pm_message_t state)
static int brcms_pci_suspend(struct pci_dev *pdev)
{
pci_save_state(pdev);
pci_disable_device(pdev);
return pci_set_power_state(pdev, PCI_D3hot);
}
static int brcms_suspend(struct bcma_device *pdev, pm_message_t state)
{
struct brcms_info *wl;
struct ieee80211_hw *hw;
hw = pci_get_drvdata(pdev);
hw = bcma_get_drvdata(pdev);
wl = hw->priv;
if (!wl) {
wiphy_err(wl->wiphy,
"brcms_suspend: pci_get_drvdata failed\n");
"brcms_suspend: bcma_get_drvdata failed\n");
return -ENODEV;
}
@ -1188,25 +1153,14 @@ static int brcms_suspend(struct pci_dev *pdev, pm_message_t state)
wl->pub->hw_up = false;
spin_unlock_bh(&wl->lock);
pci_save_state(pdev);
pci_disable_device(pdev);
return pci_set_power_state(pdev, PCI_D3hot);
/* temporarily do suspend ourselves */
return brcms_pci_suspend(pdev->bus->host_pci);
}
static int brcms_resume(struct pci_dev *pdev)
static int brcms_pci_resume(struct pci_dev *pdev)
{
struct brcms_info *wl;
struct ieee80211_hw *hw;
int err = 0;
u32 val;
hw = pci_get_drvdata(pdev);
wl = hw->priv;
if (!wl) {
wiphy_err(wl->wiphy,
"wl: brcms_resume: pci_get_drvdata failed\n");
return -ENODEV;
}
uint val;
err = pci_set_power_state(pdev, PCI_D0);
if (err)
@ -1224,24 +1178,28 @@ static int brcms_resume(struct pci_dev *pdev)
if ((val & 0x0000ff00) != 0)
pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
/*
* done. driver will be put in up state
* in brcms_ops_add_interface() call.
*/
return err;
return 0;
}
static struct pci_driver brcms_pci_driver = {
static int brcms_resume(struct bcma_device *pdev)
{
/*
* just do pci resume for now until bcma supports it.
*/
return brcms_pci_resume(pdev->bus->host_pci);
}
static struct bcma_driver brcms_bcma_driver = {
.name = KBUILD_MODNAME,
.probe = brcms_pci_probe,
.probe = brcms_bcma_probe,
.suspend = brcms_suspend,
.resume = brcms_resume,
.remove = __devexit_p(brcms_remove),
.id_table = brcms_pci_id_table,
.id_table = brcms_coreid_table,
};
/**
* This is the main entry point for the WL driver.
* This is the main entry point for the brcmsmac driver.
*
* This function determines if a device pointed to by pdev is a WL device,
* and if so, performs a brcms_attach() on it.
@ -1256,26 +1214,24 @@ static int __init brcms_module_init(void)
brcm_msg_level = msglevel;
#endif /* BCMDBG */
error = pci_register_driver(&brcms_pci_driver);
error = bcma_driver_register(&brcms_bcma_driver);
printk(KERN_ERR "%s: register returned %d\n", __func__, error);
if (!error)
return 0;
return error;
}
/**
* This function unloads the WL driver from the system.
* This function unloads the brcmsmac driver from the system.
*
* This function unconditionally unloads the WL driver module from the
* This function unconditionally unloads the brcmsmac driver module from the
* system.
*
*/
static void __exit brcms_module_exit(void)
{
pci_unregister_driver(&brcms_pci_driver);
bcma_driver_unregister(&brcms_bcma_driver);
}
module_init(brcms_module_init);
@ -1562,7 +1518,7 @@ fail:
}
/*
* Precondition: Since this function is called in brcms_pci_probe() context,
* Precondition: Since this function is called in brcms_bcma_probe() context,
* no locking is required.
*/
int brcms_ucode_init_uint(struct brcms_info *wl, size_t *n_bytes, u32 idx)
@ -1602,7 +1558,7 @@ void brcms_ucode_free_buf(void *p)
/*
* checks validity of all firmware images loaded from user space
*
* Precondition: Since this function is called in brcms_pci_probe() context,
* Precondition: Since this function is called in brcms_bcma_probe() context,
* no locking is required.
*/
int brcms_check_firmwares(struct brcms_info *wl)

View File

@ -68,8 +68,6 @@ struct brcms_info {
spinlock_t lock; /* per-device perimeter lock */
spinlock_t isr_lock; /* per-device ISR synchronization lock */
/* regsva for unmap in brcms_free() */
void __iomem *regsva; /* opaque chip registers virtual address */
/* timer related fields */
atomic_t callbacks; /* # outstanding callback functions */

File diff suppressed because it is too large Load Diff

View File

@ -334,7 +334,7 @@ struct brcms_hardware {
u32 machwcap_backup; /* backup of machwcap */
struct si_pub *sih; /* SI handle (cookie for siutils calls) */
struct d11regs __iomem *regs; /* pointer to device registers */
struct bcma_device *d11core; /* pointer to 802.11 core */
struct phy_shim_info *physhim; /* phy shim layer handler */
struct shared_phy *phy_sh; /* pointer to shared phy state */
struct brcms_hw_band *band;/* pointer to active per-band state */
@ -400,7 +400,6 @@ struct brcms_txq_info {
*
* pub: pointer to driver public state.
* wl: pointer to specific private state.
* regs: pointer to device registers.
* hw: HW related state.
* clkreq_override: setting for clkreq for PCIE : Auto, 0, 1.
* fastpwrup_dly: time in us needed to bring up d11 fast clock.
@ -477,7 +476,6 @@ struct brcms_txq_info {
struct brcms_c_info {
struct brcms_pub *pub;
struct brcms_info *wl;
struct d11regs __iomem *regs;
struct brcms_hardware *hw;
/* clock */

View File

@ -139,6 +139,9 @@
#define SRSH_PI_MASK 0xf000 /* bit 15:12 */
#define SRSH_PI_SHIFT 12 /* bit 15:12 */
#define PCIREGOFFS(field) offsetof(struct sbpciregs, field)
#define PCIEREGOFFS(field) offsetof(struct sbpcieregs, field)
/* Sonics side: PCI core and host control registers */
struct sbpciregs {
u32 control; /* PCI control */
@ -205,11 +208,7 @@ struct sbpcieregs {
};
struct pcicore_info {
union {
struct sbpcieregs __iomem *pcieregs;
struct sbpciregs __iomem *pciregs;
} regs; /* Memory mapped register to the core */
struct bcma_device *core;
struct si_pub *sih; /* System interconnect handle */
struct pci_dev *dev;
u8 pciecap_lcreg_offset;/* PCIE capability LCreg offset
@ -224,9 +223,9 @@ struct pcicore_info {
};
#define PCIE_ASPM(sih) \
(((sih)->buscoretype == PCIE_CORE_ID) && \
(((sih)->buscorerev >= 3) && \
((sih)->buscorerev <= 5)))
((ai_get_buscoretype(sih) == PCIE_CORE_ID) && \
((ai_get_buscorerev(sih) >= 3) && \
(ai_get_buscorerev(sih) <= 5)))
/* delay needed between the mdio control/ mdiodata register data access */
@ -238,8 +237,7 @@ static void pr28829_delay(void)
/* Initialize the PCI core.
* It's caller's responsibility to make sure that this is done only once
*/
struct pcicore_info *pcicore_init(struct si_pub *sih, struct pci_dev *pdev,
void __iomem *regs)
struct pcicore_info *pcicore_init(struct si_pub *sih, struct bcma_device *core)
{
struct pcicore_info *pi;
@ -249,17 +247,15 @@ struct pcicore_info *pcicore_init(struct si_pub *sih, struct pci_dev *pdev,
return NULL;
pi->sih = sih;
pi->dev = pdev;
pi->dev = core->bus->host_pci;
pi->core = core;
if (sih->buscoretype == PCIE_CORE_ID) {
if (core->id.id == PCIE_CORE_ID) {
u8 cap_ptr;
pi->regs.pcieregs = regs;
cap_ptr = pcicore_find_pci_capability(pi->dev, PCI_CAP_ID_EXP,
NULL, NULL);
pi->pciecap_lcreg_offset = cap_ptr + PCIE_CAP_LINKCTRL_OFFSET;
} else
pi->regs.pciregs = regs;
}
return pi;
}
@ -334,37 +330,37 @@ end:
/* ***** Register Access API */
static uint
pcie_readreg(struct sbpcieregs __iomem *pcieregs, uint addrtype, uint offset)
pcie_readreg(struct bcma_device *core, uint addrtype, uint offset)
{
uint retval = 0xFFFFFFFF;
switch (addrtype) {
case PCIE_CONFIGREGS:
W_REG(&pcieregs->configaddr, offset);
(void)R_REG((&pcieregs->configaddr));
retval = R_REG(&pcieregs->configdata);
bcma_write32(core, PCIEREGOFFS(configaddr), offset);
(void)bcma_read32(core, PCIEREGOFFS(configaddr));
retval = bcma_read32(core, PCIEREGOFFS(configdata));
break;
case PCIE_PCIEREGS:
W_REG(&pcieregs->pcieindaddr, offset);
(void)R_REG(&pcieregs->pcieindaddr);
retval = R_REG(&pcieregs->pcieinddata);
bcma_write32(core, PCIEREGOFFS(pcieindaddr), offset);
(void)bcma_read32(core, PCIEREGOFFS(pcieindaddr));
retval = bcma_read32(core, PCIEREGOFFS(pcieinddata));
break;
}
return retval;
}
static uint pcie_writereg(struct sbpcieregs __iomem *pcieregs, uint addrtype,
static uint pcie_writereg(struct bcma_device *core, uint addrtype,
uint offset, uint val)
{
switch (addrtype) {
case PCIE_CONFIGREGS:
W_REG((&pcieregs->configaddr), offset);
W_REG((&pcieregs->configdata), val);
bcma_write32(core, PCIEREGOFFS(configaddr), offset);
bcma_write32(core, PCIEREGOFFS(configdata), val);
break;
case PCIE_PCIEREGS:
W_REG((&pcieregs->pcieindaddr), offset);
W_REG((&pcieregs->pcieinddata), val);
bcma_write32(core, PCIEREGOFFS(pcieindaddr), offset);
bcma_write32(core, PCIEREGOFFS(pcieinddata), val);
break;
default:
break;
@ -374,7 +370,6 @@ static uint pcie_writereg(struct sbpcieregs __iomem *pcieregs, uint addrtype,
static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk)
{
struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
uint mdiodata, i = 0;
uint pcie_serdes_spinwait = 200;
@ -382,12 +377,13 @@ static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk)
(MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) |
(MDIODATA_BLK_ADDR << MDIODATA_REGADDR_SHF) |
(blk << 4));
W_REG(&pcieregs->mdiodata, mdiodata);
bcma_write32(pi->core, PCIEREGOFFS(mdiodata), mdiodata);
pr28829_delay();
/* retry till the transaction is complete */
while (i < pcie_serdes_spinwait) {
if (R_REG(&pcieregs->mdiocontrol) & MDIOCTL_ACCESS_DONE)
if (bcma_read32(pi->core, PCIEREGOFFS(mdiocontrol)) &
MDIOCTL_ACCESS_DONE)
break;
udelay(1000);
@ -404,15 +400,15 @@ static int
pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write,
uint *val)
{
struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
uint mdiodata;
uint i = 0;
uint pcie_serdes_spinwait = 10;
/* enable mdio access to SERDES */
W_REG(&pcieregs->mdiocontrol, MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL);
bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol),
MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL);
if (pi->sih->buscorerev >= 10) {
if (ai_get_buscorerev(pi->sih) >= 10) {
/* new serdes is slower in rw,
* using two layers of reg address mapping
*/
@ -432,20 +428,22 @@ pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write,
mdiodata |= (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA |
*val);
W_REG(&pcieregs->mdiodata, mdiodata);
bcma_write32(pi->core, PCIEREGOFFS(mdiodata), mdiodata);
pr28829_delay();
/* retry till the transaction is complete */
while (i < pcie_serdes_spinwait) {
if (R_REG(&pcieregs->mdiocontrol) & MDIOCTL_ACCESS_DONE) {
if (bcma_read32(pi->core, PCIEREGOFFS(mdiocontrol)) &
MDIOCTL_ACCESS_DONE) {
if (!write) {
pr28829_delay();
*val = (R_REG(&pcieregs->mdiodata) &
*val = (bcma_read32(pi->core,
PCIEREGOFFS(mdiodata)) &
MDIODATA_MASK);
}
/* Disable mdio access to SERDES */
W_REG(&pcieregs->mdiocontrol, 0);
bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), 0);
return 0;
}
udelay(1000);
@ -453,7 +451,7 @@ pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write,
}
/* Timed out. Disable mdio access to SERDES. */
W_REG(&pcieregs->mdiocontrol, 0);
bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), 0);
return 1;
}
@ -502,18 +500,18 @@ static void pcie_extendL1timer(struct pcicore_info *pi, bool extend)
{
u32 w;
struct si_pub *sih = pi->sih;
struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
if (sih->buscoretype != PCIE_CORE_ID || sih->buscorerev < 7)
if (ai_get_buscoretype(sih) != PCIE_CORE_ID ||
ai_get_buscorerev(sih) < 7)
return;
w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
if (extend)
w |= PCIE_ASPMTIMER_EXTEND;
else
w &= ~PCIE_ASPMTIMER_EXTEND;
pcie_writereg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG, w);
w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
pcie_writereg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG, w);
w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
}
/* centralized clkreq control policy */
@ -527,25 +525,27 @@ static void pcie_clkreq_upd(struct pcicore_info *pi, uint state)
pcie_clkreq(pi, 1, 0);
break;
case SI_PCIDOWN:
if (sih->buscorerev == 6) { /* turn on serdes PLL down */
ai_corereg(sih, SI_CC_IDX,
offsetof(struct chipcregs, chipcontrol_addr),
~0, 0);
ai_corereg(sih, SI_CC_IDX,
offsetof(struct chipcregs, chipcontrol_data),
~0x40, 0);
/* turn on serdes PLL down */
if (ai_get_buscorerev(sih) == 6) {
ai_cc_reg(sih,
offsetof(struct chipcregs, chipcontrol_addr),
~0, 0);
ai_cc_reg(sih,
offsetof(struct chipcregs, chipcontrol_data),
~0x40, 0);
} else if (pi->pcie_pr42767) {
pcie_clkreq(pi, 1, 1);
}
break;
case SI_PCIUP:
if (sih->buscorerev == 6) { /* turn off serdes PLL down */
ai_corereg(sih, SI_CC_IDX,
offsetof(struct chipcregs, chipcontrol_addr),
~0, 0);
ai_corereg(sih, SI_CC_IDX,
offsetof(struct chipcregs, chipcontrol_data),
~0x40, 0x40);
/* turn off serdes PLL down */
if (ai_get_buscorerev(sih) == 6) {
ai_cc_reg(sih,
offsetof(struct chipcregs, chipcontrol_addr),
~0, 0);
ai_cc_reg(sih,
offsetof(struct chipcregs, chipcontrol_data),
~0x40, 0x40);
} else if (PCIE_ASPM(sih)) { /* disable clkreq */
pcie_clkreq(pi, 1, 0);
}
@ -562,7 +562,7 @@ static void pcie_war_polarity(struct pcicore_info *pi)
if (pi->pcie_polarity != 0)
return;
w = pcie_readreg(pi->regs.pcieregs, PCIE_PCIEREGS, PCIE_PLP_STATUSREG);
w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_PLP_STATUSREG);
/* Detect the current polarity at attach and force that polarity and
* disable changing the polarity
@ -581,18 +581,15 @@ static void pcie_war_polarity(struct pcicore_info *pi)
*/
static void pcie_war_aspm_clkreq(struct pcicore_info *pi)
{
struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
struct si_pub *sih = pi->sih;
u16 val16;
u16 __iomem *reg16;
u32 w;
if (!PCIE_ASPM(sih))
return;
/* bypass this on QT or VSIM */
reg16 = &pcieregs->sprom[SRSH_ASPM_OFFSET];
val16 = R_REG(reg16);
val16 = bcma_read16(pi->core, PCIEREGOFFS(sprom[SRSH_ASPM_OFFSET]));
val16 &= ~SRSH_ASPM_ENB;
if (pi->pcie_war_aspm_ovr == PCIE_ASPM_ENAB)
@ -602,15 +599,15 @@ static void pcie_war_aspm_clkreq(struct pcicore_info *pi)
else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L0s_ENAB)
val16 |= SRSH_ASPM_L0s_ENB;
W_REG(reg16, val16);
bcma_write16(pi->core, PCIEREGOFFS(sprom[SRSH_ASPM_OFFSET]), val16);
pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w);
w &= ~PCIE_ASPM_ENAB;
w |= pi->pcie_war_aspm_ovr;
pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w);
reg16 = &pcieregs->sprom[SRSH_CLKREQ_OFFSET_REV5];
val16 = R_REG(reg16);
val16 = bcma_read16(pi->core,
PCIEREGOFFS(sprom[SRSH_CLKREQ_OFFSET_REV5]));
if (pi->pcie_war_aspm_ovr != PCIE_ASPM_DISAB) {
val16 |= SRSH_CLKREQ_ENB;
@ -618,7 +615,8 @@ static void pcie_war_aspm_clkreq(struct pcicore_info *pi)
} else
val16 &= ~SRSH_CLKREQ_ENB;
W_REG(reg16, val16);
bcma_write16(pi->core, PCIEREGOFFS(sprom[SRSH_CLKREQ_OFFSET_REV5]),
val16);
}
/* Apply the polarity determined at the start */
@ -642,16 +640,15 @@ static void pcie_war_serdes(struct pcicore_info *pi)
/* Needs to happen when coming out of 'standby'/'hibernate' */
static void pcie_misc_config_fixup(struct pcicore_info *pi)
{
struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
u16 val16;
u16 __iomem *reg16;
reg16 = &pcieregs->sprom[SRSH_PCIE_MISC_CONFIG];
val16 = R_REG(reg16);
val16 = bcma_read16(pi->core,
PCIEREGOFFS(sprom[SRSH_PCIE_MISC_CONFIG]));
if ((val16 & SRSH_L23READY_EXIT_NOPERST) == 0) {
val16 |= SRSH_L23READY_EXIT_NOPERST;
W_REG(reg16, val16);
bcma_write16(pi->core,
PCIEREGOFFS(sprom[SRSH_PCIE_MISC_CONFIG]), val16);
}
}
@ -659,62 +656,57 @@ static void pcie_misc_config_fixup(struct pcicore_info *pi)
/* Needs to happen when coming out of 'standby'/'hibernate' */
static void pcie_war_noplldown(struct pcicore_info *pi)
{
struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
u16 __iomem *reg16;
/* turn off serdes PLL down */
ai_corereg(pi->sih, SI_CC_IDX, offsetof(struct chipcregs, chipcontrol),
CHIPCTRL_4321_PLL_DOWN, CHIPCTRL_4321_PLL_DOWN);
ai_cc_reg(pi->sih, offsetof(struct chipcregs, chipcontrol),
CHIPCTRL_4321_PLL_DOWN, CHIPCTRL_4321_PLL_DOWN);
/* clear srom shadow backdoor */
reg16 = &pcieregs->sprom[SRSH_BD_OFFSET];
W_REG(reg16, 0);
bcma_write16(pi->core, PCIEREGOFFS(sprom[SRSH_BD_OFFSET]), 0);
}
/* Needs to happen when coming out of 'standby'/'hibernate' */
static void pcie_war_pci_setup(struct pcicore_info *pi)
{
struct si_pub *sih = pi->sih;
struct sbpcieregs __iomem *pcieregs = pi->regs.pcieregs;
u32 w;
if (sih->buscorerev == 0 || sih->buscorerev == 1) {
w = pcie_readreg(pcieregs, PCIE_PCIEREGS,
if (ai_get_buscorerev(sih) == 0 || ai_get_buscorerev(sih) == 1) {
w = pcie_readreg(pi->core, PCIE_PCIEREGS,
PCIE_TLP_WORKAROUNDSREG);
w |= 0x8;
pcie_writereg(pcieregs, PCIE_PCIEREGS,
pcie_writereg(pi->core, PCIE_PCIEREGS,
PCIE_TLP_WORKAROUNDSREG, w);
}
if (sih->buscorerev == 1) {
w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG);
if (ai_get_buscorerev(sih) == 1) {
w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_LCREG);
w |= 0x40;
pcie_writereg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG, w);
pcie_writereg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_LCREG, w);
}
if (sih->buscorerev == 0) {
if (ai_get_buscorerev(sih) == 0) {
pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_TIMER1, 0x8128);
pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDR, 0x0100);
pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDRBW, 0x1466);
} else if (PCIE_ASPM(sih)) {
/* Change the L1 threshold for better performance */
w = pcie_readreg(pcieregs, PCIE_PCIEREGS,
w = pcie_readreg(pi->core, PCIE_PCIEREGS,
PCIE_DLLP_PMTHRESHREG);
w &= ~PCIE_L1THRESHOLDTIME_MASK;
w |= PCIE_L1THRESHOLD_WARVAL << PCIE_L1THRESHOLDTIME_SHIFT;
pcie_writereg(pcieregs, PCIE_PCIEREGS,
pcie_writereg(pi->core, PCIE_PCIEREGS,
PCIE_DLLP_PMTHRESHREG, w);
pcie_war_serdes(pi);
pcie_war_aspm_clkreq(pi);
} else if (pi->sih->buscorerev == 7)
} else if (ai_get_buscorerev(pi->sih) == 7)
pcie_war_noplldown(pi);
/* Note that the fix is actually in the SROM,
* that's why this is open-ended
*/
if (pi->sih->buscorerev >= 6)
if (ai_get_buscorerev(pi->sih) >= 6)
pcie_misc_config_fixup(pi);
}
@ -745,7 +737,7 @@ void pcicore_attach(struct pcicore_info *pi, int state)
void pcicore_hwup(struct pcicore_info *pi)
{
if (!pi || pi->sih->buscoretype != PCIE_CORE_ID)
if (!pi || ai_get_buscoretype(pi->sih) != PCIE_CORE_ID)
return;
pcie_war_pci_setup(pi);
@ -753,7 +745,7 @@ void pcicore_hwup(struct pcicore_info *pi)
void pcicore_up(struct pcicore_info *pi, int state)
{
if (!pi || pi->sih->buscoretype != PCIE_CORE_ID)
if (!pi || ai_get_buscoretype(pi->sih) != PCIE_CORE_ID)
return;
/* Restore L1 timer for better performance */
@ -781,7 +773,7 @@ void pcicore_sleep(struct pcicore_info *pi)
void pcicore_down(struct pcicore_info *pi, int state)
{
if (!pi || pi->sih->buscoretype != PCIE_CORE_ID)
if (!pi || ai_get_buscoretype(pi->sih) != PCIE_CORE_ID)
return;
pcie_clkreq_upd(pi, state);
@ -790,46 +782,45 @@ void pcicore_down(struct pcicore_info *pi, int state)
pcie_extendL1timer(pi, false);
}
/* precondition: current core is sii->buscoretype */
static void pcicore_fixcfg(struct pcicore_info *pi, u16 __iomem *reg16)
void pcicore_fixcfg(struct pcicore_info *pi)
{
struct si_info *sii = (struct si_info *)(pi->sih);
struct bcma_device *core = pi->core;
u16 val16;
uint pciidx;
uint regoff;
pciidx = ai_coreidx(&sii->pub);
val16 = R_REG(reg16);
if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (u16)pciidx) {
val16 = (u16)(pciidx << SRSH_PI_SHIFT) |
(val16 & ~SRSH_PI_MASK);
W_REG(reg16, val16);
switch (pi->core->id.id) {
case BCMA_CORE_PCI:
regoff = PCIREGOFFS(sprom[SRSH_PI_OFFSET]);
break;
case BCMA_CORE_PCIE:
regoff = PCIEREGOFFS(sprom[SRSH_PI_OFFSET]);
break;
default:
return;
}
}
void
pcicore_fixcfg_pci(struct pcicore_info *pi, struct sbpciregs __iomem *pciregs)
{
pcicore_fixcfg(pi, &pciregs->sprom[SRSH_PI_OFFSET]);
}
void pcicore_fixcfg_pcie(struct pcicore_info *pi,
struct sbpcieregs __iomem *pcieregs)
{
pcicore_fixcfg(pi, &pcieregs->sprom[SRSH_PI_OFFSET]);
val16 = bcma_read16(pi->core, regoff);
if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) !=
(u16)core->core_index) {
val16 = ((u16)core->core_index << SRSH_PI_SHIFT) |
(val16 & ~SRSH_PI_MASK);
bcma_write16(pi->core, regoff, val16);
}
}
/* precondition: current core is pci core */
void
pcicore_pci_setup(struct pcicore_info *pi, struct sbpciregs __iomem *pciregs)
pcicore_pci_setup(struct pcicore_info *pi)
{
u32 w;
bcma_set32(pi->core, PCIREGOFFS(sbtopci2),
SBTOPCI_PREF | SBTOPCI_BURST);
OR_REG(&pciregs->sbtopci2, SBTOPCI_PREF | SBTOPCI_BURST);
if (((struct si_info *)(pi->sih))->pub.buscorerev >= 11) {
OR_REG(&pciregs->sbtopci2, SBTOPCI_RC_READMULTI);
w = R_REG(&pciregs->clkrun);
W_REG(&pciregs->clkrun, w | PCI_CLKRUN_DSBL);
w = R_REG(&pciregs->clkrun);
if (pi->core->id.rev >= 11) {
bcma_set32(pi->core, PCIREGOFFS(sbtopci2),
SBTOPCI_RC_READMULTI);
bcma_set32(pi->core, PCIREGOFFS(clkrun), PCI_CLKRUN_DSBL);
(void)bcma_read32(pi->core, PCIREGOFFS(clkrun));
}
}

View File

@ -62,8 +62,7 @@ struct sbpciregs;
struct sbpcieregs;
extern struct pcicore_info *pcicore_init(struct si_pub *sih,
struct pci_dev *pdev,
void __iomem *regs);
struct bcma_device *core);
extern void pcicore_deinit(struct pcicore_info *pch);
extern void pcicore_attach(struct pcicore_info *pch, int state);
extern void pcicore_hwup(struct pcicore_info *pch);
@ -72,11 +71,7 @@ extern void pcicore_sleep(struct pcicore_info *pch);
extern void pcicore_down(struct pcicore_info *pch, int state);
extern u8 pcicore_find_pci_capability(struct pci_dev *dev, u8 req_cap_id,
unsigned char *buf, u32 *buflen);
extern void pcicore_fixcfg_pci(struct pcicore_info *pch,
struct sbpciregs __iomem *pciregs);
extern void pcicore_fixcfg_pcie(struct pcicore_info *pch,
struct sbpcieregs __iomem *pciregs);
extern void pcicore_pci_setup(struct pcicore_info *pch,
struct sbpciregs __iomem *pciregs);
extern void pcicore_fixcfg(struct pcicore_info *pch);
extern void pcicore_pci_setup(struct pcicore_info *pch);
#endif /* _BRCM_NICPCI_H_ */

View File

@ -77,7 +77,7 @@ struct otp_fn_s {
};
struct otpinfo {
uint ccrev; /* chipc revision */
struct bcma_device *core; /* chipc core */
const struct otp_fn_s *fn; /* OTP functions */
struct si_pub *sih; /* Saved sb handle */
@ -133,9 +133,10 @@ struct otpinfo {
#define OTP_SZ_FU_144 (144/8) /* 144 bits */
static u16
ipxotp_otpr(struct otpinfo *oi, struct chipcregs __iomem *cc, uint wn)
ipxotp_otpr(struct otpinfo *oi, uint wn)
{
return R_REG(&cc->sromotp[wn]);
return bcma_read16(oi->core,
CHIPCREGOFFS(sromotp[wn]));
}
/*
@ -146,7 +147,7 @@ static int ipxotp_max_rgnsz(struct si_pub *sih, int osizew)
{
int ret = 0;
switch (sih->chip) {
switch (ai_get_chip_id(sih)) {
case BCM43224_CHIP_ID:
case BCM43225_CHIP_ID:
ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM;
@ -161,19 +162,21 @@ static int ipxotp_max_rgnsz(struct si_pub *sih, int osizew)
return ret;
}
static void _ipxotp_init(struct otpinfo *oi, struct chipcregs __iomem *cc)
static void _ipxotp_init(struct otpinfo *oi)
{
uint k;
u32 otpp, st;
int ccrev = ai_get_ccrev(oi->sih);
/*
* record word offset of General Use Region
* for various chipcommon revs
*/
if (oi->sih->ccrev == 21 || oi->sih->ccrev == 24
|| oi->sih->ccrev == 27) {
if (ccrev == 21 || ccrev == 24
|| ccrev == 27) {
oi->otpgu_base = REVA4_OTPGU_BASE;
} else if (oi->sih->ccrev == 36) {
} else if (ccrev == 36) {
/*
* OTP size greater than equal to 2KB (128 words),
* otpgu_base is similar to rev23
@ -182,7 +185,7 @@ static void _ipxotp_init(struct otpinfo *oi, struct chipcregs __iomem *cc)
oi->otpgu_base = REVB8_OTPGU_BASE;
else
oi->otpgu_base = REV36_OTPGU_BASE;
} else if (oi->sih->ccrev == 23 || oi->sih->ccrev >= 25) {
} else if (ccrev == 23 || ccrev >= 25) {
oi->otpgu_base = REVB8_OTPGU_BASE;
}
@ -190,24 +193,21 @@ static void _ipxotp_init(struct otpinfo *oi, struct chipcregs __iomem *cc)
otpp =
OTPP_START_BUSY | ((OTPPOC_INIT << OTPP_OC_SHIFT) & OTPP_OC_MASK);
W_REG(&cc->otpprog, otpp);
for (k = 0;
((st = R_REG(&cc->otpprog)) & OTPP_START_BUSY)
&& (k < OTPP_TRIES); k++)
;
bcma_write32(oi->core, CHIPCREGOFFS(otpprog), otpp);
st = bcma_read32(oi->core, CHIPCREGOFFS(otpprog));
for (k = 0; (st & OTPP_START_BUSY) && (k < OTPP_TRIES); k++)
st = bcma_read32(oi->core, CHIPCREGOFFS(otpprog));
if (k >= OTPP_TRIES)
return;
/* Read OTP lock bits and subregion programmed indication bits */
oi->status = R_REG(&cc->otpstatus);
oi->status = bcma_read32(oi->core, CHIPCREGOFFS(otpstatus));
if ((oi->sih->chip == BCM43224_CHIP_ID)
|| (oi->sih->chip == BCM43225_CHIP_ID)) {
if ((ai_get_chip_id(oi->sih) == BCM43224_CHIP_ID)
|| (ai_get_chip_id(oi->sih) == BCM43225_CHIP_ID)) {
u32 p_bits;
p_bits =
(ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_P_OFF) &
OTPGU_P_MSK)
>> OTPGU_P_SHIFT;
p_bits = (ipxotp_otpr(oi, oi->otpgu_base + OTPGU_P_OFF) &
OTPGU_P_MSK) >> OTPGU_P_SHIFT;
oi->status |= (p_bits << OTPS_GUP_SHIFT);
}
@ -220,7 +220,7 @@ static void _ipxotp_init(struct otpinfo *oi, struct chipcregs __iomem *cc)
oi->hwlim = oi->wsize;
if (oi->status & OTPS_GUP_HW) {
oi->hwlim =
ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_HSB_OFF) / 16;
ipxotp_otpr(oi, oi->otpgu_base + OTPGU_HSB_OFF) / 16;
oi->swbase = oi->hwlim;
} else
oi->swbase = oi->hwbase;
@ -230,7 +230,7 @@ static void _ipxotp_init(struct otpinfo *oi, struct chipcregs __iomem *cc)
if (oi->status & OTPS_GUP_SW) {
oi->swlim =
ipxotp_otpr(oi, cc, oi->otpgu_base + OTPGU_SFB_OFF) / 16;
ipxotp_otpr(oi, oi->otpgu_base + OTPGU_SFB_OFF) / 16;
oi->fbase = oi->swlim;
} else
oi->fbase = oi->swbase;
@ -240,11 +240,8 @@ static void _ipxotp_init(struct otpinfo *oi, struct chipcregs __iomem *cc)
static int ipxotp_init(struct si_pub *sih, struct otpinfo *oi)
{
uint idx;
struct chipcregs __iomem *cc;
/* Make sure we're running IPX OTP */
if (!OTPTYPE_IPX(sih->ccrev))
if (!OTPTYPE_IPX(ai_get_ccrev(sih)))
return -EBADE;
/* Make sure OTP is not disabled */
@ -252,7 +249,7 @@ static int ipxotp_init(struct si_pub *sih, struct otpinfo *oi)
return -EBADE;
/* Check for otp size */
switch ((sih->cccaps & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) {
switch ((ai_get_cccaps(sih) & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) {
case 0:
/* Nothing there */
return -EBADE;
@ -282,21 +279,13 @@ static int ipxotp_init(struct si_pub *sih, struct otpinfo *oi)
}
/* Retrieve OTP region info */
idx = ai_coreidx(sih);
cc = ai_setcoreidx(sih, SI_CC_IDX);
_ipxotp_init(oi, cc);
ai_setcoreidx(sih, idx);
_ipxotp_init(oi);
return 0;
}
static int
ipxotp_read_region(struct otpinfo *oi, int region, u16 *data, uint *wlen)
{
uint idx;
struct chipcregs __iomem *cc;
uint base, i, sz;
/* Validate region selection */
@ -365,14 +354,10 @@ ipxotp_read_region(struct otpinfo *oi, int region, u16 *data, uint *wlen)
return -EINVAL;
}
idx = ai_coreidx(oi->sih);
cc = ai_setcoreidx(oi->sih, SI_CC_IDX);
/* Read the data */
for (i = 0; i < sz; i++)
data[i] = ipxotp_otpr(oi, cc, base + i);
data[i] = ipxotp_otpr(oi, base + i);
ai_setcoreidx(oi->sih, idx);
*wlen = sz;
return 0;
}
@ -384,14 +369,13 @@ static const struct otp_fn_s ipxotp_fn = {
static int otp_init(struct si_pub *sih, struct otpinfo *oi)
{
int ret;
memset(oi, 0, sizeof(struct otpinfo));
oi->ccrev = sih->ccrev;
oi->core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
if (OTPTYPE_IPX(oi->ccrev))
if (OTPTYPE_IPX(ai_get_ccrev(sih)))
oi->fn = &ipxotp_fn;
if (oi->fn == NULL)
@ -399,7 +383,7 @@ static int otp_init(struct si_pub *sih, struct otpinfo *oi)
oi->sih = sih;
ret = (oi->fn->init) (sih, oi);
ret = (oi->fn->init)(sih, oi);
return ret;
}

View File

@ -149,9 +149,8 @@ void wlc_radioreg_enter(struct brcms_phy_pub *pih)
void wlc_radioreg_exit(struct brcms_phy_pub *pih)
{
struct brcms_phy *pi = (struct brcms_phy *) pih;
u16 dummy;
dummy = R_REG(&pi->regs->phyversion);
(void)bcma_read16(pi->d11core, D11REGOFFS(phyversion));
pi->phy_wreg = 0;
wlapi_bmac_mctrl(pi->sh->physhim, MCTL_LOCK_RADIO, 0);
}
@ -186,11 +185,11 @@ u16 read_radio_reg(struct brcms_phy *pi, u16 addr)
if ((D11REV_GE(pi->sh->corerev, 24)) ||
(D11REV_IS(pi->sh->corerev, 22)
&& (pi->pubpi.phy_type != PHY_TYPE_SSN))) {
W_REG_FLUSH(&pi->regs->radioregaddr, addr);
data = R_REG(&pi->regs->radioregdata);
bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), addr);
data = bcma_read16(pi->d11core, D11REGOFFS(radioregdata));
} else {
W_REG_FLUSH(&pi->regs->phy4waddr, addr);
data = R_REG(&pi->regs->phy4wdatalo);
bcma_wflush16(pi->d11core, D11REGOFFS(phy4waddr), addr);
data = bcma_read16(pi->d11core, D11REGOFFS(phy4wdatalo));
}
pi->phy_wreg = 0;
@ -203,15 +202,15 @@ void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
(D11REV_IS(pi->sh->corerev, 22)
&& (pi->pubpi.phy_type != PHY_TYPE_SSN))) {
W_REG_FLUSH(&pi->regs->radioregaddr, addr);
W_REG(&pi->regs->radioregdata, val);
bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), addr);
bcma_write16(pi->d11core, D11REGOFFS(radioregdata), val);
} else {
W_REG_FLUSH(&pi->regs->phy4waddr, addr);
W_REG(&pi->regs->phy4wdatalo, val);
bcma_wflush16(pi->d11core, D11REGOFFS(phy4waddr), addr);
bcma_write16(pi->d11core, D11REGOFFS(phy4wdatalo), val);
}
if (++pi->phy_wreg >= pi->phy_wreg_limit) {
(void)R_REG(&pi->regs->maccontrol);
(void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
pi->phy_wreg = 0;
}
}
@ -223,19 +222,20 @@ static u32 read_radio_id(struct brcms_phy *pi)
if (D11REV_GE(pi->sh->corerev, 24)) {
u32 b0, b1, b2;
W_REG_FLUSH(&pi->regs->radioregaddr, 0);
b0 = (u32) R_REG(&pi->regs->radioregdata);
W_REG_FLUSH(&pi->regs->radioregaddr, 1);
b1 = (u32) R_REG(&pi->regs->radioregdata);
W_REG_FLUSH(&pi->regs->radioregaddr, 2);
b2 = (u32) R_REG(&pi->regs->radioregdata);
bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), 0);
b0 = (u32) bcma_read16(pi->d11core, D11REGOFFS(radioregdata));
bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), 1);
b1 = (u32) bcma_read16(pi->d11core, D11REGOFFS(radioregdata));
bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), 2);
b2 = (u32) bcma_read16(pi->d11core, D11REGOFFS(radioregdata));
id = ((b0 & 0xf) << 28) | (((b2 << 8) | b1) << 12) | ((b0 >> 4)
& 0xf);
} else {
W_REG_FLUSH(&pi->regs->phy4waddr, RADIO_IDCODE);
id = (u32) R_REG(&pi->regs->phy4wdatalo);
id |= (u32) R_REG(&pi->regs->phy4wdatahi) << 16;
bcma_wflush16(pi->d11core, D11REGOFFS(phy4waddr), RADIO_IDCODE);
id = (u32) bcma_read16(pi->d11core, D11REGOFFS(phy4wdatalo));
id |= (u32) bcma_read16(pi->d11core,
D11REGOFFS(phy4wdatahi)) << 16;
}
pi->phy_wreg = 0;
return id;
@ -275,75 +275,52 @@ void mod_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val)
void write_phy_channel_reg(struct brcms_phy *pi, uint val)
{
W_REG(&pi->regs->phychannel, val);
bcma_write16(pi->d11core, D11REGOFFS(phychannel), val);
}
u16 read_phy_reg(struct brcms_phy *pi, u16 addr)
{
struct d11regs __iomem *regs;
regs = pi->regs;
W_REG_FLUSH(&regs->phyregaddr, addr);
bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr);
pi->phy_wreg = 0;
return R_REG(&regs->phyregdata);
return bcma_read16(pi->d11core, D11REGOFFS(phyregdata));
}
void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
{
struct d11regs __iomem *regs;
regs = pi->regs;
#ifdef CONFIG_BCM47XX
W_REG_FLUSH(&regs->phyregaddr, addr);
W_REG(&regs->phyregdata, val);
bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr);
bcma_write16(pi->d11core, D11REGOFFS(phyregdata), val);
if (addr == 0x72)
(void)R_REG(&regs->phyregdata);
(void)bcma_read16(pi->d11core, D11REGOFFS(phyversion));
#else
W_REG((u32 __iomem *)(&regs->phyregaddr), addr | (val << 16));
bcma_write32(pi->d11core, D11REGOFFS(phyregaddr), addr | (val << 16));
if (++pi->phy_wreg >= pi->phy_wreg_limit) {
pi->phy_wreg = 0;
(void)R_REG(&regs->phyversion);
(void)bcma_read16(pi->d11core, D11REGOFFS(phyversion));
}
#endif
}
void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
{
struct d11regs __iomem *regs;
regs = pi->regs;
W_REG_FLUSH(&regs->phyregaddr, addr);
W_REG(&regs->phyregdata, (R_REG(&regs->phyregdata) & val));
bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr);
bcma_mask16(pi->d11core, D11REGOFFS(phyregdata), val);
pi->phy_wreg = 0;
}
void or_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
{
struct d11regs __iomem *regs;
regs = pi->regs;
W_REG_FLUSH(&regs->phyregaddr, addr);
W_REG(&regs->phyregdata, (R_REG(&regs->phyregdata) | val));
bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr);
bcma_set16(pi->d11core, D11REGOFFS(phyregdata), val);
pi->phy_wreg = 0;
}
void mod_phy_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val)
{
struct d11regs __iomem *regs;
regs = pi->regs;
W_REG_FLUSH(&regs->phyregaddr, addr);
W_REG(&regs->phyregdata,
((R_REG(&regs->phyregdata) & ~mask) | (val & mask)));
val &= mask;
bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr);
bcma_maskset16(pi->d11core, D11REGOFFS(phyregdata), ~mask, val);
pi->phy_wreg = 0;
}
@ -404,10 +381,8 @@ struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp)
sh->sromrev = shp->sromrev;
sh->boardtype = shp->boardtype;
sh->boardrev = shp->boardrev;
sh->boardvendor = shp->boardvendor;
sh->boardflags = shp->boardflags;
sh->boardflags2 = shp->boardflags2;
sh->buscorerev = shp->buscorerev;
sh->fast_timer = PHY_SW_TIMER_FAST;
sh->slow_timer = PHY_SW_TIMER_SLOW;
@ -450,7 +425,7 @@ static u32 wlc_phy_get_radio_ver(struct brcms_phy *pi)
}
struct brcms_phy_pub *
wlc_phy_attach(struct shared_phy *sh, struct d11regs __iomem *regs,
wlc_phy_attach(struct shared_phy *sh, struct bcma_device *d11core,
int bandtype, struct wiphy *wiphy)
{
struct brcms_phy *pi;
@ -462,7 +437,7 @@ wlc_phy_attach(struct shared_phy *sh, struct d11regs __iomem *regs,
if (D11REV_IS(sh->corerev, 4))
sflags = SISF_2G_PHY | SISF_5G_PHY;
else
sflags = ai_core_sflags(sh->sih, 0, 0);
sflags = bcma_aread32(d11core, BCMA_IOST);
if (bandtype == BRCM_BAND_5G) {
if ((sflags & (SISF_5G_PHY | SISF_DB_PHY)) == 0)
@ -480,7 +455,7 @@ wlc_phy_attach(struct shared_phy *sh, struct d11regs __iomem *regs,
if (pi == NULL)
return NULL;
pi->wiphy = wiphy;
pi->regs = regs;
pi->d11core = d11core;
pi->sh = sh;
pi->phy_init_por = true;
pi->phy_wreg_limit = PHY_WREG_LIMIT;
@ -495,7 +470,7 @@ wlc_phy_attach(struct shared_phy *sh, struct d11regs __iomem *regs,
pi->pubpi.coreflags = SICF_GMODE;
wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags);
phyversion = R_REG(&pi->regs->phyversion);
phyversion = bcma_read16(pi->d11core, D11REGOFFS(phyversion));
pi->pubpi.phy_type = PHY_TYPE(phyversion);
pi->pubpi.phy_rev = phyversion & PV_PV_MASK;
@ -507,8 +482,8 @@ wlc_phy_attach(struct shared_phy *sh, struct d11regs __iomem *regs,
pi->pubpi.phy_corenum = PHY_CORE_NUM_2;
pi->pubpi.ana_rev = (phyversion & PV_AV_MASK) >> PV_AV_SHIFT;
if (!pi->pubpi.phy_type == PHY_TYPE_N &&
!pi->pubpi.phy_type == PHY_TYPE_LCN)
if (pi->pubpi.phy_type != PHY_TYPE_N &&
pi->pubpi.phy_type != PHY_TYPE_LCN)
goto err;
if (bandtype == BRCM_BAND_5G) {
@ -779,14 +754,14 @@ void wlc_phy_init(struct brcms_phy_pub *pih, u16 chanspec)
pi->radio_chanspec = chanspec;
mc = R_REG(&pi->regs->maccontrol);
mc = bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
if (WARN(mc & MCTL_EN_MAC, "HW error MAC running on init"))
return;
if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN))
pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC;
if (WARN(!(ai_core_sflags(pi->sh->sih, 0, 0) & SISF_FCLKA),
if (WARN(!(bcma_aread32(pi->d11core, BCMA_IOST) & SISF_FCLKA),
"HW error SISF_FCLKA\n"))
return;
@ -825,8 +800,8 @@ void wlc_phy_cal_init(struct brcms_phy_pub *pih)
struct brcms_phy *pi = (struct brcms_phy *) pih;
void (*cal_init)(struct brcms_phy *) = NULL;
if (WARN((R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) != 0,
"HW error: MAC enabled during phy cal\n"))
if (WARN((bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
MCTL_EN_MAC) != 0, "HW error: MAC enabled during phy cal\n"))
return;
if (!pi->initialized) {
@ -1017,7 +992,7 @@ wlc_phy_init_radio_regs(struct brcms_phy *pi,
void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on)
{
#define DUMMY_PKT_LEN 20
struct d11regs __iomem *regs = pi->regs;
struct bcma_device *core = pi->d11core;
int i, count;
u8 ofdmpkt[DUMMY_PKT_LEN] = {
0xcc, 0x01, 0x02, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00,
@ -1033,26 +1008,28 @@ void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on)
wlapi_bmac_write_template_ram(pi->sh->physhim, 0, DUMMY_PKT_LEN,
dummypkt);
W_REG(&regs->xmtsel, 0);
bcma_write16(core, D11REGOFFS(xmtsel), 0);
if (D11REV_GE(pi->sh->corerev, 11))
W_REG(&regs->wepctl, 0x100);
bcma_write16(core, D11REGOFFS(wepctl), 0x100);
else
W_REG(&regs->wepctl, 0);
bcma_write16(core, D11REGOFFS(wepctl), 0);
W_REG(&regs->txe_phyctl, (ofdm ? 1 : 0) | PHY_TXC_ANT_0);
bcma_write16(core, D11REGOFFS(txe_phyctl),
(ofdm ? 1 : 0) | PHY_TXC_ANT_0);
if (ISNPHY(pi) || ISLCNPHY(pi))
W_REG(&regs->txe_phyctl1, 0x1A02);
bcma_write16(core, D11REGOFFS(txe_phyctl1), 0x1A02);
W_REG(&regs->txe_wm_0, 0);
W_REG(&regs->txe_wm_1, 0);
bcma_write16(core, D11REGOFFS(txe_wm_0), 0);
bcma_write16(core, D11REGOFFS(txe_wm_1), 0);
W_REG(&regs->xmttplatetxptr, 0);
W_REG(&regs->xmttxcnt, DUMMY_PKT_LEN);
bcma_write16(core, D11REGOFFS(xmttplatetxptr), 0);
bcma_write16(core, D11REGOFFS(xmttxcnt), DUMMY_PKT_LEN);
W_REG(&regs->xmtsel, ((8 << 8) | (1 << 5) | (1 << 2) | 2));
bcma_write16(core, D11REGOFFS(xmtsel),
((8 << 8) | (1 << 5) | (1 << 2) | 2));
W_REG(&regs->txe_ctl, 0);
bcma_write16(core, D11REGOFFS(txe_ctl), 0);
if (!pa_on) {
if (ISNPHY(pi))
@ -1060,27 +1037,28 @@ void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on)
}
if (ISNPHY(pi) || ISLCNPHY(pi))
W_REG(&regs->txe_aux, 0xD0);
bcma_write16(core, D11REGOFFS(txe_aux), 0xD0);
else
W_REG(&regs->txe_aux, ((1 << 5) | (1 << 4)));
bcma_write16(core, D11REGOFFS(txe_aux), ((1 << 5) | (1 << 4)));
(void)R_REG(&regs->txe_aux);
(void)bcma_read16(core, D11REGOFFS(txe_aux));
i = 0;
count = ofdm ? 30 : 250;
while ((i++ < count)
&& (R_REG(&regs->txe_status) & (1 << 7)))
&& (bcma_read16(core, D11REGOFFS(txe_status)) & (1 << 7)))
udelay(10);
i = 0;
while ((i++ < 10)
&& ((R_REG(&regs->txe_status) & (1 << 10)) == 0))
while ((i++ < 10) &&
((bcma_read16(core, D11REGOFFS(txe_status)) & (1 << 10)) == 0))
udelay(10);
i = 0;
while ((i++ < 10) && ((R_REG(&regs->ifsstat) & (1 << 8))))
while ((i++ < 10) &&
((bcma_read16(core, D11REGOFFS(ifsstat)) & (1 << 8))))
udelay(10);
if (!pa_on) {
@ -1137,7 +1115,7 @@ static bool wlc_phy_cal_txpower_recalc_sw(struct brcms_phy *pi)
void wlc_phy_switch_radio(struct brcms_phy_pub *pih, bool on)
{
struct brcms_phy *pi = (struct brcms_phy *) pih;
(void)R_REG(&pi->regs->maccontrol);
(void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
if (ISNPHY(pi)) {
wlc_phy_switch_radio_nphy(pi, on);
@ -1377,7 +1355,7 @@ void wlc_phy_txpower_target_set(struct brcms_phy_pub *ppi,
memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_SDM],
&txpwr->mcs_40_mimo[0], BRCMS_NUM_RATES_MCS_2_STREAM);
if (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)
if (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & MCTL_EN_MAC)
mac_enabled = true;
if (mac_enabled)
@ -1407,7 +1385,8 @@ int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm, bool override)
if (!SCAN_INPROG_PHY(pi)) {
bool suspend;
suspend = (0 == (R_REG(&pi->regs->maccontrol) &
suspend = (0 == (bcma_read32(pi->d11core,
D11REGOFFS(maccontrol)) &
MCTL_EN_MAC));
if (!suspend)
@ -1860,18 +1839,17 @@ void wlc_phy_runbist_config(struct brcms_phy_pub *ppi, bool start_end)
if (NREV_IS(pi->pubpi.phy_rev, 3)
|| NREV_IS(pi->pubpi.phy_rev, 4)) {
W_REG(&pi->regs->phyregaddr, 0xa0);
(void)R_REG(&pi->regs->phyregaddr);
rxc = R_REG(&pi->regs->phyregdata);
W_REG(&pi->regs->phyregdata,
(0x1 << 15) | rxc);
bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr),
0xa0);
bcma_set16(pi->d11core, D11REGOFFS(phyregdata),
0x1 << 15);
}
} else {
if (NREV_IS(pi->pubpi.phy_rev, 3)
|| NREV_IS(pi->pubpi.phy_rev, 4)) {
W_REG(&pi->regs->phyregaddr, 0xa0);
(void)R_REG(&pi->regs->phyregaddr);
W_REG(&pi->regs->phyregdata, rxc);
bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr),
0xa0);
bcma_write16(pi->d11core, D11REGOFFS(phyregdata), rxc);
}
wlc_phy_por_inform(ppi);
@ -1991,7 +1969,9 @@ void wlc_phy_txpower_hw_ctrl_set(struct brcms_phy_pub *ppi, bool hwpwrctrl)
pi->txpwrctrl = hwpwrctrl;
if (ISNPHY(pi)) {
suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
suspend = (0 == (bcma_read32(pi->d11core,
D11REGOFFS(maccontrol)) &
MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
@ -2193,7 +2173,8 @@ void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val)
if (!pi->sh->clk)
return;
suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
@ -2411,8 +2392,8 @@ wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch)
wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0);
wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0);
OR_REG(&pi->regs->maccommand,
MCMD_BG_NOISE);
bcma_set32(pi->d11core, D11REGOFFS(maccommand),
MCMD_BG_NOISE);
} else {
wlapi_suspend_mac_and_wait(pi->sh->physhim);
wlc_lcnphy_deaf_mode(pi, (bool) 0);
@ -2430,8 +2411,8 @@ wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch)
wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0);
wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0);
OR_REG(&pi->regs->maccommand,
MCMD_BG_NOISE);
bcma_set32(pi->d11core, D11REGOFFS(maccommand),
MCMD_BG_NOISE);
} else {
struct phy_iq_est est[PHY_CORE_MAX];
u32 cmplx_pwr[PHY_CORE_MAX];
@ -2924,29 +2905,29 @@ void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode)
mod_phy_reg(pi, 0x44c, (0x1 << 2), (1) << 2);
}
ai_corereg(pi->sh->sih, SI_CC_IDX,
offsetof(struct chipcregs, gpiocontrol),
~0x0, 0x0);
ai_corereg(pi->sh->sih, SI_CC_IDX,
offsetof(struct chipcregs, gpioout), 0x40,
0x40);
ai_corereg(pi->sh->sih, SI_CC_IDX,
offsetof(struct chipcregs, gpioouten), 0x40,
0x40);
ai_cc_reg(pi->sh->sih,
offsetof(struct chipcregs, gpiocontrol),
~0x0, 0x0);
ai_cc_reg(pi->sh->sih,
offsetof(struct chipcregs, gpioout),
0x40, 0x40);
ai_cc_reg(pi->sh->sih,
offsetof(struct chipcregs, gpioouten),
0x40, 0x40);
} else {
mod_phy_reg(pi, 0x44c, (0x1 << 2), (0) << 2);
mod_phy_reg(pi, 0x44d, (0x1 << 2), (0) << 2);
ai_corereg(pi->sh->sih, SI_CC_IDX,
offsetof(struct chipcregs, gpioout), 0x40,
0x00);
ai_corereg(pi->sh->sih, SI_CC_IDX,
offsetof(struct chipcregs, gpioouten), 0x40,
0x0);
ai_corereg(pi->sh->sih, SI_CC_IDX,
offsetof(struct chipcregs, gpiocontrol),
~0x0, 0x40);
ai_cc_reg(pi->sh->sih,
offsetof(struct chipcregs, gpioout),
0x40, 0x00);
ai_cc_reg(pi->sh->sih,
offsetof(struct chipcregs, gpioouten),
0x40, 0x0);
ai_cc_reg(pi->sh->sih,
offsetof(struct chipcregs, gpiocontrol),
~0x0, 0x40);
}
}
}

View File

@ -166,7 +166,6 @@ struct shared_phy_params {
struct phy_shim_info *physhim;
uint unit;
uint corerev;
uint buscorerev;
u16 vid;
u16 did;
uint chip;
@ -175,7 +174,6 @@ struct shared_phy_params {
uint sromrev;
uint boardtype;
uint boardrev;
uint boardvendor;
u32 boardflags;
u32 boardflags2;
};
@ -183,7 +181,7 @@ struct shared_phy_params {
extern struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp);
extern struct brcms_phy_pub *wlc_phy_attach(struct shared_phy *sh,
struct d11regs __iomem *regs,
struct bcma_device *d11core,
int bandtype, struct wiphy *wiphy);
extern void wlc_phy_detach(struct brcms_phy_pub *ppi);

View File

@ -503,10 +503,8 @@ struct shared_phy {
uint sromrev;
uint boardtype;
uint boardrev;
uint boardvendor;
u32 boardflags;
u32 boardflags2;
uint buscorerev;
uint fast_timer;
uint slow_timer;
uint glacial_timer;
@ -559,7 +557,7 @@ struct brcms_phy {
} u;
bool user_txpwr_at_rfport;
struct d11regs __iomem *regs;
struct bcma_device *d11core;
struct brcms_phy *next;
struct brcms_phy_pub pubpi;
@ -1090,7 +1088,7 @@ extern void wlc_phy_table_write_nphy(struct brcms_phy *pi, u32, u32, u32,
#define BRCMS_PHY_WAR_PR51571(pi) \
if (NREV_LT((pi)->pubpi.phy_rev, 3)) \
(void)R_REG(&(pi)->regs->maccontrol)
(void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol))
extern void wlc_phy_cal_perical_nphy_run(struct brcms_phy *pi, u8 caltype);
extern void wlc_phy_aci_reset_nphy(struct brcms_phy *pi);

View File

@ -2813,10 +2813,8 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10;
u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4;
idleTssi = read_phy_reg(pi, 0x4ab);
suspend =
(0 ==
(R_REG(&((struct brcms_phy *) pi)->regs->maccontrol) &
MCTL_EN_MAC));
suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
@ -2890,7 +2888,8 @@ static void wlc_lcnphy_vbat_temp_sense_setup(struct brcms_phy *pi, u8 mode)
for (i = 0; i < 14; i++)
values_to_save[i] = read_phy_reg(pi, tempsense_phy_regs[i]);
suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
save_txpwrCtrlEn = read_radio_reg(pi, 0x4a4);
@ -3016,8 +3015,8 @@ static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi)
bool suspend;
struct brcms_phy *pi = (struct brcms_phy *) ppi;
suspend =
(0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
@ -3535,15 +3534,17 @@ wlc_lcnphy_samp_cap(struct brcms_phy *pi, int clip_detect_algo, u16 thresh,
timer = 0;
old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
curval1 = R_REG(&pi->regs->psm_corectlsts);
curval1 = bcma_read16(pi->d11core, D11REGOFFS(psm_corectlsts));
ptr[130] = 0;
W_REG(&pi->regs->psm_corectlsts, ((1 << 6) | curval1));
bcma_write16(pi->d11core, D11REGOFFS(psm_corectlsts),
((1 << 6) | curval1));
W_REG(&pi->regs->smpl_clct_strptr, 0x7E00);
W_REG(&pi->regs->smpl_clct_stpptr, 0x8000);
bcma_write16(pi->d11core, D11REGOFFS(smpl_clct_strptr), 0x7E00);
bcma_write16(pi->d11core, D11REGOFFS(smpl_clct_stpptr), 0x8000);
udelay(20);
curval2 = R_REG(&pi->regs->psm_phy_hdr_param);
W_REG(&pi->regs->psm_phy_hdr_param, curval2 | 0x30);
curval2 = bcma_read16(pi->d11core, D11REGOFFS(psm_phy_hdr_param));
bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param),
curval2 | 0x30);
write_phy_reg(pi, 0x555, 0x0);
write_phy_reg(pi, 0x5a6, 0x5);
@ -3560,19 +3561,19 @@ wlc_lcnphy_samp_cap(struct brcms_phy *pi, int clip_detect_algo, u16 thresh,
sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
write_phy_reg(pi, 0x6da, (u32) (sslpnCalibClkEnCtrl | 0x2008));
stpptr = R_REG(&pi->regs->smpl_clct_stpptr);
curptr = R_REG(&pi->regs->smpl_clct_curptr);
stpptr = bcma_read16(pi->d11core, D11REGOFFS(smpl_clct_stpptr));
curptr = bcma_read16(pi->d11core, D11REGOFFS(smpl_clct_curptr));
do {
udelay(10);
curptr = R_REG(&pi->regs->smpl_clct_curptr);
curptr = bcma_read16(pi->d11core, D11REGOFFS(smpl_clct_curptr));
timer++;
} while ((curptr != stpptr) && (timer < 500));
W_REG(&pi->regs->psm_phy_hdr_param, 0x2);
bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param), 0x2);
strptr = 0x7E00;
W_REG(&pi->regs->tplatewrptr, strptr);
bcma_write32(pi->d11core, D11REGOFFS(tplatewrptr), strptr);
while (strptr < 0x8000) {
val = R_REG(&pi->regs->tplatewrdata);
val = bcma_read32(pi->d11core, D11REGOFFS(tplatewrdata));
imag = ((val >> 16) & 0x3ff);
real = ((val) & 0x3ff);
if (imag > 511)
@ -3597,8 +3598,8 @@ wlc_lcnphy_samp_cap(struct brcms_phy *pi, int clip_detect_algo, u16 thresh,
}
write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
W_REG(&pi->regs->psm_phy_hdr_param, curval2);
W_REG(&pi->regs->psm_corectlsts, curval1);
bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param), curval2);
bcma_write16(pi->d11core, D11REGOFFS(psm_corectlsts), curval1);
}
static void
@ -3968,9 +3969,9 @@ s16 wlc_lcnphy_tempsense_new(struct brcms_phy *pi, bool mode)
bool suspend = 0;
if (mode == 1) {
suspend =
(0 ==
(R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
suspend = (0 == (bcma_read32(pi->d11core,
D11REGOFFS(maccontrol)) &
MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
@ -4012,9 +4013,9 @@ u16 wlc_lcnphy_tempsense(struct brcms_phy *pi, bool mode)
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
if (mode == 1) {
suspend =
(0 ==
(R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
suspend = (0 == (bcma_read32(pi->d11core,
D11REGOFFS(maccontrol)) &
MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
@ -4078,9 +4079,9 @@ s8 wlc_lcnphy_vbatsense(struct brcms_phy *pi, bool mode)
bool suspend = 0;
if (mode == 1) {
suspend =
(0 ==
(R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
suspend = (0 == (bcma_read32(pi->d11core,
D11REGOFFS(maccontrol)) &
MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
wlc_lcnphy_vbat_temp_sense_setup(pi, VBATSENSE);
@ -4127,8 +4128,8 @@ static void wlc_lcnphy_glacial_timer_based_cal(struct brcms_phy *pi)
s8 index;
u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
suspend =
(0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
wlc_lcnphy_deaf_mode(pi, true);
@ -4166,8 +4167,8 @@ static void wlc_lcnphy_periodic_cal(struct brcms_phy *pi)
pi_lcn->lcnphy_full_cal_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
index = pi_lcn->lcnphy_current_index;
suspend =
(0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
MCTL_EN_MAC));
if (!suspend) {
wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000);
wlapi_suspend_mac_and_wait(pi->sh->physhim);

View File

@ -17802,7 +17802,7 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi)
if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
(void)R_REG(&pi->regs->maccontrol);
(void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
udelay(1);
}
@ -17953,7 +17953,7 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi)
if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
(void)R_REG(&pi->regs->maccontrol);
(void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
udelay(1);
}
@ -19447,8 +19447,6 @@ void wlc_phy_init_nphy(struct brcms_phy *pi)
u8 tx_pwr_ctrl_state;
bool do_nphy_cal = false;
uint core;
uint origidx, intr_val;
struct d11regs __iomem *regs;
u32 d11_clk_ctl_st;
bool do_rssi_cal = false;
@ -19462,25 +19460,21 @@ void wlc_phy_init_nphy(struct brcms_phy *pi)
(pi->sh->chippkg == BCM4718_PKG_ID))) {
if ((pi->sh->boardflags & BFL_EXTLNA) &&
(CHSPEC_IS2G(pi->radio_chanspec)))
ai_corereg(pi->sh->sih, SI_CC_IDX,
offsetof(struct chipcregs, chipcontrol),
0x40, 0x40);
ai_cc_reg(pi->sh->sih,
offsetof(struct chipcregs, chipcontrol),
0x40, 0x40);
}
if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) &&
CHSPEC_IS40(pi->radio_chanspec)) {
regs = (struct d11regs __iomem *)
ai_switch_core(pi->sh->sih,
D11_CORE_ID, &origidx,
&intr_val);
d11_clk_ctl_st = R_REG(&regs->clk_ctl_st);
AND_REG(&regs->clk_ctl_st,
~(CCS_FORCEHT | CCS_HTAREQ));
d11_clk_ctl_st = bcma_read32(pi->d11core,
D11REGOFFS(clk_ctl_st));
bcma_mask32(pi->d11core, D11REGOFFS(clk_ctl_st),
~(CCS_FORCEHT | CCS_HTAREQ));
W_REG(&regs->clk_ctl_st, d11_clk_ctl_st);
ai_restore_core(pi->sh->sih, origidx, intr_val);
bcma_write32(pi->d11core, D11REGOFFS(clk_ctl_st),
d11_clk_ctl_st);
}
pi->use_int_tx_iqlo_cal_nphy =
@ -19885,7 +19879,8 @@ void wlc_phy_rxcore_setstate_nphy(struct brcms_phy_pub *pih, u8 rxcore_bitmask)
if (!pi->sh->clk)
return;
suspend = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
MCTL_EN_MAC));
if (!suspend)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
@ -21263,28 +21258,28 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec,
val = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
if (CHSPEC_IS5G(chanspec) && !val) {
val = R_REG(&pi->regs->psm_phy_hdr_param);
W_REG(&pi->regs->psm_phy_hdr_param,
val = bcma_read16(pi->d11core, D11REGOFFS(psm_phy_hdr_param));
bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param),
(val | MAC_PHY_FORCE_CLK));
or_phy_reg(pi, (NPHY_TO_BPHY_OFF + BPHY_BB_CONFIG),
(BBCFG_RESETCCA | BBCFG_RESETRX));
W_REG(&pi->regs->psm_phy_hdr_param, val);
bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param), val);
or_phy_reg(pi, 0x09, NPHY_BandControl_currentBand);
} else if (!CHSPEC_IS5G(chanspec) && val) {
and_phy_reg(pi, 0x09, ~NPHY_BandControl_currentBand);
val = R_REG(&pi->regs->psm_phy_hdr_param);
W_REG(&pi->regs->psm_phy_hdr_param,
val = bcma_read16(pi->d11core, D11REGOFFS(psm_phy_hdr_param));
bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param),
(val | MAC_PHY_FORCE_CLK));
and_phy_reg(pi, (NPHY_TO_BPHY_OFF + BPHY_BB_CONFIG),
(u16) (~(BBCFG_RESETCCA | BBCFG_RESETRX)));
W_REG(&pi->regs->psm_phy_hdr_param, val);
bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param), val);
}
write_phy_reg(pi, 0x1ce, ci->PHY_BW1a);
@ -21342,24 +21337,23 @@ wlc_phy_chanspec_nphy_setup(struct brcms_phy *pi, u16 chanspec,
spuravoid = 1;
wlapi_bmac_core_phypll_ctl(pi->sh->physhim, false);
si_pmu_spuravoid(pi->sh->sih, spuravoid);
si_pmu_spuravoid_pllupdate(pi->sh->sih, spuravoid);
wlapi_bmac_core_phypll_ctl(pi->sh->physhim, true);
if ((pi->sh->chip == BCM43224_CHIP_ID) ||
(pi->sh->chip == BCM43225_CHIP_ID)) {
if (spuravoid == 1) {
W_REG(&pi->regs->tsf_clk_frac_l,
0x5341);
W_REG(&pi->regs->tsf_clk_frac_h,
0x8);
bcma_write16(pi->d11core,
D11REGOFFS(tsf_clk_frac_l),
0x5341);
bcma_write16(pi->d11core,
D11REGOFFS(tsf_clk_frac_h), 0x8);
} else {
W_REG(&pi->regs->tsf_clk_frac_l,
0x8889);
W_REG(&pi->regs->tsf_clk_frac_h,
0x8);
bcma_write16(pi->d11core,
D11REGOFFS(tsf_clk_frac_l),
0x8889);
bcma_write16(pi->d11core,
D11REGOFFS(tsf_clk_frac_h), 0x8);
}
}
@ -21499,13 +21493,13 @@ void wlc_phy_antsel_init(struct brcms_phy_pub *ppi, bool lut_init)
ai_gpiocontrol(pi->sh->sih, mask, mask, GPIO_DRV_PRIORITY);
mc = R_REG(&pi->regs->maccontrol);
mc = bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
mc &= ~MCTL_GPOUT_SEL_MASK;
W_REG(&pi->regs->maccontrol, mc);
bcma_write32(pi->d11core, D11REGOFFS(maccontrol), mc);
OR_REG(&pi->regs->psm_gpio_oe, mask);
bcma_set16(pi->d11core, D11REGOFFS(psm_gpio_oe), mask);
AND_REG(&pi->regs->psm_gpio_out, ~mask);
bcma_mask16(pi->d11core, D11REGOFFS(psm_gpio_out), ~mask);
if (lut_init) {
write_phy_reg(pi, 0xf8, 0x02d8);
@ -21522,9 +21516,8 @@ u16 wlc_phy_classifier_nphy(struct brcms_phy *pi, u16 mask, u16 val)
bool suspended = false;
if (D11REV_IS(pi->sh->corerev, 16)) {
suspended =
(R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) ?
false : true;
suspended = (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
MCTL_EN_MAC) ? false : true;
if (!suspended)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
}
@ -25383,7 +25376,8 @@ static void wlc_phy_a4(struct brcms_phy *pi, bool full_cal)
if (pi->nphy_papd_skip == 1)
return;
phy_b3 = (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
phy_b3 = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
MCTL_EN_MAC));
if (!phy_b3)
wlapi_suspend_mac_and_wait(pi->sh->physhim);
@ -28357,7 +28351,7 @@ void wlc_phy_txpower_recalc_target_nphy(struct brcms_phy *pi)
if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
(void)R_REG(&pi->regs->maccontrol);
(void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
udelay(1);
}

View File

@ -115,10 +115,10 @@ static void si_pmu_res_masks(struct si_pub *sih, u32 * pmin, u32 * pmax)
uint rsrcs;
/* # resources */
rsrcs = (sih->pmucaps & PCAP_RC_MASK) >> PCAP_RC_SHIFT;
rsrcs = (ai_get_pmucaps(sih) & PCAP_RC_MASK) >> PCAP_RC_SHIFT;
/* determine min/max rsrc masks */
switch (sih->chip) {
switch (ai_get_chip_id(sih)) {
case BCM43224_CHIP_ID:
case BCM43225_CHIP_ID:
/* ??? */
@ -139,75 +139,84 @@ static void si_pmu_res_masks(struct si_pub *sih, u32 * pmin, u32 * pmax)
*pmax = max_mask;
}
static void
si_pmu_spuravoid_pllupdate(struct si_pub *sih, struct chipcregs __iomem *cc,
u8 spuravoid)
void si_pmu_spuravoid_pllupdate(struct si_pub *sih, u8 spuravoid)
{
u32 tmp = 0;
struct bcma_device *core;
switch (sih->chip) {
/* switch to chipc */
core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
switch (ai_get_chip_id(sih)) {
case BCM43224_CHIP_ID:
case BCM43225_CHIP_ID:
if (spuravoid == 1) {
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
W_REG(&cc->pllcontrol_data, 0x11500010);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
W_REG(&cc->pllcontrol_data, 0x000C0C06);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
W_REG(&cc->pllcontrol_data, 0x0F600a08);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
W_REG(&cc->pllcontrol_data, 0x00000000);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
W_REG(&cc->pllcontrol_data, 0x2001E920);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
W_REG(&cc->pllcontrol_data, 0x88888815);
bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
PMU1_PLL0_PLLCTL0);
bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
0x11500010);
bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
PMU1_PLL0_PLLCTL1);
bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
0x000C0C06);
bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
PMU1_PLL0_PLLCTL2);
bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
0x0F600a08);
bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
PMU1_PLL0_PLLCTL3);
bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
0x00000000);
bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
PMU1_PLL0_PLLCTL4);
bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
0x2001E920);
bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
PMU1_PLL0_PLLCTL5);
bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
0x88888815);
} else {
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
W_REG(&cc->pllcontrol_data, 0x11100010);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
W_REG(&cc->pllcontrol_data, 0x000c0c06);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
W_REG(&cc->pllcontrol_data, 0x03000a08);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
W_REG(&cc->pllcontrol_data, 0x00000000);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
W_REG(&cc->pllcontrol_data, 0x200005c0);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
W_REG(&cc->pllcontrol_data, 0x88888815);
bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
PMU1_PLL0_PLLCTL0);
bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
0x11100010);
bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
PMU1_PLL0_PLLCTL1);
bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
0x000c0c06);
bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
PMU1_PLL0_PLLCTL2);
bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
0x03000a08);
bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
PMU1_PLL0_PLLCTL3);
bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
0x00000000);
bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
PMU1_PLL0_PLLCTL4);
bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
0x200005c0);
bcma_write32(core, CHIPCREGOFFS(pllcontrol_addr),
PMU1_PLL0_PLLCTL5);
bcma_write32(core, CHIPCREGOFFS(pllcontrol_data),
0x88888815);
}
tmp = 1 << 10;
break;
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
W_REG(&cc->pllcontrol_data, 0x11100008);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
W_REG(&cc->pllcontrol_data, 0x0c000c06);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
W_REG(&cc->pllcontrol_data, 0x03000a08);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
W_REG(&cc->pllcontrol_data, 0x00000000);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
W_REG(&cc->pllcontrol_data, 0x200005c0);
W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
W_REG(&cc->pllcontrol_data, 0x88888855);
tmp = 1 << 10;
break;
default:
/* bail out */
return;
}
tmp |= R_REG(&cc->pmucontrol);
W_REG(&cc->pmucontrol, tmp);
bcma_set32(core, CHIPCREGOFFS(pmucontrol), tmp);
}
u16 si_pmu_fast_pwrup_delay(struct si_pub *sih)
{
uint delay = PMU_MAX_TRANSITION_DLY;
switch (sih->chip) {
switch (ai_get_chip_id(sih)) {
case BCM43224_CHIP_ID:
case BCM43225_CHIP_ID:
case BCM4313_CHIP_ID:
@ -220,54 +229,35 @@ u16 si_pmu_fast_pwrup_delay(struct si_pub *sih)
return (u16) delay;
}
void si_pmu_sprom_enable(struct si_pub *sih, bool enable)
{
struct chipcregs __iomem *cc;
uint origidx;
/* Remember original core before switch to chipc */
origidx = ai_coreidx(sih);
cc = ai_setcoreidx(sih, SI_CC_IDX);
/* Return to original core */
ai_setcoreidx(sih, origidx);
}
/* Read/write a chipcontrol reg */
u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val)
{
ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, chipcontrol_addr),
~0, reg);
return ai_corereg(sih, SI_CC_IDX,
offsetof(struct chipcregs, chipcontrol_data), mask,
val);
ai_cc_reg(sih, offsetof(struct chipcregs, chipcontrol_addr), ~0, reg);
return ai_cc_reg(sih, offsetof(struct chipcregs, chipcontrol_data),
mask, val);
}
/* Read/write a regcontrol reg */
u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val)
{
ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, regcontrol_addr),
~0, reg);
return ai_corereg(sih, SI_CC_IDX,
offsetof(struct chipcregs, regcontrol_data), mask,
val);
ai_cc_reg(sih, offsetof(struct chipcregs, regcontrol_addr), ~0, reg);
return ai_cc_reg(sih, offsetof(struct chipcregs, regcontrol_data),
mask, val);
}
/* Read/write a pllcontrol reg */
u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val)
{
ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, pllcontrol_addr),
~0, reg);
return ai_corereg(sih, SI_CC_IDX,
offsetof(struct chipcregs, pllcontrol_data), mask,
val);
ai_cc_reg(sih, offsetof(struct chipcregs, pllcontrol_addr), ~0, reg);
return ai_cc_reg(sih, offsetof(struct chipcregs, pllcontrol_data),
mask, val);
}
/* PMU PLL update */
void si_pmu_pllupd(struct si_pub *sih)
{
ai_corereg(sih, SI_CC_IDX, offsetof(struct chipcregs, pmucontrol),
PCTL_PLL_PLLCTL_UPD, PCTL_PLL_PLLCTL_UPD);
ai_cc_reg(sih, offsetof(struct chipcregs, pmucontrol),
PCTL_PLL_PLLCTL_UPD, PCTL_PLL_PLLCTL_UPD);
}
/* query alp/xtal clock frequency */
@ -276,10 +266,10 @@ u32 si_pmu_alp_clock(struct si_pub *sih)
u32 clock = ALP_CLOCK;
/* bail out with default */
if (!(sih->cccaps & CC_CAP_PMU))
if (!(ai_get_cccaps(sih) & CC_CAP_PMU))
return clock;
switch (sih->chip) {
switch (ai_get_chip_id(sih)) {
case BCM43224_CHIP_ID:
case BCM43225_CHIP_ID:
case BCM4313_CHIP_ID:
@ -293,95 +283,29 @@ u32 si_pmu_alp_clock(struct si_pub *sih)
return clock;
}
void si_pmu_spuravoid(struct si_pub *sih, u8 spuravoid)
{
struct chipcregs __iomem *cc;
uint origidx, intr_val;
/* Remember original core before switch to chipc */
cc = (struct chipcregs __iomem *)
ai_switch_core(sih, CC_CORE_ID, &origidx, &intr_val);
/* update the pll changes */
si_pmu_spuravoid_pllupdate(sih, cc, spuravoid);
/* Return to original core */
ai_restore_core(sih, origidx, intr_val);
}
/* initialize PMU */
void si_pmu_init(struct si_pub *sih)
{
struct chipcregs __iomem *cc;
uint origidx;
struct bcma_device *core;
/* Remember original core before switch to chipc */
origidx = ai_coreidx(sih);
cc = ai_setcoreidx(sih, SI_CC_IDX);
/* select chipc */
core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
if (sih->pmurev == 1)
AND_REG(&cc->pmucontrol, ~PCTL_NOILP_ON_WAIT);
else if (sih->pmurev >= 2)
OR_REG(&cc->pmucontrol, PCTL_NOILP_ON_WAIT);
/* Return to original core */
ai_setcoreidx(sih, origidx);
}
/* initialize PMU chip controls and other chip level stuff */
void si_pmu_chip_init(struct si_pub *sih)
{
uint origidx;
/* Gate off SPROM clock and chip select signals */
si_pmu_sprom_enable(sih, false);
/* Remember original core */
origidx = ai_coreidx(sih);
/* Return to original core */
ai_setcoreidx(sih, origidx);
}
/* initialize PMU switch/regulators */
void si_pmu_swreg_init(struct si_pub *sih)
{
}
/* initialize PLL */
void si_pmu_pll_init(struct si_pub *sih, uint xtalfreq)
{
struct chipcregs __iomem *cc;
uint origidx;
/* Remember original core before switch to chipc */
origidx = ai_coreidx(sih);
cc = ai_setcoreidx(sih, SI_CC_IDX);
switch (sih->chip) {
case BCM4313_CHIP_ID:
case BCM43224_CHIP_ID:
case BCM43225_CHIP_ID:
/* ??? */
break;
default:
break;
}
/* Return to original core */
ai_setcoreidx(sih, origidx);
if (ai_get_pmurev(sih) == 1)
bcma_mask32(core, CHIPCREGOFFS(pmucontrol),
~PCTL_NOILP_ON_WAIT);
else if (ai_get_pmurev(sih) >= 2)
bcma_set32(core, CHIPCREGOFFS(pmucontrol), PCTL_NOILP_ON_WAIT);
}
/* initialize PMU resources */
void si_pmu_res_init(struct si_pub *sih)
{
struct chipcregs __iomem *cc;
uint origidx;
struct bcma_device *core;
u32 min_mask = 0, max_mask = 0;
/* Remember original core before switch to chipc */
origidx = ai_coreidx(sih);
cc = ai_setcoreidx(sih, SI_CC_IDX);
/* select to chipc */
core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
/* Determine min/max rsrc masks */
si_pmu_res_masks(sih, &min_mask, &max_mask);
@ -391,55 +315,50 @@ void si_pmu_res_init(struct si_pub *sih)
/* Program max resource mask */
if (max_mask)
W_REG(&cc->max_res_mask, max_mask);
bcma_write32(core, CHIPCREGOFFS(max_res_mask), max_mask);
/* Program min resource mask */
if (min_mask)
W_REG(&cc->min_res_mask, min_mask);
bcma_write32(core, CHIPCREGOFFS(min_res_mask), min_mask);
/* Add some delay; allow resources to come up and settle. */
mdelay(2);
/* Return to original core */
ai_setcoreidx(sih, origidx);
}
u32 si_pmu_measure_alpclk(struct si_pub *sih)
{
struct chipcregs __iomem *cc;
uint origidx;
struct bcma_device *core;
u32 alp_khz;
if (sih->pmurev < 10)
if (ai_get_pmurev(sih) < 10)
return 0;
/* Remember original core before switch to chipc */
origidx = ai_coreidx(sih);
cc = ai_setcoreidx(sih, SI_CC_IDX);
core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
if (R_REG(&cc->pmustatus) & PST_EXTLPOAVAIL) {
if (bcma_read32(core, CHIPCREGOFFS(pmustatus)) & PST_EXTLPOAVAIL) {
u32 ilp_ctr, alp_hz;
/*
* Enable the reg to measure the freq,
* in case it was disabled before
*/
W_REG(&cc->pmu_xtalfreq,
1U << PMU_XTALFREQ_REG_MEASURE_SHIFT);
bcma_write32(core, CHIPCREGOFFS(pmu_xtalfreq),
1U << PMU_XTALFREQ_REG_MEASURE_SHIFT);
/* Delay for well over 4 ILP clocks */
udelay(1000);
/* Read the latched number of ALP ticks per 4 ILP ticks */
ilp_ctr =
R_REG(&cc->pmu_xtalfreq) & PMU_XTALFREQ_REG_ILPCTR_MASK;
ilp_ctr = bcma_read32(core, CHIPCREGOFFS(pmu_xtalfreq)) &
PMU_XTALFREQ_REG_ILPCTR_MASK;
/*
* Turn off the PMU_XTALFREQ_REG_MEASURE_SHIFT
* bit to save power
*/
W_REG(&cc->pmu_xtalfreq, 0);
bcma_write32(core, CHIPCREGOFFS(pmu_xtalfreq), 0);
/* Calculate ALP frequency */
alp_hz = (ilp_ctr * EXT_ILP_HZ) / 4;
@ -452,8 +371,5 @@ u32 si_pmu_measure_alpclk(struct si_pub *sih)
} else
alp_khz = 0;
/* Return to original core */
ai_setcoreidx(sih, origidx);
return alp_khz;
}

View File

@ -26,13 +26,10 @@ extern u32 si_pmu_chipcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val);
extern u32 si_pmu_regcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val);
extern u32 si_pmu_alp_clock(struct si_pub *sih);
extern void si_pmu_pllupd(struct si_pub *sih);
extern void si_pmu_spuravoid(struct si_pub *sih, u8 spuravoid);
extern void si_pmu_spuravoid_pllupdate(struct si_pub *sih, u8 spuravoid);
extern u32 si_pmu_pllcontrol(struct si_pub *sih, uint reg, u32 mask, u32 val);
extern void si_pmu_init(struct si_pub *sih);
extern void si_pmu_chip_init(struct si_pub *sih);
extern void si_pmu_pll_init(struct si_pub *sih, u32 xtalfreq);
extern void si_pmu_res_init(struct si_pub *sih);
extern void si_pmu_swreg_init(struct si_pub *sih);
extern u32 si_pmu_measure_alpclk(struct si_pub *sih);
#endif /* _BRCM_PMU_H_ */

View File

@ -17,6 +17,7 @@
#ifndef _BRCM_PUB_H_
#define _BRCM_PUB_H_
#include <linux/bcma/bcma.h>
#include <brcmu_wifi.h>
#include "types.h"
#include "defs.h"
@ -530,9 +531,8 @@ struct brcms_antselcfg {
/* common functions for every port */
extern struct brcms_c_info *
brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit,
bool piomode, void __iomem *regsva, struct pci_dev *btparam,
uint *perr);
brcms_c_attach(struct brcms_info *wl, struct bcma_device *core, uint unit,
bool piomode, uint *perr);
extern uint brcms_c_detach(struct brcms_c_info *wlc);
extern int brcms_c_up(struct brcms_c_info *wlc);
extern uint brcms_c_down(struct brcms_c_info *wlc);

View File

@ -586,17 +586,6 @@ static const struct brcms_sromvar perpath_pci_sromvars[] = {
* shared between devices. */
static u8 brcms_srom_crc8_table[CRC8_TABLE_SIZE];
static u8 __iomem *
srom_window_address(struct si_pub *sih, u8 __iomem *curmap)
{
if (sih->ccrev < 32)
return curmap + PCI_BAR0_SPROM_OFFSET;
if (sih->cccaps & CC_CAP_SROM)
return curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP;
return NULL;
}
static uint mask_shift(u16 mask)
{
uint i;
@ -779,17 +768,27 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list)
* Return 0 on success, nonzero on error.
*/
static int
sprom_read_pci(struct si_pub *sih, u8 __iomem *sprom, uint wordoff,
u16 *buf, uint nwords, bool check_crc)
sprom_read_pci(struct si_pub *sih, u16 *buf, uint nwords, bool check_crc)
{
int err = 0;
uint i;
u8 *bbuf = (u8 *)buf; /* byte buffer */
uint nbytes = nwords << 1;
struct bcma_device *core;
uint sprom_offset;
/* determine core to read */
if (ai_get_ccrev(sih) < 32) {
core = ai_findcore(sih, BCMA_CORE_80211, 0);
sprom_offset = PCI_BAR0_SPROM_OFFSET;
} else {
core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0);
sprom_offset = CHIPCREGOFFS(sromotp);
}
/* read the sprom in bytes */
for (i = 0; i < nbytes; i++)
bbuf[i] = readb(sprom+i);
bbuf[i] = bcma_read8(core, sprom_offset+i);
if (buf[0] == 0xffff)
/*
@ -851,10 +850,9 @@ static int otp_read_pci(struct si_pub *sih, u16 *buf, uint nwords)
* Initialize nonvolatile variable table from sprom.
* Return 0 on success, nonzero on error.
*/
static int initvars_srom_pci(struct si_pub *sih, void __iomem *curmap)
int srom_var_init(struct si_pub *sih)
{
u16 *srom;
u8 __iomem *sromwindow;
u8 sromrev = 0;
u32 sr;
int err = 0;
@ -866,12 +864,9 @@ static int initvars_srom_pci(struct si_pub *sih, void __iomem *curmap)
if (!srom)
return -ENOMEM;
sromwindow = srom_window_address(sih, curmap);
crc8_populate_lsb(brcms_srom_crc8_table, SROM_CRC8_POLY);
if (ai_is_sprom_available(sih)) {
err = sprom_read_pci(sih, sromwindow, 0, srom,
SROM4_WORDS, true);
err = sprom_read_pci(sih, srom, SROM4_WORDS, true);
if (err == 0)
/* srom read and passed crc */
@ -921,21 +916,6 @@ void srom_free_vars(struct si_pub *sih)
kfree(entry);
}
}
/*
* Initialize local vars from the right source for this platform.
* Return 0 on success, nonzero on error.
*/
int srom_var_init(struct si_pub *sih, void __iomem *curmap)
{
uint len;
len = 0;
if (curmap != NULL)
return initvars_srom_pci(sih, curmap);
return -EINVAL;
}
/*
* Search the name=value vars for a specific one and return its value.

View File

@ -20,7 +20,7 @@
#include "types.h"
/* Prototypes */
extern int srom_var_init(struct si_pub *sih, void __iomem *curmap);
extern int srom_var_init(struct si_pub *sih);
extern void srom_free_vars(struct si_pub *sih);
extern int srom_read(struct si_pub *sih, uint bus, void *curmap,

View File

@ -250,66 +250,18 @@ do { \
wiphy_err(dev, "%s: " fmt, __func__, ##args); \
} while (0)
/*
* Register access macros.
*
* These macro's take a pointer to the address to read as one of their
* arguments. The macro itself deduces the size of the IO transaction (u8, u16
* or u32). Advantage of this approach in combination with using a struct to
* define the registers in a register block, is that access size and access
* location are defined in only one spot. This reduces the risk of the
* programmer trying to use an unsupported transaction size on a register.
*
*/
#define R_REG(r) \
({ \
__typeof(*(r)) __osl_v; \
switch (sizeof(*(r))) { \
case sizeof(u8): \
__osl_v = readb((u8 __iomem *)(r)); \
break; \
case sizeof(u16): \
__osl_v = readw((u16 __iomem *)(r)); \
break; \
case sizeof(u32): \
__osl_v = readl((u32 __iomem *)(r)); \
break; \
} \
__osl_v; \
})
#define W_REG(r, v) do { \
switch (sizeof(*(r))) { \
case sizeof(u8): \
writeb((u8)((v) & 0xFF), (u8 __iomem *)(r)); \
break; \
case sizeof(u16): \
writew((u16)((v) & 0xFFFF), (u16 __iomem *)(r)); \
break; \
case sizeof(u32): \
writel((u32)(v), (u32 __iomem *)(r)); \
break; \
} \
} while (0)
#ifdef CONFIG_BCM47XX
/*
* bcm4716 (which includes 4717 & 4718), plus 4706 on PCIe can reorder
* transactions. As a fix, a read after write is performed on certain places
* in the code. Older chips and the newer 5357 family don't require this fix.
*/
#define W_REG_FLUSH(r, v) ({ W_REG((r), (v)); (void)R_REG(r); })
#define bcma_wflush16(c, o, v) \
({ bcma_write16(c, o, v); (void)bcma_read16(c, o); })
#else
#define W_REG_FLUSH(r, v) W_REG((r), (v))
#define bcma_wflush16(c, o, v) bcma_write16(c, o, v)
#endif /* CONFIG_BCM47XX */
#define AND_REG(r, v) W_REG((r), R_REG(r) & (v))
#define OR_REG(r, v) W_REG((r), R_REG(r) | (v))
#define SET_REG(r, mask, val) \
W_REG((r), ((R_REG(r) & ~(mask)) | (val)))
/* multi-bool data type: set of bools, mbool is true if any is set */
/* set one bool */

View File

@ -19,6 +19,8 @@
#include "defs.h" /* for PAD macro */
#define CHIPCREGOFFS(field) offsetof(struct chipcregs, field)
struct chipcregs {
u32 chipid; /* 0x0 */
u32 capabilities;

View File

@ -102,12 +102,28 @@ config IWLWIFI_DEVICE_TRACING
occur.
endmenu
config IWLWIFI_DEVICE_SVTOOL
bool "iwlwifi device svtool support"
config IWLWIFI_DEVICE_TESTMODE
def_bool y
depends on IWLWIFI
select NL80211_TESTMODE
depends on NL80211_TESTMODE
help
This option enables the svtool support for iwlwifi device through
NL80211_TESTMODE. svtool is a software validation tool that runs in
the user space and interacts with the device in the kernel space
through the generic netlink message via NL80211_TESTMODE channel.
This option enables the testmode support for iwlwifi device through
NL80211_TESTMODE. This provide the capabilities of enable user space
validation applications to interacts with the device through the
generic netlink message via NL80211_TESTMODE channel.
config IWLWIFI_P2P
bool "iwlwifi experimental P2P support"
depends on IWLWIFI
help
This option enables experimental P2P support for some devices
based on microcode support. Since P2P support is still under
development, this option may even enable it for some devices
now that turn out to not support it in the future due to
microcode restrictions.
To determine if your microcode supports the experimental P2P
offered by this option, check if the driver advertises AP
support when it is loaded.
Say Y only if you want to experiment with P2P.

View File

@ -18,7 +18,7 @@ iwlwifi-objs += iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o
iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
iwlwifi-$(CONFIG_IWLWIFI_DEVICE_SVTOOL) += iwl-testmode.o
iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += iwl-testmode.o
CFLAGS_iwl-devtrace.o := -I$(src)

View File

@ -134,10 +134,10 @@ static struct iwl_sensitivity_ranges iwl5150_sensitivity = {
#define IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF (-5)
static s32 iwl_temp_calib_to_offset(struct iwl_priv *priv)
static s32 iwl_temp_calib_to_offset(struct iwl_shared *shrd)
{
u16 temperature, voltage;
__le16 *temp_calib = (__le16 *)iwl_eeprom_query_addr(priv,
__le16 *temp_calib = (__le16 *)iwl_eeprom_query_addr(shrd,
EEPROM_KELVIN_TEMPERATURE);
temperature = le16_to_cpu(temp_calib[0]);
@ -151,7 +151,7 @@ static void iwl5150_set_ct_threshold(struct iwl_priv *priv)
{
const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF;
s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY) -
iwl_temp_calib_to_offset(priv);
iwl_temp_calib_to_offset(priv->shrd);
hw_params(priv).ct_kill_threshold = threshold * volt2temp_coef;
}
@ -223,7 +223,7 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
static void iwl5150_temperature(struct iwl_priv *priv)
{
u32 vt = 0;
s32 offset = iwl_temp_calib_to_offset(priv);
s32 offset = iwl_temp_calib_to_offset(priv->shrd);
vt = le32_to_cpu(priv->statistics.common.temperature);
vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset;

View File

@ -81,7 +81,7 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
static void iwl6050_additional_nic_config(struct iwl_priv *priv)
{
/* Indicate calibration version to uCode. */
if (iwlagn_eeprom_calib_version(priv) >= 6)
if (iwl_eeprom_calib_version(priv->shrd) >= 6)
iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG,
CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
}
@ -89,7 +89,7 @@ static void iwl6050_additional_nic_config(struct iwl_priv *priv)
static void iwl6150_additional_nic_config(struct iwl_priv *priv)
{
/* Indicate calibration version to uCode. */
if (iwlagn_eeprom_calib_version(priv) >= 6)
if (iwl_eeprom_calib_version(priv->shrd) >= 6)
iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG,
CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
iwl_set_bit(bus(priv), CSR_GP_DRIVER_REG,

View File

@ -82,7 +82,7 @@ struct statistics_general_data {
u32 beacon_energy_c;
};
int iwl_send_calib_results(struct iwl_priv *priv)
int iwl_send_calib_results(struct iwl_trans *trans)
{
struct iwl_host_cmd hcmd = {
.id = REPLY_PHY_CALIBRATION_CMD,
@ -90,15 +90,15 @@ int iwl_send_calib_results(struct iwl_priv *priv)
};
struct iwl_calib_result *res;
list_for_each_entry(res, &priv->calib_results, list) {
list_for_each_entry(res, &trans->calib_results, list) {
int ret;
hcmd.len[0] = res->cmd_len;
hcmd.data[0] = &res->hdr;
hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
ret = iwl_trans_send_cmd(trans(priv), &hcmd);
ret = iwl_trans_send_cmd(trans, &hcmd);
if (ret) {
IWL_ERR(priv, "Error %d on calib cmd %d\n",
IWL_ERR(trans, "Error %d on calib cmd %d\n",
ret, res->hdr.op_code);
return ret;
}
@ -107,7 +107,7 @@ int iwl_send_calib_results(struct iwl_priv *priv)
return 0;
}
int iwl_calib_set(struct iwl_priv *priv,
int iwl_calib_set(struct iwl_trans *trans,
const struct iwl_calib_hdr *cmd, int len)
{
struct iwl_calib_result *res, *tmp;
@ -119,7 +119,7 @@ int iwl_calib_set(struct iwl_priv *priv,
memcpy(&res->hdr, cmd, len);
res->cmd_len = len;
list_for_each_entry(tmp, &priv->calib_results, list) {
list_for_each_entry(tmp, &trans->calib_results, list) {
if (tmp->hdr.op_code == res->hdr.op_code) {
list_replace(&tmp->list, &res->list);
kfree(tmp);
@ -128,16 +128,16 @@ int iwl_calib_set(struct iwl_priv *priv,
}
/* wasn't in list already */
list_add_tail(&res->list, &priv->calib_results);
list_add_tail(&res->list, &trans->calib_results);
return 0;
}
void iwl_calib_free_results(struct iwl_priv *priv)
void iwl_calib_free_results(struct iwl_trans *trans)
{
struct iwl_calib_result *res, *tmp;
list_for_each_entry_safe(res, tmp, &priv->calib_results, list) {
list_for_each_entry_safe(res, tmp, &trans->calib_results, list) {
list_del(&res->list);
kfree(res);
}

View File

@ -72,9 +72,4 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv);
void iwl_init_sensitivity(struct iwl_priv *priv);
void iwl_reset_run_time_calib(struct iwl_priv *priv);
int iwl_send_calib_results(struct iwl_priv *priv);
int iwl_calib_set(struct iwl_priv *priv,
const struct iwl_calib_hdr *cmd, int len);
void iwl_calib_free_results(struct iwl_priv *priv);
#endif /* __iwl_calib_h__ */

View File

@ -92,11 +92,11 @@ void iwlagn_temperature(struct iwl_priv *priv)
iwl_tt_handler(priv);
}
u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv)
u16 iwl_eeprom_calib_version(struct iwl_shared *shrd)
{
struct iwl_eeprom_calib_hdr *hdr;
hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv,
hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(shrd,
EEPROM_CALIB_ALL);
return hdr->version;
@ -105,7 +105,7 @@ u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv)
/*
* EEPROM
*/
static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address)
static u32 eeprom_indirect_address(const struct iwl_shared *shrd, u32 address)
{
u16 offset = 0;
@ -114,31 +114,31 @@ static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address)
switch (address & INDIRECT_TYPE_MSK) {
case INDIRECT_HOST:
offset = iwl_eeprom_query16(priv, EEPROM_LINK_HOST);
offset = iwl_eeprom_query16(shrd, EEPROM_LINK_HOST);
break;
case INDIRECT_GENERAL:
offset = iwl_eeprom_query16(priv, EEPROM_LINK_GENERAL);
offset = iwl_eeprom_query16(shrd, EEPROM_LINK_GENERAL);
break;
case INDIRECT_REGULATORY:
offset = iwl_eeprom_query16(priv, EEPROM_LINK_REGULATORY);
offset = iwl_eeprom_query16(shrd, EEPROM_LINK_REGULATORY);
break;
case INDIRECT_TXP_LIMIT:
offset = iwl_eeprom_query16(priv, EEPROM_LINK_TXP_LIMIT);
offset = iwl_eeprom_query16(shrd, EEPROM_LINK_TXP_LIMIT);
break;
case INDIRECT_TXP_LIMIT_SIZE:
offset = iwl_eeprom_query16(priv, EEPROM_LINK_TXP_LIMIT_SIZE);
offset = iwl_eeprom_query16(shrd, EEPROM_LINK_TXP_LIMIT_SIZE);
break;
case INDIRECT_CALIBRATION:
offset = iwl_eeprom_query16(priv, EEPROM_LINK_CALIBRATION);
offset = iwl_eeprom_query16(shrd, EEPROM_LINK_CALIBRATION);
break;
case INDIRECT_PROCESS_ADJST:
offset = iwl_eeprom_query16(priv, EEPROM_LINK_PROCESS_ADJST);
offset = iwl_eeprom_query16(shrd, EEPROM_LINK_PROCESS_ADJST);
break;
case INDIRECT_OTHERS:
offset = iwl_eeprom_query16(priv, EEPROM_LINK_OTHERS);
offset = iwl_eeprom_query16(shrd, EEPROM_LINK_OTHERS);
break;
default:
IWL_ERR(priv, "illegal indirect type: 0x%X\n",
IWL_ERR(shrd->trans, "illegal indirect type: 0x%X\n",
address & INDIRECT_TYPE_MSK);
break;
}
@ -147,11 +147,11 @@ static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address)
return (address & ADDRESS_MSK) + (offset << 1);
}
const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
const u8 *iwl_eeprom_query_addr(const struct iwl_shared *shrd, size_t offset)
{
u32 address = eeprom_indirect_address(priv, offset);
BUG_ON(address >= priv->cfg->base_params->eeprom_size);
return &priv->eeprom[address];
u32 address = eeprom_indirect_address(shrd, offset);
BUG_ON(address >= shrd->priv->cfg->base_params->eeprom_size);
return &shrd->eeprom[address];
}
struct iwl_mod_params iwlagn_mod_params = {
@ -1157,7 +1157,7 @@ int iwlagn_suspend(struct iwl_priv *priv,
* For QoS counters, we store the one to use next, so subtract 0x10
* since the uCode will add 0x10 before using the value.
*/
for (i = 0; i < 8; i++) {
for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
seq = priv->shrd->tid_data[IWL_AP_ID][i].seq_number;
seq -= 0x10;
wakeup_filter_cmd.qos_seq[i] = cpu_to_le16(seq);

View File

@ -298,7 +298,7 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data,
} else
return IWL_MAX_TID_COUNT;
if (unlikely(tid >= TID_MAX_LOAD_COUNT))
if (unlikely(tid >= IWL_MAX_TID_COUNT))
return IWL_MAX_TID_COUNT;
tl = &lq_data->load[tid];
@ -352,7 +352,7 @@ static void rs_program_fix_rate(struct iwl_priv *priv,
lq_sta->active_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */
lq_sta->active_mimo3_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */
#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
/* testmode has higher priority to overwirte the fixed rate */
if (priv->tm_fixed_rate)
lq_sta->dbg_fixed_rate = priv->tm_fixed_rate;
@ -379,7 +379,7 @@ static u32 rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid)
s32 index;
struct iwl_traffic_load *tl = NULL;
if (tid >= TID_MAX_LOAD_COUNT)
if (tid >= IWL_MAX_TID_COUNT)
return 0;
tl = &(lq_data->load[tid]);
@ -444,11 +444,11 @@ static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid,
struct iwl_lq_sta *lq_data,
struct ieee80211_sta *sta)
{
if (tid < TID_MAX_LOAD_COUNT)
if (tid < IWL_MAX_TID_COUNT)
rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta);
else
IWL_ERR(priv, "tid exceeds max load count: %d/%d\n",
tid, TID_MAX_LOAD_COUNT);
IWL_ERR(priv, "tid exceeds max TID count: %d/%d\n",
tid, IWL_MAX_TID_COUNT);
}
static inline int get_num_of_ant_from_rate(u32 rate_n_flags)
@ -1081,7 +1081,7 @@ done:
if (sta && sta->supp_rates[sband->band])
rs_rate_scale_perform(priv, skb, sta, lq_sta);
#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_IWLWIFI_DEVICE_SVTOOL)
#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_IWLWIFI_DEVICE_TESTMODE)
if ((priv->tm_fixed_rate) &&
(priv->tm_fixed_rate != lq_sta->dbg_fixed_rate))
rs_program_fix_rate(priv, lq_sta);
@ -2904,7 +2904,7 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
if (sband->band == IEEE80211_BAND_5GHZ)
lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
lq_sta->is_agg = 0;
#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
priv->tm_fixed_rate = 0;
#endif
#ifdef CONFIG_MAC80211_DEBUGFS

View File

@ -281,7 +281,6 @@ enum {
#define TID_QUEUE_CELL_SPACING 50 /*mS */
#define TID_QUEUE_MAX_SIZE 20
#define TID_ROUND_VALUE 5 /* mS */
#define TID_MAX_LOAD_COUNT 8
#define TID_MAX_TIME_DIFF ((TID_QUEUE_MAX_SIZE - 1) * TID_QUEUE_CELL_SPACING)
#define TIME_WRAP_AROUND(x, y) (((y) > (x)) ? (y) - (x) : (0-(x)) + (y))
@ -402,7 +401,7 @@ struct iwl_lq_sta {
struct iwl_link_quality_cmd lq;
struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */
struct iwl_traffic_load load[TID_MAX_LOAD_COUNT];
struct iwl_traffic_load load[IWL_MAX_TID_COUNT];
u8 tx_agg_tid_en;
#ifdef CONFIG_MAC80211_DEBUGFS
struct dentry *rs_sta_dbgfs_scale_table_file;

View File

@ -1165,7 +1165,7 @@ int iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
pkt->hdr.cmd);
w->triggered = true;
if (w->fn)
w->fn(priv, pkt, w->fn_data);
w->fn(trans(priv), pkt, w->fn_data);
}
spin_unlock(&priv->shrd->notif_wait_lock);

View File

@ -610,8 +610,8 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
if (ctx->ht.enabled) {
/* if HT40 is used, it should not change
* after associated except channel switch */
if (iwl_is_associated_ctx(ctx) &&
!ctx->ht.is_40mhz)
if (!ctx->ht.is_40mhz ||
!iwl_is_associated_ctx(ctx))
iwlagn_config_ht40(conf, ctx);
} else
ctx->ht.is_40mhz = false;

View File

@ -135,8 +135,8 @@ static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
u16 size = (u16)sizeof(struct iwl_addsta_cmd);
struct iwl_addsta_cmd *addsta = (struct iwl_addsta_cmd *)data;
memcpy(addsta, cmd, size);
/* resrved in 5000 */
addsta->rate_n_flags = cpu_to_le16(0);
/* resrved in agn */
addsta->legacy_reserved = cpu_to_le16(0);
return size;
}

View File

@ -91,7 +91,10 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
tx_cmd->tid_tspec = qc[0] & 0xf;
tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
} else {
tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
else
tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
}
iwlagn_tx_cmd_protection(priv, info, fc, &tx_flags);
@ -148,7 +151,7 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
if (ieee80211_is_data(fc)) {
tx_cmd->initial_rate_index = 0;
tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK;
#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
if (priv->tm_fixed_rate) {
/*
* rate overwrite by testmode
@ -161,7 +164,8 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
}
#endif
return;
}
} else if (ieee80211_is_back_req(fc))
tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK;
/**
* If the current TX rate stored in mac80211 has the MCS bit set, it's

View File

@ -366,7 +366,7 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv)
u32 num_wraps; /* # times uCode wrapped to top of log */
u32 next_entry; /* index of next entry to be written by uCode */
base = priv->device_pointers.error_event_table;
base = priv->shrd->device_pointers.error_event_table;
if (iwlagn_hw_valid_rtc_data_addr(base)) {
capacity = iwl_read_targ_mem(bus(priv), base);
num_wraps = iwl_read_targ_mem(bus(priv),
@ -1036,6 +1036,9 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
priv->inst_evtlog_size =
priv->cfg->base_params->max_event_log_size;
priv->inst_errlog_ptr = pieces.inst_errlog_ptr;
#ifndef CONFIG_IWLWIFI_P2P
ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
#endif
priv->new_scan_threshold_behaviour =
!!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN);
@ -1057,7 +1060,6 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
priv->sta_key_max_num = STA_KEY_MAX_NUM;
priv->shrd->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
}
/*
* figure out the offset of chain noise reset and gain commands
* base on the size of standard phy calibration commands table size
@ -1575,7 +1577,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
mutex_init(&priv->shrd->mutex);
INIT_LIST_HEAD(&priv->calib_results);
INIT_LIST_HEAD(&trans(priv)->calib_results);
priv->ieee_channels = NULL;
priv->ieee_rates = NULL;
@ -1633,7 +1635,6 @@ err:
static void iwl_uninit_drv(struct iwl_priv *priv)
{
iwl_calib_free_results(priv);
iwl_free_geos(priv);
iwl_free_channel_map(priv);
if (priv->tx_cmd_pool)
@ -1703,8 +1704,14 @@ static void iwl_debug_config(struct iwl_priv *priv)
"disabled\n");
#endif
dev_printk(KERN_INFO, bus(priv)->dev, "CONFIG_IWLWIFI_DEVICE_SVTOOL "
#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
dev_printk(KERN_INFO, bus(priv)->dev, "CONFIG_IWLWIFI_DEVICE_TESTMODE "
#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
"enabled\n");
#else
"disabled\n");
#endif
dev_printk(KERN_INFO, bus(priv)->dev, "CONFIG_IWLWIFI_P2P "
#ifdef CONFIG_IWLWIFI_P2P
"enabled\n");
#else
"disabled\n");
@ -1814,11 +1821,11 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
goto out_free_eeprom;
/* extract MAC Address */
iwl_eeprom_get_mac(priv, priv->addresses[0].addr);
iwl_eeprom_get_mac(priv->shrd, priv->addresses[0].addr);
IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->addresses[0].addr);
priv->hw->wiphy->addresses = priv->addresses;
priv->hw->wiphy->n_addresses = 1;
num_mac = iwl_eeprom_query16(priv, EEPROM_NUM_MAC_ADDRESS);
num_mac = iwl_eeprom_query16(priv->shrd, EEPROM_NUM_MAC_ADDRESS);
if (num_mac > 1) {
memcpy(priv->addresses[1].addr, priv->addresses[0].addr,
ETH_ALEN);
@ -1883,7 +1890,7 @@ out_destroy_workqueue:
priv->shrd->workqueue = NULL;
iwl_uninit_drv(priv);
out_free_eeprom:
iwl_eeprom_free(priv);
iwl_eeprom_free(priv->shrd);
out_free_trans:
iwl_trans_free(trans(priv));
out_free_traffic_mem:
@ -1922,7 +1929,7 @@ void __devexit iwl_remove(struct iwl_priv * priv)
iwl_dealloc_ucode(trans(priv));
iwl_eeprom_free(priv);
iwl_eeprom_free(priv->shrd);
/*netif_stop_queue(dev); */
flush_workqueue(priv->shrd->workqueue);

View File

@ -117,7 +117,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
/* lib */
int iwlagn_send_tx_power(struct iwl_priv *priv);
void iwlagn_temperature(struct iwl_priv *priv);
u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv);
u16 iwl_eeprom_calib_version(struct iwl_shared *shrd);
int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
int iwlagn_send_beacon_cmd(struct iwl_priv *priv);
@ -354,12 +354,12 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags)
/* eeprom */
void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv);
void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac);
void iwl_eeprom_get_mac(const struct iwl_shared *shrd, u8 *mac);
extern int iwlagn_init_alive_start(struct iwl_priv *priv);
extern int iwl_alive_start(struct iwl_priv *priv);
/* svtool */
#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
extern int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data,
int len);
extern int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw,

View File

@ -109,10 +109,10 @@ enum {
/* RX, TX, LEDs */
REPLY_TX = 0x1c,
REPLY_LEDS_CMD = 0x48,
REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* for 4965 and up */
REPLY_TX_LINK_QUALITY_CMD = 0x4e,
/* WiMAX coexistence */
COEX_PRIORITY_TABLE_CMD = 0x5a, /* for 5000 series and up */
COEX_PRIORITY_TABLE_CMD = 0x5a,
COEX_MEDIUM_NOTIFICATION = 0x5b,
COEX_EVENT_CMD = 0x5c,
@ -466,23 +466,27 @@ struct iwl_error_event_table {
u32 frame_ptr; /* frame pointer */
u32 stack_ptr; /* stack pointer */
u32 hcmd; /* last host command header */
#if 0
/* no need to read the remainder, we don't use the values */
u32 isr0; /* isr status register LMPM_NIC_ISR0: rxtx_flag */
u32 isr1; /* isr status register LMPM_NIC_ISR1: host_flag */
u32 isr2; /* isr status register LMPM_NIC_ISR2: enc_flag */
u32 isr3; /* isr status register LMPM_NIC_ISR3: time_flag */
u32 isr4; /* isr status register LMPM_NIC_ISR4: wico interrupt */
u32 isr0; /* isr status register LMPM_NIC_ISR0:
* rxtx_flag */
u32 isr1; /* isr status register LMPM_NIC_ISR1:
* host_flag */
u32 isr2; /* isr status register LMPM_NIC_ISR2:
* enc_flag */
u32 isr3; /* isr status register LMPM_NIC_ISR3:
* time_flag */
u32 isr4; /* isr status register LMPM_NIC_ISR4:
* wico interrupt */
u32 isr_pref; /* isr status register LMPM_NIC_PREF_STAT */
u32 wait_event; /* wait event() caller address */
u32 l2p_control; /* L2pControlField */
u32 l2p_duration; /* L2pDurationField */
u32 l2p_mhvalid; /* L2pMhValidBits */
u32 l2p_addr_match; /* L2pAddrMatchStat */
u32 lmpm_pmg_sel; /* indicate which clocks are turned on (LMPM_PMG_SEL) */
u32 u_timestamp; /* indicate when the date and time of the compilation */
u32 lmpm_pmg_sel; /* indicate which clocks are turned on
* (LMPM_PMG_SEL) */
u32 u_timestamp; /* indicate when the date and time of the
* compilation */
u32 flow_handler; /* FH read/write pointers, RX credit */
#endif
} __packed;
struct iwl_alive_resp {
@ -810,7 +814,7 @@ struct iwl_qosparam_cmd {
#define IWLAGN_STATION_COUNT 16
#define IWL_INVALID_STATION 255
#define IWL_MAX_TID_COUNT 9
#define IWL_MAX_TID_COUNT 8
#define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2)
#define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8)
@ -931,8 +935,7 @@ struct iwl_addsta_cmd {
* corresponding to bit (e.g. bit 5 controls TID 5).
* Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */
__le16 tid_disable_tx;
__le16 rate_n_flags; /* 3945 only */
__le16 legacy_reserved;
/* TID for which to add block-ack support.
* Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
@ -1162,8 +1165,7 @@ struct iwl_rx_mpdu_res_start {
*
* uCode handles retrying Tx when an ACK is expected but not received.
* This includes trying lower data rates than the one requested in the Tx
* command, as set up by the REPLY_RATE_SCALE (for 3945) or
* REPLY_TX_LINK_QUALITY_CMD (agn).
* command, as set up by the REPLY_TX_LINK_QUALITY_CMD (agn).
*
* Driver sets up transmit power for various rates via REPLY_TX_PWR_TABLE_CMD.
* This command must be executed after every RXON command, before Tx can occur.
@ -1175,25 +1177,9 @@ struct iwl_rx_mpdu_res_start {
* 1: Use RTS/CTS protocol or CTS-to-self if spec allows it
* before this frame. if CTS-to-self required check
* RXON_FLG_SELF_CTS_EN status.
* unused in 3945/4965, used in 5000 series and after
*/
#define TX_CMD_FLG_PROT_REQUIRE_MSK cpu_to_le32(1 << 0)
/*
* 1: Use Request-To-Send protocol before this frame.
* Mutually exclusive vs. TX_CMD_FLG_CTS_MSK.
* used in 3945/4965, unused in 5000 series and after
*/
#define TX_CMD_FLG_RTS_MSK cpu_to_le32(1 << 1)
/*
* 1: Transmit Clear-To-Send to self before this frame.
* Driver should set this for AUTH/DEAUTH/ASSOC-REQ/REASSOC mgmnt frames.
* Mutually exclusive vs. TX_CMD_FLG_RTS_MSK.
* used in 3945/4965, unused in 5000 series and after
*/
#define TX_CMD_FLG_CTS_MSK cpu_to_le32(1 << 2)
/* 1: Expect ACK from receiving station
* 0: Don't expect ACK (MAC header's duration field s/b 0)
* Set this for unicast frames, but not broadcast/multicast. */
@ -1211,18 +1197,8 @@ struct iwl_rx_mpdu_res_start {
* Set when Txing a block-ack request frame. Also set TX_CMD_FLG_ACK_MSK. */
#define TX_CMD_FLG_IMM_BA_RSP_MASK cpu_to_le32(1 << 6)
/*
* 1: Frame requires full Tx-Op protection.
* Set this if either RTS or CTS Tx Flag gets set.
* used in 3945/4965, unused in 5000 series and after
*/
#define TX_CMD_FLG_FULL_TXOP_PROT_MSK cpu_to_le32(1 << 7)
/* Tx antenna selection field; used only for 3945, reserved (0) for agn devices.
* Set field to "0" to allow 3945 uCode to select antenna (normal usage). */
/* Tx antenna selection field; reserved (0) for agn devices. */
#define TX_CMD_FLG_ANT_SEL_MSK cpu_to_le32(0xf00)
#define TX_CMD_FLG_ANT_A_MSK cpu_to_le32(1 << 8)
#define TX_CMD_FLG_ANT_B_MSK cpu_to_le32(1 << 9)
/* 1: Ignore Bluetooth priority for this frame.
* 0: Delay Tx until Bluetooth device is done (normal usage). */
@ -1568,7 +1544,6 @@ struct iwl_compressed_ba_resp {
__le64 bitmap;
__le16 scd_flow;
__le16 scd_ssn;
/* following only for 5000 series and up */
u8 txed; /* number of frames sent */
u8 txed_2_done; /* number of frames acked */
} __packed;
@ -1670,7 +1645,7 @@ struct iwl_link_qual_agg_params {
/*
* REPLY_TX_LINK_QUALITY_CMD = 0x4e (command, has simple generic response)
*
* For agn devices only; 3945 uses REPLY_RATE_SCALE.
* For agn devices
*
* Each station in the agn device's internal station table has its own table
* of 16
@ -1919,7 +1894,7 @@ struct iwl_link_quality_cmd {
/*
* REPLY_BT_CONFIG = 0x9b (command, has simple generic response)
*
* 3945 and agn devices support hardware handshake with Bluetooth device on
* agn devices support hardware handshake with Bluetooth device on
* same platform. Bluetooth device alerts wireless device when it will Tx;
* wireless device can delay or kill its own Tx to accommodate.
*/
@ -2203,8 +2178,8 @@ struct iwl_spectrum_notification {
struct iwl_powertable_cmd {
__le16 flags;
u8 keep_alive_seconds; /* 3945 reserved */
u8 debug_flags; /* 3945 reserved */
u8 keep_alive_seconds;
u8 debug_flags;
__le32 rx_data_timeout;
__le32 tx_data_timeout;
__le32 sleep_interval[IWL_POWER_VEC_SIZE];
@ -2325,9 +2300,9 @@ struct iwl_scan_channel {
/**
* struct iwl_ssid_ie - directed scan network information element
*
* Up to 20 of these may appear in REPLY_SCAN_CMD (Note: Only 4 are in
* 3945 SCAN api), selected by "type" bit field in struct iwl_scan_channel;
* each channel may select different ssids from among the 20 (4) entries.
* Up to 20 of these may appear in REPLY_SCAN_CMD,
* selected by "type" bit field in struct iwl_scan_channel;
* each channel may select different ssids from among the 20 entries.
* SSID IEs get transmitted in reverse order of entry.
*/
struct iwl_ssid_ie {
@ -2336,7 +2311,6 @@ struct iwl_ssid_ie {
u8 ssid[32];
} __packed;
#define PROBE_OPTION_MAX_3945 4
#define PROBE_OPTION_MAX 20
#define TX_CMD_LIFE_TIME_INFINITE cpu_to_le32(0xFFFFFFFF)
#define IWL_GOOD_CRC_TH_DISABLED 0
@ -2417,8 +2391,6 @@ struct iwl_scan_cmd {
* channel */
__le32 suspend_time; /* pause scan this long (in "extended beacon
* format") when returning to service chnl:
* 3945; 31:24 # beacons, 19:0 additional usec,
* 4965; 31:22 # beacons, 21:0 additional usec.
*/
__le32 flags; /* RXON_FLG_* */
__le32 filter_flags; /* RXON_FILTER_* */
@ -2734,7 +2706,7 @@ struct statistics_div {
struct statistics_general_common {
__le32 temperature; /* radio temperature */
__le32 temperature_m; /* for 5000 and up, this is radio voltage */
__le32 temperature_m; /* radio voltage */
struct statistics_dbg dbg;
__le32 sleep_time;
__le32 slots_out;

View File

@ -416,7 +416,7 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file,
return -ENODATA;
}
ptr = priv->eeprom;
ptr = priv->shrd->eeprom;
if (!ptr) {
IWL_ERR(priv, "Invalid EEPROM/OTP memory\n");
return -ENOMEM;
@ -428,7 +428,7 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file,
IWL_ERR(priv, "Can not allocate Buffer\n");
return -ENOMEM;
}
eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
eeprom_ver = iwl_eeprom_query16(priv->shrd, EEPROM_VERSION);
pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s, "
"version: 0x%x\n",
(trans(priv)->nvm_device_type == NVM_DEVICE_TYPE_OTP)

View File

@ -60,11 +60,10 @@ struct iwl_tx_queue;
/* Default noise level to report when noise measurement is not available.
* This may be because we're:
* 1) Not associated (4965, no beacon statistics being sent to driver)
* 1) Not associated no beacon statistics being sent to driver)
* 2) Scanning (noise measurement does not apply to associated channel)
* 3) Receiving CCK (3945 delivers noise info only for OFDM frames)
* Use default noise value of -127 ... this is below the range of measurable
* Rx dBm for either 3945 or 4965, so it can indicate "unmeasurable" to user.
* Rx dBm for all agn devices, so it can indicate "unmeasurable" to user.
* Also, -127 works better than 0 when averaging frames with/without
* noise info (e.g. averaging might be done in app); measured dBm values are
* always negative ... using a negative value as the default keeps all
@ -441,15 +440,6 @@ enum iwlagn_chain_noise_state {
IWL_CHAIN_NOISE_DONE,
};
/* Opaque calibration results */
struct iwl_calib_result {
struct list_head list;
size_t cmd_len;
struct iwl_calib_hdr hdr;
/* data follows */
};
/* Sensitivity calib data */
struct iwl_sensitivity_data {
u32 auto_corr_ofdm;
@ -751,7 +741,7 @@ enum iwl_scan_type {
IWL_SCAN_ROC,
};
#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
struct iwl_testmode_trace {
u32 buff_size;
u32 total_size;
@ -831,9 +821,6 @@ struct iwl_priv {
s32 temperature; /* Celsius */
s32 last_temperature;
/* init calibration results */
struct list_head calib_results;
struct iwl_wipan_noa_data __rcu *noa_data;
/* Scan related variables */
@ -866,11 +853,6 @@ struct iwl_priv {
__le16 switch_channel;
struct {
u32 error_event_table;
u32 log_event_table;
} device_pointers;
u16 active_rate;
u8 start_calib;
@ -904,10 +886,6 @@ struct iwl_priv {
/* Indication if ieee80211_ops->open has been called */
u8 is_open;
/* eeprom -- this is in the card's little endian byte order */
u8 *eeprom;
struct iwl_eeprom_calib_info *calib_info;
enum nl80211_iftype iw_mode;
/* Last Rx'd beacon timestamp */
@ -1040,7 +1018,7 @@ struct iwl_priv {
struct led_classdev led;
unsigned long blink_on, blink_off;
bool led_registered;
#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
struct iwl_testmode_trace testmode_trace;
struct iwl_testmode_sram testmode_sram;
u32 tm_fixed_rate;

View File

@ -215,11 +215,11 @@ static int iwl_eeprom_verify_signature(struct iwl_trans *trans)
return ret;
}
u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)
u16 iwl_eeprom_query16(const struct iwl_shared *shrd, size_t offset)
{
if (!priv->eeprom)
if (!shrd->eeprom)
return 0;
return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8);
return (u16)shrd->eeprom[offset] | ((u16)shrd->eeprom[offset + 1] << 8);
}
int iwl_eeprom_check_version(struct iwl_priv *priv)
@ -227,8 +227,8 @@ int iwl_eeprom_check_version(struct iwl_priv *priv)
u16 eeprom_ver;
u16 calib_ver;
eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
calib_ver = iwlagn_eeprom_calib_version(priv);
eeprom_ver = iwl_eeprom_query16(priv->shrd, EEPROM_VERSION);
calib_ver = iwl_eeprom_calib_version(priv->shrd);
if (eeprom_ver < priv->cfg->eeprom_ver ||
calib_ver < priv->cfg->eeprom_calib_ver)
@ -249,11 +249,12 @@ err:
int iwl_eeprom_check_sku(struct iwl_priv *priv)
{
struct iwl_shared *shrd = priv->shrd;
u16 radio_cfg;
if (!priv->cfg->sku) {
/* not using sku overwrite */
priv->cfg->sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP);
priv->cfg->sku = iwl_eeprom_query16(shrd, EEPROM_SKU_CAP);
if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE &&
!priv->cfg->ht_params) {
IWL_ERR(priv, "Invalid 11n configuration\n");
@ -269,7 +270,7 @@ int iwl_eeprom_check_sku(struct iwl_priv *priv)
if (!priv->cfg->valid_tx_ant && !priv->cfg->valid_rx_ant) {
/* not using .cfg overwrite */
radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
radio_cfg = iwl_eeprom_query16(shrd, EEPROM_RADIO_CONFIG);
priv->cfg->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg);
priv->cfg->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg);
if (!priv->cfg->valid_tx_ant || !priv->cfg->valid_rx_ant) {
@ -289,9 +290,9 @@ int iwl_eeprom_check_sku(struct iwl_priv *priv)
return 0;
}
void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac)
void iwl_eeprom_get_mac(const struct iwl_shared *shrd, u8 *mac)
{
const u8 *addr = iwl_eeprom_query_addr(priv,
const u8 *addr = iwl_eeprom_query_addr(shrd,
EEPROM_MAC_ADDRESS);
memcpy(mac, addr, ETH_ALEN);
}
@ -582,6 +583,7 @@ iwl_eeprom_enh_txp_read_element(struct iwl_priv *priv,
void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv)
{
struct iwl_shared *shrd = priv->shrd;
struct iwl_eeprom_enhanced_txpwr *txp_array, *txp;
int idx, entries;
__le16 *txp_len;
@ -590,10 +592,10 @@ void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv)
BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8);
/* the length is in 16-bit words, but we want entries */
txp_len = (__le16 *) iwl_eeprom_query_addr(priv, EEPROM_TXP_SZ_OFFS);
txp_len = (__le16 *) iwl_eeprom_query_addr(shrd, EEPROM_TXP_SZ_OFFS);
entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN;
txp_array = (void *) iwl_eeprom_query_addr(priv, EEPROM_TXP_OFFS);
txp_array = (void *) iwl_eeprom_query_addr(shrd, EEPROM_TXP_OFFS);
for (idx = 0; idx < entries; idx++) {
txp = &txp_array[idx];
@ -646,12 +648,13 @@ void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv)
/**
* iwl_eeprom_init - read EEPROM contents
*
* Load the EEPROM contents from adapter into priv->eeprom
* Load the EEPROM contents from adapter into shrd->eeprom
*
* NOTE: This routine uses the non-debug IO access functions.
*/
int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
{
struct iwl_shared *shrd = priv->shrd;
__le16 *e;
u32 gp = iwl_read32(bus(priv), CSR_EEPROM_GP);
int sz;
@ -666,12 +669,12 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
/* allocate eeprom */
sz = priv->cfg->base_params->eeprom_size;
IWL_DEBUG_EEPROM(priv, "NVM size = %d\n", sz);
priv->eeprom = kzalloc(sz, GFP_KERNEL);
if (!priv->eeprom) {
shrd->eeprom = kzalloc(sz, GFP_KERNEL);
if (!shrd->eeprom) {
ret = -ENOMEM;
goto alloc_err;
}
e = (__le16 *)priv->eeprom;
e = (__le16 *)shrd->eeprom;
iwl_apm_init(priv);
@ -746,7 +749,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
IWL_DEBUG_EEPROM(priv, "NVM Type: %s, version: 0x%x\n",
(trans(priv)->nvm_device_type == NVM_DEVICE_TYPE_OTP)
? "OTP" : "EEPROM",
iwl_eeprom_query16(priv, EEPROM_VERSION));
iwl_eeprom_query16(shrd, EEPROM_VERSION));
ret = 0;
done:
@ -754,17 +757,17 @@ done:
err:
if (ret)
iwl_eeprom_free(priv);
iwl_eeprom_free(priv->shrd);
/* Reset chip to save power until we load uCode during "up". */
iwl_apm_stop(priv);
alloc_err:
return ret;
}
void iwl_eeprom_free(struct iwl_priv *priv)
void iwl_eeprom_free(struct iwl_shared *shrd)
{
kfree(priv->eeprom);
priv->eeprom = NULL;
kfree(shrd->eeprom);
shrd->eeprom = NULL;
}
static void iwl_init_band_reference(const struct iwl_priv *priv,
@ -772,49 +775,50 @@ static void iwl_init_band_reference(const struct iwl_priv *priv,
const struct iwl_eeprom_channel **eeprom_ch_info,
const u8 **eeprom_ch_index)
{
struct iwl_shared *shrd = priv->shrd;
u32 offset = priv->cfg->lib->
eeprom_ops.regulatory_bands[eep_band - 1];
switch (eep_band) {
case 1: /* 2.4GHz band */
*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_1);
*eeprom_ch_info = (struct iwl_eeprom_channel *)
iwl_eeprom_query_addr(priv, offset);
iwl_eeprom_query_addr(shrd, offset);
*eeprom_ch_index = iwl_eeprom_band_1;
break;
case 2: /* 4.9GHz band */
*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_2);
*eeprom_ch_info = (struct iwl_eeprom_channel *)
iwl_eeprom_query_addr(priv, offset);
iwl_eeprom_query_addr(shrd, offset);
*eeprom_ch_index = iwl_eeprom_band_2;
break;
case 3: /* 5.2GHz band */
*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_3);
*eeprom_ch_info = (struct iwl_eeprom_channel *)
iwl_eeprom_query_addr(priv, offset);
iwl_eeprom_query_addr(shrd, offset);
*eeprom_ch_index = iwl_eeprom_band_3;
break;
case 4: /* 5.5GHz band */
*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_4);
*eeprom_ch_info = (struct iwl_eeprom_channel *)
iwl_eeprom_query_addr(priv, offset);
iwl_eeprom_query_addr(shrd, offset);
*eeprom_ch_index = iwl_eeprom_band_4;
break;
case 5: /* 5.7GHz band */
*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_5);
*eeprom_ch_info = (struct iwl_eeprom_channel *)
iwl_eeprom_query_addr(priv, offset);
iwl_eeprom_query_addr(shrd, offset);
*eeprom_ch_index = iwl_eeprom_band_5;
break;
case 6: /* 2.4GHz ht40 channels */
*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6);
*eeprom_ch_info = (struct iwl_eeprom_channel *)
iwl_eeprom_query_addr(priv, offset);
iwl_eeprom_query_addr(shrd, offset);
*eeprom_ch_index = iwl_eeprom_band_6;
break;
case 7: /* 5 GHz ht40 channels */
*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7);
*eeprom_ch_info = (struct iwl_eeprom_channel *)
iwl_eeprom_query_addr(priv, offset);
iwl_eeprom_query_addr(shrd, offset);
*eeprom_ch_index = iwl_eeprom_band_7;
break;
default:
@ -1064,7 +1068,7 @@ void iwl_rf_config(struct iwl_priv *priv)
{
u16 radio_cfg;
radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
radio_cfg = iwl_eeprom_query16(priv->shrd, EEPROM_RADIO_CONFIG);
/* write radio config values to register */
if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) {

View File

@ -66,6 +66,7 @@
#include <net/mac80211.h>
struct iwl_priv;
struct iwl_shared;
/*
* EEPROM access time values:
@ -305,11 +306,11 @@ struct iwl_eeprom_ops {
int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev);
void iwl_eeprom_free(struct iwl_priv *priv);
void iwl_eeprom_free(struct iwl_shared *shrd);
int iwl_eeprom_check_version(struct iwl_priv *priv);
int iwl_eeprom_check_sku(struct iwl_priv *priv);
const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset);
u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset);
const u8 *iwl_eeprom_query_addr(const struct iwl_shared *shrd, size_t offset);
u16 iwl_eeprom_query16(const struct iwl_shared *shrd, size_t offset);
int iwl_init_channel_map(struct iwl_priv *priv);
void iwl_free_channel_map(struct iwl_priv *priv);
const struct iwl_channel_info *iwl_get_channel_info(

View File

@ -427,7 +427,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
iwl_write32(bus(priv), CSR_UCODE_DRV_GP1_CLR,
CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
base = priv->device_pointers.error_event_table;
base = priv->shrd->device_pointers.error_event_table;
if (iwlagn_hw_valid_rtc_data_addr(base)) {
spin_lock_irqsave(&bus(priv)->reg_lock, flags);
ret = iwl_grab_nic_access_silent(bus(priv));
@ -811,21 +811,9 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
/* Configure HT40 channels */
ctx->ht.enabled = conf_is_ht(conf);
if (ctx->ht.enabled) {
if (conf_is_ht40_minus(conf)) {
ctx->ht.extension_chan_offset =
IEEE80211_HT_PARAM_CHA_SEC_BELOW;
ctx->ht.is_40mhz = true;
} else if (conf_is_ht40_plus(conf)) {
ctx->ht.extension_chan_offset =
IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
ctx->ht.is_40mhz = true;
} else {
ctx->ht.extension_chan_offset =
IEEE80211_HT_PARAM_CHA_SEC_NONE;
ctx->ht.is_40mhz = false;
}
} else
if (ctx->ht.enabled)
iwlagn_config_ht40(conf, ctx);
else
ctx->ht.is_40mhz = false;
if ((le16_to_cpu(ctx->staging.channel) != ch))
@ -1060,6 +1048,9 @@ static int iwlagn_mac_tx_sync(struct ieee80211_hw *hw,
int ret;
u8 sta_id;
if (ctx->ctxid != IWL_RXON_CTX_PAN)
return 0;
IWL_DEBUG_MAC80211(priv, "enter\n");
mutex_lock(&priv->shrd->mutex);
@ -1109,6 +1100,9 @@ static void iwlagn_mac_finish_tx_sync(struct ieee80211_hw *hw,
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
struct iwl_rxon_context *ctx = vif_priv->ctx;
if (ctx->ctxid != IWL_RXON_CTX_PAN)
return;
IWL_DEBUG_MAC80211(priv, "enter\n");
mutex_lock(&priv->shrd->mutex);

View File

@ -97,6 +97,7 @@
struct iwl_cfg;
struct iwl_bus;
struct iwl_priv;
struct iwl_trans;
struct iwl_sensitivity_ranges;
struct iwl_trans_ops;
@ -294,7 +295,7 @@ enum iwl_ucode_type {
struct iwl_notification_wait {
struct list_head list;
void (*fn)(struct iwl_priv *priv, struct iwl_rx_packet *pkt,
void (*fn)(struct iwl_trans *trans, struct iwl_rx_packet *pkt,
void *data);
void *fn_data;
@ -323,6 +324,7 @@ struct iwl_notification_wait {
* @notif_waits: things waiting for notification
* @notif_wait_lock: lock protecting notification
* @notif_waitq: head of notification wait queue
* @device_pointers: pointers to ucode event tables
*/
struct iwl_shared {
#ifdef CONFIG_IWLWIFI_DEBUG
@ -351,6 +353,9 @@ struct iwl_shared {
wait_queue_head_t wait_command_queue;
/* eeprom -- this is in the card's little endian byte order */
u8 *eeprom;
/* ucode related variables */
enum iwl_ucode_type ucode_type;
@ -358,6 +363,12 @@ struct iwl_shared {
struct list_head notif_waits;
spinlock_t notif_wait_lock;
wait_queue_head_t notif_waitq;
struct {
u32 error_event_table;
u32 log_event_table;
} device_pointers;
};
/*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */
@ -507,7 +518,7 @@ void __acquires(wait_entry)
iwl_init_notification_wait(struct iwl_shared *shrd,
struct iwl_notification_wait *wait_entry,
u8 cmd,
void (*fn)(struct iwl_priv *priv,
void (*fn)(struct iwl_trans *trans,
struct iwl_rx_packet *pkt,
void *data),
void *fn_data);

View File

@ -77,6 +77,7 @@
#include "iwl-agn.h"
#include "iwl-testmode.h"
#include "iwl-trans.h"
#include "iwl-bus.h"
/* The TLVs used in the gnl message policy between the kernel module and
* user space application. iwl_testmode_gnl_msg_policy is to be carried
@ -110,6 +111,9 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = {
[IWL_TM_ATTR_SRAM_ADDR] = { .type = NLA_U32, },
[IWL_TM_ATTR_SRAM_SIZE] = { .type = NLA_U32, },
[IWL_TM_ATTR_SRAM_DUMP] = { .type = NLA_UNSPEC, },
[IWL_TM_ATTR_FW_VERSION] = { .type = NLA_U32, },
[IWL_TM_ATTR_DEVICE_ID] = { .type = NLA_U32, },
};
/*
@ -416,6 +420,8 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
struct sk_buff *skb;
unsigned char *rsp_data_ptr = NULL;
int status = 0, rsp_data_len = 0;
char buf[32], *ptr = NULL;
unsigned int num, devid;
switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
case IWL_TM_CMD_APP2DEV_GET_DEVICENAME:
@ -479,7 +485,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
break;
case IWL_TM_CMD_APP2DEV_GET_EEPROM:
if (priv->eeprom) {
if (priv->shrd->eeprom) {
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
priv->cfg->base_params->eeprom_size + 20);
if (!skb) {
@ -491,7 +497,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
IWL_TM_CMD_DEV2APP_EEPROM_RSP);
NLA_PUT(skb, IWL_TM_ATTR_EEPROM,
priv->cfg->base_params->eeprom_size,
priv->eeprom);
priv->shrd->eeprom);
status = cfg80211_testmode_reply(skb);
if (status < 0)
IWL_DEBUG_INFO(priv,
@ -510,6 +516,43 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
priv->tm_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]);
break;
case IWL_TM_CMD_APP2DEV_GET_FW_VERSION:
IWL_INFO(priv, "uCode version raw: 0x%x\n", priv->ucode_ver);
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20);
if (!skb) {
IWL_DEBUG_INFO(priv, "Error allocating memory\n");
return -ENOMEM;
}
NLA_PUT_U32(skb, IWL_TM_ATTR_FW_VERSION, priv->ucode_ver);
status = cfg80211_testmode_reply(skb);
if (status < 0)
IWL_DEBUG_INFO(priv,
"Error sending msg : %d\n", status);
break;
case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID:
bus_get_hw_id(bus(priv), buf, sizeof(buf));
ptr = buf;
strsep(&ptr, ":");
sscanf(strsep(&ptr, ":"), "%x", &num);
sscanf(strsep(&ptr, ":"), "%x", &devid);
IWL_INFO(priv, "Device ID = 0x%04x, SubDevice ID= 0x%04x\n",
num, devid);
devid |= (num << 16);
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20);
if (!skb) {
IWL_DEBUG_INFO(priv, "Error allocating memory\n");
return -ENOMEM;
}
NLA_PUT_U32(skb, IWL_TM_ATTR_DEVICE_ID, devid);
status = cfg80211_testmode_reply(skb);
if (status < 0)
IWL_DEBUG_INFO(priv,
"Error sending msg : %d\n", status);
break;
default:
IWL_DEBUG_INFO(priv, "Unknown testmode driver command ID\n");
return -ENOSYS;
@ -842,6 +885,8 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
case IWL_TM_CMD_APP2DEV_GET_EEPROM:
case IWL_TM_CMD_APP2DEV_FIXRATE_REQ:
case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW:
case IWL_TM_CMD_APP2DEV_GET_FW_VERSION:
case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID:
IWL_DEBUG_INFO(priv, "testmode cmd to driver\n");
result = iwl_testmode_driver(hw, tb);
break;

View File

@ -118,6 +118,8 @@
* commands from user applicaiton to read data in sram
*
* @IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: load Weak On Wireless LAN uCode image
* @IWL_TM_CMD_APP2DEV_GET_FW_VERSION: retrieve uCode version
* @IWL_TM_CMD_APP2DEV_GET_DEVICE_ID: retrieve ID information in device
*
*/
enum iwl_tm_cmd_t {
@ -143,7 +145,9 @@ enum iwl_tm_cmd_t {
IWL_TM_CMD_APP2DEV_READ_SRAM = 20,
IWL_TM_CMD_APP2DEV_DUMP_SRAM = 21,
IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW = 22,
IWL_TM_CMD_MAX = 23,
IWL_TM_CMD_APP2DEV_GET_FW_VERSION = 23,
IWL_TM_CMD_APP2DEV_GET_DEVICE_ID = 24,
IWL_TM_CMD_MAX = 25,
};
/*
@ -225,6 +229,14 @@ enum iwl_tm_cmd_t {
* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_DUMP_SRAM,
* IWL_TM_ATTR_SRAM_DUMP for the data in sram
*
* @IWL_TM_ATTR_FW_VERSION:
* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_GET_FW_VERSION,
* IWL_TM_ATTR_FW_VERSION for the uCode version
*
* @IWL_TM_ATTR_DEVICE_ID:
* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_GET_DEVICE_ID,
* IWL_TM_ATTR_DEVICE_ID for the device ID information
*
*/
enum iwl_tm_attr_t {
IWL_TM_ATTR_NOT_APPLICABLE = 0,
@ -245,7 +257,9 @@ enum iwl_tm_attr_t {
IWL_TM_ATTR_SRAM_ADDR = 15,
IWL_TM_ATTR_SRAM_SIZE = 16,
IWL_TM_ATTR_SRAM_DUMP = 17,
IWL_TM_ATTR_MAX = 18,
IWL_TM_ATTR_FW_VERSION = 18,
IWL_TM_ATTR_DEVICE_ID = 19,
IWL_TM_ATTR_MAX = 20,
};
/* uCode trace buffer */

View File

@ -594,7 +594,7 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans)
struct iwl_trans_pcie *trans_pcie =
IWL_TRANS_GET_PCIE_TRANS(trans);
base = priv->device_pointers.error_event_table;
base = trans->shrd->device_pointers.error_event_table;
if (trans->shrd->ucode_type == IWL_UCODE_INIT) {
if (!base)
base = priv->init_errlog_ptr;
@ -648,6 +648,21 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans)
IWL_ERR(trans, "0x%08X | hw version\n", table.hw_ver);
IWL_ERR(trans, "0x%08X | board version\n", table.brd_ver);
IWL_ERR(trans, "0x%08X | hcmd\n", table.hcmd);
IWL_ERR(trans, "0x%08X | isr0\n", table.isr0);
IWL_ERR(trans, "0x%08X | isr1\n", table.isr1);
IWL_ERR(trans, "0x%08X | isr2\n", table.isr2);
IWL_ERR(trans, "0x%08X | isr3\n", table.isr3);
IWL_ERR(trans, "0x%08X | isr4\n", table.isr4);
IWL_ERR(trans, "0x%08X | isr_pref\n", table.isr_pref);
IWL_ERR(trans, "0x%08X | wait_event\n", table.wait_event);
IWL_ERR(trans, "0x%08X | l2p_control\n", table.l2p_control);
IWL_ERR(trans, "0x%08X | l2p_duration\n", table.l2p_duration);
IWL_ERR(trans, "0x%08X | l2p_mhvalid\n", table.l2p_mhvalid);
IWL_ERR(trans, "0x%08X | l2p_addr_match\n", table.l2p_addr_match);
IWL_ERR(trans, "0x%08X | lmpm_pmg_sel\n", table.lmpm_pmg_sel);
IWL_ERR(trans, "0x%08X | timestamp\n", table.u_timestamp);
IWL_ERR(trans, "0x%08X | flow_handler\n", table.flow_handler);
}
/**
@ -709,7 +724,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
if (num_events == 0)
return pos;
base = priv->device_pointers.log_event_table;
base = trans->shrd->device_pointers.log_event_table;
if (trans->shrd->ucode_type == IWL_UCODE_INIT) {
if (!base)
base = priv->init_evtlog_ptr;
@ -823,7 +838,7 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log,
size_t bufsz = 0;
struct iwl_priv *priv = priv(trans);
base = priv->device_pointers.log_event_table;
base = trans->shrd->device_pointers.log_event_table;
if (trans->shrd->ucode_type == IWL_UCODE_INIT) {
logsize = priv->init_evtlog_size;
if (!base)

View File

@ -1373,6 +1373,7 @@ static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
static void iwl_trans_pcie_free(struct iwl_trans *trans)
{
iwl_calib_free_results(trans);
iwl_trans_pcie_tx_free(trans);
iwl_trans_pcie_rx_free(trans);
free_irq(bus(trans)->irq, trans);

View File

@ -220,6 +220,14 @@ struct fw_img {
struct fw_desc data; /* firmware data image */
};
/* Opaque calibration results */
struct iwl_calib_result {
struct list_head list;
size_t cmd_len;
struct iwl_calib_hdr hdr;
/* data follows */
};
/**
* struct iwl_trans - transport common data
* @ops - pointer to iwl_trans_ops
@ -229,6 +237,8 @@ struct fw_img {
* @ucode_rt: run time ucode image
* @ucode_init: init ucode image
* @ucode_wowlan: wake on wireless ucode image (optional)
* @nvm_device_type: indicates OTP or eeprom
* @calib_results: list head for init calibration results
*/
struct iwl_trans {
const struct iwl_trans_ops *ops;
@ -243,6 +253,9 @@ struct iwl_trans {
/* eeprom related variables */
int nvm_device_type;
/* init calibration results */
struct list_head calib_results;
/* pointer to trans specific struct */
/*Ensure that this pointer will always be aligned to sizeof pointer */
char trans_specific[0] __attribute__((__aligned__(sizeof(void *))));
@ -379,4 +392,9 @@ int iwl_alloc_fw_desc(struct iwl_bus *bus, struct fw_desc *desc,
const void *data, size_t len);
void iwl_dealloc_ucode(struct iwl_trans *trans);
int iwl_send_calib_results(struct iwl_trans *trans);
int iwl_calib_set(struct iwl_trans *trans,
const struct iwl_calib_hdr *cmd, int len);
void iwl_calib_free_results(struct iwl_trans *trans);
#endif /* __iwl_trans_h__ */

View File

@ -217,19 +217,20 @@ static int iwl_set_Xtal_calib(struct iwl_priv *priv)
{
struct iwl_calib_xtal_freq_cmd cmd;
__le16 *xtal_calib =
(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_XTAL);
(__le16 *)iwl_eeprom_query_addr(priv->shrd, EEPROM_XTAL);
iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD);
cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]);
cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]);
return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd));
return iwl_calib_set(trans(priv), (void *)&cmd, sizeof(cmd));
}
static int iwl_set_temperature_offset_calib(struct iwl_priv *priv)
{
struct iwl_calib_temperature_offset_cmd cmd;
__le16 *offset_calib =
(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE);
(__le16 *)iwl_eeprom_query_addr(priv->shrd,
EEPROM_RAW_TEMPERATURE);
memset(&cmd, 0, sizeof(cmd));
iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);
@ -239,21 +240,22 @@ static int iwl_set_temperature_offset_calib(struct iwl_priv *priv)
IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n",
le16_to_cpu(cmd.radio_sensor_offset));
return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd));
return iwl_calib_set(trans(priv), (void *)&cmd, sizeof(cmd));
}
static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv)
{
struct iwl_calib_temperature_offset_v2_cmd cmd;
__le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv,
__le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv->shrd,
EEPROM_KELVIN_TEMPERATURE);
__le16 *offset_calib_low =
(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE);
(__le16 *)iwl_eeprom_query_addr(priv->shrd,
EEPROM_RAW_TEMPERATURE);
struct iwl_eeprom_calib_hdr *hdr;
memset(&cmd, 0, sizeof(cmd));
iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);
hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv,
hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv->shrd,
EEPROM_CALIB_ALL);
memcpy(&cmd.radio_sensor_offset_high, offset_calib_high,
sizeof(*offset_calib_high));
@ -274,7 +276,7 @@ static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv)
IWL_DEBUG_CALIB(priv, "Voltage Ref: %d\n",
le16_to_cpu(cmd.burntVoltageRef));
return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd));
return iwl_calib_set(trans(priv), (void *)&cmd, sizeof(cmd));
}
static int iwl_send_calib_cfg(struct iwl_trans *trans)
@ -307,7 +309,7 @@ int iwlagn_rx_calib_result(struct iwl_priv *priv,
/* reduce the size of the length field itself */
len -= 4;
if (iwl_calib_set(priv, hdr, len))
if (iwl_calib_set(trans(priv), hdr, len))
IWL_ERR(priv, "Failed to record calibration data %d\n",
hdr->op_code);
@ -457,7 +459,7 @@ static int iwl_alive_notify(struct iwl_priv *priv)
return ret;
}
return iwl_send_calib_results(priv);
return iwl_send_calib_results(trans(priv));
}
@ -548,7 +550,7 @@ struct iwlagn_alive_data {
u8 subtype;
};
static void iwl_alive_fn(struct iwl_priv *priv,
static void iwl_alive_fn(struct iwl_trans *trans,
struct iwl_rx_packet *pkt,
void *data)
{
@ -557,14 +559,14 @@ static void iwl_alive_fn(struct iwl_priv *priv,
palive = &pkt->u.alive_frame;
IWL_DEBUG_FW(priv, "Alive ucode status 0x%08X revision "
IWL_DEBUG_FW(trans, "Alive ucode status 0x%08X revision "
"0x%01X 0x%01X\n",
palive->is_valid, palive->ver_type,
palive->ver_subtype);
priv->device_pointers.error_event_table =
trans->shrd->device_pointers.error_event_table =
le32_to_cpu(palive->error_event_table_ptr);
priv->device_pointers.log_event_table =
trans->shrd->device_pointers.log_event_table =
le32_to_cpu(palive->log_event_table_ptr);
alive_data->subtype = palive->ver_subtype;
@ -575,7 +577,7 @@ static void iwl_alive_fn(struct iwl_priv *priv,
void iwl_init_notification_wait(struct iwl_shared *shrd,
struct iwl_notification_wait *wait_entry,
u8 cmd,
void (*fn)(struct iwl_priv *priv,
void (*fn)(struct iwl_trans *trans,
struct iwl_rx_packet *pkt,
void *data),
void *fn_data)

View File

@ -37,7 +37,8 @@ MODULE_AUTHOR("Jouni Malinen");
MODULE_DESCRIPTION("Software simulator of 802.11 radio(s) for mac80211");
MODULE_LICENSE("GPL");
int wmediumd_pid;
static u32 wmediumd_pid;
static int radios = 2;
module_param(radios, int, 0444);
MODULE_PARM_DESC(radios, "Number of simulated radios");
@ -665,7 +666,7 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
bool ack;
struct ieee80211_tx_info *txi;
int _pid;
u32 _pid;
mac80211_hwsim_monitor_rx(hw, skb);
@ -676,7 +677,7 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
}
/* wmediumd mode check */
_pid = wmediumd_pid;
_pid = ACCESS_ONCE(wmediumd_pid);
if (_pid)
return mac80211_hwsim_tx_frame_nl(hw, skb, _pid);
@ -764,7 +765,7 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
struct ieee80211_hw *hw = arg;
struct sk_buff *skb;
struct ieee80211_tx_info *info;
int _pid;
u32 _pid;
hwsim_check_magic(vif);
@ -781,7 +782,7 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
mac80211_hwsim_monitor_rx(hw, skb);
/* wmediumd mode check */
_pid = wmediumd_pid;
_pid = ACCESS_ONCE(wmediumd_pid);
if (_pid)
return mac80211_hwsim_tx_frame_nl(hw, skb, _pid);
@ -1254,7 +1255,7 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif)
struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
struct sk_buff *skb;
struct ieee80211_pspoll *pspoll;
int _pid;
u32 _pid;
if (!vp->assoc)
return;
@ -1275,7 +1276,7 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif)
memcpy(pspoll->ta, mac, ETH_ALEN);
/* wmediumd mode check */
_pid = wmediumd_pid;
_pid = ACCESS_ONCE(wmediumd_pid);
if (_pid)
return mac80211_hwsim_tx_frame_nl(data->hw, skb, _pid);
@ -1292,7 +1293,7 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac,
struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
struct sk_buff *skb;
struct ieee80211_hdr *hdr;
int _pid;
u32 _pid;
if (!vp->assoc)
return;
@ -1314,7 +1315,7 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac,
memcpy(hdr->addr3, vp->bssid, ETH_ALEN);
/* wmediumd mode check */
_pid = wmediumd_pid;
_pid = ACCESS_ONCE(wmediumd_pid);
if (_pid)
return mac80211_hwsim_tx_frame_nl(data->hw, skb, _pid);
@ -1634,8 +1635,6 @@ static int hwsim_init_netlink(void)
int rc;
printk(KERN_INFO "mac80211_hwsim: initializing netlink\n");
wmediumd_pid = 0;
rc = genl_register_family_with_ops(&hwsim_genl_family,
hwsim_ops, ARRAY_SIZE(hwsim_ops));
if (rc)

View File

@ -751,17 +751,13 @@ mwifiex_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
if (priv->disconnect)
return -EBUSY;
priv->disconnect = 1;
if (mwifiex_deauthenticate(priv, NULL))
return -EFAULT;
wiphy_dbg(wiphy, "info: successfully disconnected from %pM:"
" reason code %d\n", priv->cfg_bssid, reason_code);
queue_work(priv->workqueue, &priv->cfg_workqueue);
memset(priv->cfg_bssid, 0, ETH_ALEN);
return 0;
}
@ -981,27 +977,32 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
int ret = 0;
if (priv->assoc_request)
return -EBUSY;
if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {
wiphy_err(wiphy, "received infra assoc request "
"when station is in ibss mode\n");
goto done;
}
priv->assoc_request = -EINPROGRESS;
wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n",
(char *) sme->ssid, sme->bssid);
ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid,
priv->bss_mode, sme->channel, sme, 0);
priv->assoc_request = 1;
done:
priv->assoc_result = ret;
queue_work(priv->workqueue, &priv->cfg_workqueue);
if (!ret) {
cfg80211_connect_result(priv->netdev, priv->cfg_bssid, NULL, 0,
NULL, 0, WLAN_STATUS_SUCCESS,
GFP_KERNEL);
dev_dbg(priv->adapter->dev,
"info: associated to bssid %pM successfully\n",
priv->cfg_bssid);
} else {
dev_dbg(priv->adapter->dev,
"info: association to bssid %pM failed\n",
priv->cfg_bssid);
memset(priv->cfg_bssid, 0, ETH_ALEN);
}
return ret;
}
@ -1018,28 +1019,29 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy);
int ret = 0;
if (priv->ibss_join_request)
return -EBUSY;
if (priv->bss_mode != NL80211_IFTYPE_ADHOC) {
wiphy_err(wiphy, "request to join ibss received "
"when station is not in ibss mode\n");
goto done;
}
priv->ibss_join_request = -EINPROGRESS;
wiphy_dbg(wiphy, "info: trying to join to %s and bssid %pM\n",
(char *) params->ssid, params->bssid);
ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid,
params->bssid, priv->bss_mode,
params->channel, NULL, params->privacy);
priv->ibss_join_request = 1;
done:
priv->ibss_join_result = ret;
queue_work(priv->workqueue, &priv->cfg_workqueue);
if (!ret) {
cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL);
dev_dbg(priv->adapter->dev,
"info: joined/created adhoc network with bssid"
" %pM successfully\n", priv->cfg_bssid);
} else {
dev_dbg(priv->adapter->dev,
"info: failed creating/joining adhoc network\n");
}
return ret;
}
@ -1054,17 +1056,12 @@ mwifiex_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
{
struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy);
if (priv->disconnect)
return -EBUSY;
priv->disconnect = 1;
wiphy_dbg(wiphy, "info: disconnecting from essid %pM\n",
priv->cfg_bssid);
if (mwifiex_deauthenticate(priv, NULL))
return -EFAULT;
queue_work(priv->workqueue, &priv->cfg_workqueue);
memset(priv->cfg_bssid, 0, ETH_ALEN);
return 0;
}
@ -1081,15 +1078,42 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_scan_request *request)
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
int i;
struct ieee80211_channel *chan;
wiphy_dbg(wiphy, "info: received scan request on %s\n", dev->name);
if (priv->scan_request && priv->scan_request != request)
return -EBUSY;
priv->scan_request = request;
queue_work(priv->workqueue, &priv->cfg_workqueue);
priv->user_scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg),
GFP_KERNEL);
if (!priv->user_scan_cfg) {
dev_err(priv->adapter->dev, "failed to alloc scan_req\n");
return -ENOMEM;
}
for (i = 0; i < request->n_ssids; i++) {
memcpy(priv->user_scan_cfg->ssid_list[i].ssid,
request->ssids[i].ssid, request->ssids[i].ssid_len);
priv->user_scan_cfg->ssid_list[i].max_len =
request->ssids[i].ssid_len;
}
for (i = 0; i < request->n_channels; i++) {
chan = request->channels[i];
priv->user_scan_cfg->chan_list[i].chan_number = chan->hw_value;
priv->user_scan_cfg->chan_list[i].radio_type = chan->band;
if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
priv->user_scan_cfg->chan_list[i].scan_type =
MWIFIEX_SCAN_TYPE_PASSIVE;
else
priv->user_scan_cfg->chan_list[i].scan_type =
MWIFIEX_SCAN_TYPE_ACTIVE;
priv->user_scan_cfg->chan_list[i].scan_time = 0;
}
if (mwifiex_set_user_scan_ioctl(priv, priv->user_scan_cfg))
return -EFAULT;
return 0;
}
@ -1295,10 +1319,6 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev)
priv->media_connected = false;
cancel_work_sync(&priv->cfg_workqueue);
flush_workqueue(priv->workqueue);
destroy_workqueue(priv->workqueue);
priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
return 0;
@ -1376,9 +1396,6 @@ int mwifiex_register_cfg80211(struct mwifiex_private *priv)
memcpy(wdev->wiphy->perm_addr, priv->curr_addr, ETH_ALEN);
wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
/* We are using custom domains */
wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
/* Reserve space for bss band information */
wdev->wiphy->bss_priv_size = sizeof(u8);
@ -1407,100 +1424,3 @@ int mwifiex_register_cfg80211(struct mwifiex_private *priv)
return ret;
}
/*
* This function handles the result of different pending network operations.
*
* The following operations are handled and CFG802.11 subsystem is
* notified accordingly -
* - Scan request completion
* - Association request completion
* - IBSS join request completion
* - Disconnect request completion
*/
void
mwifiex_cfg80211_results(struct work_struct *work)
{
struct mwifiex_private *priv =
container_of(work, struct mwifiex_private, cfg_workqueue);
struct mwifiex_user_scan_cfg *scan_req;
int ret = 0, i;
struct ieee80211_channel *chan;
if (priv->scan_request) {
scan_req = kzalloc(sizeof(struct mwifiex_user_scan_cfg),
GFP_KERNEL);
if (!scan_req) {
dev_err(priv->adapter->dev, "failed to alloc "
"scan_req\n");
return;
}
for (i = 0; i < priv->scan_request->n_ssids; i++) {
memcpy(scan_req->ssid_list[i].ssid,
priv->scan_request->ssids[i].ssid,
priv->scan_request->ssids[i].ssid_len);
scan_req->ssid_list[i].max_len =
priv->scan_request->ssids[i].ssid_len;
}
for (i = 0; i < priv->scan_request->n_channels; i++) {
chan = priv->scan_request->channels[i];
scan_req->chan_list[i].chan_number = chan->hw_value;
scan_req->chan_list[i].radio_type = chan->band;
if (chan->flags & IEEE80211_CHAN_DISABLED)
scan_req->chan_list[i].scan_type =
MWIFIEX_SCAN_TYPE_PASSIVE;
else
scan_req->chan_list[i].scan_type =
MWIFIEX_SCAN_TYPE_ACTIVE;
scan_req->chan_list[i].scan_time = 0;
}
if (mwifiex_set_user_scan_ioctl(priv, scan_req))
ret = -EFAULT;
priv->scan_result_status = ret;
dev_dbg(priv->adapter->dev, "info: %s: sending scan results\n",
__func__);
cfg80211_scan_done(priv->scan_request,
(priv->scan_result_status < 0));
priv->scan_request = NULL;
kfree(scan_req);
}
if (priv->assoc_request == 1) {
if (!priv->assoc_result) {
cfg80211_connect_result(priv->netdev, priv->cfg_bssid,
NULL, 0, NULL, 0,
WLAN_STATUS_SUCCESS,
GFP_KERNEL);
dev_dbg(priv->adapter->dev,
"info: associated to bssid %pM successfully\n",
priv->cfg_bssid);
} else {
dev_dbg(priv->adapter->dev,
"info: association to bssid %pM failed\n",
priv->cfg_bssid);
memset(priv->cfg_bssid, 0, ETH_ALEN);
}
priv->assoc_request = 0;
priv->assoc_result = 0;
}
if (priv->ibss_join_request == 1) {
if (!priv->ibss_join_result) {
cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid,
GFP_KERNEL);
dev_dbg(priv->adapter->dev,
"info: joined/created adhoc network with bssid"
" %pM successfully\n", priv->cfg_bssid);
} else {
dev_dbg(priv->adapter->dev,
"info: failed creating/joining adhoc network\n");
}
priv->ibss_join_request = 0;
priv->ibss_join_result = 0;
}
if (priv->disconnect) {
memset(priv->cfg_bssid, 0, ETH_ALEN);
priv->disconnect = 0;
}
}

View File

@ -26,5 +26,4 @@
int mwifiex_register_cfg80211(struct mwifiex_private *);
void mwifiex_cfg80211_results(struct work_struct *work);
#endif

View File

@ -939,7 +939,6 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
{
struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL;
unsigned long cmd_flags;
unsigned long cmd_pending_q_flags;
unsigned long scan_pending_q_flags;
uint16_t cancel_scan_cmd = false;
@ -949,12 +948,9 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
cmd_node = adapter->curr_cmd;
cmd_node->wait_q_enabled = false;
cmd_node->cmd_flag |= CMD_F_CANCELED;
spin_lock_irqsave(&adapter->cmd_pending_q_lock,
cmd_pending_q_flags);
list_del(&cmd_node->list);
spin_unlock_irqrestore(&adapter->cmd_pending_q_lock,
cmd_pending_q_flags);
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
mwifiex_complete_cmd(adapter, adapter->curr_cmd);
adapter->curr_cmd = NULL;
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
}
@ -981,7 +977,6 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
}
adapter->cmd_wait_q.status = -1;
mwifiex_complete_cmd(adapter, adapter->curr_cmd);
}
/*

View File

@ -282,6 +282,45 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
adapter->arp_filter_size = 0;
}
/*
* This function sets trans_start per tx_queue
*/
void mwifiex_set_trans_start(struct net_device *dev)
{
int i;
for (i = 0; i < dev->num_tx_queues; i++)
netdev_get_tx_queue(dev, i)->trans_start = jiffies;
dev->trans_start = jiffies;
}
/*
* This function wakes up all queues in net_device
*/
void mwifiex_wake_up_net_dev_queue(struct net_device *netdev,
struct mwifiex_adapter *adapter)
{
unsigned long dev_queue_flags;
spin_lock_irqsave(&adapter->queue_lock, dev_queue_flags);
netif_tx_wake_all_queues(netdev);
spin_unlock_irqrestore(&adapter->queue_lock, dev_queue_flags);
}
/*
* This function stops all queues in net_device
*/
void mwifiex_stop_net_dev_queue(struct net_device *netdev,
struct mwifiex_adapter *adapter)
{
unsigned long dev_queue_flags;
spin_lock_irqsave(&adapter->queue_lock, dev_queue_flags);
netif_tx_stop_all_queues(netdev);
spin_unlock_irqrestore(&adapter->queue_lock, dev_queue_flags);
}
/*
* This function releases the lock variables and frees the locks and
* associated locks.
@ -359,6 +398,7 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter)
spin_lock_init(&adapter->int_lock);
spin_lock_init(&adapter->main_proc_lock);
spin_lock_init(&adapter->mwifiex_cmd_lock);
spin_lock_init(&adapter->queue_lock);
for (i = 0; i < adapter->priv_num; i++) {
if (adapter->priv[i]) {
priv = adapter->priv[i];

View File

@ -401,7 +401,7 @@ mwifiex_fill_buffer(struct sk_buff *skb)
static int
mwifiex_open(struct net_device *dev)
{
netif_start_queue(dev);
netif_tx_start_all_queues(dev);
return 0;
}
@ -465,8 +465,8 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
atomic_inc(&priv->adapter->tx_pending);
if (atomic_read(&priv->adapter->tx_pending) >= MAX_TX_PENDING) {
netif_stop_queue(priv->netdev);
dev->trans_start = jiffies;
mwifiex_set_trans_start(dev);
mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
}
queue_work(priv->adapter->workqueue, &priv->adapter->main_work);
@ -533,7 +533,7 @@ mwifiex_tx_timeout(struct net_device *dev)
dev_err(priv->adapter->dev, "%lu : Tx timeout, bss_index=%d\n",
jiffies, priv->bss_index);
dev->trans_start = jiffies;
mwifiex_set_trans_start(dev);
priv->num_tx_timeout++;
}
@ -586,8 +586,6 @@ void mwifiex_init_priv_params(struct mwifiex_private *priv,
priv->media_connected = false;
memset(&priv->nick_name, 0, sizeof(priv->nick_name));
priv->num_tx_timeout = 0;
priv->workqueue = create_singlethread_workqueue("cfg80211_wq");
INIT_WORK(&priv->cfg_workqueue, mwifiex_cfg80211_results);
memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN);
}
@ -793,7 +791,8 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
priv = adapter->priv[i];
if (priv && priv->netdev) {
if (!netif_queue_stopped(priv->netdev))
netif_stop_queue(priv->netdev);
mwifiex_stop_net_dev_queue(priv->netdev,
adapter);
if (netif_carrier_ok(priv->netdev))
netif_carrier_off(priv->netdev);
}

View File

@ -453,15 +453,8 @@ struct mwifiex_private {
u8 scan_pending_on_block;
u8 report_scan_result;
struct cfg80211_scan_request *scan_request;
int scan_result_status;
int assoc_request;
u16 assoc_result;
int ibss_join_request;
u16 ibss_join_result;
bool disconnect;
struct mwifiex_user_scan_cfg *user_scan_cfg;
u8 cfg_bssid[6];
struct workqueue_struct *workqueue;
struct work_struct cfg_workqueue;
u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
struct wps wps;
u8 scan_block;
@ -655,10 +648,19 @@ struct mwifiex_adapter {
struct mwifiex_wait_queue cmd_wait_q;
u8 scan_wait_q_woken;
struct cmd_ctrl_node *cmd_queued;
spinlock_t queue_lock; /* lock for tx queues */
};
int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);
void mwifiex_set_trans_start(struct net_device *dev);
void mwifiex_stop_net_dev_queue(struct net_device *netdev,
struct mwifiex_adapter *adapter);
void mwifiex_wake_up_net_dev_queue(struct net_device *netdev,
struct mwifiex_adapter *adapter);
int mwifiex_init_fw(struct mwifiex_adapter *adapter);
int mwifiex_init_fw_complete(struct mwifiex_adapter *adapter);

Some files were not shown because too many files have changed in this diff Show More