forked from Minki/linux
iwlwifi
* bug fix for TDLS * fixes and cleanups in scan * support of several scan plans * improvements in FTM * fixes in FW API * improvements in the failure paths when the bus is dead * other various small things here and there ath10k * add QCA9377 support * fw_stats support for 10.4 firmware ath6kl * report antenna configuration to user space * implement ethtool stats ssb * add Kconfig SSB_HOST_SOC for compiling SoC related code * move functions specific to SoC hosted bus to separated file * pick PCMCIA host code support from b43 driver -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQEcBAABAgAGBQJWMnbHAAoJEG4XJFUm622bGmMH/3MuH5mMdhT79Y1ySM9e+/1m 6NHaRLK7Ibk1PHRUWpJqflZG5dc3arxjit5DciUZjInzjMWGWjNEYY6zFeT/fWw3 dc+EZiFRsKIhYGTXi3a2uuRlEpxfx8Rvz2o6gh/kq4uQxrbdMVyKjgV+PF5HsUbp PDNV3L+ZeMZcGbDR3IFyBZHoH6yHZ9k49J/+OOXq+Z9lUGTeM135ZwaYNleORb/o dKcHlW0MY0lK32rD+XJI/2L8E8ne/TUe8fQQQH3XdyFS+4523HtY9ogLzk41Jfsj qzKhybzRnRXox+ZpjSNceENpE7XjhXIOshbjZMa3ZChDGwKCOSNA4BLyb314kMo= =YlL0 -----END PGP SIGNATURE----- Merge tag 'wireless-drivers-next-for-davem-2015-10-29' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next Kalle Valo says: ==================== iwlwifi * bug fix for TDLS * fixes and cleanups in scan * support of several scan plans * improvements in FTM * fixes in FW API * improvements in the failure paths when the bus is dead * other various small things here and there ath10k * add QCA9377 support * fw_stats support for 10.4 firmware ath6kl * report antenna configuration to user space * implement ethtool stats ssb * add Kconfig SSB_HOST_SOC for compiling SoC related code * move functions specific to SoC hosted bus to separated file * pick PCMCIA host code support from b43 driver ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
a493bcf8d6
@ -4,6 +4,7 @@ config BCM47XX_SSB
|
||||
bool "SSB Support for Broadcom BCM47XX"
|
||||
select SYS_HAS_CPU_BMIPS32_3300
|
||||
select SSB
|
||||
select SSB_HOST_SOC
|
||||
select SSB_DRIVER_MIPS
|
||||
select SSB_DRIVER_EXTIF
|
||||
select SSB_EMBEDDED
|
||||
|
@ -1231,7 +1231,7 @@ struct airo_info {
|
||||
dma_addr_t shared_dma;
|
||||
pm_message_t power;
|
||||
SsidRid *SSID;
|
||||
APListRid *APList;
|
||||
APListRid APList;
|
||||
#define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE
|
||||
char proc_name[IFNAMSIZ];
|
||||
|
||||
@ -1848,11 +1848,6 @@ static int readStatusRid(struct airo_info *ai, StatusRid *statr, int lock)
|
||||
return PC4500_readrid(ai, RID_STATUS, statr, sizeof(*statr), lock);
|
||||
}
|
||||
|
||||
static int readAPListRid(struct airo_info *ai, APListRid *aplr)
|
||||
{
|
||||
return PC4500_readrid(ai, RID_APLIST, aplr, sizeof(*aplr), 1);
|
||||
}
|
||||
|
||||
static int writeAPListRid(struct airo_info *ai, APListRid *aplr, int lock)
|
||||
{
|
||||
return PC4500_writerid(ai, RID_APLIST, aplr, sizeof(*aplr), lock);
|
||||
@ -2413,7 +2408,6 @@ void stop_airo_card( struct net_device *dev, int freeres )
|
||||
|
||||
kfree(ai->flash);
|
||||
kfree(ai->rssi);
|
||||
kfree(ai->APList);
|
||||
kfree(ai->SSID);
|
||||
if (freeres) {
|
||||
/* PCMCIA frees this stuff, so only for PCI and ISA */
|
||||
@ -2809,6 +2803,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
|
||||
init_waitqueue_head (&ai->thr_wait);
|
||||
ai->tfm = NULL;
|
||||
add_airo_dev(ai);
|
||||
ai->APList.len = cpu_to_le16(sizeof(struct APListRid));
|
||||
|
||||
if (airo_networks_allocate (ai))
|
||||
goto err_out_free;
|
||||
@ -3042,6 +3037,11 @@ static void airo_process_scan_results (struct airo_info *ai) {
|
||||
}
|
||||
|
||||
out:
|
||||
/* write APList back (we cleared it in airo_set_scan) */
|
||||
disable_MAC(ai, 2);
|
||||
writeAPListRid(ai, &ai->APList, 0);
|
||||
enable_MAC(ai, 0);
|
||||
|
||||
ai->scan_timeout = 0;
|
||||
clear_bit(JOB_SCAN_RESULTS, &ai->jobs);
|
||||
up(&ai->sem);
|
||||
@ -3613,17 +3613,18 @@ static void disable_MAC( struct airo_info *ai, int lock ) {
|
||||
Cmd cmd;
|
||||
Resp rsp;
|
||||
|
||||
if (lock && down_interruptible(&ai->sem))
|
||||
if (lock == 1 && down_interruptible(&ai->sem))
|
||||
return;
|
||||
|
||||
if (test_bit(FLAG_ENABLED, &ai->flags)) {
|
||||
netif_carrier_off(ai->dev);
|
||||
if (lock != 2) /* lock == 2 means don't disable carrier */
|
||||
netif_carrier_off(ai->dev);
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.cmd = MAC_DISABLE; // disable in case already enabled
|
||||
issuecommand(ai, &cmd, &rsp);
|
||||
clear_bit(FLAG_ENABLED, &ai->flags);
|
||||
}
|
||||
if (lock)
|
||||
if (lock == 1)
|
||||
up(&ai->sem);
|
||||
}
|
||||
|
||||
@ -3852,8 +3853,6 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
|
||||
tdsRssiRid rssi_rid;
|
||||
CapabilityRid cap_rid;
|
||||
|
||||
kfree(ai->APList);
|
||||
ai->APList = NULL;
|
||||
kfree(ai->SSID);
|
||||
ai->SSID = NULL;
|
||||
// general configuration (read/modify/write)
|
||||
@ -5130,31 +5129,31 @@ static void proc_APList_on_close( struct inode *inode, struct file *file ) {
|
||||
struct proc_data *data = file->private_data;
|
||||
struct net_device *dev = PDE_DATA(inode);
|
||||
struct airo_info *ai = dev->ml_priv;
|
||||
APListRid APList_rid;
|
||||
APListRid *APList_rid = &ai->APList;
|
||||
int i;
|
||||
|
||||
if ( !data->writelen ) return;
|
||||
|
||||
memset( &APList_rid, 0, sizeof(APList_rid) );
|
||||
APList_rid.len = cpu_to_le16(sizeof(APList_rid));
|
||||
memset(APList_rid, 0, sizeof(*APList_rid));
|
||||
APList_rid->len = cpu_to_le16(sizeof(*APList_rid));
|
||||
|
||||
for( i = 0; i < 4 && data->writelen >= (i+1)*6*3; i++ ) {
|
||||
int j;
|
||||
for( j = 0; j < 6*3 && data->wbuffer[j+i*6*3]; j++ ) {
|
||||
switch(j%3) {
|
||||
case 0:
|
||||
APList_rid.ap[i][j/3]=
|
||||
APList_rid->ap[i][j/3]=
|
||||
hex_to_bin(data->wbuffer[j+i*6*3])<<4;
|
||||
break;
|
||||
case 1:
|
||||
APList_rid.ap[i][j/3]|=
|
||||
APList_rid->ap[i][j/3]|=
|
||||
hex_to_bin(data->wbuffer[j+i*6*3]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
disable_MAC(ai, 1);
|
||||
writeAPListRid(ai, &APList_rid, 1);
|
||||
writeAPListRid(ai, APList_rid, 1);
|
||||
enable_MAC(ai, 1);
|
||||
}
|
||||
|
||||
@ -5408,7 +5407,7 @@ static int proc_APList_open( struct inode *inode, struct file *file ) {
|
||||
struct airo_info *ai = dev->ml_priv;
|
||||
int i;
|
||||
char *ptr;
|
||||
APListRid APList_rid;
|
||||
APListRid *APList_rid = &ai->APList;
|
||||
|
||||
if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
|
||||
return -ENOMEM;
|
||||
@ -5426,13 +5425,12 @@ static int proc_APList_open( struct inode *inode, struct file *file ) {
|
||||
}
|
||||
data->on_close = proc_APList_on_close;
|
||||
|
||||
readAPListRid(ai, &APList_rid);
|
||||
ptr = data->rbuffer;
|
||||
for( i = 0; i < 4; i++ ) {
|
||||
// We end when we find a zero MAC
|
||||
if ( !*(int*)APList_rid.ap[i] &&
|
||||
!*(int*)&APList_rid.ap[i][2]) break;
|
||||
ptr += sprintf(ptr, "%pM\n", APList_rid.ap[i]);
|
||||
if ( !*(int*)APList_rid->ap[i] &&
|
||||
!*(int*)&APList_rid->ap[i][2]) break;
|
||||
ptr += sprintf(ptr, "%pM\n", APList_rid->ap[i]);
|
||||
}
|
||||
if (i==0) ptr += sprintf(ptr, "Not using specific APs\n");
|
||||
|
||||
@ -5596,15 +5594,10 @@ static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
Cmd cmd;
|
||||
Resp rsp;
|
||||
|
||||
if (!ai->APList)
|
||||
ai->APList = kmalloc(sizeof(APListRid), GFP_KERNEL);
|
||||
if (!ai->APList)
|
||||
return -ENOMEM;
|
||||
if (!ai->SSID)
|
||||
ai->SSID = kmalloc(sizeof(SsidRid), GFP_KERNEL);
|
||||
if (!ai->SSID)
|
||||
return -ENOMEM;
|
||||
readAPListRid(ai, ai->APList);
|
||||
readSsidRid(ai, ai->SSID);
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
/* the lock will be released at the end of the resume callback */
|
||||
@ -5652,11 +5645,7 @@ static int airo_pci_resume(struct pci_dev *pdev)
|
||||
kfree(ai->SSID);
|
||||
ai->SSID = NULL;
|
||||
}
|
||||
if (ai->APList) {
|
||||
writeAPListRid(ai, ai->APList, 0);
|
||||
kfree(ai->APList);
|
||||
ai->APList = NULL;
|
||||
}
|
||||
writeAPListRid(ai, &ai->APList, 0);
|
||||
writeConfigRid(ai, 0);
|
||||
enable_MAC(ai, 0);
|
||||
ai->power = PMSG_ON;
|
||||
@ -5954,7 +5943,7 @@ static int airo_set_wap(struct net_device *dev,
|
||||
struct airo_info *local = dev->ml_priv;
|
||||
Cmd cmd;
|
||||
Resp rsp;
|
||||
APListRid APList_rid;
|
||||
APListRid *APList_rid = &local->APList;
|
||||
|
||||
if (awrq->sa_family != ARPHRD_ETHER)
|
||||
return -EINVAL;
|
||||
@ -5967,11 +5956,11 @@ static int airo_set_wap(struct net_device *dev,
|
||||
issuecommand(local, &cmd, &rsp);
|
||||
up(&local->sem);
|
||||
} else {
|
||||
memset(&APList_rid, 0, sizeof(APList_rid));
|
||||
APList_rid.len = cpu_to_le16(sizeof(APList_rid));
|
||||
memcpy(APList_rid.ap[0], awrq->sa_data, ETH_ALEN);
|
||||
memset(APList_rid, 0, sizeof(*APList_rid));
|
||||
APList_rid->len = cpu_to_le16(sizeof(*APList_rid));
|
||||
memcpy(APList_rid->ap[0], awrq->sa_data, ETH_ALEN);
|
||||
disable_MAC(local, 1);
|
||||
writeAPListRid(local, &APList_rid, 1);
|
||||
writeAPListRid(local, APList_rid, 1);
|
||||
enable_MAC(local, 1);
|
||||
}
|
||||
return 0;
|
||||
@ -7233,6 +7222,7 @@ static int airo_set_scan(struct net_device *dev,
|
||||
Cmd cmd;
|
||||
Resp rsp;
|
||||
int wake = 0;
|
||||
APListRid APList_rid_empty;
|
||||
|
||||
/* Note : you may have realised that, as this is a SET operation,
|
||||
* this is privileged and therefore a normal user can't
|
||||
@ -7250,6 +7240,13 @@ static int airo_set_scan(struct net_device *dev,
|
||||
if (ai->scan_timeout > 0)
|
||||
goto out;
|
||||
|
||||
/* Clear APList as it affects scan results */
|
||||
memset(&APList_rid_empty, 0, sizeof(APList_rid_empty));
|
||||
APList_rid_empty.len = cpu_to_le16(sizeof(APList_rid_empty));
|
||||
disable_MAC(ai, 2);
|
||||
writeAPListRid(ai, &APList_rid_empty, 0);
|
||||
enable_MAC(ai, 0);
|
||||
|
||||
/* Initiate a scan command */
|
||||
ai->scan_timeout = RUN_AT(3*HZ);
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
@ -7505,10 +7502,8 @@ static int airo_config_commit(struct net_device *dev,
|
||||
* parameters. It's now time to commit them in the card */
|
||||
disable_MAC(local, 1);
|
||||
if (test_bit (FLAG_RESET, &local->flags)) {
|
||||
APListRid APList_rid;
|
||||
SsidRid SSID_rid;
|
||||
|
||||
readAPListRid(local, &APList_rid);
|
||||
readSsidRid(local, &SSID_rid);
|
||||
if (test_bit(FLAG_MPI,&local->flags))
|
||||
setup_card(local, dev->dev_addr, 1 );
|
||||
@ -7516,7 +7511,7 @@ static int airo_config_commit(struct net_device *dev,
|
||||
reset_airo_card(dev);
|
||||
disable_MAC(local, 1);
|
||||
writeSsidRid(local, &SSID_rid, 1);
|
||||
writeAPListRid(local, &APList_rid, 1);
|
||||
writeAPListRid(local, &local->APList, 1);
|
||||
}
|
||||
if (down_interruptible(&local->sem))
|
||||
return -ERESTARTSYS;
|
||||
|
@ -274,7 +274,7 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state,
|
||||
{
|
||||
struct ath10k *ar = ce_state->ar;
|
||||
struct ath10k_ce_ring *src_ring = ce_state->src_ring;
|
||||
struct ce_desc *desc, *sdesc;
|
||||
struct ce_desc *desc, sdesc;
|
||||
unsigned int nentries_mask = src_ring->nentries_mask;
|
||||
unsigned int sw_index = src_ring->sw_index;
|
||||
unsigned int write_index = src_ring->write_index;
|
||||
@ -294,7 +294,6 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state,
|
||||
|
||||
desc = CE_SRC_RING_TO_DESC(src_ring->base_addr_owner_space,
|
||||
write_index);
|
||||
sdesc = CE_SRC_RING_TO_DESC(src_ring->shadow_base, write_index);
|
||||
|
||||
desc_flags |= SM(transfer_id, CE_DESC_FLAGS_META_DATA);
|
||||
|
||||
@ -303,11 +302,11 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state,
|
||||
if (flags & CE_SEND_FLAG_BYTE_SWAP)
|
||||
desc_flags |= CE_DESC_FLAGS_BYTE_SWAP;
|
||||
|
||||
sdesc->addr = __cpu_to_le32(buffer);
|
||||
sdesc->nbytes = __cpu_to_le16(nbytes);
|
||||
sdesc->flags = __cpu_to_le16(desc_flags);
|
||||
sdesc.addr = __cpu_to_le32(buffer);
|
||||
sdesc.nbytes = __cpu_to_le16(nbytes);
|
||||
sdesc.flags = __cpu_to_le16(desc_flags);
|
||||
|
||||
*desc = *sdesc;
|
||||
*desc = sdesc;
|
||||
|
||||
src_ring->per_transfer_context[write_index] = per_transfer_context;
|
||||
|
||||
@ -579,17 +578,13 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state,
|
||||
* The caller takes responsibility for any necessary locking.
|
||||
*/
|
||||
int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
|
||||
void **per_transfer_contextp,
|
||||
u32 *bufferp,
|
||||
unsigned int *nbytesp,
|
||||
unsigned int *transfer_idp)
|
||||
void **per_transfer_contextp)
|
||||
{
|
||||
struct ath10k_ce_ring *src_ring = ce_state->src_ring;
|
||||
u32 ctrl_addr = ce_state->ctrl_addr;
|
||||
struct ath10k *ar = ce_state->ar;
|
||||
unsigned int nentries_mask = src_ring->nentries_mask;
|
||||
unsigned int sw_index = src_ring->sw_index;
|
||||
struct ce_desc *sdesc, *sbase;
|
||||
unsigned int read_index;
|
||||
|
||||
if (src_ring->hw_index == sw_index) {
|
||||
@ -614,15 +609,6 @@ int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
|
||||
if (read_index == sw_index)
|
||||
return -EIO;
|
||||
|
||||
sbase = src_ring->shadow_base;
|
||||
sdesc = CE_SRC_RING_TO_DESC(sbase, sw_index);
|
||||
|
||||
/* Return data from completed source descriptor */
|
||||
*bufferp = __le32_to_cpu(sdesc->addr);
|
||||
*nbytesp = __le16_to_cpu(sdesc->nbytes);
|
||||
*transfer_idp = MS(__le16_to_cpu(sdesc->flags),
|
||||
CE_DESC_FLAGS_META_DATA);
|
||||
|
||||
if (per_transfer_contextp)
|
||||
*per_transfer_contextp =
|
||||
src_ring->per_transfer_context[sw_index];
|
||||
@ -697,10 +683,7 @@ int ath10k_ce_cancel_send_next(struct ath10k_ce_pipe *ce_state,
|
||||
}
|
||||
|
||||
int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state,
|
||||
void **per_transfer_contextp,
|
||||
u32 *bufferp,
|
||||
unsigned int *nbytesp,
|
||||
unsigned int *transfer_idp)
|
||||
void **per_transfer_contextp)
|
||||
{
|
||||
struct ath10k *ar = ce_state->ar;
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
@ -708,9 +691,7 @@ int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state,
|
||||
|
||||
spin_lock_bh(&ar_pci->ce_lock);
|
||||
ret = ath10k_ce_completed_send_next_nolock(ce_state,
|
||||
per_transfer_contextp,
|
||||
bufferp, nbytesp,
|
||||
transfer_idp);
|
||||
per_transfer_contextp);
|
||||
spin_unlock_bh(&ar_pci->ce_lock);
|
||||
|
||||
return ret;
|
||||
@ -940,27 +921,6 @@ ath10k_ce_alloc_src_ring(struct ath10k *ar, unsigned int ce_id,
|
||||
src_ring->base_addr_ce_space_unaligned,
|
||||
CE_DESC_RING_ALIGN);
|
||||
|
||||
/*
|
||||
* Also allocate a shadow src ring in regular
|
||||
* mem to use for faster access.
|
||||
*/
|
||||
src_ring->shadow_base_unaligned =
|
||||
kmalloc((nentries * sizeof(struct ce_desc) +
|
||||
CE_DESC_RING_ALIGN), GFP_KERNEL);
|
||||
if (!src_ring->shadow_base_unaligned) {
|
||||
dma_free_coherent(ar->dev,
|
||||
(nentries * sizeof(struct ce_desc) +
|
||||
CE_DESC_RING_ALIGN),
|
||||
src_ring->base_addr_owner_space,
|
||||
src_ring->base_addr_ce_space);
|
||||
kfree(src_ring);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
src_ring->shadow_base = PTR_ALIGN(
|
||||
src_ring->shadow_base_unaligned,
|
||||
CE_DESC_RING_ALIGN);
|
||||
|
||||
return src_ring;
|
||||
}
|
||||
|
||||
@ -1139,7 +1099,6 @@ void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id)
|
||||
struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
|
||||
|
||||
if (ce_state->src_ring) {
|
||||
kfree(ce_state->src_ring->shadow_base_unaligned);
|
||||
dma_free_coherent(ar->dev,
|
||||
(ce_state->src_ring->nentries *
|
||||
sizeof(struct ce_desc) +
|
||||
|
@ -100,12 +100,6 @@ struct ath10k_ce_ring {
|
||||
|
||||
/* CE address space */
|
||||
u32 base_addr_ce_space;
|
||||
/*
|
||||
* Start of shadow copy of descriptors, within regular memory.
|
||||
* Aligned to descriptor-size boundary.
|
||||
*/
|
||||
void *shadow_base_unaligned;
|
||||
struct ce_desc *shadow_base;
|
||||
|
||||
/* keep last */
|
||||
void *per_transfer_context[0];
|
||||
@ -192,16 +186,10 @@ int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state,
|
||||
* Pops 1 completed send buffer from Source ring.
|
||||
*/
|
||||
int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state,
|
||||
void **per_transfer_contextp,
|
||||
u32 *bufferp,
|
||||
unsigned int *nbytesp,
|
||||
unsigned int *transfer_idp);
|
||||
void **per_transfer_contextp);
|
||||
|
||||
int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
|
||||
void **per_transfer_contextp,
|
||||
u32 *bufferp,
|
||||
unsigned int *nbytesp,
|
||||
unsigned int *transfer_idp);
|
||||
void **per_transfer_contextp);
|
||||
|
||||
/*==================CE Engine Initialization=======================*/
|
||||
|
||||
|
@ -137,6 +137,21 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
},
|
||||
{
|
||||
.id = QCA9377_HW_1_0_DEV_VERSION,
|
||||
.name = "qca9377 hw1.0",
|
||||
.patch_load_addr = QCA9377_HW_1_0_PATCH_LOAD_ADDR,
|
||||
.uart_pin = 7,
|
||||
.otp_exe_param = 0,
|
||||
.fw = {
|
||||
.dir = QCA9377_HW_1_0_FW_DIR,
|
||||
.fw = QCA9377_HW_1_0_FW_FILE,
|
||||
.otp = QCA9377_HW_1_0_OTP_FILE,
|
||||
.board = QCA9377_HW_1_0_BOARD_DATA_FILE,
|
||||
.board_size = QCA9377_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA9377_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static const char *const ath10k_core_fw_feature_str[] = {
|
||||
@ -151,6 +166,7 @@ static const char *const ath10k_core_fw_feature_str[] = {
|
||||
[ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING] = "no-4addr-pad",
|
||||
[ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT] = "skip-clock-init",
|
||||
[ATH10K_FW_FEATURE_RAW_MODE_SUPPORT] = "raw-mode",
|
||||
[ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA] = "adaptive-cca",
|
||||
};
|
||||
|
||||
static unsigned int ath10k_core_get_fw_feature_str(char *buf,
|
||||
@ -568,8 +584,8 @@ static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode)
|
||||
}
|
||||
break;
|
||||
case ATH10K_FIRMWARE_MODE_UTF:
|
||||
data = ar->testmode.utf->data;
|
||||
data_len = ar->testmode.utf->size;
|
||||
data = ar->testmode.utf_firmware_data;
|
||||
data_len = ar->testmode.utf_firmware_len;
|
||||
mode_name = "utf";
|
||||
break;
|
||||
default:
|
||||
@ -1900,6 +1916,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
|
||||
ar->hw_values = &qca988x_values;
|
||||
break;
|
||||
case ATH10K_HW_QCA6174:
|
||||
case ATH10K_HW_QCA9377:
|
||||
ar->regs = &qca6174_regs;
|
||||
ar->hw_values = &qca6174_values;
|
||||
break;
|
||||
|
@ -214,6 +214,7 @@ struct ath10k_fw_stats_pdev {
|
||||
s32 hw_queued;
|
||||
s32 hw_reaped;
|
||||
s32 underrun;
|
||||
u32 hw_paused;
|
||||
s32 tx_abort;
|
||||
s32 mpdus_requed;
|
||||
u32 tx_ko;
|
||||
@ -226,6 +227,16 @@ struct ath10k_fw_stats_pdev {
|
||||
u32 pdev_resets;
|
||||
u32 phy_underrun;
|
||||
u32 txop_ovf;
|
||||
u32 seq_posted;
|
||||
u32 seq_failed_queueing;
|
||||
u32 seq_completed;
|
||||
u32 seq_restarted;
|
||||
u32 mu_seq_posted;
|
||||
u32 mpdus_sw_flush;
|
||||
u32 mpdus_hw_filter;
|
||||
u32 mpdus_truncated;
|
||||
u32 mpdus_ack_failed;
|
||||
u32 mpdus_expired;
|
||||
|
||||
/* PDEV RX stats */
|
||||
s32 mid_ppdu_route_change;
|
||||
@ -242,6 +253,7 @@ struct ath10k_fw_stats_pdev {
|
||||
s32 phy_errs;
|
||||
s32 phy_err_drop;
|
||||
s32 mpdu_errs;
|
||||
s32 rx_ovfl_errs;
|
||||
};
|
||||
|
||||
struct ath10k_fw_stats {
|
||||
@ -497,6 +509,9 @@ enum ath10k_fw_features {
|
||||
*/
|
||||
ATH10K_FW_FEATURE_RAW_MODE_SUPPORT = 10,
|
||||
|
||||
/* Firmware Supports Adaptive CCA*/
|
||||
ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA = 11,
|
||||
|
||||
/* keep last */
|
||||
ATH10K_FW_FEATURE_COUNT,
|
||||
};
|
||||
@ -730,8 +745,6 @@ struct ath10k {
|
||||
int num_started_vdevs;
|
||||
|
||||
/* Protected by conf-mutex */
|
||||
u8 supp_tx_chainmask;
|
||||
u8 supp_rx_chainmask;
|
||||
u8 cfg_tx_chainmask;
|
||||
u8 cfg_rx_chainmask;
|
||||
|
||||
@ -814,9 +827,12 @@ struct ath10k {
|
||||
struct {
|
||||
/* protected by conf_mutex */
|
||||
const struct firmware *utf;
|
||||
char utf_version[32];
|
||||
const void *utf_firmware_data;
|
||||
size_t utf_firmware_len;
|
||||
DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT);
|
||||
enum ath10k_fw_wmi_op_version orig_wmi_op_version;
|
||||
|
||||
enum ath10k_fw_wmi_op_version op_version;
|
||||
/* protected by data_lock */
|
||||
bool utf_monitor;
|
||||
} testmode;
|
||||
|
@ -84,6 +84,15 @@ enum qca6174_chip_id_rev {
|
||||
#define QCA99X0_HW_2_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA99X0_HW_2_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
/* QCA9377 1.0 definitions */
|
||||
#define QCA9377_HW_1_0_DEV_VERSION 0x05020001
|
||||
#define QCA9377_HW_1_0_CHIP_ID_REV 0x1
|
||||
#define QCA9377_HW_1_0_FW_DIR ATH10K_FW_DIR "/QCA9377/hw1.0"
|
||||
#define QCA9377_HW_1_0_FW_FILE "firmware.bin"
|
||||
#define QCA9377_HW_1_0_OTP_FILE "otp.bin"
|
||||
#define QCA9377_HW_1_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA9377_HW_1_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
#define ATH10K_FW_API2_FILE "firmware-2.bin"
|
||||
#define ATH10K_FW_API3_FILE "firmware-3.bin"
|
||||
|
||||
@ -94,6 +103,7 @@ enum qca6174_chip_id_rev {
|
||||
#define ATH10K_FW_API5_FILE "firmware-5.bin"
|
||||
|
||||
#define ATH10K_FW_UTF_FILE "utf.bin"
|
||||
#define ATH10K_FW_UTF_API2_FILE "utf-2.bin"
|
||||
|
||||
/* includes also the null byte */
|
||||
#define ATH10K_FIRMWARE_MAGIC "QCA-ATH10K"
|
||||
@ -176,6 +186,7 @@ enum ath10k_hw_rev {
|
||||
ATH10K_HW_QCA988X,
|
||||
ATH10K_HW_QCA6174,
|
||||
ATH10K_HW_QCA99X0,
|
||||
ATH10K_HW_QCA9377,
|
||||
};
|
||||
|
||||
struct ath10k_hw_regs {
|
||||
@ -228,6 +239,7 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
|
||||
#define QCA_REV_988X(ar) ((ar)->hw_rev == ATH10K_HW_QCA988X)
|
||||
#define QCA_REV_6174(ar) ((ar)->hw_rev == ATH10K_HW_QCA6174)
|
||||
#define QCA_REV_99X0(ar) ((ar)->hw_rev == ATH10K_HW_QCA99X0)
|
||||
#define QCA_REV_9377(ar) ((ar)->hw_rev == ATH10K_HW_QCA9377)
|
||||
|
||||
/* Known pecularities:
|
||||
* - raw appears in nwifi decap, raw and nwifi appear in ethernet decap
|
||||
|
@ -3736,13 +3736,8 @@ static int ath10k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (ar->cfg_tx_chainmask) {
|
||||
*tx_ant = ar->cfg_tx_chainmask;
|
||||
*rx_ant = ar->cfg_rx_chainmask;
|
||||
} else {
|
||||
*tx_ant = ar->supp_tx_chainmask;
|
||||
*rx_ant = ar->supp_rx_chainmask;
|
||||
}
|
||||
*tx_ant = ar->cfg_tx_chainmask;
|
||||
*rx_ant = ar->cfg_rx_chainmask;
|
||||
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
@ -3762,6 +3757,169 @@ static void ath10k_check_chain_mask(struct ath10k *ar, u32 cm, const char *dbg)
|
||||
dbg, cm);
|
||||
}
|
||||
|
||||
static int ath10k_mac_get_vht_cap_bf_sts(struct ath10k *ar)
|
||||
{
|
||||
int nsts = ar->vht_cap_info;
|
||||
|
||||
nsts &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
|
||||
nsts >>= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;
|
||||
|
||||
/* If firmware does not deliver to host number of space-time
|
||||
* streams supported, assume it support up to 4 BF STS and return
|
||||
* the value for VHT CAP: nsts-1)
|
||||
*/
|
||||
if (nsts == 0)
|
||||
return 3;
|
||||
|
||||
return nsts;
|
||||
}
|
||||
|
||||
static int ath10k_mac_get_vht_cap_bf_sound_dim(struct ath10k *ar)
|
||||
{
|
||||
int sound_dim = ar->vht_cap_info;
|
||||
|
||||
sound_dim &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK;
|
||||
sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;
|
||||
|
||||
/* If the sounding dimension is not advertised by the firmware,
|
||||
* let's use a default value of 1
|
||||
*/
|
||||
if (sound_dim == 0)
|
||||
return 1;
|
||||
|
||||
return sound_dim;
|
||||
}
|
||||
|
||||
static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
|
||||
{
|
||||
struct ieee80211_sta_vht_cap vht_cap = {0};
|
||||
u16 mcs_map;
|
||||
u32 val;
|
||||
int i;
|
||||
|
||||
vht_cap.vht_supported = 1;
|
||||
vht_cap.cap = ar->vht_cap_info;
|
||||
|
||||
if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
|
||||
IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) {
|
||||
val = ath10k_mac_get_vht_cap_bf_sts(ar);
|
||||
val <<= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;
|
||||
val &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
|
||||
|
||||
vht_cap.cap |= val;
|
||||
}
|
||||
|
||||
if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
|
||||
IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) {
|
||||
val = ath10k_mac_get_vht_cap_bf_sound_dim(ar);
|
||||
val <<= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;
|
||||
val &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK;
|
||||
|
||||
vht_cap.cap |= val;
|
||||
}
|
||||
|
||||
mcs_map = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if ((i < ar->num_rf_chains) && (ar->cfg_tx_chainmask & BIT(i)))
|
||||
mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2);
|
||||
else
|
||||
mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2);
|
||||
}
|
||||
|
||||
vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
|
||||
vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
|
||||
|
||||
return vht_cap;
|
||||
}
|
||||
|
||||
static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar)
|
||||
{
|
||||
int i;
|
||||
struct ieee80211_sta_ht_cap ht_cap = {0};
|
||||
|
||||
if (!(ar->ht_cap_info & WMI_HT_CAP_ENABLED))
|
||||
return ht_cap;
|
||||
|
||||
ht_cap.ht_supported = 1;
|
||||
ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
|
||||
ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
|
||||
ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
|
||||
ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
|
||||
ht_cap.cap |= WLAN_HT_CAP_SM_PS_STATIC << IEEE80211_HT_CAP_SM_PS_SHIFT;
|
||||
|
||||
if (ar->ht_cap_info & WMI_HT_CAP_HT20_SGI)
|
||||
ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
|
||||
|
||||
if (ar->ht_cap_info & WMI_HT_CAP_HT40_SGI)
|
||||
ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
|
||||
|
||||
if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS) {
|
||||
u32 smps;
|
||||
|
||||
smps = WLAN_HT_CAP_SM_PS_DYNAMIC;
|
||||
smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT;
|
||||
|
||||
ht_cap.cap |= smps;
|
||||
}
|
||||
|
||||
if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC)
|
||||
ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
|
||||
|
||||
if (ar->ht_cap_info & WMI_HT_CAP_RX_STBC) {
|
||||
u32 stbc;
|
||||
|
||||
stbc = ar->ht_cap_info;
|
||||
stbc &= WMI_HT_CAP_RX_STBC;
|
||||
stbc >>= WMI_HT_CAP_RX_STBC_MASK_SHIFT;
|
||||
stbc <<= IEEE80211_HT_CAP_RX_STBC_SHIFT;
|
||||
stbc &= IEEE80211_HT_CAP_RX_STBC;
|
||||
|
||||
ht_cap.cap |= stbc;
|
||||
}
|
||||
|
||||
if (ar->ht_cap_info & WMI_HT_CAP_LDPC)
|
||||
ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
|
||||
|
||||
if (ar->ht_cap_info & WMI_HT_CAP_L_SIG_TXOP_PROT)
|
||||
ht_cap.cap |= IEEE80211_HT_CAP_LSIG_TXOP_PROT;
|
||||
|
||||
/* max AMSDU is implicitly taken from vht_cap_info */
|
||||
if (ar->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_MASK)
|
||||
ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU;
|
||||
|
||||
for (i = 0; i < ar->num_rf_chains; i++) {
|
||||
if (ar->cfg_rx_chainmask & BIT(i))
|
||||
ht_cap.mcs.rx_mask[i] = 0xFF;
|
||||
}
|
||||
|
||||
ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
|
||||
|
||||
return ht_cap;
|
||||
}
|
||||
|
||||
static void ath10k_mac_setup_ht_vht_cap(struct ath10k *ar)
|
||||
{
|
||||
struct ieee80211_supported_band *band;
|
||||
struct ieee80211_sta_vht_cap vht_cap;
|
||||
struct ieee80211_sta_ht_cap ht_cap;
|
||||
|
||||
ht_cap = ath10k_get_ht_cap(ar);
|
||||
vht_cap = ath10k_create_vht_cap(ar);
|
||||
|
||||
if (ar->phy_capability & WHAL_WLAN_11G_CAPABILITY) {
|
||||
band = &ar->mac.sbands[IEEE80211_BAND_2GHZ];
|
||||
band->ht_cap = ht_cap;
|
||||
|
||||
/* Enable the VHT support at 2.4 GHz */
|
||||
band->vht_cap = vht_cap;
|
||||
}
|
||||
if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY) {
|
||||
band = &ar->mac.sbands[IEEE80211_BAND_5GHZ];
|
||||
band->ht_cap = ht_cap;
|
||||
band->vht_cap = vht_cap;
|
||||
}
|
||||
}
|
||||
|
||||
static int __ath10k_set_antenna(struct ath10k *ar, u32 tx_ant, u32 rx_ant)
|
||||
{
|
||||
int ret;
|
||||
@ -3794,6 +3952,9 @@ static int __ath10k_set_antenna(struct ath10k *ar, u32 tx_ant, u32 rx_ant)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Reload HT/VHT capability */
|
||||
ath10k_mac_setup_ht_vht_cap(ar);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3884,9 +4045,7 @@ static int ath10k_start(struct ieee80211_hw *hw)
|
||||
}
|
||||
}
|
||||
|
||||
if (ar->cfg_tx_chainmask)
|
||||
__ath10k_set_antenna(ar, ar->cfg_tx_chainmask,
|
||||
ar->cfg_rx_chainmask);
|
||||
__ath10k_set_antenna(ar, ar->cfg_tx_chainmask, ar->cfg_rx_chainmask);
|
||||
|
||||
/*
|
||||
* By default FW set ARP frames ac to voice (6). In that case ARP
|
||||
@ -3905,6 +4064,18 @@ static int ath10k_start(struct ieee80211_hw *hw)
|
||||
goto err_core_stop;
|
||||
}
|
||||
|
||||
if (test_bit(ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA,
|
||||
ar->fw_features)) {
|
||||
ret = ath10k_wmi_pdev_enable_adaptive_cca(ar, 1,
|
||||
WMI_CCA_DETECT_LEVEL_AUTO,
|
||||
WMI_CCA_DETECT_MARGIN_AUTO);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to enable adaptive cca: %d\n",
|
||||
ret);
|
||||
goto err_core_stop;
|
||||
}
|
||||
}
|
||||
|
||||
ret = ath10k_wmi_pdev_set_param(ar,
|
||||
ar->wmi.pdev_param->ani_enable, 1);
|
||||
if (ret) {
|
||||
@ -4063,39 +4234,6 @@ static u32 get_nss_from_chainmask(u16 chain_mask)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ath10k_mac_get_vht_cap_bf_sts(struct ath10k *ar)
|
||||
{
|
||||
int nsts = ar->vht_cap_info;
|
||||
|
||||
nsts &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
|
||||
nsts >>= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;
|
||||
|
||||
/* If firmware does not deliver to host number of space-time
|
||||
* streams supported, assume it support up to 4 BF STS and return
|
||||
* the value for VHT CAP: nsts-1)
|
||||
* */
|
||||
if (nsts == 0)
|
||||
return 3;
|
||||
|
||||
return nsts;
|
||||
}
|
||||
|
||||
static int ath10k_mac_get_vht_cap_bf_sound_dim(struct ath10k *ar)
|
||||
{
|
||||
int sound_dim = ar->vht_cap_info;
|
||||
|
||||
sound_dim &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK;
|
||||
sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;
|
||||
|
||||
/* If the sounding dimension is not advertised by the firmware,
|
||||
* let's use a default value of 1
|
||||
*/
|
||||
if (sound_dim == 0)
|
||||
return 1;
|
||||
|
||||
return sound_dim;
|
||||
}
|
||||
|
||||
static int ath10k_mac_set_txbf_conf(struct ath10k_vif *arvif)
|
||||
{
|
||||
u32 value = 0;
|
||||
@ -6949,111 +7087,6 @@ static const struct ieee80211_iface_combination ath10k_10_4_if_comb[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
|
||||
{
|
||||
struct ieee80211_sta_vht_cap vht_cap = {0};
|
||||
u16 mcs_map;
|
||||
u32 val;
|
||||
int i;
|
||||
|
||||
vht_cap.vht_supported = 1;
|
||||
vht_cap.cap = ar->vht_cap_info;
|
||||
|
||||
if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
|
||||
IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) {
|
||||
val = ath10k_mac_get_vht_cap_bf_sts(ar);
|
||||
val <<= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT;
|
||||
val &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
|
||||
|
||||
vht_cap.cap |= val;
|
||||
}
|
||||
|
||||
if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
|
||||
IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) {
|
||||
val = ath10k_mac_get_vht_cap_bf_sound_dim(ar);
|
||||
val <<= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;
|
||||
val &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK;
|
||||
|
||||
vht_cap.cap |= val;
|
||||
}
|
||||
|
||||
mcs_map = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (i < ar->num_rf_chains)
|
||||
mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i*2);
|
||||
else
|
||||
mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2);
|
||||
}
|
||||
|
||||
vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
|
||||
vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
|
||||
|
||||
return vht_cap;
|
||||
}
|
||||
|
||||
static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar)
|
||||
{
|
||||
int i;
|
||||
struct ieee80211_sta_ht_cap ht_cap = {0};
|
||||
|
||||
if (!(ar->ht_cap_info & WMI_HT_CAP_ENABLED))
|
||||
return ht_cap;
|
||||
|
||||
ht_cap.ht_supported = 1;
|
||||
ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
|
||||
ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
|
||||
ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
|
||||
ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
|
||||
ht_cap.cap |= WLAN_HT_CAP_SM_PS_STATIC << IEEE80211_HT_CAP_SM_PS_SHIFT;
|
||||
|
||||
if (ar->ht_cap_info & WMI_HT_CAP_HT20_SGI)
|
||||
ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
|
||||
|
||||
if (ar->ht_cap_info & WMI_HT_CAP_HT40_SGI)
|
||||
ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
|
||||
|
||||
if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS) {
|
||||
u32 smps;
|
||||
|
||||
smps = WLAN_HT_CAP_SM_PS_DYNAMIC;
|
||||
smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT;
|
||||
|
||||
ht_cap.cap |= smps;
|
||||
}
|
||||
|
||||
if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC)
|
||||
ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
|
||||
|
||||
if (ar->ht_cap_info & WMI_HT_CAP_RX_STBC) {
|
||||
u32 stbc;
|
||||
|
||||
stbc = ar->ht_cap_info;
|
||||
stbc &= WMI_HT_CAP_RX_STBC;
|
||||
stbc >>= WMI_HT_CAP_RX_STBC_MASK_SHIFT;
|
||||
stbc <<= IEEE80211_HT_CAP_RX_STBC_SHIFT;
|
||||
stbc &= IEEE80211_HT_CAP_RX_STBC;
|
||||
|
||||
ht_cap.cap |= stbc;
|
||||
}
|
||||
|
||||
if (ar->ht_cap_info & WMI_HT_CAP_LDPC)
|
||||
ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
|
||||
|
||||
if (ar->ht_cap_info & WMI_HT_CAP_L_SIG_TXOP_PROT)
|
||||
ht_cap.cap |= IEEE80211_HT_CAP_LSIG_TXOP_PROT;
|
||||
|
||||
/* max AMSDU is implicitly taken from vht_cap_info */
|
||||
if (ar->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_MASK)
|
||||
ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU;
|
||||
|
||||
for (i = 0; i < ar->num_rf_chains; i++)
|
||||
ht_cap.mcs.rx_mask[i] = 0xFF;
|
||||
|
||||
ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
|
||||
|
||||
return ht_cap;
|
||||
}
|
||||
|
||||
static void ath10k_get_arvif_iter(void *data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
@ -7095,8 +7128,6 @@ int ath10k_mac_register(struct ath10k *ar)
|
||||
WLAN_CIPHER_SUITE_AES_CMAC,
|
||||
};
|
||||
struct ieee80211_supported_band *band;
|
||||
struct ieee80211_sta_vht_cap vht_cap;
|
||||
struct ieee80211_sta_ht_cap ht_cap;
|
||||
void *channels;
|
||||
int ret;
|
||||
|
||||
@ -7104,9 +7135,6 @@ int ath10k_mac_register(struct ath10k *ar)
|
||||
|
||||
SET_IEEE80211_DEV(ar->hw, ar->dev);
|
||||
|
||||
ht_cap = ath10k_get_ht_cap(ar);
|
||||
vht_cap = ath10k_create_vht_cap(ar);
|
||||
|
||||
BUILD_BUG_ON((ARRAY_SIZE(ath10k_2ghz_channels) +
|
||||
ARRAY_SIZE(ath10k_5ghz_channels)) !=
|
||||
ATH10K_NUM_CHANS);
|
||||
@ -7125,10 +7153,6 @@ int ath10k_mac_register(struct ath10k *ar)
|
||||
band->channels = channels;
|
||||
band->n_bitrates = ath10k_g_rates_size;
|
||||
band->bitrates = ath10k_g_rates;
|
||||
band->ht_cap = ht_cap;
|
||||
|
||||
/* Enable the VHT support at 2.4 GHz */
|
||||
band->vht_cap = vht_cap;
|
||||
|
||||
ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = band;
|
||||
}
|
||||
@ -7147,18 +7171,18 @@ int ath10k_mac_register(struct ath10k *ar)
|
||||
band->channels = channels;
|
||||
band->n_bitrates = ath10k_a_rates_size;
|
||||
band->bitrates = ath10k_a_rates;
|
||||
band->ht_cap = ht_cap;
|
||||
band->vht_cap = vht_cap;
|
||||
ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = band;
|
||||
}
|
||||
|
||||
ath10k_mac_setup_ht_vht_cap(ar);
|
||||
|
||||
ar->hw->wiphy->interface_modes =
|
||||
BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_MESH_POINT);
|
||||
|
||||
ar->hw->wiphy->available_antennas_rx = ar->supp_rx_chainmask;
|
||||
ar->hw->wiphy->available_antennas_tx = ar->supp_tx_chainmask;
|
||||
ar->hw->wiphy->available_antennas_rx = ar->cfg_rx_chainmask;
|
||||
ar->hw->wiphy->available_antennas_tx = ar->cfg_tx_chainmask;
|
||||
|
||||
if (!test_bit(ATH10K_FW_FEATURE_NO_P2P, ar->fw_features))
|
||||
ar->hw->wiphy->interface_modes |=
|
||||
|
@ -61,12 +61,14 @@ MODULE_PARM_DESC(reset_mode, "0: auto, 1: warm only (default: 0)");
|
||||
#define QCA6164_2_1_DEVICE_ID (0x0041)
|
||||
#define QCA6174_2_1_DEVICE_ID (0x003e)
|
||||
#define QCA99X0_2_0_DEVICE_ID (0x0040)
|
||||
#define QCA9377_1_0_DEVICE_ID (0x0042)
|
||||
|
||||
static const struct pci_device_id ath10k_pci_id_table[] = {
|
||||
{ PCI_VDEVICE(ATHEROS, QCA988X_2_0_DEVICE_ID) }, /* PCI-E QCA988X V2 */
|
||||
{ PCI_VDEVICE(ATHEROS, QCA6164_2_1_DEVICE_ID) }, /* PCI-E QCA6164 V2.1 */
|
||||
{ PCI_VDEVICE(ATHEROS, QCA6174_2_1_DEVICE_ID) }, /* PCI-E QCA6174 V2.1 */
|
||||
{ PCI_VDEVICE(ATHEROS, QCA99X0_2_0_DEVICE_ID) }, /* PCI-E QCA99X0 V2 */
|
||||
{ PCI_VDEVICE(ATHEROS, QCA9377_1_0_DEVICE_ID) }, /* PCI-E QCA9377 V1 */
|
||||
{0}
|
||||
};
|
||||
|
||||
@ -90,6 +92,7 @@ static const struct ath10k_pci_supp_chip ath10k_pci_supp_chips[] = {
|
||||
{ QCA6174_2_1_DEVICE_ID, QCA6174_HW_3_2_CHIP_ID_REV },
|
||||
|
||||
{ QCA99X0_2_0_DEVICE_ID, QCA99X0_HW_2_0_CHIP_ID_REV },
|
||||
{ QCA9377_1_0_DEVICE_ID, QCA9377_HW_1_0_CHIP_ID_REV },
|
||||
};
|
||||
|
||||
static void ath10k_pci_buffer_cleanup(struct ath10k *ar);
|
||||
@ -827,6 +830,7 @@ static u32 ath10k_pci_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr)
|
||||
switch (ar->hw_rev) {
|
||||
case ATH10K_HW_QCA988X:
|
||||
case ATH10K_HW_QCA6174:
|
||||
case ATH10K_HW_QCA9377:
|
||||
val = (ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
|
||||
CORE_CTRL_ADDRESS) &
|
||||
0x7ff) << 21;
|
||||
@ -910,9 +914,8 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
|
||||
goto done;
|
||||
|
||||
i = 0;
|
||||
while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf,
|
||||
&completed_nbytes,
|
||||
&id) != 0) {
|
||||
while (ath10k_ce_completed_send_next_nolock(ce_diag,
|
||||
NULL) != 0) {
|
||||
mdelay(1);
|
||||
if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
|
||||
ret = -EBUSY;
|
||||
@ -920,16 +923,6 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
|
||||
}
|
||||
}
|
||||
|
||||
if (nbytes != completed_nbytes) {
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (buf != (u32)address) {
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf,
|
||||
&completed_nbytes,
|
||||
@ -1083,9 +1076,8 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
|
||||
goto done;
|
||||
|
||||
i = 0;
|
||||
while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf,
|
||||
&completed_nbytes,
|
||||
&id) != 0) {
|
||||
while (ath10k_ce_completed_send_next_nolock(ce_diag,
|
||||
NULL) != 0) {
|
||||
mdelay(1);
|
||||
|
||||
if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
|
||||
@ -1094,16 +1086,6 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
|
||||
}
|
||||
}
|
||||
|
||||
if (nbytes != completed_nbytes) {
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (buf != ce_data) {
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf,
|
||||
&completed_nbytes,
|
||||
@ -1159,13 +1141,9 @@ static void ath10k_pci_htc_tx_cb(struct ath10k_ce_pipe *ce_state)
|
||||
struct ath10k *ar = ce_state->ar;
|
||||
struct sk_buff_head list;
|
||||
struct sk_buff *skb;
|
||||
u32 ce_data;
|
||||
unsigned int nbytes;
|
||||
unsigned int transfer_id;
|
||||
|
||||
__skb_queue_head_init(&list);
|
||||
while (ath10k_ce_completed_send_next(ce_state, (void **)&skb, &ce_data,
|
||||
&nbytes, &transfer_id) == 0) {
|
||||
while (ath10k_ce_completed_send_next(ce_state, (void **)&skb) == 0) {
|
||||
/* no need to call tx completion for NULL pointers */
|
||||
if (skb == NULL)
|
||||
continue;
|
||||
@ -1235,12 +1213,8 @@ static void ath10k_pci_htt_tx_cb(struct ath10k_ce_pipe *ce_state)
|
||||
{
|
||||
struct ath10k *ar = ce_state->ar;
|
||||
struct sk_buff *skb;
|
||||
u32 ce_data;
|
||||
unsigned int nbytes;
|
||||
unsigned int transfer_id;
|
||||
|
||||
while (ath10k_ce_completed_send_next(ce_state, (void **)&skb, &ce_data,
|
||||
&nbytes, &transfer_id) == 0) {
|
||||
while (ath10k_ce_completed_send_next(ce_state, (void **)&skb) == 0) {
|
||||
/* no need to call tx completion for NULL pointers */
|
||||
if (!skb)
|
||||
continue;
|
||||
@ -1513,6 +1487,7 @@ static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar)
|
||||
switch (ar->hw_rev) {
|
||||
case ATH10K_HW_QCA988X:
|
||||
case ATH10K_HW_QCA6174:
|
||||
case ATH10K_HW_QCA9377:
|
||||
val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
|
||||
CORE_CTRL_ADDRESS);
|
||||
val &= ~CORE_CTRL_PCIE_REG_31_MASK;
|
||||
@ -1534,6 +1509,7 @@ static void ath10k_pci_irq_msi_fw_unmask(struct ath10k *ar)
|
||||
switch (ar->hw_rev) {
|
||||
case ATH10K_HW_QCA988X:
|
||||
case ATH10K_HW_QCA6174:
|
||||
case ATH10K_HW_QCA9377:
|
||||
val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
|
||||
CORE_CTRL_ADDRESS);
|
||||
val |= CORE_CTRL_PCIE_REG_31_MASK;
|
||||
@ -1624,7 +1600,6 @@ static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe)
|
||||
struct ath10k_pci *ar_pci;
|
||||
struct ath10k_ce_pipe *ce_pipe;
|
||||
struct ath10k_ce_ring *ce_ring;
|
||||
struct ce_desc *ce_desc;
|
||||
struct sk_buff *skb;
|
||||
int i;
|
||||
|
||||
@ -1639,10 +1614,6 @@ static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe)
|
||||
if (!pci_pipe->buf_sz)
|
||||
return;
|
||||
|
||||
ce_desc = ce_ring->shadow_base;
|
||||
if (WARN_ON(!ce_desc))
|
||||
return;
|
||||
|
||||
for (i = 0; i < ce_ring->nentries; i++) {
|
||||
skb = ce_ring->per_transfer_context[i];
|
||||
if (!skb)
|
||||
@ -1816,12 +1787,8 @@ err_dma:
|
||||
static void ath10k_pci_bmi_send_done(struct ath10k_ce_pipe *ce_state)
|
||||
{
|
||||
struct bmi_xfer *xfer;
|
||||
u32 ce_data;
|
||||
unsigned int nbytes;
|
||||
unsigned int transfer_id;
|
||||
|
||||
if (ath10k_ce_completed_send_next(ce_state, (void **)&xfer, &ce_data,
|
||||
&nbytes, &transfer_id))
|
||||
if (ath10k_ce_completed_send_next(ce_state, (void **)&xfer))
|
||||
return;
|
||||
|
||||
xfer->tx_done = true;
|
||||
@ -1911,6 +1878,8 @@ static int ath10k_pci_get_num_banks(struct ath10k *ar)
|
||||
return 9;
|
||||
}
|
||||
break;
|
||||
case QCA9377_1_0_DEVICE_ID:
|
||||
return 2;
|
||||
}
|
||||
|
||||
ath10k_warn(ar, "unknown number of banks, assuming 1\n");
|
||||
@ -2371,6 +2340,8 @@ static int ath10k_pci_chip_reset(struct ath10k *ar)
|
||||
return ath10k_pci_qca988x_chip_reset(ar);
|
||||
else if (QCA_REV_6174(ar))
|
||||
return ath10k_pci_qca6174_chip_reset(ar);
|
||||
else if (QCA_REV_9377(ar))
|
||||
return ath10k_pci_qca6174_chip_reset(ar);
|
||||
else if (QCA_REV_99X0(ar))
|
||||
return ath10k_pci_qca99x0_chip_reset(ar);
|
||||
else
|
||||
@ -3003,6 +2974,10 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
|
||||
hw_rev = ATH10K_HW_QCA99X0;
|
||||
pci_ps = false;
|
||||
break;
|
||||
case QCA9377_1_0_DEVICE_ID:
|
||||
hw_rev = ATH10K_HW_QCA9377;
|
||||
pci_ps = true;
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
return -ENOTSUPP;
|
||||
@ -3204,3 +3179,7 @@ MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_FW_API4_FILE);
|
||||
MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_FW_API5_FILE);
|
||||
MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" QCA6174_HW_3_0_BOARD_DATA_FILE);
|
||||
MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_BOARD_API2_FILE);
|
||||
|
||||
/* QCA9377 1.0 firmware files */
|
||||
MODULE_FIRMWARE(QCA9377_HW_1_0_FW_DIR "/" ATH10K_FW_API5_FILE);
|
||||
MODULE_FIRMWARE(QCA9377_HW_1_0_FW_DIR "/" QCA9377_HW_1_0_BOARD_DATA_FILE);
|
||||
|
@ -450,6 +450,9 @@ Fw Mode/SubMode Mask
|
||||
#define QCA6174_BOARD_DATA_SZ 8192
|
||||
#define QCA6174_BOARD_EXT_DATA_SZ 0
|
||||
|
||||
#define QCA9377_BOARD_DATA_SZ QCA6174_BOARD_DATA_SZ
|
||||
#define QCA9377_BOARD_EXT_DATA_SZ 0
|
||||
|
||||
#define QCA99X0_BOARD_DATA_SZ 12288
|
||||
#define QCA99X0_BOARD_EXT_DATA_SZ 0
|
||||
|
||||
|
@ -139,11 +139,181 @@ static int ath10k_tm_cmd_get_version(struct ath10k *ar, struct nlattr *tb[])
|
||||
return cfg80211_testmode_reply(skb);
|
||||
}
|
||||
|
||||
static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
|
||||
static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar)
|
||||
{
|
||||
size_t len, magic_len, ie_len;
|
||||
struct ath10k_fw_ie *hdr;
|
||||
char filename[100];
|
||||
__le32 *version;
|
||||
const u8 *data;
|
||||
int ie_id, ret;
|
||||
|
||||
snprintf(filename, sizeof(filename), "%s/%s",
|
||||
ar->hw_params.fw.dir, ATH10K_FW_UTF_API2_FILE);
|
||||
|
||||
/* load utf firmware image */
|
||||
ret = request_firmware(&ar->testmode.utf, filename, ar->dev);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n",
|
||||
filename, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
data = ar->testmode.utf->data;
|
||||
len = ar->testmode.utf->size;
|
||||
|
||||
/* FIXME: call release_firmware() in error cases */
|
||||
|
||||
/* magic also includes the null byte, check that as well */
|
||||
magic_len = strlen(ATH10K_FIRMWARE_MAGIC) + 1;
|
||||
|
||||
if (len < magic_len) {
|
||||
ath10k_err(ar, "utf firmware file is too small to contain magic\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (memcmp(data, ATH10K_FIRMWARE_MAGIC, magic_len) != 0) {
|
||||
ath10k_err(ar, "invalid firmware magic\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* jump over the padding */
|
||||
magic_len = ALIGN(magic_len, 4);
|
||||
|
||||
len -= magic_len;
|
||||
data += magic_len;
|
||||
|
||||
/* loop elements */
|
||||
while (len > sizeof(struct ath10k_fw_ie)) {
|
||||
hdr = (struct ath10k_fw_ie *)data;
|
||||
|
||||
ie_id = le32_to_cpu(hdr->id);
|
||||
ie_len = le32_to_cpu(hdr->len);
|
||||
|
||||
len -= sizeof(*hdr);
|
||||
data += sizeof(*hdr);
|
||||
|
||||
if (len < ie_len) {
|
||||
ath10k_err(ar, "invalid length for FW IE %d (%zu < %zu)\n",
|
||||
ie_id, len, ie_len);
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
switch (ie_id) {
|
||||
case ATH10K_FW_IE_FW_VERSION:
|
||||
if (ie_len > sizeof(ar->testmode.utf_version) - 1)
|
||||
break;
|
||||
|
||||
memcpy(ar->testmode.utf_version, data, ie_len);
|
||||
ar->testmode.utf_version[ie_len] = '\0';
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
|
||||
"testmode found fw utf version %s\n",
|
||||
ar->testmode.utf_version);
|
||||
break;
|
||||
case ATH10K_FW_IE_TIMESTAMP:
|
||||
/* ignore timestamp, but don't warn about it either */
|
||||
break;
|
||||
case ATH10K_FW_IE_FW_IMAGE:
|
||||
ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
|
||||
"testmode found fw image ie (%zd B)\n",
|
||||
ie_len);
|
||||
|
||||
ar->testmode.utf_firmware_data = data;
|
||||
ar->testmode.utf_firmware_len = ie_len;
|
||||
break;
|
||||
case ATH10K_FW_IE_WMI_OP_VERSION:
|
||||
if (ie_len != sizeof(u32))
|
||||
break;
|
||||
version = (__le32 *)data;
|
||||
ar->testmode.op_version = le32_to_cpup(version);
|
||||
ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode found fw ie wmi op version %d\n",
|
||||
ar->testmode.op_version);
|
||||
break;
|
||||
default:
|
||||
ath10k_warn(ar, "Unknown testmode FW IE: %u\n",
|
||||
le32_to_cpu(hdr->id));
|
||||
break;
|
||||
}
|
||||
/* jump over the padding */
|
||||
ie_len = ALIGN(ie_len, 4);
|
||||
|
||||
len -= ie_len;
|
||||
data += ie_len;
|
||||
}
|
||||
|
||||
if (!ar->testmode.utf_firmware_data || !ar->testmode.utf_firmware_len) {
|
||||
ath10k_err(ar, "No ATH10K_FW_IE_FW_IMAGE found\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
release_firmware(ar->testmode.utf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar)
|
||||
{
|
||||
char filename[100];
|
||||
int ret;
|
||||
|
||||
snprintf(filename, sizeof(filename), "%s/%s",
|
||||
ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE);
|
||||
|
||||
/* load utf firmware image */
|
||||
ret = request_firmware(&ar->testmode.utf, filename, ar->dev);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n",
|
||||
filename, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* We didn't find FW UTF API 1 ("utf.bin") does not advertise
|
||||
* firmware features. Do an ugly hack where we force the firmware
|
||||
* features to match with 10.1 branch so that wmi.c will use the
|
||||
* correct WMI interface.
|
||||
*/
|
||||
|
||||
ar->testmode.op_version = ATH10K_FW_WMI_OP_VERSION_10_1;
|
||||
ar->testmode.utf_firmware_data = ar->testmode.utf->data;
|
||||
ar->testmode.utf_firmware_len = ar->testmode.utf->size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_tm_fetch_firmware(struct ath10k *ar)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ath10k_tm_fetch_utf_firmware_api_2(ar);
|
||||
if (ret == 0) {
|
||||
ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using fw utf api 2");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = ath10k_tm_fetch_utf_firmware_api_1(ar);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to fetch utf firmware binary: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using utf api 1");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
|
||||
{
|
||||
const char *ver;
|
||||
int ret;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf start\n");
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
@ -165,36 +335,27 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
|
||||
goto err;
|
||||
}
|
||||
|
||||
snprintf(filename, sizeof(filename), "%s/%s",
|
||||
ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE);
|
||||
|
||||
/* load utf firmware image */
|
||||
ret = request_firmware(&ar->testmode.utf, filename, ar->dev);
|
||||
ret = ath10k_tm_fetch_firmware(ar);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n",
|
||||
filename, ret);
|
||||
ath10k_err(ar, "failed to fetch UTF firmware: %d", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
ar->testmode.utf_monitor = true;
|
||||
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
BUILD_BUG_ON(sizeof(ar->fw_features) !=
|
||||
sizeof(ar->testmode.orig_fw_features));
|
||||
|
||||
memcpy(ar->testmode.orig_fw_features, ar->fw_features,
|
||||
sizeof(ar->fw_features));
|
||||
ar->testmode.orig_wmi_op_version = ar->wmi.op_version;
|
||||
|
||||
/* utf.bin firmware image does not advertise firmware features. Do
|
||||
* an ugly hack where we force the firmware features so that wmi.c
|
||||
* will use the correct WMI interface.
|
||||
*/
|
||||
memset(ar->fw_features, 0, sizeof(ar->fw_features));
|
||||
ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_1;
|
||||
|
||||
ar->wmi.op_version = ar->testmode.op_version;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode wmi version %d\n",
|
||||
ar->wmi.op_version);
|
||||
|
||||
ret = ath10k_hif_power_up(ar);
|
||||
if (ret) {
|
||||
@ -212,7 +373,12 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
|
||||
|
||||
ar->state = ATH10K_STATE_UTF;
|
||||
|
||||
ath10k_info(ar, "UTF firmware started\n");
|
||||
if (strlen(ar->testmode.utf_version) > 0)
|
||||
ver = ar->testmode.utf_version;
|
||||
else
|
||||
ver = "API 1";
|
||||
|
||||
ath10k_info(ar, "UTF firmware %s started\n", ver);
|
||||
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
|
@ -182,6 +182,10 @@ struct wmi_ops {
|
||||
void (*fw_stats_fill)(struct ath10k *ar,
|
||||
struct ath10k_fw_stats *fw_stats,
|
||||
char *buf);
|
||||
struct sk_buff *(*gen_pdev_enable_adaptive_cca)(struct ath10k *ar,
|
||||
u8 enable,
|
||||
u32 detect_level,
|
||||
u32 detect_margin);
|
||||
};
|
||||
|
||||
int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
|
||||
@ -1302,4 +1306,25 @@ ath10k_wmi_fw_stats_fill(struct ath10k *ar, struct ath10k_fw_stats *fw_stats,
|
||||
ar->wmi.ops->fw_stats_fill(ar, fw_stats, buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ath10k_wmi_pdev_enable_adaptive_cca(struct ath10k *ar, u8 enable,
|
||||
u32 detect_level, u32 detect_margin)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (!ar->wmi.ops->gen_pdev_enable_adaptive_cca)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
skb = ar->wmi.ops->gen_pdev_enable_adaptive_cca(ar, enable,
|
||||
detect_level,
|
||||
detect_margin);
|
||||
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
return ath10k_wmi_cmd_send(ar, skb,
|
||||
ar->wmi.cmd->pdev_enable_adaptive_cca_cmdid);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "wmi-ops.h"
|
||||
#include "wmi-tlv.h"
|
||||
#include "p2p.h"
|
||||
#include "testmode.h"
|
||||
|
||||
/***************/
|
||||
/* TLV helpers */
|
||||
@ -419,6 +420,7 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
|
||||
{
|
||||
struct wmi_cmd_hdr *cmd_hdr;
|
||||
enum wmi_tlv_event_id id;
|
||||
bool consumed;
|
||||
|
||||
cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
|
||||
id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
|
||||
@ -428,6 +430,18 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
|
||||
|
||||
trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
|
||||
|
||||
consumed = ath10k_tm_event_wmi(ar, id, skb);
|
||||
|
||||
/* Ready event must be handled normally also in UTF mode so that we
|
||||
* know the UTF firmware has booted, others we are just bypass WMI
|
||||
* events to testmode.
|
||||
*/
|
||||
if (consumed && id != WMI_TLV_READY_EVENTID) {
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI,
|
||||
"wmi tlv testmode consumed 0x%x\n", id);
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (id) {
|
||||
case WMI_TLV_MGMT_RX_EVENTID:
|
||||
ath10k_wmi_event_mgmt_rx(ar, skb);
|
||||
|
@ -148,6 +148,7 @@ static struct wmi_cmd_map wmi_cmd_map = {
|
||||
.gpio_config_cmdid = WMI_GPIO_CONFIG_CMDID,
|
||||
.gpio_output_cmdid = WMI_GPIO_OUTPUT_CMDID,
|
||||
.pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.pdev_enable_adaptive_cca_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.scan_update_request_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
@ -313,6 +314,7 @@ static struct wmi_cmd_map wmi_10x_cmd_map = {
|
||||
.gpio_config_cmdid = WMI_10X_GPIO_CONFIG_CMDID,
|
||||
.gpio_output_cmdid = WMI_10X_GPIO_OUTPUT_CMDID,
|
||||
.pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.pdev_enable_adaptive_cca_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.scan_update_request_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
@ -477,6 +479,7 @@ static struct wmi_cmd_map wmi_10_2_4_cmd_map = {
|
||||
.gpio_config_cmdid = WMI_10_2_GPIO_CONFIG_CMDID,
|
||||
.gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID,
|
||||
.pdev_get_temperature_cmdid = WMI_10_2_PDEV_GET_TEMPERATURE_CMDID,
|
||||
.pdev_enable_adaptive_cca_cmdid = WMI_10_2_SET_CCA_PARAMS,
|
||||
.scan_update_request_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
@ -1407,6 +1410,7 @@ static struct wmi_cmd_map wmi_10_2_cmd_map = {
|
||||
.gpio_config_cmdid = WMI_10_2_GPIO_CONFIG_CMDID,
|
||||
.gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID,
|
||||
.pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.pdev_enable_adaptive_cca_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.scan_update_request_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
.vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED,
|
||||
@ -2475,6 +2479,47 @@ void ath10k_wmi_pull_pdev_stats_tx(const struct wmi_pdev_stats_tx *src,
|
||||
dst->txop_ovf = __le32_to_cpu(src->txop_ovf);
|
||||
}
|
||||
|
||||
static void
|
||||
ath10k_wmi_10_4_pull_pdev_stats_tx(const struct wmi_10_4_pdev_stats_tx *src,
|
||||
struct ath10k_fw_stats_pdev *dst)
|
||||
{
|
||||
dst->comp_queued = __le32_to_cpu(src->comp_queued);
|
||||
dst->comp_delivered = __le32_to_cpu(src->comp_delivered);
|
||||
dst->msdu_enqued = __le32_to_cpu(src->msdu_enqued);
|
||||
dst->mpdu_enqued = __le32_to_cpu(src->mpdu_enqued);
|
||||
dst->wmm_drop = __le32_to_cpu(src->wmm_drop);
|
||||
dst->local_enqued = __le32_to_cpu(src->local_enqued);
|
||||
dst->local_freed = __le32_to_cpu(src->local_freed);
|
||||
dst->hw_queued = __le32_to_cpu(src->hw_queued);
|
||||
dst->hw_reaped = __le32_to_cpu(src->hw_reaped);
|
||||
dst->underrun = __le32_to_cpu(src->underrun);
|
||||
dst->tx_abort = __le32_to_cpu(src->tx_abort);
|
||||
dst->mpdus_requed = __le32_to_cpu(src->mpdus_requed);
|
||||
dst->tx_ko = __le32_to_cpu(src->tx_ko);
|
||||
dst->data_rc = __le32_to_cpu(src->data_rc);
|
||||
dst->self_triggers = __le32_to_cpu(src->self_triggers);
|
||||
dst->sw_retry_failure = __le32_to_cpu(src->sw_retry_failure);
|
||||
dst->illgl_rate_phy_err = __le32_to_cpu(src->illgl_rate_phy_err);
|
||||
dst->pdev_cont_xretry = __le32_to_cpu(src->pdev_cont_xretry);
|
||||
dst->pdev_tx_timeout = __le32_to_cpu(src->pdev_tx_timeout);
|
||||
dst->pdev_resets = __le32_to_cpu(src->pdev_resets);
|
||||
dst->phy_underrun = __le32_to_cpu(src->phy_underrun);
|
||||
dst->txop_ovf = __le32_to_cpu(src->txop_ovf);
|
||||
dst->hw_paused = __le32_to_cpu(src->hw_paused);
|
||||
dst->seq_posted = __le32_to_cpu(src->seq_posted);
|
||||
dst->seq_failed_queueing =
|
||||
__le32_to_cpu(src->seq_failed_queueing);
|
||||
dst->seq_completed = __le32_to_cpu(src->seq_completed);
|
||||
dst->seq_restarted = __le32_to_cpu(src->seq_restarted);
|
||||
dst->mu_seq_posted = __le32_to_cpu(src->mu_seq_posted);
|
||||
dst->mpdus_sw_flush = __le32_to_cpu(src->mpdus_sw_flush);
|
||||
dst->mpdus_hw_filter = __le32_to_cpu(src->mpdus_hw_filter);
|
||||
dst->mpdus_truncated = __le32_to_cpu(src->mpdus_truncated);
|
||||
dst->mpdus_ack_failed = __le32_to_cpu(src->mpdus_ack_failed);
|
||||
dst->mpdus_hw_filter = __le32_to_cpu(src->mpdus_hw_filter);
|
||||
dst->mpdus_expired = __le32_to_cpu(src->mpdus_expired);
|
||||
}
|
||||
|
||||
void ath10k_wmi_pull_pdev_stats_rx(const struct wmi_pdev_stats_rx *src,
|
||||
struct ath10k_fw_stats_pdev *dst)
|
||||
{
|
||||
@ -2785,6 +2830,86 @@ static int ath10k_wmi_10_2_4_op_pull_fw_stats(struct ath10k *ar,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar,
|
||||
struct sk_buff *skb,
|
||||
struct ath10k_fw_stats *stats)
|
||||
{
|
||||
const struct wmi_10_2_stats_event *ev = (void *)skb->data;
|
||||
u32 num_pdev_stats;
|
||||
u32 num_pdev_ext_stats;
|
||||
u32 num_vdev_stats;
|
||||
u32 num_peer_stats;
|
||||
int i;
|
||||
|
||||
if (!skb_pull(skb, sizeof(*ev)))
|
||||
return -EPROTO;
|
||||
|
||||
num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats);
|
||||
num_pdev_ext_stats = __le32_to_cpu(ev->num_pdev_ext_stats);
|
||||
num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
|
||||
num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
|
||||
|
||||
for (i = 0; i < num_pdev_stats; i++) {
|
||||
const struct wmi_10_4_pdev_stats *src;
|
||||
struct ath10k_fw_stats_pdev *dst;
|
||||
|
||||
src = (void *)skb->data;
|
||||
if (!skb_pull(skb, sizeof(*src)))
|
||||
return -EPROTO;
|
||||
|
||||
dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
|
||||
if (!dst)
|
||||
continue;
|
||||
|
||||
ath10k_wmi_pull_pdev_stats_base(&src->base, dst);
|
||||
ath10k_wmi_10_4_pull_pdev_stats_tx(&src->tx, dst);
|
||||
ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst);
|
||||
dst->rx_ovfl_errs = __le32_to_cpu(src->rx_ovfl_errs);
|
||||
ath10k_wmi_pull_pdev_stats_extra(&src->extra, dst);
|
||||
|
||||
list_add_tail(&dst->list, &stats->pdevs);
|
||||
}
|
||||
|
||||
for (i = 0; i < num_pdev_ext_stats; i++) {
|
||||
const struct wmi_10_2_pdev_ext_stats *src;
|
||||
|
||||
src = (void *)skb->data;
|
||||
if (!skb_pull(skb, sizeof(*src)))
|
||||
return -EPROTO;
|
||||
|
||||
/* FIXME: expose values to userspace
|
||||
*
|
||||
* Note: Even though this loop seems to do nothing it is
|
||||
* required to parse following sub-structures properly.
|
||||
*/
|
||||
}
|
||||
|
||||
/* fw doesn't implement vdev stats */
|
||||
|
||||
for (i = 0; i < num_peer_stats; i++) {
|
||||
const struct wmi_10_4_peer_stats *src;
|
||||
struct ath10k_fw_stats_peer *dst;
|
||||
|
||||
src = (void *)skb->data;
|
||||
if (!skb_pull(skb, sizeof(*src)))
|
||||
return -EPROTO;
|
||||
|
||||
dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
|
||||
if (!dst)
|
||||
continue;
|
||||
|
||||
ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr);
|
||||
dst->peer_rssi = __le32_to_cpu(src->peer_rssi);
|
||||
dst->peer_tx_rate = __le32_to_cpu(src->peer_tx_rate);
|
||||
dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
|
||||
/* FIXME: expose 10.4 specific values */
|
||||
|
||||
list_add_tail(&dst->list, &stats->peers);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ath10k_wmi_event_update_stats(struct ath10k *ar, struct sk_buff *skb)
|
||||
{
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_UPDATE_STATS_EVENTID\n");
|
||||
@ -4335,8 +4460,10 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work)
|
||||
ar->num_rf_chains = ar->max_spatial_stream;
|
||||
}
|
||||
|
||||
ar->supp_tx_chainmask = (1 << ar->num_rf_chains) - 1;
|
||||
ar->supp_rx_chainmask = (1 << ar->num_rf_chains) - 1;
|
||||
if (!ar->cfg_tx_chainmask) {
|
||||
ar->cfg_tx_chainmask = (1 << ar->num_rf_chains) - 1;
|
||||
ar->cfg_rx_chainmask = (1 << ar->num_rf_chains) - 1;
|
||||
}
|
||||
|
||||
if (strlen(ar->hw->wiphy->fw_version) == 0) {
|
||||
snprintf(ar->hw->wiphy->fw_version,
|
||||
@ -4931,6 +5058,9 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb)
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI,
|
||||
"received event id %d not implemented\n", id);
|
||||
break;
|
||||
case WMI_10_4_UPDATE_STATS_EVENTID:
|
||||
ath10k_wmi_event_update_stats(ar, skb);
|
||||
break;
|
||||
default:
|
||||
ath10k_warn(ar, "Unknown eventid: %d\n", id);
|
||||
break;
|
||||
@ -6996,6 +7126,112 @@ unlock:
|
||||
buf[len] = 0;
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
ath10k_wmi_op_gen_pdev_enable_adaptive_cca(struct ath10k *ar, u8 enable,
|
||||
u32 detect_level, u32 detect_margin)
|
||||
{
|
||||
struct wmi_pdev_set_adaptive_cca_params *cmd;
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
|
||||
if (!skb)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
cmd = (struct wmi_pdev_set_adaptive_cca_params *)skb->data;
|
||||
cmd->enable = __cpu_to_le32(enable);
|
||||
cmd->cca_detect_level = __cpu_to_le32(detect_level);
|
||||
cmd->cca_detect_margin = __cpu_to_le32(detect_margin);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI,
|
||||
"wmi pdev set adaptive cca params enable:%d detection level:%d detection margin:%d\n",
|
||||
enable, detect_level, detect_margin);
|
||||
return skb;
|
||||
}
|
||||
|
||||
void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
|
||||
struct ath10k_fw_stats *fw_stats,
|
||||
char *buf)
|
||||
{
|
||||
u32 len = 0;
|
||||
u32 buf_len = ATH10K_FW_STATS_BUF_SIZE;
|
||||
const struct ath10k_fw_stats_pdev *pdev;
|
||||
const struct ath10k_fw_stats_vdev *vdev;
|
||||
const struct ath10k_fw_stats_peer *peer;
|
||||
size_t num_peers;
|
||||
size_t num_vdevs;
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
pdev = list_first_entry_or_null(&fw_stats->pdevs,
|
||||
struct ath10k_fw_stats_pdev, list);
|
||||
if (!pdev) {
|
||||
ath10k_warn(ar, "failed to get pdev stats\n");
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers);
|
||||
num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs);
|
||||
|
||||
ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len);
|
||||
ath10k_wmi_fw_pdev_extra_stats_fill(pdev, buf, &len);
|
||||
ath10k_wmi_fw_pdev_tx_stats_fill(pdev, buf, &len);
|
||||
|
||||
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
||||
"HW paused", pdev->hw_paused);
|
||||
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
||||
"Seqs posted", pdev->seq_posted);
|
||||
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
||||
"Seqs failed queueing", pdev->seq_failed_queueing);
|
||||
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
||||
"Seqs completed", pdev->seq_completed);
|
||||
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
||||
"Seqs restarted", pdev->seq_restarted);
|
||||
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
||||
"MU Seqs posted", pdev->mu_seq_posted);
|
||||
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
||||
"MPDUs SW flushed", pdev->mpdus_sw_flush);
|
||||
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
||||
"MPDUs HW filtered", pdev->mpdus_hw_filter);
|
||||
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
||||
"MPDUs truncated", pdev->mpdus_truncated);
|
||||
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
||||
"MPDUs receive no ACK", pdev->mpdus_ack_failed);
|
||||
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
||||
"MPDUs expired", pdev->mpdus_expired);
|
||||
|
||||
ath10k_wmi_fw_pdev_rx_stats_fill(pdev, buf, &len);
|
||||
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
|
||||
"Num Rx Overflow errors", pdev->rx_ovfl_errs);
|
||||
|
||||
len += scnprintf(buf + len, buf_len - len, "\n");
|
||||
len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
|
||||
"ath10k VDEV stats", num_vdevs);
|
||||
len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
|
||||
"=================");
|
||||
|
||||
list_for_each_entry(vdev, &fw_stats->vdevs, list) {
|
||||
ath10k_wmi_fw_vdev_stats_fill(vdev, buf, &len);
|
||||
}
|
||||
|
||||
len += scnprintf(buf + len, buf_len - len, "\n");
|
||||
len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
|
||||
"ath10k PEER stats", num_peers);
|
||||
len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
|
||||
"=================");
|
||||
|
||||
list_for_each_entry(peer, &fw_stats->peers, list) {
|
||||
ath10k_wmi_fw_peer_stats_fill(peer, buf, &len);
|
||||
}
|
||||
|
||||
unlock:
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
if (len >= buf_len)
|
||||
buf[len - 1] = 0;
|
||||
else
|
||||
buf[len] = 0;
|
||||
}
|
||||
|
||||
static const struct wmi_ops wmi_ops = {
|
||||
.rx = ath10k_wmi_op_rx,
|
||||
.map_svc = wmi_main_svc_map,
|
||||
@ -7059,6 +7295,7 @@ static const struct wmi_ops wmi_ops = {
|
||||
/* .gen_prb_tmpl not implemented */
|
||||
/* .gen_p2p_go_bcn_ie not implemented */
|
||||
/* .gen_adaptive_qcs not implemented */
|
||||
/* .gen_pdev_enable_adaptive_cca not implemented */
|
||||
};
|
||||
|
||||
static const struct wmi_ops wmi_10_1_ops = {
|
||||
@ -7125,6 +7362,7 @@ static const struct wmi_ops wmi_10_1_ops = {
|
||||
/* .gen_prb_tmpl not implemented */
|
||||
/* .gen_p2p_go_bcn_ie not implemented */
|
||||
/* .gen_adaptive_qcs not implemented */
|
||||
/* .gen_pdev_enable_adaptive_cca not implemented */
|
||||
};
|
||||
|
||||
static const struct wmi_ops wmi_10_2_ops = {
|
||||
@ -7188,6 +7426,7 @@ static const struct wmi_ops wmi_10_2_ops = {
|
||||
.gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
|
||||
.gen_delba_send = ath10k_wmi_op_gen_delba_send,
|
||||
.fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill,
|
||||
/* .gen_pdev_enable_adaptive_cca not implemented */
|
||||
};
|
||||
|
||||
static const struct wmi_ops wmi_10_2_4_ops = {
|
||||
@ -7251,6 +7490,8 @@ static const struct wmi_ops wmi_10_2_4_ops = {
|
||||
.gen_delba_send = ath10k_wmi_op_gen_delba_send,
|
||||
.gen_pdev_get_tpc_config = ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config,
|
||||
.fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill,
|
||||
.gen_pdev_enable_adaptive_cca =
|
||||
ath10k_wmi_op_gen_pdev_enable_adaptive_cca,
|
||||
/* .gen_bcn_tmpl not implemented */
|
||||
/* .gen_prb_tmpl not implemented */
|
||||
/* .gen_p2p_go_bcn_ie not implemented */
|
||||
@ -7261,6 +7502,7 @@ static const struct wmi_ops wmi_10_4_ops = {
|
||||
.rx = ath10k_wmi_10_4_op_rx,
|
||||
.map_svc = wmi_10_4_svc_map,
|
||||
|
||||
.pull_fw_stats = ath10k_wmi_10_4_op_pull_fw_stats,
|
||||
.pull_scan = ath10k_wmi_op_pull_scan_ev,
|
||||
.pull_mgmt_rx = ath10k_wmi_10_4_op_pull_mgmt_rx_ev,
|
||||
.pull_ch_info = ath10k_wmi_10_4_op_pull_ch_info_ev,
|
||||
@ -7310,9 +7552,11 @@ static const struct wmi_ops wmi_10_4_ops = {
|
||||
.gen_addba_send = ath10k_wmi_op_gen_addba_send,
|
||||
.gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
|
||||
.gen_delba_send = ath10k_wmi_op_gen_delba_send,
|
||||
.fw_stats_fill = ath10k_wmi_10_4_op_fw_stats_fill,
|
||||
|
||||
/* shared with 10.2 */
|
||||
.gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc,
|
||||
.gen_request_stats = ath10k_wmi_op_gen_request_stats,
|
||||
};
|
||||
|
||||
int ath10k_wmi_attach(struct ath10k *ar)
|
||||
|
@ -772,6 +772,7 @@ struct wmi_cmd_map {
|
||||
u32 mu_cal_start_cmdid;
|
||||
u32 set_cca_params_cmdid;
|
||||
u32 pdev_bss_chan_info_request_cmdid;
|
||||
u32 pdev_enable_adaptive_cca_cmdid;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -1381,6 +1382,9 @@ enum wmi_10_2_cmd_id {
|
||||
WMI_10_2_VDEV_ATF_REQUEST_CMDID,
|
||||
WMI_10_2_PEER_ATF_REQUEST_CMDID,
|
||||
WMI_10_2_PDEV_GET_TEMPERATURE_CMDID,
|
||||
WMI_10_2_MU_CAL_START_CMDID,
|
||||
WMI_10_2_SET_LTEU_CONFIG_CMDID,
|
||||
WMI_10_2_SET_CCA_PARAMS,
|
||||
WMI_10_2_PDEV_UTF_CMDID = WMI_10_2_END_CMDID - 1,
|
||||
};
|
||||
|
||||
@ -3862,6 +3866,111 @@ struct wmi_pdev_stats_tx {
|
||||
__le32 txop_ovf;
|
||||
} __packed;
|
||||
|
||||
struct wmi_10_4_pdev_stats_tx {
|
||||
/* Num HTT cookies queued to dispatch list */
|
||||
__le32 comp_queued;
|
||||
|
||||
/* Num HTT cookies dispatched */
|
||||
__le32 comp_delivered;
|
||||
|
||||
/* Num MSDU queued to WAL */
|
||||
__le32 msdu_enqued;
|
||||
|
||||
/* Num MPDU queue to WAL */
|
||||
__le32 mpdu_enqued;
|
||||
|
||||
/* Num MSDUs dropped by WMM limit */
|
||||
__le32 wmm_drop;
|
||||
|
||||
/* Num Local frames queued */
|
||||
__le32 local_enqued;
|
||||
|
||||
/* Num Local frames done */
|
||||
__le32 local_freed;
|
||||
|
||||
/* Num queued to HW */
|
||||
__le32 hw_queued;
|
||||
|
||||
/* Num PPDU reaped from HW */
|
||||
__le32 hw_reaped;
|
||||
|
||||
/* Num underruns */
|
||||
__le32 underrun;
|
||||
|
||||
/* HW Paused. */
|
||||
__le32 hw_paused;
|
||||
|
||||
/* Num PPDUs cleaned up in TX abort */
|
||||
__le32 tx_abort;
|
||||
|
||||
/* Num MPDUs requed by SW */
|
||||
__le32 mpdus_requed;
|
||||
|
||||
/* excessive retries */
|
||||
__le32 tx_ko;
|
||||
|
||||
/* data hw rate code */
|
||||
__le32 data_rc;
|
||||
|
||||
/* Scheduler self triggers */
|
||||
__le32 self_triggers;
|
||||
|
||||
/* frames dropped due to excessive sw retries */
|
||||
__le32 sw_retry_failure;
|
||||
|
||||
/* illegal rate phy errors */
|
||||
__le32 illgl_rate_phy_err;
|
||||
|
||||
/* wal pdev continuous xretry */
|
||||
__le32 pdev_cont_xretry;
|
||||
|
||||
/* wal pdev tx timeouts */
|
||||
__le32 pdev_tx_timeout;
|
||||
|
||||
/* wal pdev resets */
|
||||
__le32 pdev_resets;
|
||||
|
||||
/* frames dropped due to non-availability of stateless TIDs */
|
||||
__le32 stateless_tid_alloc_failure;
|
||||
|
||||
__le32 phy_underrun;
|
||||
|
||||
/* MPDU is more than txop limit */
|
||||
__le32 txop_ovf;
|
||||
|
||||
/* Number of Sequences posted */
|
||||
__le32 seq_posted;
|
||||
|
||||
/* Number of Sequences failed queueing */
|
||||
__le32 seq_failed_queueing;
|
||||
|
||||
/* Number of Sequences completed */
|
||||
__le32 seq_completed;
|
||||
|
||||
/* Number of Sequences restarted */
|
||||
__le32 seq_restarted;
|
||||
|
||||
/* Number of MU Sequences posted */
|
||||
__le32 mu_seq_posted;
|
||||
|
||||
/* Num MPDUs flushed by SW, HWPAUSED,SW TXABORT(Reset,channel change) */
|
||||
__le32 mpdus_sw_flush;
|
||||
|
||||
/* Num MPDUs filtered by HW, all filter condition (TTL expired) */
|
||||
__le32 mpdus_hw_filter;
|
||||
|
||||
/* Num MPDUs truncated by PDG
|
||||
* (TXOP, TBTT, PPDU_duration based on rate, dyn_bw)
|
||||
*/
|
||||
__le32 mpdus_truncated;
|
||||
|
||||
/* Num MPDUs that was tried but didn't receive ACK or BA */
|
||||
__le32 mpdus_ack_failed;
|
||||
|
||||
/* Num MPDUs that was dropped due to expiry. */
|
||||
__le32 mpdus_expired;
|
||||
} __packed;
|
||||
|
||||
struct wmi_pdev_stats_rx {
|
||||
/* Cnts any change in ring routing mid-ppdu */
|
||||
__le32 mid_ppdu_route_change;
|
||||
@ -4035,6 +4144,16 @@ struct wmi_10_2_pdev_stats {
|
||||
struct wmi_pdev_stats_extra extra;
|
||||
} __packed;
|
||||
|
||||
struct wmi_10_4_pdev_stats {
|
||||
struct wmi_pdev_stats_base base;
|
||||
struct wmi_10_4_pdev_stats_tx tx;
|
||||
struct wmi_pdev_stats_rx rx;
|
||||
__le32 rx_ovfl_errs;
|
||||
struct wmi_pdev_stats_mem mem;
|
||||
__le32 sram_free_size;
|
||||
struct wmi_pdev_stats_extra extra;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* VDEV statistics
|
||||
* TODO: add all VDEV stats here
|
||||
@ -4076,6 +4195,23 @@ struct wmi_10_2_4_peer_stats {
|
||||
__le32 unknown_value; /* FIXME: what is this word? */
|
||||
} __packed;
|
||||
|
||||
struct wmi_10_4_peer_stats {
|
||||
struct wmi_mac_addr peer_macaddr;
|
||||
__le32 peer_rssi;
|
||||
__le32 peer_rssi_seq_num;
|
||||
__le32 peer_tx_rate;
|
||||
__le32 peer_rx_rate;
|
||||
__le32 current_per;
|
||||
__le32 retries;
|
||||
__le32 tx_rate_count;
|
||||
__le32 max_4ms_frame_len;
|
||||
__le32 total_sub_frames;
|
||||
__le32 tx_bytes;
|
||||
__le32 num_pkt_loss_overflow[4];
|
||||
__le32 num_pkt_loss_excess_retry[4];
|
||||
__le32 peer_rssi_changed;
|
||||
} __packed;
|
||||
|
||||
struct wmi_10_2_pdev_ext_stats {
|
||||
__le32 rx_rssi_comb;
|
||||
__le32 rx_rssi[4];
|
||||
@ -6094,6 +6230,15 @@ enum wmi_txbf_conf {
|
||||
WMI_TXBF_CONF_AFTER_ASSOC,
|
||||
};
|
||||
|
||||
#define WMI_CCA_DETECT_LEVEL_AUTO 0
|
||||
#define WMI_CCA_DETECT_MARGIN_AUTO 0
|
||||
|
||||
struct wmi_pdev_set_adaptive_cca_params {
|
||||
__le32 enable;
|
||||
__le32 cca_detect_level;
|
||||
__le32 cca_detect_margin;
|
||||
} __packed;
|
||||
|
||||
struct ath10k;
|
||||
struct ath10k_vif;
|
||||
struct ath10k_fw_stats_pdev;
|
||||
@ -6188,5 +6333,8 @@ void ath10k_wmi_10x_op_fw_stats_fill(struct ath10k *ar,
|
||||
char *buf);
|
||||
size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head);
|
||||
size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head);
|
||||
void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar,
|
||||
struct ath10k_fw_stats *fw_stats,
|
||||
char *buf);
|
||||
|
||||
#endif /* _WMI_H_ */
|
||||
|
@ -3231,6 +3231,15 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
wait, buf, len, no_cck);
|
||||
}
|
||||
|
||||
static int ath6kl_get_antenna(struct wiphy *wiphy,
|
||||
u32 *tx_ant, u32 *rx_ant)
|
||||
{
|
||||
struct ath6kl *ar = wiphy_priv(wiphy);
|
||||
*tx_ant = ar->hw.tx_ant;
|
||||
*rx_ant = ar->hw.rx_ant;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath6kl_mgmt_frame_register(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev,
|
||||
u16 frame_type, bool reg)
|
||||
@ -3447,6 +3456,7 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = {
|
||||
.cancel_remain_on_channel = ath6kl_cancel_remain_on_channel,
|
||||
.mgmt_tx = ath6kl_mgmt_tx,
|
||||
.mgmt_frame_register = ath6kl_mgmt_frame_register,
|
||||
.get_antenna = ath6kl_get_antenna,
|
||||
.sched_scan_start = ath6kl_cfg80211_sscan_start,
|
||||
.sched_scan_stop = ath6kl_cfg80211_sscan_stop,
|
||||
.set_bitrate_mask = ath6kl_cfg80211_set_bitrate,
|
||||
@ -3634,6 +3644,127 @@ void ath6kl_cfg80211_vif_cleanup(struct ath6kl_vif *vif)
|
||||
ar->num_vif--;
|
||||
}
|
||||
|
||||
static const char ath6kl_gstrings_sta_stats[][ETH_GSTRING_LEN] = {
|
||||
/* Common stats names used by many drivers. */
|
||||
"tx_pkts_nic", "tx_bytes_nic", "rx_pkts_nic", "rx_bytes_nic",
|
||||
|
||||
/* TX stats. */
|
||||
"d_tx_ucast_pkts", "d_tx_bcast_pkts",
|
||||
"d_tx_ucast_bytes", "d_tx_bcast_bytes",
|
||||
"d_tx_rts_ok", "d_tx_error", "d_tx_fail",
|
||||
"d_tx_retry", "d_tx_multi_retry", "d_tx_rts_fail",
|
||||
"d_tx_tkip_counter_measures",
|
||||
|
||||
/* RX Stats. */
|
||||
"d_rx_ucast_pkts", "d_rx_ucast_rate", "d_rx_bcast_pkts",
|
||||
"d_rx_ucast_bytes", "d_rx_bcast_bytes", "d_rx_frag_pkt",
|
||||
"d_rx_error", "d_rx_crc_err", "d_rx_keycache_miss",
|
||||
"d_rx_decrypt_crc_err", "d_rx_duplicate_frames",
|
||||
"d_rx_mic_err", "d_rx_tkip_format_err", "d_rx_ccmp_format_err",
|
||||
"d_rx_ccmp_replay_err",
|
||||
|
||||
/* Misc stats. */
|
||||
"d_beacon_miss", "d_num_connects", "d_num_disconnects",
|
||||
"d_beacon_avg_rssi", "d_arp_received", "d_arp_matched",
|
||||
"d_arp_replied"
|
||||
};
|
||||
|
||||
#define ATH6KL_STATS_LEN ARRAY_SIZE(ath6kl_gstrings_sta_stats)
|
||||
|
||||
static int ath6kl_get_sset_count(struct net_device *dev, int sset)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
if (sset == ETH_SS_STATS)
|
||||
rv += ATH6KL_STATS_LEN;
|
||||
|
||||
if (rv == 0)
|
||||
return -EOPNOTSUPP;
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void ath6kl_get_stats(struct net_device *dev,
|
||||
struct ethtool_stats *stats,
|
||||
u64 *data)
|
||||
{
|
||||
struct ath6kl_vif *vif = netdev_priv(dev);
|
||||
struct ath6kl *ar = vif->ar;
|
||||
int i = 0;
|
||||
struct target_stats *tgt_stats;
|
||||
|
||||
memset(data, 0, sizeof(u64) * ATH6KL_STATS_LEN);
|
||||
|
||||
ath6kl_read_tgt_stats(ar, vif);
|
||||
|
||||
tgt_stats = &vif->target_stats;
|
||||
|
||||
data[i++] = tgt_stats->tx_ucast_pkt + tgt_stats->tx_bcast_pkt;
|
||||
data[i++] = tgt_stats->tx_ucast_byte + tgt_stats->tx_bcast_byte;
|
||||
data[i++] = tgt_stats->rx_ucast_pkt + tgt_stats->rx_bcast_pkt;
|
||||
data[i++] = tgt_stats->rx_ucast_byte + tgt_stats->rx_bcast_byte;
|
||||
|
||||
data[i++] = tgt_stats->tx_ucast_pkt;
|
||||
data[i++] = tgt_stats->tx_bcast_pkt;
|
||||
data[i++] = tgt_stats->tx_ucast_byte;
|
||||
data[i++] = tgt_stats->tx_bcast_byte;
|
||||
data[i++] = tgt_stats->tx_rts_success_cnt;
|
||||
data[i++] = tgt_stats->tx_err;
|
||||
data[i++] = tgt_stats->tx_fail_cnt;
|
||||
data[i++] = tgt_stats->tx_retry_cnt;
|
||||
data[i++] = tgt_stats->tx_mult_retry_cnt;
|
||||
data[i++] = tgt_stats->tx_rts_fail_cnt;
|
||||
data[i++] = tgt_stats->tkip_cnter_measures_invoked;
|
||||
|
||||
data[i++] = tgt_stats->rx_ucast_pkt;
|
||||
data[i++] = tgt_stats->rx_ucast_rate;
|
||||
data[i++] = tgt_stats->rx_bcast_pkt;
|
||||
data[i++] = tgt_stats->rx_ucast_byte;
|
||||
data[i++] = tgt_stats->rx_bcast_byte;
|
||||
data[i++] = tgt_stats->rx_frgment_pkt;
|
||||
data[i++] = tgt_stats->rx_err;
|
||||
data[i++] = tgt_stats->rx_crc_err;
|
||||
data[i++] = tgt_stats->rx_key_cache_miss;
|
||||
data[i++] = tgt_stats->rx_decrypt_err;
|
||||
data[i++] = tgt_stats->rx_dupl_frame;
|
||||
data[i++] = tgt_stats->tkip_local_mic_fail;
|
||||
data[i++] = tgt_stats->tkip_fmt_err;
|
||||
data[i++] = tgt_stats->ccmp_fmt_err;
|
||||
data[i++] = tgt_stats->ccmp_replays;
|
||||
|
||||
data[i++] = tgt_stats->cs_bmiss_cnt;
|
||||
data[i++] = tgt_stats->cs_connect_cnt;
|
||||
data[i++] = tgt_stats->cs_discon_cnt;
|
||||
data[i++] = tgt_stats->cs_ave_beacon_rssi;
|
||||
data[i++] = tgt_stats->arp_received;
|
||||
data[i++] = tgt_stats->arp_matched;
|
||||
data[i++] = tgt_stats->arp_replied;
|
||||
|
||||
if (i != ATH6KL_STATS_LEN) {
|
||||
WARN_ON_ONCE(1);
|
||||
ath6kl_err("ethtool stats error, i: %d STATS_LEN: %d\n",
|
||||
i, (int)ATH6KL_STATS_LEN);
|
||||
}
|
||||
}
|
||||
|
||||
/* These stats are per NIC, not really per vdev, so we just ignore dev. */
|
||||
static void ath6kl_get_strings(struct net_device *dev, u32 sset, u8 *data)
|
||||
{
|
||||
int sz_sta_stats = 0;
|
||||
|
||||
if (sset == ETH_SS_STATS) {
|
||||
sz_sta_stats = sizeof(ath6kl_gstrings_sta_stats);
|
||||
memcpy(data, ath6kl_gstrings_sta_stats, sz_sta_stats);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct ethtool_ops ath6kl_ethtool_ops = {
|
||||
.get_drvinfo = cfg80211_get_drvinfo,
|
||||
.get_link = ethtool_op_get_link,
|
||||
.get_strings = ath6kl_get_strings,
|
||||
.get_ethtool_stats = ath6kl_get_stats,
|
||||
.get_sset_count = ath6kl_get_sset_count,
|
||||
};
|
||||
|
||||
struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name,
|
||||
unsigned char name_assign_type,
|
||||
enum nl80211_iftype type,
|
||||
@ -3679,6 +3810,8 @@ struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name,
|
||||
if (ath6kl_cfg80211_vif_init(vif))
|
||||
goto err;
|
||||
|
||||
netdev_set_default_ethtool_ops(ndev, &ath6kl_ethtool_ops);
|
||||
|
||||
if (register_netdevice(ndev))
|
||||
goto err;
|
||||
|
||||
@ -3786,6 +3919,9 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
|
||||
ath6kl_band_2ghz.ht_cap.ht_supported = false;
|
||||
ath6kl_band_5ghz.ht_cap.cap = 0;
|
||||
ath6kl_band_5ghz.ht_cap.ht_supported = false;
|
||||
|
||||
if (ht)
|
||||
ath6kl_err("Firmware lacks RSN-CAP-OVERRIDE, so HT (802.11n) is disabled.");
|
||||
}
|
||||
|
||||
if (test_bit(ATH6KL_FW_CAPABILITY_64BIT_RATES,
|
||||
@ -3794,11 +3930,18 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
|
||||
ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
|
||||
ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff;
|
||||
ath6kl_band_5ghz.ht_cap.mcs.rx_mask[1] = 0xff;
|
||||
ar->hw.tx_ant = 2;
|
||||
ar->hw.rx_ant = 2;
|
||||
} else {
|
||||
ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
|
||||
ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
|
||||
ar->hw.tx_ant = 1;
|
||||
ar->hw.rx_ant = 1;
|
||||
}
|
||||
|
||||
wiphy->available_antennas_tx = ar->hw.tx_ant;
|
||||
wiphy->available_antennas_rx = ar->hw.rx_ant;
|
||||
|
||||
if (band_2gig)
|
||||
wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz;
|
||||
if (band_5gig)
|
||||
|
@ -782,6 +782,8 @@ struct ath6kl {
|
||||
u32 refclk_hz;
|
||||
u32 uarttx_pin;
|
||||
u32 testscript_addr;
|
||||
u8 tx_ant;
|
||||
u8 rx_ant;
|
||||
enum wmi_phy_cap cap;
|
||||
|
||||
u32 flags;
|
||||
|
@ -98,6 +98,33 @@ void ath6kl_warn(const char *fmt, ...)
|
||||
}
|
||||
EXPORT_SYMBOL(ath6kl_warn);
|
||||
|
||||
int ath6kl_read_tgt_stats(struct ath6kl *ar, struct ath6kl_vif *vif)
|
||||
{
|
||||
long left;
|
||||
|
||||
if (down_interruptible(&ar->sem))
|
||||
return -EBUSY;
|
||||
|
||||
set_bit(STATS_UPDATE_PEND, &vif->flags);
|
||||
|
||||
if (ath6kl_wmi_get_stats_cmd(ar->wmi, 0)) {
|
||||
up(&ar->sem);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
left = wait_event_interruptible_timeout(ar->event_wq,
|
||||
!test_bit(STATS_UPDATE_PEND,
|
||||
&vif->flags), WMI_TIMEOUT);
|
||||
|
||||
up(&ar->sem);
|
||||
|
||||
if (left <= 0)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ath6kl_read_tgt_stats);
|
||||
|
||||
#ifdef CONFIG_ATH6KL_DEBUG
|
||||
|
||||
void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...)
|
||||
@ -544,42 +571,24 @@ static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf,
|
||||
char *buf;
|
||||
unsigned int len = 0, buf_len = 1500;
|
||||
int i;
|
||||
long left;
|
||||
ssize_t ret_cnt;
|
||||
int rv;
|
||||
|
||||
vif = ath6kl_vif_first(ar);
|
||||
if (!vif)
|
||||
return -EIO;
|
||||
|
||||
tgt_stats = &vif->target_stats;
|
||||
|
||||
buf = kzalloc(buf_len, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
if (down_interruptible(&ar->sem)) {
|
||||
rv = ath6kl_read_tgt_stats(ar, vif);
|
||||
if (rv < 0) {
|
||||
kfree(buf);
|
||||
return -EBUSY;
|
||||
return rv;
|
||||
}
|
||||
|
||||
set_bit(STATS_UPDATE_PEND, &vif->flags);
|
||||
|
||||
if (ath6kl_wmi_get_stats_cmd(ar->wmi, 0)) {
|
||||
up(&ar->sem);
|
||||
kfree(buf);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
left = wait_event_interruptible_timeout(ar->event_wq,
|
||||
!test_bit(STATS_UPDATE_PEND,
|
||||
&vif->flags), WMI_TIMEOUT);
|
||||
|
||||
up(&ar->sem);
|
||||
|
||||
if (left <= 0) {
|
||||
kfree(buf);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
tgt_stats = &vif->target_stats;
|
||||
|
||||
len += scnprintf(buf + len, buf_len - len, "\n");
|
||||
len += scnprintf(buf + len, buf_len - len, "%25s\n",
|
||||
|
@ -59,6 +59,8 @@ enum ath6kl_war {
|
||||
ATH6KL_WAR_INVALID_RATE,
|
||||
};
|
||||
|
||||
int ath6kl_read_tgt_stats(struct ath6kl *ar, struct ath6kl_vif *vif);
|
||||
|
||||
#ifdef CONFIG_ATH6KL_DEBUG
|
||||
|
||||
void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...);
|
||||
|
@ -994,7 +994,7 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
|
||||
switch (ie_id) {
|
||||
case ATH6KL_FW_IE_FW_VERSION:
|
||||
strlcpy(ar->wiphy->fw_version, data,
|
||||
sizeof(ar->wiphy->fw_version));
|
||||
min(sizeof(ar->wiphy->fw_version), ie_len+1));
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_BOOT,
|
||||
"found fw version %s\n",
|
||||
|
@ -207,6 +207,7 @@ static ssize_t read_file_phy_err(struct file *file, char __user *user_buf,
|
||||
PHY_ERR("RADAR ERR", ATH9K_PHYERR_RADAR);
|
||||
PHY_ERR("SERVICE ERR", ATH9K_PHYERR_SERVICE);
|
||||
PHY_ERR("TOR ERR", ATH9K_PHYERR_TOR);
|
||||
|
||||
PHY_ERR("OFDM-TIMING ERR", ATH9K_PHYERR_OFDM_TIMING);
|
||||
PHY_ERR("OFDM-SIGNAL-PARITY ERR", ATH9K_PHYERR_OFDM_SIGNAL_PARITY);
|
||||
PHY_ERR("OFDM-RATE ERR", ATH9K_PHYERR_OFDM_RATE_ILLEGAL);
|
||||
@ -214,17 +215,24 @@ static ssize_t read_file_phy_err(struct file *file, char __user *user_buf,
|
||||
PHY_ERR("OFDM-POWER-DROP ERR", ATH9K_PHYERR_OFDM_POWER_DROP);
|
||||
PHY_ERR("OFDM-SERVICE ERR", ATH9K_PHYERR_OFDM_SERVICE);
|
||||
PHY_ERR("OFDM-RESTART ERR", ATH9K_PHYERR_OFDM_RESTART);
|
||||
PHY_ERR("FALSE-RADAR-EXT ERR", ATH9K_PHYERR_FALSE_RADAR_EXT);
|
||||
|
||||
PHY_ERR("CCK-BLOCKER ERR", ATH9K_PHYERR_CCK_BLOCKER);
|
||||
PHY_ERR("CCK-TIMING ERR", ATH9K_PHYERR_CCK_TIMING);
|
||||
PHY_ERR("CCK-HEADER-CRC ERR", ATH9K_PHYERR_CCK_HEADER_CRC);
|
||||
PHY_ERR("CCK-RATE ERR", ATH9K_PHYERR_CCK_RATE_ILLEGAL);
|
||||
PHY_ERR("CCK-SERVICE ERR", ATH9K_PHYERR_CCK_SERVICE);
|
||||
PHY_ERR("CCK-RESTART ERR", ATH9K_PHYERR_CCK_RESTART);
|
||||
PHY_ERR("CCK-LENGTH ERR", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL);
|
||||
PHY_ERR("CCK-POWER-DROP ERR", ATH9K_PHYERR_CCK_POWER_DROP);
|
||||
PHY_ERR("CCK-SERVICE ERR", ATH9K_PHYERR_CCK_SERVICE);
|
||||
PHY_ERR("CCK-RESTART ERR", ATH9K_PHYERR_CCK_RESTART);
|
||||
|
||||
PHY_ERR("HT-CRC ERR", ATH9K_PHYERR_HT_CRC_ERROR);
|
||||
PHY_ERR("HT-LENGTH ERR", ATH9K_PHYERR_HT_LENGTH_ILLEGAL);
|
||||
PHY_ERR("HT-RATE ERR", ATH9K_PHYERR_HT_RATE_ILLEGAL);
|
||||
PHY_ERR("HT-ZLF ERR", ATH9K_PHYERR_HT_ZLF);
|
||||
|
||||
PHY_ERR("FALSE-RADAR-EXT ERR", ATH9K_PHYERR_FALSE_RADAR_EXT);
|
||||
PHY_ERR("GREEN-FIELD ERR", ATH9K_PHYERR_GREEN_FIELD);
|
||||
PHY_ERR("SPECTRAL ERR", ATH9K_PHYERR_SPECTRAL);
|
||||
|
||||
if (len > size)
|
||||
len = size;
|
||||
|
@ -209,21 +209,25 @@ enum ath9k_phyerr {
|
||||
ATH9K_PHYERR_OFDM_POWER_DROP = 21,
|
||||
ATH9K_PHYERR_OFDM_SERVICE = 22,
|
||||
ATH9K_PHYERR_OFDM_RESTART = 23,
|
||||
ATH9K_PHYERR_FALSE_RADAR_EXT = 24,
|
||||
|
||||
ATH9K_PHYERR_CCK_BLOCKER = 24,
|
||||
ATH9K_PHYERR_CCK_TIMING = 25,
|
||||
ATH9K_PHYERR_CCK_HEADER_CRC = 26,
|
||||
ATH9K_PHYERR_CCK_RATE_ILLEGAL = 27,
|
||||
ATH9K_PHYERR_CCK_LENGTH_ILLEGAL = 28,
|
||||
ATH9K_PHYERR_CCK_POWER_DROP = 29,
|
||||
ATH9K_PHYERR_CCK_SERVICE = 30,
|
||||
ATH9K_PHYERR_CCK_RESTART = 31,
|
||||
ATH9K_PHYERR_CCK_LENGTH_ILLEGAL = 32,
|
||||
ATH9K_PHYERR_CCK_POWER_DROP = 33,
|
||||
|
||||
ATH9K_PHYERR_HT_CRC_ERROR = 34,
|
||||
ATH9K_PHYERR_HT_LENGTH_ILLEGAL = 35,
|
||||
ATH9K_PHYERR_HT_RATE_ILLEGAL = 36,
|
||||
ATH9K_PHYERR_HT_CRC_ERROR = 32,
|
||||
ATH9K_PHYERR_HT_LENGTH_ILLEGAL = 33,
|
||||
ATH9K_PHYERR_HT_RATE_ILLEGAL = 34,
|
||||
ATH9K_PHYERR_HT_ZLF = 35,
|
||||
|
||||
ATH9K_PHYERR_FALSE_RADAR_EXT = 36,
|
||||
ATH9K_PHYERR_GREEN_FIELD = 37,
|
||||
ATH9K_PHYERR_SPECTRAL = 38,
|
||||
|
||||
ATH9K_PHYERR_SPECTRAL = 38,
|
||||
ATH9K_PHYERR_MAX = 39,
|
||||
};
|
||||
|
||||
|
@ -79,6 +79,7 @@ static int wcn36xx_dxe_allocate_ctl_block(struct wcn36xx_dxe_ch *ch)
|
||||
struct wcn36xx_dxe_ctl *cur_ctl = NULL;
|
||||
int i;
|
||||
|
||||
spin_lock_init(&ch->lock);
|
||||
for (i = 0; i < ch->desc_num; i++) {
|
||||
cur_ctl = kzalloc(sizeof(*cur_ctl), GFP_KERNEL);
|
||||
if (!cur_ctl)
|
||||
@ -169,7 +170,7 @@ void wcn36xx_dxe_free_ctl_blks(struct wcn36xx *wcn)
|
||||
wcn36xx_dxe_free_ctl_block(&wcn->dxe_rx_h_ch);
|
||||
}
|
||||
|
||||
static int wcn36xx_dxe_init_descs(struct wcn36xx_dxe_ch *wcn_ch)
|
||||
static int wcn36xx_dxe_init_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn_ch)
|
||||
{
|
||||
struct wcn36xx_dxe_desc *cur_dxe = NULL;
|
||||
struct wcn36xx_dxe_desc *prev_dxe = NULL;
|
||||
@ -178,7 +179,7 @@ static int wcn36xx_dxe_init_descs(struct wcn36xx_dxe_ch *wcn_ch)
|
||||
int i;
|
||||
|
||||
size = wcn_ch->desc_num * sizeof(struct wcn36xx_dxe_desc);
|
||||
wcn_ch->cpu_addr = dma_alloc_coherent(NULL, size, &wcn_ch->dma_addr,
|
||||
wcn_ch->cpu_addr = dma_alloc_coherent(dev, size, &wcn_ch->dma_addr,
|
||||
GFP_KERNEL);
|
||||
if (!wcn_ch->cpu_addr)
|
||||
return -ENOMEM;
|
||||
@ -270,7 +271,7 @@ static int wcn36xx_dxe_enable_ch_int(struct wcn36xx *wcn, u16 wcn_ch)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wcn36xx_dxe_fill_skb(struct wcn36xx_dxe_ctl *ctl)
|
||||
static int wcn36xx_dxe_fill_skb(struct device *dev, struct wcn36xx_dxe_ctl *ctl)
|
||||
{
|
||||
struct wcn36xx_dxe_desc *dxe = ctl->desc;
|
||||
struct sk_buff *skb;
|
||||
@ -279,7 +280,7 @@ static int wcn36xx_dxe_fill_skb(struct wcn36xx_dxe_ctl *ctl)
|
||||
if (skb == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
dxe->dst_addr_l = dma_map_single(NULL,
|
||||
dxe->dst_addr_l = dma_map_single(dev,
|
||||
skb_tail_pointer(skb),
|
||||
WCN36XX_PKT_SIZE,
|
||||
DMA_FROM_DEVICE);
|
||||
@ -297,7 +298,7 @@ static int wcn36xx_dxe_ch_alloc_skb(struct wcn36xx *wcn,
|
||||
cur_ctl = wcn_ch->head_blk_ctl;
|
||||
|
||||
for (i = 0; i < wcn_ch->desc_num; i++) {
|
||||
wcn36xx_dxe_fill_skb(cur_ctl);
|
||||
wcn36xx_dxe_fill_skb(wcn->dev, cur_ctl);
|
||||
cur_ctl = cur_ctl->next;
|
||||
}
|
||||
|
||||
@ -345,7 +346,7 @@ void wcn36xx_dxe_tx_ack_ind(struct wcn36xx *wcn, u32 status)
|
||||
|
||||
static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch)
|
||||
{
|
||||
struct wcn36xx_dxe_ctl *ctl = ch->tail_blk_ctl;
|
||||
struct wcn36xx_dxe_ctl *ctl;
|
||||
struct ieee80211_tx_info *info;
|
||||
unsigned long flags;
|
||||
|
||||
@ -354,23 +355,25 @@ static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch)
|
||||
* completely full head and tail are pointing to the same element
|
||||
* and while-do will not make any cycles.
|
||||
*/
|
||||
spin_lock_irqsave(&ch->lock, flags);
|
||||
ctl = ch->tail_blk_ctl;
|
||||
do {
|
||||
if (ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)
|
||||
break;
|
||||
if (ctl->skb) {
|
||||
dma_unmap_single(NULL, ctl->desc->src_addr_l,
|
||||
dma_unmap_single(wcn->dev, ctl->desc->src_addr_l,
|
||||
ctl->skb->len, DMA_TO_DEVICE);
|
||||
info = IEEE80211_SKB_CB(ctl->skb);
|
||||
if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) {
|
||||
/* Keep frame until TX status comes */
|
||||
ieee80211_free_txskb(wcn->hw, ctl->skb);
|
||||
}
|
||||
spin_lock_irqsave(&ctl->skb_lock, flags);
|
||||
spin_lock(&ctl->skb_lock);
|
||||
if (wcn->queues_stopped) {
|
||||
wcn->queues_stopped = false;
|
||||
ieee80211_wake_queues(wcn->hw);
|
||||
}
|
||||
spin_unlock_irqrestore(&ctl->skb_lock, flags);
|
||||
spin_unlock(&ctl->skb_lock);
|
||||
|
||||
ctl->skb = NULL;
|
||||
}
|
||||
@ -379,6 +382,7 @@ static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch)
|
||||
!(ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK));
|
||||
|
||||
ch->tail_blk_ctl = ctl;
|
||||
spin_unlock_irqrestore(&ch->lock, flags);
|
||||
}
|
||||
|
||||
static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev)
|
||||
@ -474,7 +478,7 @@ static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn,
|
||||
while (!(dxe->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)) {
|
||||
skb = ctl->skb;
|
||||
dma_addr = dxe->dst_addr_l;
|
||||
wcn36xx_dxe_fill_skb(ctl);
|
||||
wcn36xx_dxe_fill_skb(wcn->dev, ctl);
|
||||
|
||||
switch (ch->ch_type) {
|
||||
case WCN36XX_DXE_CH_RX_L:
|
||||
@ -491,7 +495,7 @@ static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn,
|
||||
wcn36xx_warn("Unknown channel\n");
|
||||
}
|
||||
|
||||
dma_unmap_single(NULL, dma_addr, WCN36XX_PKT_SIZE,
|
||||
dma_unmap_single(wcn->dev, dma_addr, WCN36XX_PKT_SIZE,
|
||||
DMA_FROM_DEVICE);
|
||||
wcn36xx_rx_skb(wcn, skb);
|
||||
ctl = ctl->next;
|
||||
@ -540,7 +544,7 @@ int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn)
|
||||
16 - (WCN36XX_BD_CHUNK_SIZE % 8);
|
||||
|
||||
s = wcn->mgmt_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_H;
|
||||
cpu_addr = dma_alloc_coherent(NULL, s, &wcn->mgmt_mem_pool.phy_addr,
|
||||
cpu_addr = dma_alloc_coherent(wcn->dev, s, &wcn->mgmt_mem_pool.phy_addr,
|
||||
GFP_KERNEL);
|
||||
if (!cpu_addr)
|
||||
goto out_err;
|
||||
@ -555,7 +559,7 @@ int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn)
|
||||
16 - (WCN36XX_BD_CHUNK_SIZE % 8);
|
||||
|
||||
s = wcn->data_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_L;
|
||||
cpu_addr = dma_alloc_coherent(NULL, s, &wcn->data_mem_pool.phy_addr,
|
||||
cpu_addr = dma_alloc_coherent(wcn->dev, s, &wcn->data_mem_pool.phy_addr,
|
||||
GFP_KERNEL);
|
||||
if (!cpu_addr)
|
||||
goto out_err;
|
||||
@ -574,13 +578,13 @@ out_err:
|
||||
void wcn36xx_dxe_free_mem_pools(struct wcn36xx *wcn)
|
||||
{
|
||||
if (wcn->mgmt_mem_pool.virt_addr)
|
||||
dma_free_coherent(NULL, wcn->mgmt_mem_pool.chunk_size *
|
||||
dma_free_coherent(wcn->dev, wcn->mgmt_mem_pool.chunk_size *
|
||||
WCN36XX_DXE_CH_DESC_NUMB_TX_H,
|
||||
wcn->mgmt_mem_pool.virt_addr,
|
||||
wcn->mgmt_mem_pool.phy_addr);
|
||||
|
||||
if (wcn->data_mem_pool.virt_addr) {
|
||||
dma_free_coherent(NULL, wcn->data_mem_pool.chunk_size *
|
||||
dma_free_coherent(wcn->dev, wcn->data_mem_pool.chunk_size *
|
||||
WCN36XX_DXE_CH_DESC_NUMB_TX_L,
|
||||
wcn->data_mem_pool.virt_addr,
|
||||
wcn->data_mem_pool.phy_addr);
|
||||
@ -596,12 +600,14 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn,
|
||||
struct wcn36xx_dxe_desc *desc = NULL;
|
||||
struct wcn36xx_dxe_ch *ch = NULL;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
ch = is_low ? &wcn->dxe_tx_l_ch : &wcn->dxe_tx_h_ch;
|
||||
|
||||
spin_lock_irqsave(&ch->lock, flags);
|
||||
ctl = ch->head_blk_ctl;
|
||||
|
||||
spin_lock_irqsave(&ctl->next->skb_lock, flags);
|
||||
spin_lock(&ctl->next->skb_lock);
|
||||
|
||||
/*
|
||||
* If skb is not null that means that we reached the tail of the ring
|
||||
@ -611,10 +617,11 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn,
|
||||
if (NULL != ctl->next->skb) {
|
||||
ieee80211_stop_queues(wcn->hw);
|
||||
wcn->queues_stopped = true;
|
||||
spin_unlock_irqrestore(&ctl->next->skb_lock, flags);
|
||||
spin_unlock(&ctl->next->skb_lock);
|
||||
spin_unlock_irqrestore(&ch->lock, flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
spin_unlock_irqrestore(&ctl->next->skb_lock, flags);
|
||||
spin_unlock(&ctl->next->skb_lock);
|
||||
|
||||
ctl->skb = NULL;
|
||||
desc = ctl->desc;
|
||||
@ -640,10 +647,11 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn,
|
||||
desc = ctl->desc;
|
||||
if (ctl->bd_cpu_addr) {
|
||||
wcn36xx_err("bd_cpu_addr cannot be NULL for skb DXE\n");
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
desc->src_addr_l = dma_map_single(NULL,
|
||||
desc->src_addr_l = dma_map_single(wcn->dev,
|
||||
ctl->skb->data,
|
||||
ctl->skb->len,
|
||||
DMA_TO_DEVICE);
|
||||
@ -679,7 +687,10 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn,
|
||||
ch->reg_ctrl, ch->def_ctrl);
|
||||
}
|
||||
|
||||
return 0;
|
||||
ret = 0;
|
||||
unlock:
|
||||
spin_unlock_irqrestore(&ch->lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wcn36xx_dxe_init(struct wcn36xx *wcn)
|
||||
@ -696,7 +707,7 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
|
||||
/***************************************/
|
||||
/* Init descriptors for TX LOW channel */
|
||||
/***************************************/
|
||||
wcn36xx_dxe_init_descs(&wcn->dxe_tx_l_ch);
|
||||
wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_l_ch);
|
||||
wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_l_ch, &wcn->data_mem_pool);
|
||||
|
||||
/* Write channel head to a NEXT register */
|
||||
@ -714,7 +725,7 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
|
||||
/***************************************/
|
||||
/* Init descriptors for TX HIGH channel */
|
||||
/***************************************/
|
||||
wcn36xx_dxe_init_descs(&wcn->dxe_tx_h_ch);
|
||||
wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_h_ch);
|
||||
wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_h_ch, &wcn->mgmt_mem_pool);
|
||||
|
||||
/* Write channel head to a NEXT register */
|
||||
@ -734,7 +745,7 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
|
||||
/***************************************/
|
||||
/* Init descriptors for RX LOW channel */
|
||||
/***************************************/
|
||||
wcn36xx_dxe_init_descs(&wcn->dxe_rx_l_ch);
|
||||
wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_l_ch);
|
||||
|
||||
/* For RX we need to preallocated buffers */
|
||||
wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_l_ch);
|
||||
@ -764,7 +775,7 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
|
||||
/***************************************/
|
||||
/* Init descriptors for RX HIGH channel */
|
||||
/***************************************/
|
||||
wcn36xx_dxe_init_descs(&wcn->dxe_rx_h_ch);
|
||||
wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_h_ch);
|
||||
|
||||
/* For RX we need to prealocat buffers */
|
||||
wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_h_ch);
|
||||
|
@ -243,6 +243,7 @@ struct wcn36xx_dxe_ctl {
|
||||
};
|
||||
|
||||
struct wcn36xx_dxe_ch {
|
||||
spinlock_t lock; /* protects head/tail ptrs */
|
||||
enum wcn36xx_dxe_ch_type ch_type;
|
||||
void *cpu_addr;
|
||||
dma_addr_t dma_addr;
|
||||
|
@ -236,7 +236,7 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
|
||||
|
||||
isr &= ~(BIT_DMA_EP_RX_ICR_RX_DONE |
|
||||
BIT_DMA_EP_RX_ICR_RX_HTRSH);
|
||||
if (likely(test_bit(wil_status_reset_done, wil->status))) {
|
||||
if (likely(test_bit(wil_status_fwready, wil->status))) {
|
||||
if (likely(test_bit(wil_status_napi_en, wil->status))) {
|
||||
wil_dbg_txrx(wil, "NAPI(Rx) schedule\n");
|
||||
need_unmask = false;
|
||||
@ -286,7 +286,7 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
|
||||
isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE;
|
||||
/* clear also all VRING interrupts */
|
||||
isr &= ~(BIT(25) - 1UL);
|
||||
if (likely(test_bit(wil_status_reset_done, wil->status))) {
|
||||
if (likely(test_bit(wil_status_fwready, wil->status))) {
|
||||
wil_dbg_txrx(wil, "NAPI(Tx) schedule\n");
|
||||
need_unmask = false;
|
||||
napi_schedule(&wil->napi_tx);
|
||||
@ -364,7 +364,7 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
|
||||
if (isr & ISR_MISC_FW_READY) {
|
||||
wil_dbg_irq(wil, "IRQ: FW ready\n");
|
||||
wil_cache_mbox_regs(wil);
|
||||
set_bit(wil_status_reset_done, wil->status);
|
||||
set_bit(wil_status_mbox_ready, wil->status);
|
||||
/**
|
||||
* Actual FW ready indicated by the
|
||||
* WMI_FW_READY_EVENTID
|
||||
|
@ -422,7 +422,7 @@ static void wil_connect_worker(struct work_struct *work)
|
||||
wil->sta[cid].status = wil_sta_connected;
|
||||
netif_tx_wake_all_queues(ndev);
|
||||
} else {
|
||||
wil->sta[cid].status = wil_sta_unused;
|
||||
wil_disconnect_cid(wil, cid, WLAN_REASON_UNSPECIFIED, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1242,6 +1242,7 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring,
|
||||
int tcp_hdr_len;
|
||||
int skb_net_hdr_len;
|
||||
int gso_type;
|
||||
int rc = -EINVAL;
|
||||
|
||||
wil_dbg_txrx(wil, "%s() %d bytes to vring %d\n",
|
||||
__func__, skb->len, vring_index);
|
||||
@ -1333,8 +1334,9 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring,
|
||||
len, rem_data, descs_used);
|
||||
|
||||
if (descs_used == avail) {
|
||||
wil_err(wil, "TSO: ring overflow\n");
|
||||
goto dma_error;
|
||||
wil_err_ratelimited(wil, "TSO: ring overflow\n");
|
||||
rc = -ENOMEM;
|
||||
goto mem_error;
|
||||
}
|
||||
|
||||
lenmss = min_t(int, rem_data, len);
|
||||
@ -1356,8 +1358,10 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring,
|
||||
headlen -= lenmss;
|
||||
}
|
||||
|
||||
if (unlikely(dma_mapping_error(dev, pa)))
|
||||
goto dma_error;
|
||||
if (unlikely(dma_mapping_error(dev, pa))) {
|
||||
wil_err(wil, "TSO: DMA map page error\n");
|
||||
goto mem_error;
|
||||
}
|
||||
|
||||
_desc = &vring->va[i].tx;
|
||||
|
||||
@ -1456,8 +1460,8 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring,
|
||||
}
|
||||
|
||||
/* advance swhead */
|
||||
wil_dbg_txrx(wil, "TSO: Tx swhead %d -> %d\n", swhead, vring->swhead);
|
||||
wil_vring_advance_head(vring, descs_used);
|
||||
wil_dbg_txrx(wil, "TSO: Tx swhead %d -> %d\n", swhead, vring->swhead);
|
||||
|
||||
/* make sure all writes to descriptors (shared memory) are done before
|
||||
* committing them to HW
|
||||
@ -1467,8 +1471,7 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring,
|
||||
wil_w(wil, vring->hwtail, vring->swhead);
|
||||
return 0;
|
||||
|
||||
dma_error:
|
||||
wil_err(wil, "TSO: DMA map page error\n");
|
||||
mem_error:
|
||||
while (descs_used > 0) {
|
||||
struct wil_ctx *ctx;
|
||||
|
||||
@ -1479,14 +1482,11 @@ dma_error:
|
||||
_desc->dma.status = TX_DMA_STATUS_DU;
|
||||
ctx = &vring->ctx[i];
|
||||
wil_txdesc_unmap(dev, d, ctx);
|
||||
if (ctx->skb)
|
||||
dev_kfree_skb_any(ctx->skb);
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
descs_used--;
|
||||
}
|
||||
|
||||
err_exit:
|
||||
return -EINVAL;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
|
||||
@ -1562,8 +1562,11 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
|
||||
_d = &vring->va[i].tx;
|
||||
pa = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag),
|
||||
DMA_TO_DEVICE);
|
||||
if (unlikely(dma_mapping_error(dev, pa)))
|
||||
if (unlikely(dma_mapping_error(dev, pa))) {
|
||||
wil_err(wil, "Tx[%2d] failed to map fragment\n",
|
||||
vring_index);
|
||||
goto dma_error;
|
||||
}
|
||||
vring->ctx[i].mapped_as = wil_mapped_as_page;
|
||||
wil_tx_desc_map(d, pa, len, vring_index);
|
||||
/* no need to check return code -
|
||||
@ -1623,9 +1626,6 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
|
||||
_d->dma.status = TX_DMA_STATUS_DU;
|
||||
wil_txdesc_unmap(dev, d, ctx);
|
||||
|
||||
if (ctx->skb)
|
||||
dev_kfree_skb_any(ctx->skb);
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
|
||||
|
@ -402,11 +402,11 @@ struct vring_tx_data {
|
||||
};
|
||||
|
||||
enum { /* for wil6210_priv.status */
|
||||
wil_status_fwready = 0,
|
||||
wil_status_fwready = 0, /* FW operational */
|
||||
wil_status_fwconnecting,
|
||||
wil_status_fwconnected,
|
||||
wil_status_dontscan,
|
||||
wil_status_reset_done,
|
||||
wil_status_mbox_ready, /* MBOX structures ready */
|
||||
wil_status_irqen, /* FIXME: interrupts enabled - for debug */
|
||||
wil_status_napi_en, /* NAPI enabled protected by wil->mutex */
|
||||
wil_status_resetting, /* reset in progress */
|
||||
|
@ -293,12 +293,6 @@ static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len)
|
||||
/* ignore MAC address, we already have it from the boot loader */
|
||||
snprintf(wdev->wiphy->fw_version, sizeof(wdev->wiphy->fw_version),
|
||||
"%d", wil->fw_version);
|
||||
}
|
||||
|
||||
static void wmi_evt_fw_ready(struct wil6210_priv *wil, int id, void *d,
|
||||
int len)
|
||||
{
|
||||
wil_dbg_wmi(wil, "WMI: got FW ready event\n");
|
||||
|
||||
wil_set_recovery_state(wil, fw_recovery_idle);
|
||||
set_bit(wil_status_fwready, wil->status);
|
||||
@ -684,13 +678,22 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
|
||||
spin_unlock_bh(&sta->tid_rx_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Some events are ignored for purpose; and need not be interpreted as
|
||||
* "unhandled events"
|
||||
*/
|
||||
static void wmi_evt_ignore(struct wil6210_priv *wil, int id, void *d, int len)
|
||||
{
|
||||
wil_dbg_wmi(wil, "Ignore event 0x%04x len %d\n", id, len);
|
||||
}
|
||||
|
||||
static const struct {
|
||||
int eventid;
|
||||
void (*handler)(struct wil6210_priv *wil, int eventid,
|
||||
void *data, int data_len);
|
||||
} wmi_evt_handlers[] = {
|
||||
{WMI_READY_EVENTID, wmi_evt_ready},
|
||||
{WMI_FW_READY_EVENTID, wmi_evt_fw_ready},
|
||||
{WMI_FW_READY_EVENTID, wmi_evt_ignore},
|
||||
{WMI_RX_MGMT_PACKET_EVENTID, wmi_evt_rx_mgmt},
|
||||
{WMI_TX_MGMT_PACKET_EVENTID, wmi_evt_tx_mgmt},
|
||||
{WMI_SCAN_COMPLETE_EVENTID, wmi_evt_scan_complete},
|
||||
@ -701,6 +704,7 @@ static const struct {
|
||||
{WMI_RCP_ADDBA_REQ_EVENTID, wmi_evt_addba_rx_req},
|
||||
{WMI_DELBA_EVENTID, wmi_evt_delba},
|
||||
{WMI_VRING_EN_EVENTID, wmi_evt_vring_en},
|
||||
{WMI_DATA_PORT_OPEN_EVENTID, wmi_evt_ignore},
|
||||
};
|
||||
|
||||
/*
|
||||
@ -720,7 +724,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
|
||||
ulong flags;
|
||||
unsigned n;
|
||||
|
||||
if (!test_bit(wil_status_reset_done, wil->status)) {
|
||||
if (!test_bit(wil_status_mbox_ready, wil->status)) {
|
||||
wil_err(wil, "Reset in progress. Cannot handle WMI event\n");
|
||||
return;
|
||||
}
|
||||
|
@ -71,26 +71,6 @@ config B43_PCICORE_AUTOSELECT
|
||||
select SSB_DRIVER_PCICORE
|
||||
default y
|
||||
|
||||
config B43_PCMCIA
|
||||
bool "Broadcom 43xx PCMCIA device support"
|
||||
depends on B43 && B43_SSB && SSB_PCMCIAHOST_POSSIBLE
|
||||
select SSB_PCMCIAHOST
|
||||
---help---
|
||||
Broadcom 43xx PCMCIA device support.
|
||||
|
||||
Support for 16bit PCMCIA devices.
|
||||
Please note that most PC-CARD devices are _NOT_ 16bit PCMCIA
|
||||
devices, but 32bit CardBUS devices. CardBUS devices are supported
|
||||
out of the box by b43.
|
||||
|
||||
With this config option you can drive b43 cards in
|
||||
CompactFlash formfactor in a PCMCIA adaptor.
|
||||
CF b43 cards can sometimes be found in handheld PCs.
|
||||
|
||||
It's safe to select Y here, even if you don't have a B43 PCMCIA device.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config B43_SDIO
|
||||
bool "Broadcom 43xx SDIO device support"
|
||||
depends on B43 && B43_SSB && SSB_SDIOHOST_POSSIBLE
|
||||
|
@ -21,7 +21,6 @@ b43-y += pio.o
|
||||
b43-y += rfkill.o
|
||||
b43-y += ppr.o
|
||||
b43-$(CONFIG_B43_LEDS) += leds.o
|
||||
b43-$(CONFIG_B43_PCMCIA) += pcmcia.o
|
||||
b43-$(CONFIG_B43_SDIO) += sdio.o
|
||||
b43-$(CONFIG_B43_DEBUG) += debugfs.o
|
||||
|
||||
|
@ -56,7 +56,6 @@
|
||||
#include "sysfs.h"
|
||||
#include "xmit.h"
|
||||
#include "lo.h"
|
||||
#include "pcmcia.h"
|
||||
#include "sdio.h"
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
|
||||
@ -5850,12 +5849,9 @@ static int __init b43_init(void)
|
||||
int err;
|
||||
|
||||
b43_debugfs_init();
|
||||
err = b43_pcmcia_init();
|
||||
if (err)
|
||||
goto err_dfs_exit;
|
||||
err = b43_sdio_init();
|
||||
if (err)
|
||||
goto err_pcmcia_exit;
|
||||
goto err_dfs_exit;
|
||||
#ifdef CONFIG_B43_BCMA
|
||||
err = bcma_driver_register(&b43_bcma_driver);
|
||||
if (err)
|
||||
@ -5878,8 +5874,6 @@ err_bcma_driver_exit:
|
||||
err_sdio_exit:
|
||||
#endif
|
||||
b43_sdio_exit();
|
||||
err_pcmcia_exit:
|
||||
b43_pcmcia_exit();
|
||||
err_dfs_exit:
|
||||
b43_debugfs_exit();
|
||||
return err;
|
||||
@ -5894,7 +5888,6 @@ static void __exit b43_exit(void)
|
||||
bcma_driver_unregister(&b43_bcma_driver);
|
||||
#endif
|
||||
b43_sdio_exit();
|
||||
b43_pcmcia_exit();
|
||||
b43_debugfs_exit();
|
||||
}
|
||||
|
||||
|
@ -1,145 +0,0 @@
|
||||
/*
|
||||
|
||||
Broadcom B43 wireless driver
|
||||
|
||||
Copyright (c) 2007 Michael Buesch <m@bues.ch>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
|
||||
#include "pcmcia.h"
|
||||
|
||||
#include <linux/ssb/ssb.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <pcmcia/cistpl.h>
|
||||
#include <pcmcia/ciscode.h>
|
||||
#include <pcmcia/ds.h>
|
||||
#include <pcmcia/cisreg.h>
|
||||
|
||||
|
||||
static const struct pcmcia_device_id b43_pcmcia_tbl[] = {
|
||||
PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448),
|
||||
PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476),
|
||||
PCMCIA_DEVICE_NULL,
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pcmcia, b43_pcmcia_tbl);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int b43_pcmcia_suspend(struct pcmcia_device *dev)
|
||||
{
|
||||
struct ssb_bus *ssb = dev->priv;
|
||||
|
||||
return ssb_bus_suspend(ssb);
|
||||
}
|
||||
|
||||
static int b43_pcmcia_resume(struct pcmcia_device *dev)
|
||||
{
|
||||
struct ssb_bus *ssb = dev->priv;
|
||||
|
||||
return ssb_bus_resume(ssb);
|
||||
}
|
||||
#else /* CONFIG_PM */
|
||||
# define b43_pcmcia_suspend NULL
|
||||
# define b43_pcmcia_resume NULL
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static int b43_pcmcia_probe(struct pcmcia_device *dev)
|
||||
{
|
||||
struct ssb_bus *ssb;
|
||||
int err = -ENOMEM;
|
||||
int res = 0;
|
||||
|
||||
ssb = kzalloc(sizeof(*ssb), GFP_KERNEL);
|
||||
if (!ssb)
|
||||
goto out_error;
|
||||
|
||||
err = -ENODEV;
|
||||
|
||||
dev->config_flags |= CONF_ENABLE_IRQ;
|
||||
|
||||
dev->resource[2]->flags |= WIN_ENABLE | WIN_DATA_WIDTH_16 |
|
||||
WIN_USE_WAIT;
|
||||
dev->resource[2]->start = 0;
|
||||
dev->resource[2]->end = SSB_CORE_SIZE;
|
||||
res = pcmcia_request_window(dev, dev->resource[2], 250);
|
||||
if (res != 0)
|
||||
goto err_kfree_ssb;
|
||||
|
||||
res = pcmcia_map_mem_page(dev, dev->resource[2], 0);
|
||||
if (res != 0)
|
||||
goto err_disable;
|
||||
|
||||
if (!dev->irq)
|
||||
goto err_disable;
|
||||
|
||||
res = pcmcia_enable_device(dev);
|
||||
if (res != 0)
|
||||
goto err_disable;
|
||||
|
||||
err = ssb_bus_pcmciabus_register(ssb, dev, dev->resource[2]->start);
|
||||
if (err)
|
||||
goto err_disable;
|
||||
dev->priv = ssb;
|
||||
|
||||
return 0;
|
||||
|
||||
err_disable:
|
||||
pcmcia_disable_device(dev);
|
||||
err_kfree_ssb:
|
||||
kfree(ssb);
|
||||
out_error:
|
||||
printk(KERN_ERR "b43-pcmcia: Initialization failed (%d, %d)\n",
|
||||
res, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void b43_pcmcia_remove(struct pcmcia_device *dev)
|
||||
{
|
||||
struct ssb_bus *ssb = dev->priv;
|
||||
|
||||
ssb_bus_unregister(ssb);
|
||||
pcmcia_disable_device(dev);
|
||||
kfree(ssb);
|
||||
dev->priv = NULL;
|
||||
}
|
||||
|
||||
static struct pcmcia_driver b43_pcmcia_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "b43-pcmcia",
|
||||
.id_table = b43_pcmcia_tbl,
|
||||
.probe = b43_pcmcia_probe,
|
||||
.remove = b43_pcmcia_remove,
|
||||
.suspend = b43_pcmcia_suspend,
|
||||
.resume = b43_pcmcia_resume,
|
||||
};
|
||||
|
||||
/*
|
||||
* These are not module init/exit functions!
|
||||
* The module_pcmcia_driver() helper cannot be used here.
|
||||
*/
|
||||
int b43_pcmcia_init(void)
|
||||
{
|
||||
return pcmcia_register_driver(&b43_pcmcia_driver);
|
||||
}
|
||||
|
||||
void b43_pcmcia_exit(void)
|
||||
{
|
||||
pcmcia_unregister_driver(&b43_pcmcia_driver);
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
#ifndef B43_PCMCIA_H_
|
||||
#define B43_PCMCIA_H_
|
||||
|
||||
#ifdef CONFIG_B43_PCMCIA
|
||||
|
||||
int b43_pcmcia_init(void);
|
||||
void b43_pcmcia_exit(void);
|
||||
|
||||
#else /* CONFIG_B43_PCMCIA */
|
||||
|
||||
static inline int b43_pcmcia_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void b43_pcmcia_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_B43_PCMCIA */
|
||||
#endif /* B43_PCMCIA_H_ */
|
@ -86,6 +86,8 @@
|
||||
* Structured as &struct iwl_fw_error_dump_trigger_desc.
|
||||
* @IWL_FW_ERROR_DUMP_RB: the content of an RB structured as
|
||||
* &struct iwl_fw_error_dump_rb
|
||||
* @IWL_FW_ERROR_PAGING: UMAC's image memory segments which were
|
||||
* paged to the DRAM.
|
||||
*/
|
||||
enum iwl_fw_error_dump_type {
|
||||
/* 0 is deprecated */
|
||||
@ -100,6 +102,7 @@ enum iwl_fw_error_dump_type {
|
||||
IWL_FW_ERROR_DUMP_MEM = 9,
|
||||
IWL_FW_ERROR_DUMP_ERROR_INFO = 10,
|
||||
IWL_FW_ERROR_DUMP_RB = 11,
|
||||
IWL_FW_ERROR_DUMP_PAGING = 12,
|
||||
|
||||
IWL_FW_ERROR_DUMP_MAX,
|
||||
};
|
||||
@ -239,6 +242,19 @@ struct iwl_fw_error_dump_rb {
|
||||
u8 data[];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_fw_error_dump_paging - content of the UMAC's image page
|
||||
* block on DRAM
|
||||
* @index: the index of the page block
|
||||
* @reserved:
|
||||
* @data: the content of the page block
|
||||
*/
|
||||
struct iwl_fw_error_dump_paging {
|
||||
__le32 index;
|
||||
__le32 reserved;
|
||||
u8 data[];
|
||||
};
|
||||
|
||||
/**
|
||||
* iwl_fw_error_next_data - advance fw error dump data pointer
|
||||
* @data: previous data block
|
||||
|
@ -306,6 +306,8 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t;
|
||||
* is supported.
|
||||
* @IWL_UCODE_TLV_CAPA_BT_COEX_RRC: supports BT Coex RRC
|
||||
* @IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT: supports gscan
|
||||
* @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement
|
||||
* @IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS: supports short PM timeouts
|
||||
*
|
||||
* @NUM_IWL_UCODE_TLV_CAPA: number of bits used
|
||||
*/
|
||||
@ -330,6 +332,8 @@ enum iwl_ucode_tlv_capa {
|
||||
IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC = (__force iwl_ucode_tlv_capa_t)29,
|
||||
IWL_UCODE_TLV_CAPA_BT_COEX_RRC = (__force iwl_ucode_tlv_capa_t)30,
|
||||
IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)31,
|
||||
IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64,
|
||||
IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65,
|
||||
|
||||
NUM_IWL_UCODE_TLV_CAPA
|
||||
#ifdef __CHECKER__
|
||||
|
@ -409,6 +409,7 @@ enum iwl_d3_status {
|
||||
* @STATUS_TRANS_GOING_IDLE: shutting down the trans, only special commands
|
||||
* are sent
|
||||
* @STATUS_TRANS_IDLE: the trans is idle - general commands are not to be sent
|
||||
* @STATUS_TRANS_DEAD: trans is dead - avoid any read/write operation
|
||||
*/
|
||||
enum iwl_trans_status {
|
||||
STATUS_SYNC_HCMD_ACTIVE,
|
||||
@ -419,6 +420,7 @@ enum iwl_trans_status {
|
||||
STATUS_FW_ERROR,
|
||||
STATUS_TRANS_GOING_IDLE,
|
||||
STATUS_TRANS_IDLE,
|
||||
STATUS_TRANS_DEAD,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -71,6 +71,9 @@
|
||||
#define IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT (100 * USEC_PER_MSEC)
|
||||
#define IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT (10 * USEC_PER_MSEC)
|
||||
#define IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT (10 * USEC_PER_MSEC)
|
||||
#define IWL_MVM_SHORT_PS_TX_DATA_TIMEOUT (2 * 1024) /* defined in TU */
|
||||
#define IWL_MVM_SHORT_PS_RX_DATA_TIMEOUT (40 * 1024) /* defined in TU */
|
||||
#define IWL_MVM_P2P_LOWLATENCY_PS_ENABLE 0
|
||||
#define IWL_MVM_UAPSD_RX_DATA_TIMEOUT (50 * USEC_PER_MSEC)
|
||||
#define IWL_MVM_UAPSD_TX_DATA_TIMEOUT (50 * USEC_PER_MSEC)
|
||||
#define IWL_MVM_UAPSD_QUEUES (IEEE80211_WMM_IE_STA_QOSINFO_AC_VO |\
|
||||
@ -101,7 +104,6 @@
|
||||
#define IWL_MVM_FW_BCAST_FILTER_PASS_ALL 0
|
||||
#define IWL_MVM_QUOTA_THRESHOLD 4
|
||||
#define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0
|
||||
#define IWL_MVM_RS_DISABLE_P2P_MIMO 0
|
||||
#define IWL_MVM_RS_80_20_FAR_RANGE_TWEAK 1
|
||||
#define IWL_MVM_TOF_IS_RESPONDER 0
|
||||
#define IWL_MVM_RS_NUM_TRY_BEFORE_ANT_TOGGLE 1
|
||||
|
@ -715,11 +715,30 @@ static ssize_t iwl_dbgfs_tof_responder_params_write(struct ieee80211_vif *vif,
|
||||
goto out;
|
||||
}
|
||||
|
||||
data = iwl_dbgfs_is_match("ctrl_ch_position=", buf);
|
||||
data = iwl_dbgfs_is_match("center_freq=", buf);
|
||||
if (data) {
|
||||
struct iwl_tof_responder_config_cmd *cmd =
|
||||
&mvm->tof_data.responder_cfg;
|
||||
|
||||
ret = kstrtou32(data, 10, &value);
|
||||
if (ret == 0)
|
||||
mvm->tof_data.responder_cfg.ctrl_ch_position = value;
|
||||
if (ret == 0 && value) {
|
||||
enum ieee80211_band band = (cmd->channel_num <= 14) ?
|
||||
IEEE80211_BAND_2GHZ :
|
||||
IEEE80211_BAND_5GHZ;
|
||||
struct ieee80211_channel chn = {
|
||||
.band = band,
|
||||
.center_freq = ieee80211_channel_to_frequency(
|
||||
cmd->channel_num, band),
|
||||
};
|
||||
struct cfg80211_chan_def chandef = {
|
||||
.chan = &chn,
|
||||
.center_freq1 =
|
||||
ieee80211_channel_to_frequency(value,
|
||||
band),
|
||||
};
|
||||
|
||||
cmd->ctrl_ch_position = iwl_mvm_get_ctrl_pos(&chandef);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf,
|
||||
IWL_ERR(mvm, "FLUSHING queues: scd_q_msk = 0x%x\n", scd_q_msk);
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
ret = iwl_mvm_flush_tx_path(mvm, scd_q_msk, true) ? : count;
|
||||
ret = iwl_mvm_flush_tx_path(mvm, scd_q_msk, 0) ? : count;
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
return ret;
|
||||
|
@ -101,6 +101,7 @@ struct iwl_ssid_ie {
|
||||
|
||||
#define IWL_FULL_SCAN_MULTIPLIER 5
|
||||
#define IWL_FAST_SCHED_SCAN_ITERATIONS 3
|
||||
#define IWL_MAX_SCHED_SCAN_PLANS 2
|
||||
|
||||
enum scan_framework_client {
|
||||
SCAN_CLIENT_SCHED_SCAN = BIT(0),
|
||||
@ -359,7 +360,7 @@ struct iwl_scan_req_lmac {
|
||||
/* SCAN_REQ_PERIODIC_PARAMS_API_S */
|
||||
__le32 iter_num;
|
||||
__le32 delay;
|
||||
struct iwl_scan_schedule_lmac schedule[2];
|
||||
struct iwl_scan_schedule_lmac schedule[IWL_MAX_SCHED_SCAN_PLANS];
|
||||
struct iwl_scan_channel_opt channel_opt[2];
|
||||
u8 data[];
|
||||
} __packed;
|
||||
@ -582,7 +583,7 @@ struct iwl_scan_umac_schedule {
|
||||
*/
|
||||
struct iwl_scan_req_umac_tail {
|
||||
/* SCAN_PERIODIC_PARAMS_API_S_VER_1 */
|
||||
struct iwl_scan_umac_schedule schedule[2];
|
||||
struct iwl_scan_umac_schedule schedule[IWL_MAX_SCHED_SCAN_PLANS];
|
||||
__le16 delay;
|
||||
__le16 reserved;
|
||||
/* SCAN_PROBE_PARAMS_API_S_VER_1 */
|
||||
|
@ -1523,6 +1523,69 @@ struct iwl_dts_measurement_cmd {
|
||||
__le32 flags;
|
||||
} __packed; /* TEMPERATURE_MEASUREMENT_TRIGGER_CMD_S */
|
||||
|
||||
/**
|
||||
* enum iwl_dts_control_measurement_mode - DTS measurement type
|
||||
* @DTS_AUTOMATIC: Automatic mode (full SW control). Provide temperature read
|
||||
* back (latest value. Not waiting for new value). Use automatic
|
||||
* SW DTS configuration.
|
||||
* @DTS_REQUEST_READ: Request DTS read. Configure DTS with manual settings,
|
||||
* trigger DTS reading and provide read back temperature read
|
||||
* when available.
|
||||
* @DTS_OVER_WRITE: over-write the DTS temperatures in the SW until next read
|
||||
* @DTS_DIRECT_WITHOUT_MEASURE: DTS returns its latest temperature result,
|
||||
* without measurement trigger.
|
||||
*/
|
||||
enum iwl_dts_control_measurement_mode {
|
||||
DTS_AUTOMATIC = 0,
|
||||
DTS_REQUEST_READ = 1,
|
||||
DTS_OVER_WRITE = 2,
|
||||
DTS_DIRECT_WITHOUT_MEASURE = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_dts_used - DTS to use or used for measurement in the DTS request
|
||||
* @DTS_USE_TOP: Top
|
||||
* @DTS_USE_CHAIN_A: chain A
|
||||
* @DTS_USE_CHAIN_B: chain B
|
||||
* @DTS_USE_CHAIN_C: chain C
|
||||
* @XTAL_TEMPERATURE - read temperature from xtal
|
||||
*/
|
||||
enum iwl_dts_used {
|
||||
DTS_USE_TOP = 0,
|
||||
DTS_USE_CHAIN_A = 1,
|
||||
DTS_USE_CHAIN_B = 2,
|
||||
DTS_USE_CHAIN_C = 3,
|
||||
XTAL_TEMPERATURE = 4,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_dts_bit_mode - bit-mode to use in DTS request read mode
|
||||
* @DTS_BIT6_MODE: bit 6 mode
|
||||
* @DTS_BIT8_MODE: bit 8 mode
|
||||
*/
|
||||
enum iwl_dts_bit_mode {
|
||||
DTS_BIT6_MODE = 0,
|
||||
DTS_BIT8_MODE = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* iwl_ext_dts_measurement_cmd - request extended DTS temperature measurements
|
||||
* @control_mode: see &enum iwl_dts_control_measurement_mode
|
||||
* @temperature: used when over write DTS mode is selected
|
||||
* @sensor: set temperature sensor to use. See &enum iwl_dts_used
|
||||
* @avg_factor: average factor to DTS in request DTS read mode
|
||||
* @bit_mode: value defines the DTS bit mode to use. See &enum iwl_dts_bit_mode
|
||||
* @step_duration: step duration for the DTS
|
||||
*/
|
||||
struct iwl_ext_dts_measurement_cmd {
|
||||
__le32 control_mode;
|
||||
__le32 temperature;
|
||||
__le32 sensor;
|
||||
__le32 avg_factor;
|
||||
__le32 bit_mode;
|
||||
__le32 step_duration;
|
||||
} __packed; /* XVT_FW_DTS_CONTROL_MEASUREMENT_REQUEST_API_S */
|
||||
|
||||
/**
|
||||
* iwl_dts_measurement_notif - notification received with the measurements
|
||||
*
|
||||
|
@ -843,6 +843,9 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
|
||||
ctxt_sta->listen_interval = cpu_to_le32(mvm->hw->conf.listen_interval);
|
||||
ctxt_sta->assoc_id = cpu_to_le32(vif->bss_conf.aid);
|
||||
|
||||
if (vif->probe_req_reg && vif->bss_conf.assoc && vif->p2p)
|
||||
cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
|
||||
|
||||
return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
|
||||
}
|
||||
|
||||
|
@ -572,6 +572,14 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
|
||||
/* we create the 802.11 header and zero length SSID IE. */
|
||||
hw->wiphy->max_sched_scan_ie_len =
|
||||
SCAN_OFFLOAD_PROBE_REQ_SIZE - 24 - 2;
|
||||
hw->wiphy->max_sched_scan_plans = IWL_MAX_SCHED_SCAN_PLANS;
|
||||
hw->wiphy->max_sched_scan_plan_interval = U16_MAX;
|
||||
|
||||
/*
|
||||
* the firmware uses u8 for num of iterations, but 0xff is saved for
|
||||
* infinite loop, so the maximum number of iterations is actually 254.
|
||||
*/
|
||||
hw->wiphy->max_sched_scan_plan_iterations = 254;
|
||||
|
||||
hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN |
|
||||
NL80211_FEATURE_LOW_PRIORITY_SCAN |
|
||||
@ -1129,6 +1137,12 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
/* there's no point in fw dump if the bus is dead */
|
||||
if (test_bit(STATUS_TRANS_DEAD, &mvm->trans->status)) {
|
||||
IWL_ERR(mvm, "Skip fw error dump since bus is dead\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mvm->fw_dump_trig &&
|
||||
mvm->fw_dump_trig->mode & IWL_FW_DBG_TRIGGER_MONITOR_ONLY)
|
||||
monitor_dump_only = true;
|
||||
@ -1192,6 +1206,13 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
|
||||
if (sram2_len)
|
||||
file_len += sizeof(*dump_data) + sizeof(*dump_mem) + sram2_len;
|
||||
|
||||
/* Make room for fw's virtual image pages, if it exists */
|
||||
if (mvm->fw->img[mvm->cur_ucode].paging_mem_size)
|
||||
file_len += mvm->num_of_paging_blk *
|
||||
(sizeof(*dump_data) +
|
||||
sizeof(struct iwl_fw_error_dump_paging) +
|
||||
PAGING_BLOCK_SIZE);
|
||||
|
||||
/* If we only want a monitor dump, reset the file length */
|
||||
if (monitor_dump_only) {
|
||||
file_len = sizeof(*dump_file) + sizeof(*dump_data) +
|
||||
@ -1302,6 +1323,26 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
|
||||
dump_mem->data, IWL8260_ICCM_LEN);
|
||||
}
|
||||
|
||||
/* Dump fw's virtual image */
|
||||
if (mvm->fw->img[mvm->cur_ucode].paging_mem_size) {
|
||||
u32 i;
|
||||
|
||||
for (i = 1; i < mvm->num_of_paging_blk + 1; i++) {
|
||||
struct iwl_fw_error_dump_paging *paging;
|
||||
struct page *pages =
|
||||
mvm->fw_paging_db[i].fw_paging_block;
|
||||
|
||||
dump_data = iwl_fw_error_next_data(dump_data);
|
||||
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PAGING);
|
||||
dump_data->len = cpu_to_le32(sizeof(*paging) +
|
||||
PAGING_BLOCK_SIZE);
|
||||
paging = (void *)dump_data->data;
|
||||
paging->index = cpu_to_le32(i);
|
||||
memcpy(paging->data, page_address(pages),
|
||||
PAGING_BLOCK_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
dump_trans_data:
|
||||
fw_error_dump->trans_ptr = iwl_trans_dump_data(mvm->trans,
|
||||
mvm->fw_dump_trig);
|
||||
@ -1754,7 +1795,7 @@ static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
|
||||
* Flush them here.
|
||||
*/
|
||||
mutex_lock(&mvm->mutex);
|
||||
iwl_mvm_flush_tx_path(mvm, tfd_msk, true);
|
||||
iwl_mvm_flush_tx_path(mvm, tfd_msk, 0);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
|
||||
/*
|
||||
@ -1955,6 +1996,27 @@ out:
|
||||
*total_flags = 0;
|
||||
}
|
||||
|
||||
static void iwl_mvm_config_iface_filter(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
unsigned int filter_flags,
|
||||
unsigned int changed_flags)
|
||||
{
|
||||
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
|
||||
|
||||
/* We support only filter for probe requests */
|
||||
if (!(changed_flags & FIF_PROBE_REQ))
|
||||
return;
|
||||
|
||||
/* Supported only for p2p client interfaces */
|
||||
if (vif->type != NL80211_IFTYPE_STATION || !vif->bss_conf.assoc ||
|
||||
!vif->p2p)
|
||||
return;
|
||||
|
||||
mutex_lock(&mvm->mutex);
|
||||
iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
|
||||
mutex_unlock(&mvm->mutex);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_BCAST_FILTERING
|
||||
struct iwl_bcast_iter_data {
|
||||
struct iwl_mvm *mvm;
|
||||
@ -3898,7 +3960,7 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,
|
||||
}
|
||||
|
||||
if (drop) {
|
||||
if (iwl_mvm_flush_tx_path(mvm, msk, true))
|
||||
if (iwl_mvm_flush_tx_path(mvm, msk, 0))
|
||||
IWL_ERR(mvm, "flush request fail\n");
|
||||
mutex_unlock(&mvm->mutex);
|
||||
} else {
|
||||
@ -4135,6 +4197,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
|
||||
.config = iwl_mvm_mac_config,
|
||||
.prepare_multicast = iwl_mvm_prepare_multicast,
|
||||
.configure_filter = iwl_mvm_configure_filter,
|
||||
.config_iface_filter = iwl_mvm_config_iface_filter,
|
||||
.bss_info_changed = iwl_mvm_bss_info_changed,
|
||||
.hw_scan = iwl_mvm_mac_hw_scan,
|
||||
.cancel_hw_scan = iwl_mvm_mac_cancel_hw_scan,
|
||||
|
@ -1036,7 +1036,7 @@ const char *iwl_mvm_get_tx_fail_reason(u32 status);
|
||||
#else
|
||||
static inline const char *iwl_mvm_get_tx_fail_reason(u32 status) { return ""; }
|
||||
#endif
|
||||
int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, bool sync);
|
||||
int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, u32 flags);
|
||||
void iwl_mvm_async_handlers_purge(struct iwl_mvm *mvm);
|
||||
|
||||
static inline void iwl_mvm_set_tx_cmd_ccmp(struct ieee80211_tx_info *info,
|
||||
|
@ -483,6 +483,7 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
kfree(mvm->nvm_sections[section_id].data);
|
||||
mvm->nvm_sections[section_id].data = temp;
|
||||
mvm->nvm_sections[section_id].length = section_size;
|
||||
|
||||
|
@ -348,7 +348,8 @@ static void iwl_mvm_power_config_skip_dtim(struct iwl_mvm *mvm,
|
||||
|
||||
static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
struct iwl_mac_power_cmd *cmd)
|
||||
struct iwl_mac_power_cmd *cmd,
|
||||
bool host_awake)
|
||||
{
|
||||
int dtimper, bi;
|
||||
int keep_alive;
|
||||
@ -376,8 +377,13 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
|
||||
|
||||
cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
|
||||
|
||||
if (!vif->bss_conf.ps || !mvmvif->pm_enabled ||
|
||||
(iwl_mvm_vif_low_latency(mvmvif) && vif->p2p))
|
||||
if (!vif->bss_conf.ps || !mvmvif->pm_enabled)
|
||||
return;
|
||||
|
||||
if (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p &&
|
||||
(!fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS) ||
|
||||
!IWL_MVM_P2P_LOWLATENCY_PS_ENABLE))
|
||||
return;
|
||||
|
||||
cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
|
||||
@ -389,19 +395,25 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
|
||||
cmd->lprx_rssi_threshold = POWER_LPRX_RSSI_THRESHOLD;
|
||||
}
|
||||
|
||||
iwl_mvm_power_config_skip_dtim(mvm, vif, cmd,
|
||||
mvm->cur_ucode != IWL_UCODE_WOWLAN);
|
||||
iwl_mvm_power_config_skip_dtim(mvm, vif, cmd, host_awake);
|
||||
|
||||
if (mvm->cur_ucode != IWL_UCODE_WOWLAN) {
|
||||
cmd->rx_data_timeout =
|
||||
cpu_to_le32(IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT);
|
||||
cmd->tx_data_timeout =
|
||||
cpu_to_le32(IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT);
|
||||
} else {
|
||||
if (!host_awake) {
|
||||
cmd->rx_data_timeout =
|
||||
cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT);
|
||||
cmd->tx_data_timeout =
|
||||
cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
|
||||
} else if (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p &&
|
||||
fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS)) {
|
||||
cmd->tx_data_timeout =
|
||||
cpu_to_le32(IWL_MVM_SHORT_PS_TX_DATA_TIMEOUT);
|
||||
cmd->rx_data_timeout =
|
||||
cpu_to_le32(IWL_MVM_SHORT_PS_RX_DATA_TIMEOUT);
|
||||
} else {
|
||||
cmd->rx_data_timeout =
|
||||
cpu_to_le32(IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT);
|
||||
cmd->tx_data_timeout =
|
||||
cpu_to_le32(IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT);
|
||||
}
|
||||
|
||||
if (iwl_mvm_power_allow_uapsd(mvm, vif))
|
||||
@ -458,7 +470,8 @@ static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm,
|
||||
{
|
||||
struct iwl_mac_power_cmd cmd = {};
|
||||
|
||||
iwl_mvm_power_build_cmd(mvm, vif, &cmd);
|
||||
iwl_mvm_power_build_cmd(mvm, vif, &cmd,
|
||||
mvm->cur_ucode != IWL_UCODE_WOWLAN);
|
||||
iwl_mvm_power_log(mvm, &cmd);
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
memcpy(&iwl_mvm_vif_from_mac80211(vif)->mac_pwr_cmd, &cmd, sizeof(cmd));
|
||||
@ -994,11 +1007,7 @@ int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm,
|
||||
if (!vif->bss_conf.assoc)
|
||||
return 0;
|
||||
|
||||
iwl_mvm_power_build_cmd(mvm, vif, &cmd);
|
||||
|
||||
/* when enabling D0i3, override the skip-over-dtim configuration */
|
||||
if (enable)
|
||||
iwl_mvm_power_config_skip_dtim(mvm, vif, &cmd, false);
|
||||
iwl_mvm_power_build_cmd(mvm, vif, &cmd, !enable);
|
||||
|
||||
iwl_mvm_power_log(mvm, &cmd);
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
|
@ -177,9 +177,6 @@ static bool rs_mimo_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
|
||||
mvmsta = iwl_mvm_sta_from_mac80211(sta);
|
||||
mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
|
||||
if (IWL_MVM_RS_DISABLE_P2P_MIMO &&
|
||||
iwl_mvm_vif_low_latency(mvmvif) && mvmsta->vif->p2p)
|
||||
return false;
|
||||
|
||||
if (mvm->nvm_data->sku_cap_mimo_disabled)
|
||||
return false;
|
||||
@ -3071,9 +3068,6 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
|
||||
else
|
||||
rs_vht_init(mvm, sta, lq_sta, vht_cap);
|
||||
|
||||
if (IWL_MVM_RS_DISABLE_P2P_MIMO && sta_priv->vif->p2p)
|
||||
lq_sta->active_mimo2_rate = 0;
|
||||
|
||||
lq_sta->max_legacy_rate_idx =
|
||||
rs_get_max_rate_from_mask(lq_sta->active_legacy_rate);
|
||||
lq_sta->max_siso_rate_idx =
|
||||
|
@ -131,7 +131,6 @@ struct iwl_mvm_scan_params {
|
||||
int n_ssids;
|
||||
struct cfg80211_ssid *ssids;
|
||||
struct ieee80211_channel **channels;
|
||||
u16 interval; /* interval between scans (in secs) */
|
||||
u32 flags;
|
||||
u8 *mac_addr;
|
||||
u8 *mac_addr_mask;
|
||||
@ -140,7 +139,8 @@ struct iwl_mvm_scan_params {
|
||||
int n_match_sets;
|
||||
struct iwl_scan_probe_req preq;
|
||||
struct cfg80211_match_set *match_sets;
|
||||
u8 iterations[2];
|
||||
int n_scan_plans;
|
||||
struct cfg80211_sched_scan_plan *scan_plans;
|
||||
};
|
||||
|
||||
static u8 iwl_mvm_scan_rx_ant(struct iwl_mvm *mvm)
|
||||
@ -474,7 +474,7 @@ iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm,
|
||||
int ret;
|
||||
|
||||
if (WARN_ON(req->n_match_sets > IWL_SCAN_MAX_PROFILES))
|
||||
return -EIO;
|
||||
return -EIO;
|
||||
|
||||
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SHORT_BL)
|
||||
blacklist_len = IWL_SCAN_SHORT_BLACKLIST_LEN;
|
||||
@ -737,8 +737,7 @@ static inline bool iwl_mvm_scan_fits(struct iwl_mvm *mvm, int n_ssids,
|
||||
}
|
||||
|
||||
static inline bool iwl_mvm_scan_use_ebs(struct iwl_mvm *mvm,
|
||||
struct ieee80211_vif *vif,
|
||||
int n_iterations)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
const struct iwl_ucode_capabilities *capa = &mvm->fw->ucode_capa;
|
||||
|
||||
@ -753,11 +752,6 @@ static inline bool iwl_mvm_scan_use_ebs(struct iwl_mvm *mvm,
|
||||
vif->type != NL80211_IFTYPE_P2P_DEVICE);
|
||||
}
|
||||
|
||||
static int iwl_mvm_scan_total_iterations(struct iwl_mvm_scan_params *params)
|
||||
{
|
||||
return params->iterations[0] + params->iterations[1];
|
||||
}
|
||||
|
||||
static int iwl_mvm_scan_lmac_flags(struct iwl_mvm *mvm,
|
||||
struct iwl_mvm_scan_params *params)
|
||||
{
|
||||
@ -796,12 +790,15 @@ static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
(void *)(cmd->data + sizeof(struct iwl_scan_channel_cfg_lmac) *
|
||||
mvm->fw->ucode_capa.n_scan_channels);
|
||||
u32 ssid_bitmap = 0;
|
||||
int n_iterations = iwl_mvm_scan_total_iterations(params);
|
||||
int i;
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
memset(cmd, 0, ksize(cmd));
|
||||
|
||||
if (WARN_ON(params->n_scan_plans > IWL_MAX_SCHED_SCAN_PLANS))
|
||||
return -EINVAL;
|
||||
|
||||
iwl_mvm_scan_lmac_dwell(mvm, cmd, params);
|
||||
|
||||
cmd->rx_chain_select = iwl_mvm_scan_rx_chain(mvm);
|
||||
@ -821,14 +818,26 @@ static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
/* this API uses bits 1-20 instead of 0-19 */
|
||||
ssid_bitmap <<= 1;
|
||||
|
||||
cmd->schedule[0].delay = cpu_to_le16(params->interval);
|
||||
cmd->schedule[0].iterations = params->iterations[0];
|
||||
cmd->schedule[0].full_scan_mul = 1;
|
||||
cmd->schedule[1].delay = cpu_to_le16(params->interval);
|
||||
cmd->schedule[1].iterations = params->iterations[1];
|
||||
cmd->schedule[1].full_scan_mul = 1;
|
||||
for (i = 0; i < params->n_scan_plans; i++) {
|
||||
struct cfg80211_sched_scan_plan *scan_plan =
|
||||
¶ms->scan_plans[i];
|
||||
|
||||
if (iwl_mvm_scan_use_ebs(mvm, vif, n_iterations)) {
|
||||
cmd->schedule[i].delay =
|
||||
cpu_to_le16(scan_plan->interval);
|
||||
cmd->schedule[i].iterations = scan_plan->iterations;
|
||||
cmd->schedule[i].full_scan_mul = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the number of iterations of the last scan plan is set to
|
||||
* zero, it should run infinitely. However, this is not always the case.
|
||||
* For example, when regular scan is requested the driver sets one scan
|
||||
* plan with one iteration.
|
||||
*/
|
||||
if (!cmd->schedule[i - 1].iterations)
|
||||
cmd->schedule[i - 1].iterations = 0xff;
|
||||
|
||||
if (iwl_mvm_scan_use_ebs(mvm, vif)) {
|
||||
cmd->channel_opt[0].flags =
|
||||
cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS |
|
||||
IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
|
||||
@ -892,7 +901,6 @@ static __le32 iwl_mvm_scan_config_rates(struct iwl_mvm *mvm)
|
||||
|
||||
int iwl_mvm_config_scan(struct iwl_mvm *mvm)
|
||||
{
|
||||
|
||||
struct iwl_scan_config *scan_config;
|
||||
struct ieee80211_supported_band *band;
|
||||
int num_channels =
|
||||
@ -968,6 +976,12 @@ static int iwl_mvm_scan_uid_by_status(struct iwl_mvm *mvm, int status)
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline bool iwl_mvm_is_regular_scan(struct iwl_mvm_scan_params *params)
|
||||
{
|
||||
return params->n_scan_plans == 1 &&
|
||||
params->scan_plans[0].iterations == 1;
|
||||
}
|
||||
|
||||
static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm,
|
||||
struct iwl_scan_req_umac *cmd,
|
||||
struct iwl_mvm_scan_params *params)
|
||||
@ -980,7 +994,7 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm,
|
||||
cmd->scan_priority =
|
||||
iwl_mvm_scan_priority(mvm, IWL_SCAN_PRIORITY_EXT_6);
|
||||
|
||||
if (iwl_mvm_scan_total_iterations(params) == 1)
|
||||
if (iwl_mvm_is_regular_scan(params))
|
||||
cmd->ooc_priority =
|
||||
iwl_mvm_scan_priority(mvm, IWL_SCAN_PRIORITY_EXT_6);
|
||||
else
|
||||
@ -1027,7 +1041,7 @@ static u32 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm,
|
||||
else
|
||||
flags |= IWL_UMAC_SCAN_GEN_FLAGS_MATCH;
|
||||
|
||||
if (iwl_mvm_scan_total_iterations(params) > 1)
|
||||
if (!iwl_mvm_is_regular_scan(params))
|
||||
flags |= IWL_UMAC_SCAN_GEN_FLAGS_PERIODIC;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
@ -1045,12 +1059,14 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
struct iwl_scan_req_umac_tail *sec_part = (void *)&cmd->data +
|
||||
sizeof(struct iwl_scan_channel_cfg_umac) *
|
||||
mvm->fw->ucode_capa.n_scan_channels;
|
||||
int uid;
|
||||
int uid, i;
|
||||
u32 ssid_bitmap = 0;
|
||||
int n_iterations = iwl_mvm_scan_total_iterations(params);
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
if (WARN_ON(params->n_scan_plans > IWL_MAX_SCHED_SCAN_PLANS))
|
||||
return -EINVAL;
|
||||
|
||||
uid = iwl_mvm_scan_uid_by_status(mvm, 0);
|
||||
if (uid < 0)
|
||||
return uid;
|
||||
@ -1067,7 +1083,7 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
if (type == IWL_MVM_SCAN_SCHED)
|
||||
cmd->flags = cpu_to_le32(IWL_UMAC_SCAN_FLAG_PREEMPTIVE);
|
||||
|
||||
if (iwl_mvm_scan_use_ebs(mvm, vif, n_iterations))
|
||||
if (iwl_mvm_scan_use_ebs(mvm, vif))
|
||||
cmd->channel_flags = IWL_SCAN_CHANNEL_FLAG_EBS |
|
||||
IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
|
||||
IWL_SCAN_CHANNEL_FLAG_CACHE_ADD;
|
||||
@ -1079,12 +1095,23 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
iwl_mvm_umac_scan_cfg_channels(mvm, params->channels,
|
||||
params->n_channels, ssid_bitmap, cmd);
|
||||
|
||||
/* With UMAC we use only one schedule for now, so use the sum
|
||||
* of the iterations (with a a maximum of 255).
|
||||
for (i = 0; i < params->n_scan_plans; i++) {
|
||||
struct cfg80211_sched_scan_plan *scan_plan =
|
||||
¶ms->scan_plans[i];
|
||||
|
||||
sec_part->schedule[i].iter_count = scan_plan->iterations;
|
||||
sec_part->schedule[i].interval =
|
||||
cpu_to_le16(scan_plan->interval);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the number of iterations of the last scan plan is set to
|
||||
* zero, it should run infinitely. However, this is not always the case.
|
||||
* For example, when regular scan is requested the driver sets one scan
|
||||
* plan with one iteration.
|
||||
*/
|
||||
sec_part->schedule[0].iter_count =
|
||||
(n_iterations > 255) ? 255 : n_iterations;
|
||||
sec_part->schedule[0].interval = cpu_to_le16(params->interval);
|
||||
if (!sec_part->schedule[i - 1].iter_count)
|
||||
sec_part->schedule[i - 1].iter_count = 0xff;
|
||||
|
||||
sec_part->delay = cpu_to_le16(params->delay);
|
||||
sec_part->preq = params->preq;
|
||||
@ -1150,6 +1177,7 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
};
|
||||
struct iwl_mvm_scan_params params = {};
|
||||
int ret;
|
||||
struct cfg80211_sched_scan_plan scan_plan = { .iterations = 1 };
|
||||
|
||||
lockdep_assert_held(&mvm->mutex);
|
||||
|
||||
@ -1162,8 +1190,6 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN);
|
||||
|
||||
/* we should have failed registration if scan_cmd was NULL */
|
||||
if (WARN_ON(!mvm->scan_cmd))
|
||||
return -ENOMEM;
|
||||
@ -1175,7 +1201,6 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
params.flags = req->flags;
|
||||
params.n_channels = req->n_channels;
|
||||
params.delay = 0;
|
||||
params.interval = 0;
|
||||
params.ssids = req->ssids;
|
||||
params.channels = req->channels;
|
||||
params.mac_addr = req->mac_addr;
|
||||
@ -1185,8 +1210,8 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
params.n_match_sets = 0;
|
||||
params.match_sets = NULL;
|
||||
|
||||
params.iterations[0] = 1;
|
||||
params.iterations[1] = 0;
|
||||
params.scan_plans = &scan_plan;
|
||||
params.n_scan_plans = 1;
|
||||
|
||||
params.type = iwl_mvm_get_scan_type(mvm, vif, ¶ms);
|
||||
|
||||
@ -1205,21 +1230,20 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
return ret;
|
||||
|
||||
ret = iwl_mvm_send_cmd(mvm, &hcmd);
|
||||
if (!ret) {
|
||||
IWL_DEBUG_SCAN(mvm, "Scan request was sent successfully\n");
|
||||
mvm->scan_status |= IWL_MVM_SCAN_REGULAR;
|
||||
} else {
|
||||
if (ret) {
|
||||
/* If the scan failed, it usually means that the FW was unable
|
||||
* to allocate the time events. Warn on it, but maybe we
|
||||
* should try to send the command again with different params.
|
||||
*/
|
||||
IWL_ERR(mvm, "Scan failed! ret %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
|
||||
IWL_DEBUG_SCAN(mvm, "Scan request was sent successfully\n");
|
||||
mvm->scan_status |= IWL_MVM_SCAN_REGULAR;
|
||||
iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
|
||||
@ -1265,20 +1289,14 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
|
||||
params.pass_all = iwl_mvm_scan_pass_all(mvm, req);
|
||||
params.n_match_sets = req->n_match_sets;
|
||||
params.match_sets = req->match_sets;
|
||||
if (!req->n_scan_plans)
|
||||
return -EINVAL;
|
||||
|
||||
params.iterations[0] = 0;
|
||||
params.iterations[1] = 0xff;
|
||||
params.n_scan_plans = req->n_scan_plans;
|
||||
params.scan_plans = req->scan_plans;
|
||||
|
||||
params.type = iwl_mvm_get_scan_type(mvm, vif, ¶ms);
|
||||
|
||||
if (req->scan_plans[0].interval > U16_MAX) {
|
||||
IWL_DEBUG_SCAN(mvm,
|
||||
"interval value is > 16-bits, set to max possible\n");
|
||||
params.interval = U16_MAX;
|
||||
} else {
|
||||
params.interval = req->scan_plans[0].interval;
|
||||
}
|
||||
|
||||
/* In theory, LMAC scans can handle a 32-bit delay, but since
|
||||
* waiting for over 18 hours to start the scan is a bit silly
|
||||
* and to keep it aligned with UMAC scans (which only support
|
||||
|
@ -255,7 +255,7 @@ static void iwl_mvm_tdls_sta_deinit(struct iwl_mvm *mvm,
|
||||
/* disable the TDLS STA-specific queues */
|
||||
sta_msk = mvmsta->tfd_queue_msk;
|
||||
for_each_set_bit(i, &sta_msk, sizeof(sta_msk) * BITS_PER_BYTE)
|
||||
iwl_mvm_disable_txq(mvm, i, i, 0, 0);
|
||||
iwl_mvm_disable_txq(mvm, i, i, IWL_MAX_TID_COUNT, 0);
|
||||
}
|
||||
|
||||
int iwl_mvm_add_sta(struct iwl_mvm *mvm,
|
||||
@ -474,7 +474,8 @@ void iwl_mvm_sta_drained_wk(struct work_struct *wk)
|
||||
unsigned long i, msk = mvm->tfd_drained[sta_id];
|
||||
|
||||
for_each_set_bit(i, &msk, sizeof(msk) * BITS_PER_BYTE)
|
||||
iwl_mvm_disable_txq(mvm, i, i, 0, 0);
|
||||
iwl_mvm_disable_txq(mvm, i, i,
|
||||
IWL_MAX_TID_COUNT, 0);
|
||||
|
||||
mvm->tfd_drained[sta_id] = 0;
|
||||
IWL_DEBUG_TDLS(mvm, "Drained sta %d, with queues %ld\n",
|
||||
@ -501,7 +502,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
|
||||
if (ret)
|
||||
return ret;
|
||||
/* flush its queues here since we are freeing mvm_sta */
|
||||
ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, true);
|
||||
ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = iwl_trans_wait_tx_queue_empty(mvm->trans,
|
||||
@ -1155,7 +1156,7 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
|
||||
|
||||
if (old_state >= IWL_AGG_ON) {
|
||||
iwl_mvm_drain_sta(mvm, mvmsta, true);
|
||||
if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), true))
|
||||
if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), 0))
|
||||
IWL_ERR(mvm, "Couldn't flush the AGG queue\n");
|
||||
iwl_trans_wait_tx_queue_empty(mvm->trans,
|
||||
mvmsta->tfd_queue_msk);
|
||||
|
@ -129,7 +129,7 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
|
||||
* issue as it will have to complete before the next command is
|
||||
* executed, and a new time event means a new command.
|
||||
*/
|
||||
iwl_mvm_flush_tx_path(mvm, queues, false);
|
||||
iwl_mvm_flush_tx_path(mvm, queues, CMD_ASYNC);
|
||||
}
|
||||
|
||||
static void iwl_mvm_roc_finished(struct iwl_mvm *mvm)
|
||||
|
@ -176,6 +176,9 @@ static int iwl_mvm_get_temp_cmd(struct iwl_mvm *mvm)
|
||||
struct iwl_dts_measurement_cmd cmd = {
|
||||
.flags = cpu_to_le32(DTS_TRIGGER_CMD_FLAGS_TEMP),
|
||||
};
|
||||
struct iwl_ext_dts_measurement_cmd extcmd = {
|
||||
.control_mode = cpu_to_le32(DTS_AUTOMATIC),
|
||||
};
|
||||
u32 cmdid;
|
||||
|
||||
if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_WIDE_CMD_HDR))
|
||||
@ -183,8 +186,12 @@ static int iwl_mvm_get_temp_cmd(struct iwl_mvm *mvm)
|
||||
PHY_OPS_GROUP, 0);
|
||||
else
|
||||
cmdid = CMD_DTS_MEASUREMENT_TRIGGER;
|
||||
return iwl_mvm_send_cmd_pdu(mvm, cmdid, 0,
|
||||
sizeof(cmd), &cmd);
|
||||
|
||||
if (!fw_has_capa(&mvm->fw->ucode_capa,
|
||||
IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE))
|
||||
return iwl_mvm_send_cmd_pdu(mvm, cmdid, 0, sizeof(cmd), &cmd);
|
||||
|
||||
return iwl_mvm_send_cmd_pdu(mvm, cmdid, 0, sizeof(extcmd), &extcmd);
|
||||
}
|
||||
|
||||
int iwl_mvm_get_temp(struct iwl_mvm *mvm)
|
||||
|
@ -1099,7 +1099,7 @@ out:
|
||||
* 2) flush the Tx path
|
||||
* 3) wait for the transport queues to be empty
|
||||
*/
|
||||
int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, bool sync)
|
||||
int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, u32 flags)
|
||||
{
|
||||
int ret;
|
||||
struct iwl_tx_path_flush_cmd flush_cmd = {
|
||||
@ -1107,8 +1107,6 @@ int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, bool sync)
|
||||
.flush_ctl = cpu_to_le16(DUMP_TX_FIFO_FLUSH),
|
||||
};
|
||||
|
||||
u32 flags = sync ? 0 : CMD_ASYNC;
|
||||
|
||||
ret = iwl_mvm_send_cmd_pdu(mvm, TXPATH_FLUSH, flags,
|
||||
sizeof(flush_cmd), &flush_cmd);
|
||||
if (ret)
|
||||
|
@ -592,10 +592,8 @@ static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans)
|
||||
|
||||
do {
|
||||
ret = iwl_pcie_set_hw_ready(trans);
|
||||
if (ret >= 0) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
if (ret >= 0)
|
||||
return 0;
|
||||
|
||||
usleep_range(200, 1000);
|
||||
t += 200;
|
||||
@ -605,10 +603,6 @@ static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans)
|
||||
|
||||
IWL_ERR(trans, "Couldn't prepare the card\n");
|
||||
|
||||
out:
|
||||
iwl_clear_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
|
||||
CSR_RESET_LINK_PWR_MGMT_DISABLED);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1821,6 +1821,10 @@ static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (netif_carrier_ok(priv->netdev))
|
||||
netif_carrier_off(priv->netdev);
|
||||
mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1925,6 +1929,10 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
|
||||
if (mwifiex_set_mgmt_ies(priv, ¶ms->beacon))
|
||||
return -1;
|
||||
|
||||
if (!netif_carrier_ok(priv->netdev))
|
||||
netif_carrier_on(priv->netdev);
|
||||
mwifiex_wake_up_net_dev_queue(priv->netdev, priv->adapter);
|
||||
|
||||
memcpy(&priv->bss_cfg, bss_cfg, sizeof(priv->bss_cfg));
|
||||
kfree(bss_cfg);
|
||||
return 0;
|
||||
|
@ -179,19 +179,12 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
|
||||
case EVENT_UAP_BSS_IDLE:
|
||||
priv->media_connected = false;
|
||||
priv->port_open = false;
|
||||
if (netif_carrier_ok(priv->netdev))
|
||||
netif_carrier_off(priv->netdev);
|
||||
mwifiex_stop_net_dev_queue(priv->netdev, adapter);
|
||||
|
||||
mwifiex_clean_txrx(priv);
|
||||
mwifiex_del_all_sta_list(priv);
|
||||
break;
|
||||
case EVENT_UAP_BSS_ACTIVE:
|
||||
priv->media_connected = true;
|
||||
priv->port_open = true;
|
||||
if (!netif_carrier_ok(priv->netdev))
|
||||
netif_carrier_on(priv->netdev);
|
||||
mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
|
||||
break;
|
||||
case EVENT_UAP_BSS_START:
|
||||
mwifiex_dbg(adapter, EVENT,
|
||||
|
@ -1576,6 +1576,7 @@ static int ezusb_probe(struct usb_interface *interface,
|
||||
ezusb_hard_reset, NULL);
|
||||
if (!priv) {
|
||||
err("Couldn't allocate orinocodev");
|
||||
retval = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -80,6 +80,15 @@ config SSB_SDIOHOST
|
||||
|
||||
If unsure, say N
|
||||
|
||||
config SSB_HOST_SOC
|
||||
bool "Support for SSB bus on SoC"
|
||||
depends on SSB
|
||||
help
|
||||
Host interface for a SSB directly mapped into memory. This is
|
||||
for some Broadcom SoCs from the BCM47xx and BCM53xx lines.
|
||||
|
||||
If unsure, say N
|
||||
|
||||
config SSB_SILENT
|
||||
bool "No SSB kernel messages"
|
||||
depends on SSB && EXPERT
|
||||
|
@ -5,8 +5,9 @@ ssb-$(CONFIG_SSB_SPROM) += sprom.o
|
||||
|
||||
# host support
|
||||
ssb-$(CONFIG_SSB_PCIHOST) += pci.o pcihost_wrapper.o
|
||||
ssb-$(CONFIG_SSB_PCMCIAHOST) += pcmcia.o
|
||||
ssb-$(CONFIG_SSB_PCMCIAHOST) += pcmcia.o bridge_pcmcia_80211.o
|
||||
ssb-$(CONFIG_SSB_SDIOHOST) += sdio.o
|
||||
ssb-$(CONFIG_SSB_HOST_SOC) += host_soc.o
|
||||
|
||||
# built-in drivers
|
||||
ssb-y += driver_chipcommon.o
|
||||
|
128
drivers/ssb/bridge_pcmcia_80211.c
Normal file
128
drivers/ssb/bridge_pcmcia_80211.c
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Broadcom 43xx PCMCIA-SSB bridge module
|
||||
*
|
||||
* Copyright (c) 2007 Michael Buesch <m@bues.ch>
|
||||
*
|
||||
* Licensed under the GNU/GPL. See COPYING for details.
|
||||
*/
|
||||
|
||||
#include <linux/ssb/ssb.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <pcmcia/cistpl.h>
|
||||
#include <pcmcia/ciscode.h>
|
||||
#include <pcmcia/ds.h>
|
||||
#include <pcmcia/cisreg.h>
|
||||
|
||||
#include "ssb_private.h"
|
||||
|
||||
static const struct pcmcia_device_id ssb_host_pcmcia_tbl[] = {
|
||||
PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448),
|
||||
PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476),
|
||||
PCMCIA_DEVICE_NULL,
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pcmcia, ssb_host_pcmcia_tbl);
|
||||
|
||||
static int ssb_host_pcmcia_probe(struct pcmcia_device *dev)
|
||||
{
|
||||
struct ssb_bus *ssb;
|
||||
int err = -ENOMEM;
|
||||
int res = 0;
|
||||
|
||||
ssb = kzalloc(sizeof(*ssb), GFP_KERNEL);
|
||||
if (!ssb)
|
||||
goto out_error;
|
||||
|
||||
err = -ENODEV;
|
||||
|
||||
dev->config_flags |= CONF_ENABLE_IRQ;
|
||||
|
||||
dev->resource[2]->flags |= WIN_ENABLE | WIN_DATA_WIDTH_16 |
|
||||
WIN_USE_WAIT;
|
||||
dev->resource[2]->start = 0;
|
||||
dev->resource[2]->end = SSB_CORE_SIZE;
|
||||
res = pcmcia_request_window(dev, dev->resource[2], 250);
|
||||
if (res != 0)
|
||||
goto err_kfree_ssb;
|
||||
|
||||
res = pcmcia_map_mem_page(dev, dev->resource[2], 0);
|
||||
if (res != 0)
|
||||
goto err_disable;
|
||||
|
||||
if (!dev->irq)
|
||||
goto err_disable;
|
||||
|
||||
res = pcmcia_enable_device(dev);
|
||||
if (res != 0)
|
||||
goto err_disable;
|
||||
|
||||
err = ssb_bus_pcmciabus_register(ssb, dev, dev->resource[2]->start);
|
||||
if (err)
|
||||
goto err_disable;
|
||||
dev->priv = ssb;
|
||||
|
||||
return 0;
|
||||
|
||||
err_disable:
|
||||
pcmcia_disable_device(dev);
|
||||
err_kfree_ssb:
|
||||
kfree(ssb);
|
||||
out_error:
|
||||
ssb_err("Initialization failed (%d, %d)\n", res, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void ssb_host_pcmcia_remove(struct pcmcia_device *dev)
|
||||
{
|
||||
struct ssb_bus *ssb = dev->priv;
|
||||
|
||||
ssb_bus_unregister(ssb);
|
||||
pcmcia_disable_device(dev);
|
||||
kfree(ssb);
|
||||
dev->priv = NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int ssb_host_pcmcia_suspend(struct pcmcia_device *dev)
|
||||
{
|
||||
struct ssb_bus *ssb = dev->priv;
|
||||
|
||||
return ssb_bus_suspend(ssb);
|
||||
}
|
||||
|
||||
static int ssb_host_pcmcia_resume(struct pcmcia_device *dev)
|
||||
{
|
||||
struct ssb_bus *ssb = dev->priv;
|
||||
|
||||
return ssb_bus_resume(ssb);
|
||||
}
|
||||
#else /* CONFIG_PM */
|
||||
# define ssb_host_pcmcia_suspend NULL
|
||||
# define ssb_host_pcmcia_resume NULL
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static struct pcmcia_driver ssb_host_pcmcia_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "ssb-pcmcia",
|
||||
.id_table = ssb_host_pcmcia_tbl,
|
||||
.probe = ssb_host_pcmcia_probe,
|
||||
.remove = ssb_host_pcmcia_remove,
|
||||
.suspend = ssb_host_pcmcia_suspend,
|
||||
.resume = ssb_host_pcmcia_resume,
|
||||
};
|
||||
|
||||
/*
|
||||
* These are not module init/exit functions!
|
||||
* The module_pcmcia_driver() helper cannot be used here.
|
||||
*/
|
||||
int ssb_host_pcmcia_init(void)
|
||||
{
|
||||
return pcmcia_register_driver(&ssb_host_pcmcia_driver);
|
||||
}
|
||||
|
||||
void ssb_host_pcmcia_exit(void)
|
||||
{
|
||||
pcmcia_unregister_driver(&ssb_host_pcmcia_driver);
|
||||
}
|
173
drivers/ssb/host_soc.c
Normal file
173
drivers/ssb/host_soc.c
Normal file
@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Sonics Silicon Backplane SoC host related functions.
|
||||
* Subsystem core
|
||||
*
|
||||
* Copyright 2005, Broadcom Corporation
|
||||
* Copyright 2006, 2007, Michael Buesch <m@bues.ch>
|
||||
*
|
||||
* Licensed under the GNU/GPL. See COPYING for details.
|
||||
*/
|
||||
|
||||
#include <linux/ssb/ssb.h>
|
||||
|
||||
#include "ssb_private.h"
|
||||
|
||||
static u8 ssb_host_soc_read8(struct ssb_device *dev, u16 offset)
|
||||
{
|
||||
struct ssb_bus *bus = dev->bus;
|
||||
|
||||
offset += dev->core_index * SSB_CORE_SIZE;
|
||||
return readb(bus->mmio + offset);
|
||||
}
|
||||
|
||||
static u16 ssb_host_soc_read16(struct ssb_device *dev, u16 offset)
|
||||
{
|
||||
struct ssb_bus *bus = dev->bus;
|
||||
|
||||
offset += dev->core_index * SSB_CORE_SIZE;
|
||||
return readw(bus->mmio + offset);
|
||||
}
|
||||
|
||||
static u32 ssb_host_soc_read32(struct ssb_device *dev, u16 offset)
|
||||
{
|
||||
struct ssb_bus *bus = dev->bus;
|
||||
|
||||
offset += dev->core_index * SSB_CORE_SIZE;
|
||||
return readl(bus->mmio + offset);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SSB_BLOCKIO
|
||||
static void ssb_host_soc_block_read(struct ssb_device *dev, void *buffer,
|
||||
size_t count, u16 offset, u8 reg_width)
|
||||
{
|
||||
struct ssb_bus *bus = dev->bus;
|
||||
void __iomem *addr;
|
||||
|
||||
offset += dev->core_index * SSB_CORE_SIZE;
|
||||
addr = bus->mmio + offset;
|
||||
|
||||
switch (reg_width) {
|
||||
case sizeof(u8): {
|
||||
u8 *buf = buffer;
|
||||
|
||||
while (count) {
|
||||
*buf = __raw_readb(addr);
|
||||
buf++;
|
||||
count--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case sizeof(u16): {
|
||||
__le16 *buf = buffer;
|
||||
|
||||
SSB_WARN_ON(count & 1);
|
||||
while (count) {
|
||||
*buf = (__force __le16)__raw_readw(addr);
|
||||
buf++;
|
||||
count -= 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case sizeof(u32): {
|
||||
__le32 *buf = buffer;
|
||||
|
||||
SSB_WARN_ON(count & 3);
|
||||
while (count) {
|
||||
*buf = (__force __le32)__raw_readl(addr);
|
||||
buf++;
|
||||
count -= 4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
SSB_WARN_ON(1);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_SSB_BLOCKIO */
|
||||
|
||||
static void ssb_host_soc_write8(struct ssb_device *dev, u16 offset, u8 value)
|
||||
{
|
||||
struct ssb_bus *bus = dev->bus;
|
||||
|
||||
offset += dev->core_index * SSB_CORE_SIZE;
|
||||
writeb(value, bus->mmio + offset);
|
||||
}
|
||||
|
||||
static void ssb_host_soc_write16(struct ssb_device *dev, u16 offset, u16 value)
|
||||
{
|
||||
struct ssb_bus *bus = dev->bus;
|
||||
|
||||
offset += dev->core_index * SSB_CORE_SIZE;
|
||||
writew(value, bus->mmio + offset);
|
||||
}
|
||||
|
||||
static void ssb_host_soc_write32(struct ssb_device *dev, u16 offset, u32 value)
|
||||
{
|
||||
struct ssb_bus *bus = dev->bus;
|
||||
|
||||
offset += dev->core_index * SSB_CORE_SIZE;
|
||||
writel(value, bus->mmio + offset);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SSB_BLOCKIO
|
||||
static void ssb_host_soc_block_write(struct ssb_device *dev, const void *buffer,
|
||||
size_t count, u16 offset, u8 reg_width)
|
||||
{
|
||||
struct ssb_bus *bus = dev->bus;
|
||||
void __iomem *addr;
|
||||
|
||||
offset += dev->core_index * SSB_CORE_SIZE;
|
||||
addr = bus->mmio + offset;
|
||||
|
||||
switch (reg_width) {
|
||||
case sizeof(u8): {
|
||||
const u8 *buf = buffer;
|
||||
|
||||
while (count) {
|
||||
__raw_writeb(*buf, addr);
|
||||
buf++;
|
||||
count--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case sizeof(u16): {
|
||||
const __le16 *buf = buffer;
|
||||
|
||||
SSB_WARN_ON(count & 1);
|
||||
while (count) {
|
||||
__raw_writew((__force u16)(*buf), addr);
|
||||
buf++;
|
||||
count -= 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case sizeof(u32): {
|
||||
const __le32 *buf = buffer;
|
||||
|
||||
SSB_WARN_ON(count & 3);
|
||||
while (count) {
|
||||
__raw_writel((__force u32)(*buf), addr);
|
||||
buf++;
|
||||
count -= 4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
SSB_WARN_ON(1);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_SSB_BLOCKIO */
|
||||
|
||||
/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */
|
||||
const struct ssb_bus_ops ssb_host_soc_ops = {
|
||||
.read8 = ssb_host_soc_read8,
|
||||
.read16 = ssb_host_soc_read16,
|
||||
.read32 = ssb_host_soc_read32,
|
||||
.write8 = ssb_host_soc_write8,
|
||||
.write16 = ssb_host_soc_write16,
|
||||
.write32 = ssb_host_soc_write32,
|
||||
#ifdef CONFIG_SSB_BLOCKIO
|
||||
.block_read = ssb_host_soc_block_read,
|
||||
.block_write = ssb_host_soc_block_write,
|
||||
#endif
|
||||
};
|
@ -596,166 +596,6 @@ error:
|
||||
return err;
|
||||
}
|
||||
|
||||
static u8 ssb_ssb_read8(struct ssb_device *dev, u16 offset)
|
||||
{
|
||||
struct ssb_bus *bus = dev->bus;
|
||||
|
||||
offset += dev->core_index * SSB_CORE_SIZE;
|
||||
return readb(bus->mmio + offset);
|
||||
}
|
||||
|
||||
static u16 ssb_ssb_read16(struct ssb_device *dev, u16 offset)
|
||||
{
|
||||
struct ssb_bus *bus = dev->bus;
|
||||
|
||||
offset += dev->core_index * SSB_CORE_SIZE;
|
||||
return readw(bus->mmio + offset);
|
||||
}
|
||||
|
||||
static u32 ssb_ssb_read32(struct ssb_device *dev, u16 offset)
|
||||
{
|
||||
struct ssb_bus *bus = dev->bus;
|
||||
|
||||
offset += dev->core_index * SSB_CORE_SIZE;
|
||||
return readl(bus->mmio + offset);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SSB_BLOCKIO
|
||||
static void ssb_ssb_block_read(struct ssb_device *dev, void *buffer,
|
||||
size_t count, u16 offset, u8 reg_width)
|
||||
{
|
||||
struct ssb_bus *bus = dev->bus;
|
||||
void __iomem *addr;
|
||||
|
||||
offset += dev->core_index * SSB_CORE_SIZE;
|
||||
addr = bus->mmio + offset;
|
||||
|
||||
switch (reg_width) {
|
||||
case sizeof(u8): {
|
||||
u8 *buf = buffer;
|
||||
|
||||
while (count) {
|
||||
*buf = __raw_readb(addr);
|
||||
buf++;
|
||||
count--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case sizeof(u16): {
|
||||
__le16 *buf = buffer;
|
||||
|
||||
SSB_WARN_ON(count & 1);
|
||||
while (count) {
|
||||
*buf = (__force __le16)__raw_readw(addr);
|
||||
buf++;
|
||||
count -= 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case sizeof(u32): {
|
||||
__le32 *buf = buffer;
|
||||
|
||||
SSB_WARN_ON(count & 3);
|
||||
while (count) {
|
||||
*buf = (__force __le32)__raw_readl(addr);
|
||||
buf++;
|
||||
count -= 4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
SSB_WARN_ON(1);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_SSB_BLOCKIO */
|
||||
|
||||
static void ssb_ssb_write8(struct ssb_device *dev, u16 offset, u8 value)
|
||||
{
|
||||
struct ssb_bus *bus = dev->bus;
|
||||
|
||||
offset += dev->core_index * SSB_CORE_SIZE;
|
||||
writeb(value, bus->mmio + offset);
|
||||
}
|
||||
|
||||
static void ssb_ssb_write16(struct ssb_device *dev, u16 offset, u16 value)
|
||||
{
|
||||
struct ssb_bus *bus = dev->bus;
|
||||
|
||||
offset += dev->core_index * SSB_CORE_SIZE;
|
||||
writew(value, bus->mmio + offset);
|
||||
}
|
||||
|
||||
static void ssb_ssb_write32(struct ssb_device *dev, u16 offset, u32 value)
|
||||
{
|
||||
struct ssb_bus *bus = dev->bus;
|
||||
|
||||
offset += dev->core_index * SSB_CORE_SIZE;
|
||||
writel(value, bus->mmio + offset);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SSB_BLOCKIO
|
||||
static void ssb_ssb_block_write(struct ssb_device *dev, const void *buffer,
|
||||
size_t count, u16 offset, u8 reg_width)
|
||||
{
|
||||
struct ssb_bus *bus = dev->bus;
|
||||
void __iomem *addr;
|
||||
|
||||
offset += dev->core_index * SSB_CORE_SIZE;
|
||||
addr = bus->mmio + offset;
|
||||
|
||||
switch (reg_width) {
|
||||
case sizeof(u8): {
|
||||
const u8 *buf = buffer;
|
||||
|
||||
while (count) {
|
||||
__raw_writeb(*buf, addr);
|
||||
buf++;
|
||||
count--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case sizeof(u16): {
|
||||
const __le16 *buf = buffer;
|
||||
|
||||
SSB_WARN_ON(count & 1);
|
||||
while (count) {
|
||||
__raw_writew((__force u16)(*buf), addr);
|
||||
buf++;
|
||||
count -= 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case sizeof(u32): {
|
||||
const __le32 *buf = buffer;
|
||||
|
||||
SSB_WARN_ON(count & 3);
|
||||
while (count) {
|
||||
__raw_writel((__force u32)(*buf), addr);
|
||||
buf++;
|
||||
count -= 4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
SSB_WARN_ON(1);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_SSB_BLOCKIO */
|
||||
|
||||
/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */
|
||||
static const struct ssb_bus_ops ssb_ssb_ops = {
|
||||
.read8 = ssb_ssb_read8,
|
||||
.read16 = ssb_ssb_read16,
|
||||
.read32 = ssb_ssb_read32,
|
||||
.write8 = ssb_ssb_write8,
|
||||
.write16 = ssb_ssb_write16,
|
||||
.write32 = ssb_ssb_write32,
|
||||
#ifdef CONFIG_SSB_BLOCKIO
|
||||
.block_read = ssb_ssb_block_read,
|
||||
.block_write = ssb_ssb_block_write,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int ssb_fetch_invariants(struct ssb_bus *bus,
|
||||
ssb_invariants_func_t get_invariants)
|
||||
{
|
||||
@ -897,7 +737,6 @@ int ssb_bus_pcmciabus_register(struct ssb_bus *bus,
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(ssb_bus_pcmciabus_register);
|
||||
#endif /* CONFIG_SSB_PCMCIAHOST */
|
||||
|
||||
#ifdef CONFIG_SSB_SDIOHOST
|
||||
@ -922,13 +761,14 @@ int ssb_bus_sdiobus_register(struct ssb_bus *bus, struct sdio_func *func,
|
||||
EXPORT_SYMBOL(ssb_bus_sdiobus_register);
|
||||
#endif /* CONFIG_SSB_PCMCIAHOST */
|
||||
|
||||
#ifdef CONFIG_SSB_HOST_SOC
|
||||
int ssb_bus_ssbbus_register(struct ssb_bus *bus, unsigned long baseaddr,
|
||||
ssb_invariants_func_t get_invariants)
|
||||
{
|
||||
int err;
|
||||
|
||||
bus->bustype = SSB_BUSTYPE_SSB;
|
||||
bus->ops = &ssb_ssb_ops;
|
||||
bus->ops = &ssb_host_soc_ops;
|
||||
|
||||
err = ssb_bus_register(bus, get_invariants, baseaddr);
|
||||
if (!err) {
|
||||
@ -938,6 +778,7 @@ int ssb_bus_ssbbus_register(struct ssb_bus *bus, unsigned long baseaddr,
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
int __ssb_driver_register(struct ssb_driver *drv, struct module *owner)
|
||||
{
|
||||
@ -1464,6 +1305,12 @@ static int __init ssb_modinit(void)
|
||||
/* don't fail SSB init because of this */
|
||||
err = 0;
|
||||
}
|
||||
err = ssb_host_pcmcia_init();
|
||||
if (err) {
|
||||
ssb_err("PCMCIA host initialization failed\n");
|
||||
/* don't fail SSB init because of this */
|
||||
err = 0;
|
||||
}
|
||||
err = ssb_gige_init();
|
||||
if (err) {
|
||||
ssb_err("SSB Broadcom Gigabit Ethernet driver initialization failed\n");
|
||||
@ -1481,6 +1328,7 @@ fs_initcall(ssb_modinit);
|
||||
static void __exit ssb_modexit(void)
|
||||
{
|
||||
ssb_gige_exit();
|
||||
ssb_host_pcmcia_exit();
|
||||
b43_pci_ssb_bridge_exit();
|
||||
bus_unregister(&ssb_bustype);
|
||||
}
|
||||
|
@ -94,6 +94,8 @@ extern int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
|
||||
extern int ssb_pcmcia_hardware_setup(struct ssb_bus *bus);
|
||||
extern void ssb_pcmcia_exit(struct ssb_bus *bus);
|
||||
extern int ssb_pcmcia_init(struct ssb_bus *bus);
|
||||
extern int ssb_host_pcmcia_init(void);
|
||||
extern void ssb_host_pcmcia_exit(void);
|
||||
extern const struct ssb_bus_ops ssb_pcmcia_ops;
|
||||
#else /* CONFIG_SSB_PCMCIAHOST */
|
||||
static inline int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
|
||||
@ -117,6 +119,13 @@ static inline int ssb_pcmcia_init(struct ssb_bus *bus)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int ssb_host_pcmcia_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void ssb_host_pcmcia_exit(void)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_SSB_PCMCIAHOST */
|
||||
|
||||
/* sdio.c */
|
||||
@ -148,6 +157,13 @@ static inline int ssb_sdio_init(struct ssb_bus *bus)
|
||||
}
|
||||
#endif /* CONFIG_SSB_SDIOHOST */
|
||||
|
||||
/**************************************************
|
||||
* host_soc.c
|
||||
**************************************************/
|
||||
|
||||
#ifdef CONFIG_SSB_HOST_SOC
|
||||
extern const struct ssb_bus_ops ssb_host_soc_ops;
|
||||
#endif
|
||||
|
||||
/* scan.c */
|
||||
extern const char *ssb_core_name(u16 coreid);
|
||||
|
Loading…
Reference in New Issue
Block a user