diff options
author | David S. Miller <davem@davemloft.net> | 2015-10-30 07:38:24 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-10-30 07:38:24 -0400 |
commit | a493bcf8d6caf28f062c5f8f2ba486fdbf1ae899 (patch) | |
tree | 66d31fa2f1296caee8f46ea019d032c1bac3b111 | |
parent | e258d919b175e0160a694a20fb309e29fc93d7b1 (diff) | |
parent | 8aaa878de83a0de3833f5b00bc822dbcd403ec36 (diff) |
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>
63 files changed, 1843 insertions, 889 deletions
diff --git a/arch/mips/bcm47xx/Kconfig b/arch/mips/bcm47xx/Kconfig index 51ed599cc894..e970fd9cf769 100644 --- a/arch/mips/bcm47xx/Kconfig +++ b/arch/mips/bcm47xx/Kconfig | |||
@@ -4,6 +4,7 @@ config BCM47XX_SSB | |||
4 | bool "SSB Support for Broadcom BCM47XX" | 4 | bool "SSB Support for Broadcom BCM47XX" |
5 | select SYS_HAS_CPU_BMIPS32_3300 | 5 | select SYS_HAS_CPU_BMIPS32_3300 |
6 | select SSB | 6 | select SSB |
7 | select SSB_HOST_SOC | ||
7 | select SSB_DRIVER_MIPS | 8 | select SSB_DRIVER_MIPS |
8 | select SSB_DRIVER_EXTIF | 9 | select SSB_DRIVER_EXTIF |
9 | select SSB_EMBEDDED | 10 | select SSB_EMBEDDED |
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 8ae838d96a9e..17c40f06f13e 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c | |||
@@ -1231,7 +1231,7 @@ struct airo_info { | |||
1231 | dma_addr_t shared_dma; | 1231 | dma_addr_t shared_dma; |
1232 | pm_message_t power; | 1232 | pm_message_t power; |
1233 | SsidRid *SSID; | 1233 | SsidRid *SSID; |
1234 | APListRid *APList; | 1234 | APListRid APList; |
1235 | #define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE | 1235 | #define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE |
1236 | char proc_name[IFNAMSIZ]; | 1236 | char proc_name[IFNAMSIZ]; |
1237 | 1237 | ||
@@ -1848,11 +1848,6 @@ static int readStatusRid(struct airo_info *ai, StatusRid *statr, int lock) | |||
1848 | return PC4500_readrid(ai, RID_STATUS, statr, sizeof(*statr), lock); | 1848 | return PC4500_readrid(ai, RID_STATUS, statr, sizeof(*statr), lock); |
1849 | } | 1849 | } |
1850 | 1850 | ||
1851 | static int readAPListRid(struct airo_info *ai, APListRid *aplr) | ||
1852 | { | ||
1853 | return PC4500_readrid(ai, RID_APLIST, aplr, sizeof(*aplr), 1); | ||
1854 | } | ||
1855 | |||
1856 | static int writeAPListRid(struct airo_info *ai, APListRid *aplr, int lock) | 1851 | static int writeAPListRid(struct airo_info *ai, APListRid *aplr, int lock) |
1857 | { | 1852 | { |
1858 | return PC4500_writerid(ai, RID_APLIST, aplr, sizeof(*aplr), lock); | 1853 | return PC4500_writerid(ai, RID_APLIST, aplr, sizeof(*aplr), lock); |
@@ -2413,7 +2408,6 @@ void stop_airo_card( struct net_device *dev, int freeres ) | |||
2413 | 2408 | ||
2414 | kfree(ai->flash); | 2409 | kfree(ai->flash); |
2415 | kfree(ai->rssi); | 2410 | kfree(ai->rssi); |
2416 | kfree(ai->APList); | ||
2417 | kfree(ai->SSID); | 2411 | kfree(ai->SSID); |
2418 | if (freeres) { | 2412 | if (freeres) { |
2419 | /* PCMCIA frees this stuff, so only for PCI and ISA */ | 2413 | /* 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, | |||
2809 | init_waitqueue_head (&ai->thr_wait); | 2803 | init_waitqueue_head (&ai->thr_wait); |
2810 | ai->tfm = NULL; | 2804 | ai->tfm = NULL; |
2811 | add_airo_dev(ai); | 2805 | add_airo_dev(ai); |
2806 | ai->APList.len = cpu_to_le16(sizeof(struct APListRid)); | ||
2812 | 2807 | ||
2813 | if (airo_networks_allocate (ai)) | 2808 | if (airo_networks_allocate (ai)) |
2814 | goto err_out_free; | 2809 | goto err_out_free; |
@@ -3042,6 +3037,11 @@ static void airo_process_scan_results (struct airo_info *ai) { | |||
3042 | } | 3037 | } |
3043 | 3038 | ||
3044 | out: | 3039 | out: |
3040 | /* write APList back (we cleared it in airo_set_scan) */ | ||
3041 | disable_MAC(ai, 2); | ||
3042 | writeAPListRid(ai, &ai->APList, 0); | ||
3043 | enable_MAC(ai, 0); | ||
3044 | |||
3045 | ai->scan_timeout = 0; | 3045 | ai->scan_timeout = 0; |
3046 | clear_bit(JOB_SCAN_RESULTS, &ai->jobs); | 3046 | clear_bit(JOB_SCAN_RESULTS, &ai->jobs); |
3047 | up(&ai->sem); | 3047 | up(&ai->sem); |
@@ -3613,17 +3613,18 @@ static void disable_MAC( struct airo_info *ai, int lock ) { | |||
3613 | Cmd cmd; | 3613 | Cmd cmd; |
3614 | Resp rsp; | 3614 | Resp rsp; |
3615 | 3615 | ||
3616 | if (lock && down_interruptible(&ai->sem)) | 3616 | if (lock == 1 && down_interruptible(&ai->sem)) |
3617 | return; | 3617 | return; |
3618 | 3618 | ||
3619 | if (test_bit(FLAG_ENABLED, &ai->flags)) { | 3619 | if (test_bit(FLAG_ENABLED, &ai->flags)) { |
3620 | netif_carrier_off(ai->dev); | 3620 | if (lock != 2) /* lock == 2 means don't disable carrier */ |
3621 | netif_carrier_off(ai->dev); | ||
3621 | memset(&cmd, 0, sizeof(cmd)); | 3622 | memset(&cmd, 0, sizeof(cmd)); |
3622 | cmd.cmd = MAC_DISABLE; // disable in case already enabled | 3623 | cmd.cmd = MAC_DISABLE; // disable in case already enabled |
3623 | issuecommand(ai, &cmd, &rsp); | 3624 | issuecommand(ai, &cmd, &rsp); |
3624 | clear_bit(FLAG_ENABLED, &ai->flags); | 3625 | clear_bit(FLAG_ENABLED, &ai->flags); |
3625 | } | 3626 | } |
3626 | if (lock) | 3627 | if (lock == 1) |
3627 | up(&ai->sem); | 3628 | up(&ai->sem); |
3628 | } | 3629 | } |
3629 | 3630 | ||
@@ -3852,8 +3853,6 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) | |||
3852 | tdsRssiRid rssi_rid; | 3853 | tdsRssiRid rssi_rid; |
3853 | CapabilityRid cap_rid; | 3854 | CapabilityRid cap_rid; |
3854 | 3855 | ||
3855 | kfree(ai->APList); | ||
3856 | ai->APList = NULL; | ||
3857 | kfree(ai->SSID); | 3856 | kfree(ai->SSID); |
3858 | ai->SSID = NULL; | 3857 | ai->SSID = NULL; |
3859 | // general configuration (read/modify/write) | 3858 | // general configuration (read/modify/write) |
@@ -5130,31 +5129,31 @@ static void proc_APList_on_close( struct inode *inode, struct file *file ) { | |||
5130 | struct proc_data *data = file->private_data; | 5129 | struct proc_data *data = file->private_data; |
5131 | struct net_device *dev = PDE_DATA(inode); | 5130 | struct net_device *dev = PDE_DATA(inode); |
5132 | struct airo_info *ai = dev->ml_priv; | 5131 | struct airo_info *ai = dev->ml_priv; |
5133 | APListRid APList_rid; | 5132 | APListRid *APList_rid = &ai->APList; |
5134 | int i; | 5133 | int i; |
5135 | 5134 | ||
5136 | if ( !data->writelen ) return; | 5135 | if ( !data->writelen ) return; |
5137 | 5136 | ||
5138 | memset( &APList_rid, 0, sizeof(APList_rid) ); | 5137 | memset(APList_rid, 0, sizeof(*APList_rid)); |
5139 | APList_rid.len = cpu_to_le16(sizeof(APList_rid)); | 5138 | APList_rid->len = cpu_to_le16(sizeof(*APList_rid)); |
5140 | 5139 | ||
5141 | for( i = 0; i < 4 && data->writelen >= (i+1)*6*3; i++ ) { | 5140 | for( i = 0; i < 4 && data->writelen >= (i+1)*6*3; i++ ) { |
5142 | int j; | 5141 | int j; |
5143 | for( j = 0; j < 6*3 && data->wbuffer[j+i*6*3]; j++ ) { | 5142 | for( j = 0; j < 6*3 && data->wbuffer[j+i*6*3]; j++ ) { |
5144 | switch(j%3) { | 5143 | switch(j%3) { |
5145 | case 0: | 5144 | case 0: |
5146 | APList_rid.ap[i][j/3]= | 5145 | APList_rid->ap[i][j/3]= |
5147 | hex_to_bin(data->wbuffer[j+i*6*3])<<4; | 5146 | hex_to_bin(data->wbuffer[j+i*6*3])<<4; |
5148 | break; | 5147 | break; |
5149 | case 1: | 5148 | case 1: |
5150 | APList_rid.ap[i][j/3]|= | 5149 | APList_rid->ap[i][j/3]|= |
5151 | hex_to_bin(data->wbuffer[j+i*6*3]); | 5150 | hex_to_bin(data->wbuffer[j+i*6*3]); |
5152 | break; | 5151 | break; |
5153 | } | 5152 | } |
5154 | } | 5153 | } |
5155 | } | 5154 | } |
5156 | disable_MAC(ai, 1); | 5155 | disable_MAC(ai, 1); |
5157 | writeAPListRid(ai, &APList_rid, 1); | 5156 | writeAPListRid(ai, APList_rid, 1); |
5158 | enable_MAC(ai, 1); | 5157 | enable_MAC(ai, 1); |
5159 | } | 5158 | } |
5160 | 5159 | ||
@@ -5408,7 +5407,7 @@ static int proc_APList_open( struct inode *inode, struct file *file ) { | |||
5408 | struct airo_info *ai = dev->ml_priv; | 5407 | struct airo_info *ai = dev->ml_priv; |
5409 | int i; | 5408 | int i; |
5410 | char *ptr; | 5409 | char *ptr; |
5411 | APListRid APList_rid; | 5410 | APListRid *APList_rid = &ai->APList; |
5412 | 5411 | ||
5413 | if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) | 5412 | if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) |
5414 | return -ENOMEM; | 5413 | return -ENOMEM; |
@@ -5426,13 +5425,12 @@ static int proc_APList_open( struct inode *inode, struct file *file ) { | |||
5426 | } | 5425 | } |
5427 | data->on_close = proc_APList_on_close; | 5426 | data->on_close = proc_APList_on_close; |
5428 | 5427 | ||
5429 | readAPListRid(ai, &APList_rid); | ||
5430 | ptr = data->rbuffer; | 5428 | ptr = data->rbuffer; |
5431 | for( i = 0; i < 4; i++ ) { | 5429 | for( i = 0; i < 4; i++ ) { |
5432 | // We end when we find a zero MAC | 5430 | // We end when we find a zero MAC |
5433 | if ( !*(int*)APList_rid.ap[i] && | 5431 | if ( !*(int*)APList_rid->ap[i] && |
5434 | !*(int*)&APList_rid.ap[i][2]) break; | 5432 | !*(int*)&APList_rid->ap[i][2]) break; |
5435 | ptr += sprintf(ptr, "%pM\n", APList_rid.ap[i]); | 5433 | ptr += sprintf(ptr, "%pM\n", APList_rid->ap[i]); |
5436 | } | 5434 | } |
5437 | if (i==0) ptr += sprintf(ptr, "Not using specific APs\n"); | 5435 | if (i==0) ptr += sprintf(ptr, "Not using specific APs\n"); |
5438 | 5436 | ||
@@ -5596,15 +5594,10 @@ static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state) | |||
5596 | Cmd cmd; | 5594 | Cmd cmd; |
5597 | Resp rsp; | 5595 | Resp rsp; |
5598 | 5596 | ||
5599 | if (!ai->APList) | ||
5600 | ai->APList = kmalloc(sizeof(APListRid), GFP_KERNEL); | ||
5601 | if (!ai->APList) | ||
5602 | return -ENOMEM; | ||
5603 | if (!ai->SSID) | 5597 | if (!ai->SSID) |
5604 | ai->SSID = kmalloc(sizeof(SsidRid), GFP_KERNEL); | 5598 | ai->SSID = kmalloc(sizeof(SsidRid), GFP_KERNEL); |
5605 | if (!ai->SSID) | 5599 | if (!ai->SSID) |
5606 | return -ENOMEM; | 5600 | return -ENOMEM; |
5607 | readAPListRid(ai, ai->APList); | ||
5608 | readSsidRid(ai, ai->SSID); | 5601 | readSsidRid(ai, ai->SSID); |
5609 | memset(&cmd, 0, sizeof(cmd)); | 5602 | memset(&cmd, 0, sizeof(cmd)); |
5610 | /* the lock will be released at the end of the resume callback */ | 5603 | /* 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) | |||
5652 | kfree(ai->SSID); | 5645 | kfree(ai->SSID); |
5653 | ai->SSID = NULL; | 5646 | ai->SSID = NULL; |
5654 | } | 5647 | } |
5655 | if (ai->APList) { | 5648 | writeAPListRid(ai, &ai->APList, 0); |
5656 | writeAPListRid(ai, ai->APList, 0); | ||
5657 | kfree(ai->APList); | ||
5658 | ai->APList = NULL; | ||
5659 | } | ||
5660 | writeConfigRid(ai, 0); | 5649 | writeConfigRid(ai, 0); |
5661 | enable_MAC(ai, 0); | 5650 | enable_MAC(ai, 0); |
5662 | ai->power = PMSG_ON; | 5651 | ai->power = PMSG_ON; |
@@ -5954,7 +5943,7 @@ static int airo_set_wap(struct net_device *dev, | |||
5954 | struct airo_info *local = dev->ml_priv; | 5943 | struct airo_info *local = dev->ml_priv; |
5955 | Cmd cmd; | 5944 | Cmd cmd; |
5956 | Resp rsp; | 5945 | Resp rsp; |
5957 | APListRid APList_rid; | 5946 | APListRid *APList_rid = &local->APList; |
5958 | 5947 | ||
5959 | if (awrq->sa_family != ARPHRD_ETHER) | 5948 | if (awrq->sa_family != ARPHRD_ETHER) |
5960 | return -EINVAL; | 5949 | return -EINVAL; |
@@ -5967,11 +5956,11 @@ static int airo_set_wap(struct net_device *dev, | |||
5967 | issuecommand(local, &cmd, &rsp); | 5956 | issuecommand(local, &cmd, &rsp); |
5968 | up(&local->sem); | 5957 | up(&local->sem); |
5969 | } else { | 5958 | } else { |
5970 | memset(&APList_rid, 0, sizeof(APList_rid)); | 5959 | memset(APList_rid, 0, sizeof(*APList_rid)); |
5971 | APList_rid.len = cpu_to_le16(sizeof(APList_rid)); | 5960 | APList_rid->len = cpu_to_le16(sizeof(*APList_rid)); |
5972 | memcpy(APList_rid.ap[0], awrq->sa_data, ETH_ALEN); | 5961 | memcpy(APList_rid->ap[0], awrq->sa_data, ETH_ALEN); |
5973 | disable_MAC(local, 1); | 5962 | disable_MAC(local, 1); |
5974 | writeAPListRid(local, &APList_rid, 1); | 5963 | writeAPListRid(local, APList_rid, 1); |
5975 | enable_MAC(local, 1); | 5964 | enable_MAC(local, 1); |
5976 | } | 5965 | } |
5977 | return 0; | 5966 | return 0; |
@@ -7233,6 +7222,7 @@ static int airo_set_scan(struct net_device *dev, | |||
7233 | Cmd cmd; | 7222 | Cmd cmd; |
7234 | Resp rsp; | 7223 | Resp rsp; |
7235 | int wake = 0; | 7224 | int wake = 0; |
7225 | APListRid APList_rid_empty; | ||
7236 | 7226 | ||
7237 | /* Note : you may have realised that, as this is a SET operation, | 7227 | /* Note : you may have realised that, as this is a SET operation, |
7238 | * this is privileged and therefore a normal user can't | 7228 | * this is privileged and therefore a normal user can't |
@@ -7250,6 +7240,13 @@ static int airo_set_scan(struct net_device *dev, | |||
7250 | if (ai->scan_timeout > 0) | 7240 | if (ai->scan_timeout > 0) |
7251 | goto out; | 7241 | goto out; |
7252 | 7242 | ||
7243 | /* Clear APList as it affects scan results */ | ||
7244 | memset(&APList_rid_empty, 0, sizeof(APList_rid_empty)); | ||
7245 | APList_rid_empty.len = cpu_to_le16(sizeof(APList_rid_empty)); | ||
7246 | disable_MAC(ai, 2); | ||
7247 | writeAPListRid(ai, &APList_rid_empty, 0); | ||
7248 | enable_MAC(ai, 0); | ||
7249 | |||
7253 | /* Initiate a scan command */ | 7250 | /* Initiate a scan command */ |
7254 | ai->scan_timeout = RUN_AT(3*HZ); | 7251 | ai->scan_timeout = RUN_AT(3*HZ); |
7255 | memset(&cmd, 0, sizeof(cmd)); | 7252 | memset(&cmd, 0, sizeof(cmd)); |
@@ -7505,10 +7502,8 @@ static int airo_config_commit(struct net_device *dev, | |||
7505 | * parameters. It's now time to commit them in the card */ | 7502 | * parameters. It's now time to commit them in the card */ |
7506 | disable_MAC(local, 1); | 7503 | disable_MAC(local, 1); |
7507 | if (test_bit (FLAG_RESET, &local->flags)) { | 7504 | if (test_bit (FLAG_RESET, &local->flags)) { |
7508 | APListRid APList_rid; | ||
7509 | SsidRid SSID_rid; | 7505 | SsidRid SSID_rid; |
7510 | 7506 | ||
7511 | readAPListRid(local, &APList_rid); | ||
7512 | readSsidRid(local, &SSID_rid); | 7507 | readSsidRid(local, &SSID_rid); |
7513 | if (test_bit(FLAG_MPI,&local->flags)) | 7508 | if (test_bit(FLAG_MPI,&local->flags)) |
7514 | setup_card(local, dev->dev_addr, 1 ); | 7509 | setup_card(local, dev->dev_addr, 1 ); |
@@ -7516,7 +7511,7 @@ static int airo_config_commit(struct net_device *dev, | |||
7516 | reset_airo_card(dev); | 7511 | reset_airo_card(dev); |
7517 | disable_MAC(local, 1); | 7512 | disable_MAC(local, 1); |
7518 | writeSsidRid(local, &SSID_rid, 1); | 7513 | writeSsidRid(local, &SSID_rid, 1); |
7519 | writeAPListRid(local, &APList_rid, 1); | 7514 | writeAPListRid(local, &local->APList, 1); |
7520 | } | 7515 | } |
7521 | if (down_interruptible(&local->sem)) | 7516 | if (down_interruptible(&local->sem)) |
7522 | return -ERESTARTSYS; | 7517 | return -ERESTARTSYS; |
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index 84220c376308..edf3629288bc 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c | |||
@@ -274,7 +274,7 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state, | |||
274 | { | 274 | { |
275 | struct ath10k *ar = ce_state->ar; | 275 | struct ath10k *ar = ce_state->ar; |
276 | struct ath10k_ce_ring *src_ring = ce_state->src_ring; | 276 | struct ath10k_ce_ring *src_ring = ce_state->src_ring; |
277 | struct ce_desc *desc, *sdesc; | 277 | struct ce_desc *desc, sdesc; |
278 | unsigned int nentries_mask = src_ring->nentries_mask; | 278 | unsigned int nentries_mask = src_ring->nentries_mask; |
279 | unsigned int sw_index = src_ring->sw_index; | 279 | unsigned int sw_index = src_ring->sw_index; |
280 | unsigned int write_index = src_ring->write_index; | 280 | unsigned int write_index = src_ring->write_index; |
@@ -294,7 +294,6 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state, | |||
294 | 294 | ||
295 | desc = CE_SRC_RING_TO_DESC(src_ring->base_addr_owner_space, | 295 | desc = CE_SRC_RING_TO_DESC(src_ring->base_addr_owner_space, |
296 | write_index); | 296 | write_index); |
297 | sdesc = CE_SRC_RING_TO_DESC(src_ring->shadow_base, write_index); | ||
298 | 297 | ||
299 | desc_flags |= SM(transfer_id, CE_DESC_FLAGS_META_DATA); | 298 | desc_flags |= SM(transfer_id, CE_DESC_FLAGS_META_DATA); |
300 | 299 | ||
@@ -303,11 +302,11 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state, | |||
303 | if (flags & CE_SEND_FLAG_BYTE_SWAP) | 302 | if (flags & CE_SEND_FLAG_BYTE_SWAP) |
304 | desc_flags |= CE_DESC_FLAGS_BYTE_SWAP; | 303 | desc_flags |= CE_DESC_FLAGS_BYTE_SWAP; |
305 | 304 | ||
306 | sdesc->addr = __cpu_to_le32(buffer); | 305 | sdesc.addr = __cpu_to_le32(buffer); |
307 | sdesc->nbytes = __cpu_to_le16(nbytes); | 306 | sdesc.nbytes = __cpu_to_le16(nbytes); |
308 | sdesc->flags = __cpu_to_le16(desc_flags); | 307 | sdesc.flags = __cpu_to_le16(desc_flags); |
309 | 308 | ||
310 | *desc = *sdesc; | 309 | *desc = sdesc; |
311 | 310 | ||
312 | src_ring->per_transfer_context[write_index] = per_transfer_context; | 311 | src_ring->per_transfer_context[write_index] = per_transfer_context; |
313 | 312 | ||
@@ -579,17 +578,13 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state, | |||
579 | * The caller takes responsibility for any necessary locking. | 578 | * The caller takes responsibility for any necessary locking. |
580 | */ | 579 | */ |
581 | int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, | 580 | int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, |
582 | void **per_transfer_contextp, | 581 | void **per_transfer_contextp) |
583 | u32 *bufferp, | ||
584 | unsigned int *nbytesp, | ||
585 | unsigned int *transfer_idp) | ||
586 | { | 582 | { |
587 | struct ath10k_ce_ring *src_ring = ce_state->src_ring; | 583 | struct ath10k_ce_ring *src_ring = ce_state->src_ring; |
588 | u32 ctrl_addr = ce_state->ctrl_addr; | 584 | u32 ctrl_addr = ce_state->ctrl_addr; |
589 | struct ath10k *ar = ce_state->ar; | 585 | struct ath10k *ar = ce_state->ar; |
590 | unsigned int nentries_mask = src_ring->nentries_mask; | 586 | unsigned int nentries_mask = src_ring->nentries_mask; |
591 | unsigned int sw_index = src_ring->sw_index; | 587 | unsigned int sw_index = src_ring->sw_index; |
592 | struct ce_desc *sdesc, *sbase; | ||
593 | unsigned int read_index; | 588 | unsigned int read_index; |
594 | 589 | ||
595 | if (src_ring->hw_index == sw_index) { | 590 | if (src_ring->hw_index == sw_index) { |
@@ -614,15 +609,6 @@ int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, | |||
614 | if (read_index == sw_index) | 609 | if (read_index == sw_index) |
615 | return -EIO; | 610 | return -EIO; |
616 | 611 | ||
617 | sbase = src_ring->shadow_base; | ||
618 | sdesc = CE_SRC_RING_TO_DESC(sbase, sw_index); | ||
619 | |||
620 | /* Return data from completed source descriptor */ | ||
621 | *bufferp = __le32_to_cpu(sdesc->addr); | ||
622 | *nbytesp = __le16_to_cpu(sdesc->nbytes); | ||
623 | *transfer_idp = MS(__le16_to_cpu(sdesc->flags), | ||
624 | CE_DESC_FLAGS_META_DATA); | ||
625 | |||
626 | if (per_transfer_contextp) | 612 | if (per_transfer_contextp) |
627 | *per_transfer_contextp = | 613 | *per_transfer_contextp = |
628 | src_ring->per_transfer_context[sw_index]; | 614 | src_ring->per_transfer_context[sw_index]; |
@@ -697,10 +683,7 @@ int ath10k_ce_cancel_send_next(struct ath10k_ce_pipe *ce_state, | |||
697 | } | 683 | } |
698 | 684 | ||
699 | int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state, | 685 | int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state, |
700 | void **per_transfer_contextp, | 686 | void **per_transfer_contextp) |
701 | u32 *bufferp, | ||
702 | unsigned int *nbytesp, | ||
703 | unsigned int *transfer_idp) | ||
704 | { | 687 | { |
705 | struct ath10k *ar = ce_state->ar; | 688 | struct ath10k *ar = ce_state->ar; |
706 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 689 | 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, | |||
708 | 691 | ||
709 | spin_lock_bh(&ar_pci->ce_lock); | 692 | spin_lock_bh(&ar_pci->ce_lock); |
710 | ret = ath10k_ce_completed_send_next_nolock(ce_state, | 693 | ret = ath10k_ce_completed_send_next_nolock(ce_state, |
711 | per_transfer_contextp, | 694 | per_transfer_contextp); |
712 | bufferp, nbytesp, | ||
713 | transfer_idp); | ||
714 | spin_unlock_bh(&ar_pci->ce_lock); | 695 | spin_unlock_bh(&ar_pci->ce_lock); |
715 | 696 | ||
716 | return ret; | 697 | return ret; |
@@ -940,27 +921,6 @@ ath10k_ce_alloc_src_ring(struct ath10k *ar, unsigned int ce_id, | |||
940 | src_ring->base_addr_ce_space_unaligned, | 921 | src_ring->base_addr_ce_space_unaligned, |
941 | CE_DESC_RING_ALIGN); | 922 | CE_DESC_RING_ALIGN); |
942 | 923 | ||
943 | /* | ||
944 | * Also allocate a shadow src ring in regular | ||
945 | * mem to use for faster access. | ||
946 | */ | ||
947 | src_ring->shadow_base_unaligned = | ||
948 | kmalloc((nentries * sizeof(struct ce_desc) + | ||
949 | CE_DESC_RING_ALIGN), GFP_KERNEL); | ||
950 | if (!src_ring->shadow_base_unaligned) { | ||
951 | dma_free_coherent(ar->dev, | ||
952 | (nentries * sizeof(struct ce_desc) + | ||
953 | CE_DESC_RING_ALIGN), | ||
954 | src_ring->base_addr_owner_space, | ||
955 | src_ring->base_addr_ce_space); | ||
956 | kfree(src_ring); | ||
957 | return ERR_PTR(-ENOMEM); | ||
958 | } | ||
959 | |||
960 | src_ring->shadow_base = PTR_ALIGN( | ||
961 | src_ring->shadow_base_unaligned, | ||
962 | CE_DESC_RING_ALIGN); | ||
963 | |||
964 | return src_ring; | 924 | return src_ring; |
965 | } | 925 | } |
966 | 926 | ||
@@ -1139,7 +1099,6 @@ void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id) | |||
1139 | struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; | 1099 | struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; |
1140 | 1100 | ||
1141 | if (ce_state->src_ring) { | 1101 | if (ce_state->src_ring) { |
1142 | kfree(ce_state->src_ring->shadow_base_unaligned); | ||
1143 | dma_free_coherent(ar->dev, | 1102 | dma_free_coherent(ar->dev, |
1144 | (ce_state->src_ring->nentries * | 1103 | (ce_state->src_ring->nentries * |
1145 | sizeof(struct ce_desc) + | 1104 | sizeof(struct ce_desc) + |
diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index dbb94fdb274b..47b734ce7ecf 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h | |||
@@ -100,12 +100,6 @@ struct ath10k_ce_ring { | |||
100 | 100 | ||
101 | /* CE address space */ | 101 | /* CE address space */ |
102 | u32 base_addr_ce_space; | 102 | u32 base_addr_ce_space; |
103 | /* | ||
104 | * Start of shadow copy of descriptors, within regular memory. | ||
105 | * Aligned to descriptor-size boundary. | ||
106 | */ | ||
107 | void *shadow_base_unaligned; | ||
108 | struct ce_desc *shadow_base; | ||
109 | 103 | ||
110 | /* keep last */ | 104 | /* keep last */ |
111 | void *per_transfer_context[0]; | 105 | void *per_transfer_context[0]; |
@@ -192,16 +186,10 @@ int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state, | |||
192 | * Pops 1 completed send buffer from Source ring. | 186 | * Pops 1 completed send buffer from Source ring. |
193 | */ | 187 | */ |
194 | int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state, | 188 | int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state, |
195 | void **per_transfer_contextp, | 189 | void **per_transfer_contextp); |
196 | u32 *bufferp, | ||
197 | unsigned int *nbytesp, | ||
198 | unsigned int *transfer_idp); | ||
199 | 190 | ||
200 | int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, | 191 | int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, |
201 | void **per_transfer_contextp, | 192 | void **per_transfer_contextp); |
202 | u32 *bufferp, | ||
203 | unsigned int *nbytesp, | ||
204 | unsigned int *transfer_idp); | ||
205 | 193 | ||
206 | /*==================CE Engine Initialization=======================*/ | 194 | /*==================CE Engine Initialization=======================*/ |
207 | 195 | ||
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 13de3617d5ab..aa9bd92ac4ed 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c | |||
@@ -137,6 +137,21 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { | |||
137 | .board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ, | 137 | .board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ, |
138 | }, | 138 | }, |
139 | }, | 139 | }, |
140 | { | ||
141 | .id = QCA9377_HW_1_0_DEV_VERSION, | ||
142 | .name = "qca9377 hw1.0", | ||
143 | .patch_load_addr = QCA9377_HW_1_0_PATCH_LOAD_ADDR, | ||
144 | .uart_pin = 7, | ||
145 | .otp_exe_param = 0, | ||
146 | .fw = { | ||
147 | .dir = QCA9377_HW_1_0_FW_DIR, | ||
148 | .fw = QCA9377_HW_1_0_FW_FILE, | ||
149 | .otp = QCA9377_HW_1_0_OTP_FILE, | ||
150 | .board = QCA9377_HW_1_0_BOARD_DATA_FILE, | ||
151 | .board_size = QCA9377_BOARD_DATA_SZ, | ||
152 | .board_ext_size = QCA9377_BOARD_EXT_DATA_SZ, | ||
153 | }, | ||
154 | }, | ||
140 | }; | 155 | }; |
141 | 156 | ||
142 | static const char *const ath10k_core_fw_feature_str[] = { | 157 | static const char *const ath10k_core_fw_feature_str[] = { |
@@ -151,6 +166,7 @@ static const char *const ath10k_core_fw_feature_str[] = { | |||
151 | [ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING] = "no-4addr-pad", | 166 | [ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING] = "no-4addr-pad", |
152 | [ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT] = "skip-clock-init", | 167 | [ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT] = "skip-clock-init", |
153 | [ATH10K_FW_FEATURE_RAW_MODE_SUPPORT] = "raw-mode", | 168 | [ATH10K_FW_FEATURE_RAW_MODE_SUPPORT] = "raw-mode", |
169 | [ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA] = "adaptive-cca", | ||
154 | }; | 170 | }; |
155 | 171 | ||
156 | static unsigned int ath10k_core_get_fw_feature_str(char *buf, | 172 | 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) | |||
568 | } | 584 | } |
569 | break; | 585 | break; |
570 | case ATH10K_FIRMWARE_MODE_UTF: | 586 | case ATH10K_FIRMWARE_MODE_UTF: |
571 | data = ar->testmode.utf->data; | 587 | data = ar->testmode.utf_firmware_data; |
572 | data_len = ar->testmode.utf->size; | 588 | data_len = ar->testmode.utf_firmware_len; |
573 | mode_name = "utf"; | 589 | mode_name = "utf"; |
574 | break; | 590 | break; |
575 | default: | 591 | default: |
@@ -1900,6 +1916,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, | |||
1900 | ar->hw_values = &qca988x_values; | 1916 | ar->hw_values = &qca988x_values; |
1901 | break; | 1917 | break; |
1902 | case ATH10K_HW_QCA6174: | 1918 | case ATH10K_HW_QCA6174: |
1919 | case ATH10K_HW_QCA9377: | ||
1903 | ar->regs = &qca6174_regs; | 1920 | ar->regs = &qca6174_regs; |
1904 | ar->hw_values = &qca6174_values; | 1921 | ar->hw_values = &qca6174_values; |
1905 | break; | 1922 | break; |
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 7cc7cdd56c95..4a2301589902 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h | |||
@@ -214,6 +214,7 @@ struct ath10k_fw_stats_pdev { | |||
214 | s32 hw_queued; | 214 | s32 hw_queued; |
215 | s32 hw_reaped; | 215 | s32 hw_reaped; |
216 | s32 underrun; | 216 | s32 underrun; |
217 | u32 hw_paused; | ||
217 | s32 tx_abort; | 218 | s32 tx_abort; |
218 | s32 mpdus_requed; | 219 | s32 mpdus_requed; |
219 | u32 tx_ko; | 220 | u32 tx_ko; |
@@ -226,6 +227,16 @@ struct ath10k_fw_stats_pdev { | |||
226 | u32 pdev_resets; | 227 | u32 pdev_resets; |
227 | u32 phy_underrun; | 228 | u32 phy_underrun; |
228 | u32 txop_ovf; | 229 | u32 txop_ovf; |
230 | u32 seq_posted; | ||
231 | u32 seq_failed_queueing; | ||
232 | u32 seq_completed; | ||
233 | u32 seq_restarted; | ||
234 | u32 mu_seq_posted; | ||
235 | u32 mpdus_sw_flush; | ||
236 | u32 mpdus_hw_filter; | ||
237 | u32 mpdus_truncated; | ||
238 | u32 mpdus_ack_failed; | ||
239 | u32 mpdus_expired; | ||
229 | 240 | ||
230 | /* PDEV RX stats */ | 241 | /* PDEV RX stats */ |
231 | s32 mid_ppdu_route_change; | 242 | s32 mid_ppdu_route_change; |
@@ -242,6 +253,7 @@ struct ath10k_fw_stats_pdev { | |||
242 | s32 phy_errs; | 253 | s32 phy_errs; |
243 | s32 phy_err_drop; | 254 | s32 phy_err_drop; |
244 | s32 mpdu_errs; | 255 | s32 mpdu_errs; |
256 | s32 rx_ovfl_errs; | ||
245 | }; | 257 | }; |
246 | 258 | ||
247 | struct ath10k_fw_stats { | 259 | struct ath10k_fw_stats { |
@@ -497,6 +509,9 @@ enum ath10k_fw_features { | |||
497 | */ | 509 | */ |
498 | ATH10K_FW_FEATURE_RAW_MODE_SUPPORT = 10, | 510 | ATH10K_FW_FEATURE_RAW_MODE_SUPPORT = 10, |
499 | 511 | ||
512 | /* Firmware Supports Adaptive CCA*/ | ||
513 | ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA = 11, | ||
514 | |||
500 | /* keep last */ | 515 | /* keep last */ |
501 | ATH10K_FW_FEATURE_COUNT, | 516 | ATH10K_FW_FEATURE_COUNT, |
502 | }; | 517 | }; |
@@ -730,8 +745,6 @@ struct ath10k { | |||
730 | int num_started_vdevs; | 745 | int num_started_vdevs; |
731 | 746 | ||
732 | /* Protected by conf-mutex */ | 747 | /* Protected by conf-mutex */ |
733 | u8 supp_tx_chainmask; | ||
734 | u8 supp_rx_chainmask; | ||
735 | u8 cfg_tx_chainmask; | 748 | u8 cfg_tx_chainmask; |
736 | u8 cfg_rx_chainmask; | 749 | u8 cfg_rx_chainmask; |
737 | 750 | ||
@@ -814,9 +827,12 @@ struct ath10k { | |||
814 | struct { | 827 | struct { |
815 | /* protected by conf_mutex */ | 828 | /* protected by conf_mutex */ |
816 | const struct firmware *utf; | 829 | const struct firmware *utf; |
830 | char utf_version[32]; | ||
831 | const void *utf_firmware_data; | ||
832 | size_t utf_firmware_len; | ||
817 | DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT); | 833 | DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT); |
818 | enum ath10k_fw_wmi_op_version orig_wmi_op_version; | 834 | enum ath10k_fw_wmi_op_version orig_wmi_op_version; |
819 | 835 | enum ath10k_fw_wmi_op_version op_version; | |
820 | /* protected by data_lock */ | 836 | /* protected by data_lock */ |
821 | bool utf_monitor; | 837 | bool utf_monitor; |
822 | } testmode; | 838 | } testmode; |
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 2d87737e35ff..39966a05c1cc 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h | |||
@@ -84,6 +84,15 @@ enum qca6174_chip_id_rev { | |||
84 | #define QCA99X0_HW_2_0_BOARD_DATA_FILE "board.bin" | 84 | #define QCA99X0_HW_2_0_BOARD_DATA_FILE "board.bin" |
85 | #define QCA99X0_HW_2_0_PATCH_LOAD_ADDR 0x1234 | 85 | #define QCA99X0_HW_2_0_PATCH_LOAD_ADDR 0x1234 |
86 | 86 | ||
87 | /* QCA9377 1.0 definitions */ | ||
88 | #define QCA9377_HW_1_0_DEV_VERSION 0x05020001 | ||
89 | #define QCA9377_HW_1_0_CHIP_ID_REV 0x1 | ||
90 | #define QCA9377_HW_1_0_FW_DIR ATH10K_FW_DIR "/QCA9377/hw1.0" | ||
91 | #define QCA9377_HW_1_0_FW_FILE "firmware.bin" | ||
92 | #define QCA9377_HW_1_0_OTP_FILE "otp.bin" | ||
93 | #define QCA9377_HW_1_0_BOARD_DATA_FILE "board.bin" | ||
94 | #define QCA9377_HW_1_0_PATCH_LOAD_ADDR 0x1234 | ||
95 | |||
87 | #define ATH10K_FW_API2_FILE "firmware-2.bin" | 96 | #define ATH10K_FW_API2_FILE "firmware-2.bin" |
88 | #define ATH10K_FW_API3_FILE "firmware-3.bin" | 97 | #define ATH10K_FW_API3_FILE "firmware-3.bin" |
89 | 98 | ||
@@ -94,6 +103,7 @@ enum qca6174_chip_id_rev { | |||
94 | #define ATH10K_FW_API5_FILE "firmware-5.bin" | 103 | #define ATH10K_FW_API5_FILE "firmware-5.bin" |
95 | 104 | ||
96 | #define ATH10K_FW_UTF_FILE "utf.bin" | 105 | #define ATH10K_FW_UTF_FILE "utf.bin" |
106 | #define ATH10K_FW_UTF_API2_FILE "utf-2.bin" | ||
97 | 107 | ||
98 | /* includes also the null byte */ | 108 | /* includes also the null byte */ |
99 | #define ATH10K_FIRMWARE_MAGIC "QCA-ATH10K" | 109 | #define ATH10K_FIRMWARE_MAGIC "QCA-ATH10K" |
@@ -176,6 +186,7 @@ enum ath10k_hw_rev { | |||
176 | ATH10K_HW_QCA988X, | 186 | ATH10K_HW_QCA988X, |
177 | ATH10K_HW_QCA6174, | 187 | ATH10K_HW_QCA6174, |
178 | ATH10K_HW_QCA99X0, | 188 | ATH10K_HW_QCA99X0, |
189 | ATH10K_HW_QCA9377, | ||
179 | }; | 190 | }; |
180 | 191 | ||
181 | struct ath10k_hw_regs { | 192 | struct ath10k_hw_regs { |
@@ -228,6 +239,7 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, | |||
228 | #define QCA_REV_988X(ar) ((ar)->hw_rev == ATH10K_HW_QCA988X) | 239 | #define QCA_REV_988X(ar) ((ar)->hw_rev == ATH10K_HW_QCA988X) |
229 | #define QCA_REV_6174(ar) ((ar)->hw_rev == ATH10K_HW_QCA6174) | 240 | #define QCA_REV_6174(ar) ((ar)->hw_rev == ATH10K_HW_QCA6174) |
230 | #define QCA_REV_99X0(ar) ((ar)->hw_rev == ATH10K_HW_QCA99X0) | 241 | #define QCA_REV_99X0(ar) ((ar)->hw_rev == ATH10K_HW_QCA99X0) |
242 | #define QCA_REV_9377(ar) ((ar)->hw_rev == ATH10K_HW_QCA9377) | ||
231 | 243 | ||
232 | /* Known pecularities: | 244 | /* Known pecularities: |
233 | * - raw appears in nwifi decap, raw and nwifi appear in ethernet decap | 245 | * - raw appears in nwifi decap, raw and nwifi appear in ethernet decap |
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 484c1a10372f..a7411fe90cc4 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c | |||
@@ -3736,13 +3736,8 @@ static int ath10k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) | |||
3736 | 3736 | ||
3737 | mutex_lock(&ar->conf_mutex); | 3737 | mutex_lock(&ar->conf_mutex); |
3738 | 3738 | ||
3739 | if (ar->cfg_tx_chainmask) { | 3739 | *tx_ant = ar->cfg_tx_chainmask; |
3740 | *tx_ant = ar->cfg_tx_chainmask; | 3740 | *rx_ant = ar->cfg_rx_chainmask; |
3741 | *rx_ant = ar->cfg_rx_chainmask; | ||
3742 | } else { | ||
3743 | *tx_ant = ar->supp_tx_chainmask; | ||
3744 | *rx_ant = ar->supp_rx_chainmask; | ||
3745 | } | ||
3746 | 3741 | ||
3747 | mutex_unlock(&ar->conf_mutex); | 3742 | mutex_unlock(&ar->conf_mutex); |
3748 | 3743 | ||
@@ -3762,6 +3757,169 @@ static void ath10k_check_chain_mask(struct ath10k *ar, u32 cm, const char *dbg) | |||
3762 | dbg, cm); | 3757 | dbg, cm); |
3763 | } | 3758 | } |
3764 | 3759 | ||
3760 | static int ath10k_mac_get_vht_cap_bf_sts(struct ath10k *ar) | ||
3761 | { | ||
3762 | int nsts = ar->vht_cap_info; | ||
3763 | |||
3764 | nsts &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK; | ||
3765 | nsts >>= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; | ||
3766 | |||
3767 | /* If firmware does not deliver to host number of space-time | ||
3768 | * streams supported, assume it support up to 4 BF STS and return | ||
3769 | * the value for VHT CAP: nsts-1) | ||
3770 | */ | ||
3771 | if (nsts == 0) | ||
3772 | return 3; | ||
3773 | |||
3774 | return nsts; | ||
3775 | } | ||
3776 | |||
3777 | static int ath10k_mac_get_vht_cap_bf_sound_dim(struct ath10k *ar) | ||
3778 | { | ||
3779 | int sound_dim = ar->vht_cap_info; | ||
3780 | |||
3781 | sound_dim &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK; | ||
3782 | sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; | ||
3783 | |||
3784 | /* If the sounding dimension is not advertised by the firmware, | ||
3785 | * let's use a default value of 1 | ||
3786 | */ | ||
3787 | if (sound_dim == 0) | ||
3788 | return 1; | ||
3789 | |||
3790 | return sound_dim; | ||
3791 | } | ||
3792 | |||
3793 | static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar) | ||
3794 | { | ||
3795 | struct ieee80211_sta_vht_cap vht_cap = {0}; | ||
3796 | u16 mcs_map; | ||
3797 | u32 val; | ||
3798 | int i; | ||
3799 | |||
3800 | vht_cap.vht_supported = 1; | ||
3801 | vht_cap.cap = ar->vht_cap_info; | ||
3802 | |||
3803 | if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | | ||
3804 | IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) { | ||
3805 | val = ath10k_mac_get_vht_cap_bf_sts(ar); | ||
3806 | val <<= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; | ||
3807 | val &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK; | ||
3808 | |||
3809 | vht_cap.cap |= val; | ||
3810 | } | ||
3811 | |||
3812 | if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | | ||
3813 | IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) { | ||
3814 | val = ath10k_mac_get_vht_cap_bf_sound_dim(ar); | ||
3815 | val <<= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; | ||
3816 | val &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK; | ||
3817 | |||
3818 | vht_cap.cap |= val; | ||
3819 | } | ||
3820 | |||
3821 | mcs_map = 0; | ||
3822 | for (i = 0; i < 8; i++) { | ||
3823 | if ((i < ar->num_rf_chains) && (ar->cfg_tx_chainmask & BIT(i))) | ||
3824 | mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2); | ||
3825 | else | ||
3826 | mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2); | ||
3827 | } | ||
3828 | |||
3829 | vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); | ||
3830 | vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); | ||
3831 | |||
3832 | return vht_cap; | ||
3833 | } | ||
3834 | |||
3835 | static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar) | ||
3836 | { | ||
3837 | int i; | ||
3838 | struct ieee80211_sta_ht_cap ht_cap = {0}; | ||
3839 | |||
3840 | if (!(ar->ht_cap_info & WMI_HT_CAP_ENABLED)) | ||
3841 | return ht_cap; | ||
3842 | |||
3843 | ht_cap.ht_supported = 1; | ||
3844 | ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; | ||
3845 | ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; | ||
3846 | ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
3847 | ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40; | ||
3848 | ht_cap.cap |= WLAN_HT_CAP_SM_PS_STATIC << IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
3849 | |||
3850 | if (ar->ht_cap_info & WMI_HT_CAP_HT20_SGI) | ||
3851 | ht_cap.cap |= IEEE80211_HT_CAP_SGI_20; | ||
3852 | |||
3853 | if (ar->ht_cap_info & WMI_HT_CAP_HT40_SGI) | ||
3854 | ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; | ||
3855 | |||
3856 | if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS) { | ||
3857 | u32 smps; | ||
3858 | |||
3859 | smps = WLAN_HT_CAP_SM_PS_DYNAMIC; | ||
3860 | smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
3861 | |||
3862 | ht_cap.cap |= smps; | ||
3863 | } | ||
3864 | |||
3865 | if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC) | ||
3866 | ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC; | ||
3867 | |||
3868 | if (ar->ht_cap_info & WMI_HT_CAP_RX_STBC) { | ||
3869 | u32 stbc; | ||
3870 | |||
3871 | stbc = ar->ht_cap_info; | ||
3872 | stbc &= WMI_HT_CAP_RX_STBC; | ||
3873 | stbc >>= WMI_HT_CAP_RX_STBC_MASK_SHIFT; | ||
3874 | stbc <<= IEEE80211_HT_CAP_RX_STBC_SHIFT; | ||
3875 | stbc &= IEEE80211_HT_CAP_RX_STBC; | ||
3876 | |||
3877 | ht_cap.cap |= stbc; | ||
3878 | } | ||
3879 | |||
3880 | if (ar->ht_cap_info & WMI_HT_CAP_LDPC) | ||
3881 | ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; | ||
3882 | |||
3883 | if (ar->ht_cap_info & WMI_HT_CAP_L_SIG_TXOP_PROT) | ||
3884 | ht_cap.cap |= IEEE80211_HT_CAP_LSIG_TXOP_PROT; | ||
3885 | |||
3886 | /* max AMSDU is implicitly taken from vht_cap_info */ | ||
3887 | if (ar->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_MASK) | ||
3888 | ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU; | ||
3889 | |||
3890 | for (i = 0; i < ar->num_rf_chains; i++) { | ||
3891 | if (ar->cfg_rx_chainmask & BIT(i)) | ||
3892 | ht_cap.mcs.rx_mask[i] = 0xFF; | ||
3893 | } | ||
3894 | |||
3895 | ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; | ||
3896 | |||
3897 | return ht_cap; | ||
3898 | } | ||
3899 | |||
3900 | static void ath10k_mac_setup_ht_vht_cap(struct ath10k *ar) | ||
3901 | { | ||
3902 | struct ieee80211_supported_band *band; | ||
3903 | struct ieee80211_sta_vht_cap vht_cap; | ||
3904 | struct ieee80211_sta_ht_cap ht_cap; | ||
3905 | |||
3906 | ht_cap = ath10k_get_ht_cap(ar); | ||
3907 | vht_cap = ath10k_create_vht_cap(ar); | ||
3908 | |||
3909 | if (ar->phy_capability & WHAL_WLAN_11G_CAPABILITY) { | ||
3910 | band = &ar->mac.sbands[IEEE80211_BAND_2GHZ]; | ||
3911 | band->ht_cap = ht_cap; | ||
3912 | |||
3913 | /* Enable the VHT support at 2.4 GHz */ | ||
3914 | band->vht_cap = vht_cap; | ||
3915 | } | ||
3916 | if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY) { | ||
3917 | band = &ar->mac.sbands[IEEE80211_BAND_5GHZ]; | ||
3918 | band->ht_cap = ht_cap; | ||
3919 | band->vht_cap = vht_cap; | ||
3920 | } | ||
3921 | } | ||
3922 | |||
3765 | static int __ath10k_set_antenna(struct ath10k *ar, u32 tx_ant, u32 rx_ant) | 3923 | static int __ath10k_set_antenna(struct ath10k *ar, u32 tx_ant, u32 rx_ant) |
3766 | { | 3924 | { |
3767 | int ret; | 3925 | int ret; |
@@ -3794,6 +3952,9 @@ static int __ath10k_set_antenna(struct ath10k *ar, u32 tx_ant, u32 rx_ant) | |||
3794 | return ret; | 3952 | return ret; |
3795 | } | 3953 | } |
3796 | 3954 | ||
3955 | /* Reload HT/VHT capability */ | ||
3956 | ath10k_mac_setup_ht_vht_cap(ar); | ||
3957 | |||
3797 | return 0; | 3958 | return 0; |
3798 | } | 3959 | } |
3799 | 3960 | ||
@@ -3884,9 +4045,7 @@ static int ath10k_start(struct ieee80211_hw *hw) | |||
3884 | } | 4045 | } |
3885 | } | 4046 | } |
3886 | 4047 | ||
3887 | if (ar->cfg_tx_chainmask) | 4048 | __ath10k_set_antenna(ar, ar->cfg_tx_chainmask, ar->cfg_rx_chainmask); |
3888 | __ath10k_set_antenna(ar, ar->cfg_tx_chainmask, | ||
3889 | ar->cfg_rx_chainmask); | ||
3890 | 4049 | ||
3891 | /* | 4050 | /* |
3892 | * By default FW set ARP frames ac to voice (6). In that case ARP | 4051 | * 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) | |||
3905 | goto err_core_stop; | 4064 | goto err_core_stop; |
3906 | } | 4065 | } |
3907 | 4066 | ||
4067 | if (test_bit(ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA, | ||
4068 | ar->fw_features)) { | ||
4069 | ret = ath10k_wmi_pdev_enable_adaptive_cca(ar, 1, | ||
4070 | WMI_CCA_DETECT_LEVEL_AUTO, | ||
4071 | WMI_CCA_DETECT_MARGIN_AUTO); | ||
4072 | if (ret) { | ||
4073 | ath10k_warn(ar, "failed to enable adaptive cca: %d\n", | ||
4074 | ret); | ||
4075 | goto err_core_stop; | ||
4076 | } | ||
4077 | } | ||
4078 | |||
3908 | ret = ath10k_wmi_pdev_set_param(ar, | 4079 | ret = ath10k_wmi_pdev_set_param(ar, |
3909 | ar->wmi.pdev_param->ani_enable, 1); | 4080 | ar->wmi.pdev_param->ani_enable, 1); |
3910 | if (ret) { | 4081 | if (ret) { |
@@ -4063,39 +4234,6 @@ static u32 get_nss_from_chainmask(u16 chain_mask) | |||
4063 | return 1; | 4234 | return 1; |
4064 | } | 4235 | } |
4065 | 4236 | ||
4066 | static int ath10k_mac_get_vht_cap_bf_sts(struct ath10k *ar) | ||
4067 | { | ||
4068 | int nsts = ar->vht_cap_info; | ||
4069 | |||
4070 | nsts &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK; | ||
4071 | nsts >>= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; | ||
4072 | |||
4073 | /* If firmware does not deliver to host number of space-time | ||
4074 | * streams supported, assume it support up to 4 BF STS and return | ||
4075 | * the value for VHT CAP: nsts-1) | ||
4076 | * */ | ||
4077 | if (nsts == 0) | ||
4078 | return 3; | ||
4079 | |||
4080 | return nsts; | ||
4081 | } | ||
4082 | |||
4083 | static int ath10k_mac_get_vht_cap_bf_sound_dim(struct ath10k *ar) | ||
4084 | { | ||
4085 | int sound_dim = ar->vht_cap_info; | ||
4086 | |||
4087 | sound_dim &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK; | ||
4088 | sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; | ||
4089 | |||
4090 | /* If the sounding dimension is not advertised by the firmware, | ||
4091 | * let's use a default value of 1 | ||
4092 | */ | ||
4093 | if (sound_dim == 0) | ||
4094 | return 1; | ||
4095 | |||
4096 | return sound_dim; | ||
4097 | } | ||
4098 | |||
4099 | static int ath10k_mac_set_txbf_conf(struct ath10k_vif *arvif) | 4237 | static int ath10k_mac_set_txbf_conf(struct ath10k_vif *arvif) |
4100 | { | 4238 | { |
4101 | u32 value = 0; | 4239 | u32 value = 0; |
@@ -6949,111 +7087,6 @@ static const struct ieee80211_iface_combination ath10k_10_4_if_comb[] = { | |||
6949 | }, | 7087 | }, |
6950 | }; | 7088 | }; |
6951 | 7089 | ||
6952 | static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar) | ||
6953 | { | ||
6954 | struct ieee80211_sta_vht_cap vht_cap = {0}; | ||
6955 | u16 mcs_map; | ||
6956 | u32 val; | ||
6957 | int i; | ||
6958 | |||
6959 | vht_cap.vht_supported = 1; | ||
6960 | vht_cap.cap = ar->vht_cap_info; | ||
6961 | |||
6962 | if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | | ||
6963 | IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) { | ||
6964 | val = ath10k_mac_get_vht_cap_bf_sts(ar); | ||
6965 | val <<= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; | ||
6966 | val &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK; | ||
6967 | |||
6968 | vht_cap.cap |= val; | ||
6969 | } | ||
6970 | |||
6971 | if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | | ||
6972 | IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) { | ||
6973 | val = ath10k_mac_get_vht_cap_bf_sound_dim(ar); | ||
6974 | val <<= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; | ||
6975 | val &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK; | ||
6976 | |||
6977 | vht_cap.cap |= val; | ||
6978 | } | ||
6979 | |||
6980 | mcs_map = 0; | ||
6981 | for (i = 0; i < 8; i++) { | ||
6982 | if (i < ar->num_rf_chains) | ||
6983 | mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i*2); | ||
6984 | else | ||
6985 | mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2); | ||
6986 | } | ||
6987 | |||
6988 | vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); | ||
6989 | vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); | ||
6990 | |||
6991 | return vht_cap; | ||
6992 | } | ||
6993 | |||
6994 | static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar) | ||
6995 | { | ||
6996 | int i; | ||
6997 | struct ieee80211_sta_ht_cap ht_cap = {0}; | ||
6998 | |||
6999 | if (!(ar->ht_cap_info & WMI_HT_CAP_ENABLED)) | ||
7000 | return ht_cap; | ||
7001 | |||
7002 | ht_cap.ht_supported = 1; | ||
7003 | ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; | ||
7004 | ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; | ||
7005 | ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
7006 | ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40; | ||
7007 | ht_cap.cap |= WLAN_HT_CAP_SM_PS_STATIC << IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
7008 | |||
7009 | if (ar->ht_cap_info & WMI_HT_CAP_HT20_SGI) | ||
7010 | ht_cap.cap |= IEEE80211_HT_CAP_SGI_20; | ||
7011 | |||
7012 | if (ar->ht_cap_info & WMI_HT_CAP_HT40_SGI) | ||
7013 | ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; | ||
7014 | |||
7015 | if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS) { | ||
7016 | u32 smps; | ||
7017 | |||
7018 | smps = WLAN_HT_CAP_SM_PS_DYNAMIC; | ||
7019 | smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
7020 | |||
7021 | ht_cap.cap |= smps; | ||
7022 | } | ||
7023 | |||
7024 | if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC) | ||
7025 | ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC; | ||
7026 | |||
7027 | if (ar->ht_cap_info & WMI_HT_CAP_RX_STBC) { | ||
7028 | u32 stbc; | ||
7029 | |||
7030 | stbc = ar->ht_cap_info; | ||
7031 | stbc &= WMI_HT_CAP_RX_STBC; | ||
7032 | stbc >>= WMI_HT_CAP_RX_STBC_MASK_SHIFT; | ||
7033 | stbc <<= IEEE80211_HT_CAP_RX_STBC_SHIFT; | ||
7034 | stbc &= IEEE80211_HT_CAP_RX_STBC; | ||
7035 | |||
7036 | ht_cap.cap |= stbc; | ||
7037 | } | ||
7038 | |||
7039 | if (ar->ht_cap_info & WMI_HT_CAP_LDPC) | ||
7040 | ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; | ||
7041 | |||
7042 | if (ar->ht_cap_info & WMI_HT_CAP_L_SIG_TXOP_PROT) | ||
7043 | ht_cap.cap |= IEEE80211_HT_CAP_LSIG_TXOP_PROT; | ||
7044 | |||
7045 | /* max AMSDU is implicitly taken from vht_cap_info */ | ||
7046 | if (ar->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_MASK) | ||
7047 | ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU; | ||
7048 | |||
7049 | for (i = 0; i < ar->num_rf_chains; i++) | ||
7050 | ht_cap.mcs.rx_mask[i] = 0xFF; | ||
7051 | |||
7052 | ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; | ||
7053 | |||
7054 | return ht_cap; | ||
7055 | } | ||
7056 | |||
7057 | static void ath10k_get_arvif_iter(void *data, u8 *mac, | 7090 | static void ath10k_get_arvif_iter(void *data, u8 *mac, |
7058 | struct ieee80211_vif *vif) | 7091 | struct ieee80211_vif *vif) |
7059 | { | 7092 | { |
@@ -7095,8 +7128,6 @@ int ath10k_mac_register(struct ath10k *ar) | |||
7095 | WLAN_CIPHER_SUITE_AES_CMAC, | 7128 | WLAN_CIPHER_SUITE_AES_CMAC, |
7096 | }; | 7129 | }; |
7097 | struct ieee80211_supported_band *band; | 7130 | struct ieee80211_supported_band *band; |
7098 | struct ieee80211_sta_vht_cap vht_cap; | ||
7099 | struct ieee80211_sta_ht_cap ht_cap; | ||
7100 | void *channels; | 7131 | void *channels; |
7101 | int ret; | 7132 | int ret; |
7102 | 7133 | ||
@@ -7104,9 +7135,6 @@ int ath10k_mac_register(struct ath10k *ar) | |||
7104 | 7135 | ||
7105 | SET_IEEE80211_DEV(ar->hw, ar->dev); | 7136 | SET_IEEE80211_DEV(ar->hw, ar->dev); |
7106 | 7137 | ||
7107 | ht_cap = ath10k_get_ht_cap(ar); | ||
7108 | vht_cap = ath10k_create_vht_cap(ar); | ||
7109 | |||
7110 | BUILD_BUG_ON((ARRAY_SIZE(ath10k_2ghz_channels) + | 7138 | BUILD_BUG_ON((ARRAY_SIZE(ath10k_2ghz_channels) + |
7111 | ARRAY_SIZE(ath10k_5ghz_channels)) != | 7139 | ARRAY_SIZE(ath10k_5ghz_channels)) != |
7112 | ATH10K_NUM_CHANS); | 7140 | ATH10K_NUM_CHANS); |
@@ -7125,10 +7153,6 @@ int ath10k_mac_register(struct ath10k *ar) | |||
7125 | band->channels = channels; | 7153 | band->channels = channels; |
7126 | band->n_bitrates = ath10k_g_rates_size; | 7154 | band->n_bitrates = ath10k_g_rates_size; |
7127 | band->bitrates = ath10k_g_rates; | 7155 | band->bitrates = ath10k_g_rates; |
7128 | band->ht_cap = ht_cap; | ||
7129 | |||
7130 | /* Enable the VHT support at 2.4 GHz */ | ||
7131 | band->vht_cap = vht_cap; | ||
7132 | 7156 | ||
7133 | ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = band; | 7157 | ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = band; |
7134 | } | 7158 | } |
@@ -7147,18 +7171,18 @@ int ath10k_mac_register(struct ath10k *ar) | |||
7147 | band->channels = channels; | 7171 | band->channels = channels; |
7148 | band->n_bitrates = ath10k_a_rates_size; | 7172 | band->n_bitrates = ath10k_a_rates_size; |
7149 | band->bitrates = ath10k_a_rates; | 7173 | band->bitrates = ath10k_a_rates; |
7150 | band->ht_cap = ht_cap; | ||
7151 | band->vht_cap = vht_cap; | ||
7152 | ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = band; | 7174 | ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = band; |
7153 | } | 7175 | } |
7154 | 7176 | ||
7177 | ath10k_mac_setup_ht_vht_cap(ar); | ||
7178 | |||
7155 | ar->hw->wiphy->interface_modes = | 7179 | ar->hw->wiphy->interface_modes = |
7156 | BIT(NL80211_IFTYPE_STATION) | | 7180 | BIT(NL80211_IFTYPE_STATION) | |
7157 | BIT(NL80211_IFTYPE_AP) | | 7181 | BIT(NL80211_IFTYPE_AP) | |
7158 | BIT(NL80211_IFTYPE_MESH_POINT); | 7182 | BIT(NL80211_IFTYPE_MESH_POINT); |
7159 | 7183 | ||
7160 | ar->hw->wiphy->available_antennas_rx = ar->supp_rx_chainmask; | 7184 | ar->hw->wiphy->available_antennas_rx = ar->cfg_rx_chainmask; |
7161 | ar->hw->wiphy->available_antennas_tx = ar->supp_tx_chainmask; | 7185 | ar->hw->wiphy->available_antennas_tx = ar->cfg_tx_chainmask; |
7162 | 7186 | ||
7163 | if (!test_bit(ATH10K_FW_FEATURE_NO_P2P, ar->fw_features)) | 7187 | if (!test_bit(ATH10K_FW_FEATURE_NO_P2P, ar->fw_features)) |
7164 | ar->hw->wiphy->interface_modes |= | 7188 | ar->hw->wiphy->interface_modes |= |
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 5c05b0cf54a1..3fca200b986c 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c | |||
@@ -61,12 +61,14 @@ MODULE_PARM_DESC(reset_mode, "0: auto, 1: warm only (default: 0)"); | |||
61 | #define QCA6164_2_1_DEVICE_ID (0x0041) | 61 | #define QCA6164_2_1_DEVICE_ID (0x0041) |
62 | #define QCA6174_2_1_DEVICE_ID (0x003e) | 62 | #define QCA6174_2_1_DEVICE_ID (0x003e) |
63 | #define QCA99X0_2_0_DEVICE_ID (0x0040) | 63 | #define QCA99X0_2_0_DEVICE_ID (0x0040) |
64 | #define QCA9377_1_0_DEVICE_ID (0x0042) | ||
64 | 65 | ||
65 | static const struct pci_device_id ath10k_pci_id_table[] = { | 66 | static const struct pci_device_id ath10k_pci_id_table[] = { |
66 | { PCI_VDEVICE(ATHEROS, QCA988X_2_0_DEVICE_ID) }, /* PCI-E QCA988X V2 */ | 67 | { PCI_VDEVICE(ATHEROS, QCA988X_2_0_DEVICE_ID) }, /* PCI-E QCA988X V2 */ |
67 | { PCI_VDEVICE(ATHEROS, QCA6164_2_1_DEVICE_ID) }, /* PCI-E QCA6164 V2.1 */ | 68 | { PCI_VDEVICE(ATHEROS, QCA6164_2_1_DEVICE_ID) }, /* PCI-E QCA6164 V2.1 */ |
68 | { PCI_VDEVICE(ATHEROS, QCA6174_2_1_DEVICE_ID) }, /* PCI-E QCA6174 V2.1 */ | 69 | { PCI_VDEVICE(ATHEROS, QCA6174_2_1_DEVICE_ID) }, /* PCI-E QCA6174 V2.1 */ |
69 | { PCI_VDEVICE(ATHEROS, QCA99X0_2_0_DEVICE_ID) }, /* PCI-E QCA99X0 V2 */ | 70 | { PCI_VDEVICE(ATHEROS, QCA99X0_2_0_DEVICE_ID) }, /* PCI-E QCA99X0 V2 */ |
71 | { PCI_VDEVICE(ATHEROS, QCA9377_1_0_DEVICE_ID) }, /* PCI-E QCA9377 V1 */ | ||
70 | {0} | 72 | {0} |
71 | }; | 73 | }; |
72 | 74 | ||
@@ -90,6 +92,7 @@ static const struct ath10k_pci_supp_chip ath10k_pci_supp_chips[] = { | |||
90 | { QCA6174_2_1_DEVICE_ID, QCA6174_HW_3_2_CHIP_ID_REV }, | 92 | { QCA6174_2_1_DEVICE_ID, QCA6174_HW_3_2_CHIP_ID_REV }, |
91 | 93 | ||
92 | { QCA99X0_2_0_DEVICE_ID, QCA99X0_HW_2_0_CHIP_ID_REV }, | 94 | { QCA99X0_2_0_DEVICE_ID, QCA99X0_HW_2_0_CHIP_ID_REV }, |
95 | { QCA9377_1_0_DEVICE_ID, QCA9377_HW_1_0_CHIP_ID_REV }, | ||
93 | }; | 96 | }; |
94 | 97 | ||
95 | static void ath10k_pci_buffer_cleanup(struct ath10k *ar); | 98 | 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) | |||
827 | switch (ar->hw_rev) { | 830 | switch (ar->hw_rev) { |
828 | case ATH10K_HW_QCA988X: | 831 | case ATH10K_HW_QCA988X: |
829 | case ATH10K_HW_QCA6174: | 832 | case ATH10K_HW_QCA6174: |
833 | case ATH10K_HW_QCA9377: | ||
830 | val = (ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + | 834 | val = (ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + |
831 | CORE_CTRL_ADDRESS) & | 835 | CORE_CTRL_ADDRESS) & |
832 | 0x7ff) << 21; | 836 | 0x7ff) << 21; |
@@ -910,9 +914,8 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, | |||
910 | goto done; | 914 | goto done; |
911 | 915 | ||
912 | i = 0; | 916 | i = 0; |
913 | while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf, | 917 | while (ath10k_ce_completed_send_next_nolock(ce_diag, |
914 | &completed_nbytes, | 918 | NULL) != 0) { |
915 | &id) != 0) { | ||
916 | mdelay(1); | 919 | mdelay(1); |
917 | if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { | 920 | if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { |
918 | ret = -EBUSY; | 921 | ret = -EBUSY; |
@@ -920,16 +923,6 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, | |||
920 | } | 923 | } |
921 | } | 924 | } |
922 | 925 | ||
923 | if (nbytes != completed_nbytes) { | ||
924 | ret = -EIO; | ||
925 | goto done; | ||
926 | } | ||
927 | |||
928 | if (buf != (u32)address) { | ||
929 | ret = -EIO; | ||
930 | goto done; | ||
931 | } | ||
932 | |||
933 | i = 0; | 926 | i = 0; |
934 | while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf, | 927 | while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf, |
935 | &completed_nbytes, | 928 | &completed_nbytes, |
@@ -1083,9 +1076,8 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, | |||
1083 | goto done; | 1076 | goto done; |
1084 | 1077 | ||
1085 | i = 0; | 1078 | i = 0; |
1086 | while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf, | 1079 | while (ath10k_ce_completed_send_next_nolock(ce_diag, |
1087 | &completed_nbytes, | 1080 | NULL) != 0) { |
1088 | &id) != 0) { | ||
1089 | mdelay(1); | 1081 | mdelay(1); |
1090 | 1082 | ||
1091 | if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { | 1083 | if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { |
@@ -1094,16 +1086,6 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, | |||
1094 | } | 1086 | } |
1095 | } | 1087 | } |
1096 | 1088 | ||
1097 | if (nbytes != completed_nbytes) { | ||
1098 | ret = -EIO; | ||
1099 | goto done; | ||
1100 | } | ||
1101 | |||
1102 | if (buf != ce_data) { | ||
1103 | ret = -EIO; | ||
1104 | goto done; | ||
1105 | } | ||
1106 | |||
1107 | i = 0; | 1089 | i = 0; |
1108 | while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf, | 1090 | while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf, |
1109 | &completed_nbytes, | 1091 | &completed_nbytes, |
@@ -1159,13 +1141,9 @@ static void ath10k_pci_htc_tx_cb(struct ath10k_ce_pipe *ce_state) | |||
1159 | struct ath10k *ar = ce_state->ar; | 1141 | struct ath10k *ar = ce_state->ar; |
1160 | struct sk_buff_head list; | 1142 | struct sk_buff_head list; |
1161 | struct sk_buff *skb; | 1143 | struct sk_buff *skb; |
1162 | u32 ce_data; | ||
1163 | unsigned int nbytes; | ||
1164 | unsigned int transfer_id; | ||
1165 | 1144 | ||
1166 | __skb_queue_head_init(&list); | 1145 | __skb_queue_head_init(&list); |
1167 | while (ath10k_ce_completed_send_next(ce_state, (void **)&skb, &ce_data, | 1146 | while (ath10k_ce_completed_send_next(ce_state, (void **)&skb) == 0) { |
1168 | &nbytes, &transfer_id) == 0) { | ||
1169 | /* no need to call tx completion for NULL pointers */ | 1147 | /* no need to call tx completion for NULL pointers */ |
1170 | if (skb == NULL) | 1148 | if (skb == NULL) |
1171 | continue; | 1149 | continue; |
@@ -1235,12 +1213,8 @@ static void ath10k_pci_htt_tx_cb(struct ath10k_ce_pipe *ce_state) | |||
1235 | { | 1213 | { |
1236 | struct ath10k *ar = ce_state->ar; | 1214 | struct ath10k *ar = ce_state->ar; |
1237 | struct sk_buff *skb; | 1215 | struct sk_buff *skb; |
1238 | u32 ce_data; | ||
1239 | unsigned int nbytes; | ||
1240 | unsigned int transfer_id; | ||
1241 | 1216 | ||
1242 | while (ath10k_ce_completed_send_next(ce_state, (void **)&skb, &ce_data, | 1217 | while (ath10k_ce_completed_send_next(ce_state, (void **)&skb) == 0) { |
1243 | &nbytes, &transfer_id) == 0) { | ||
1244 | /* no need to call tx completion for NULL pointers */ | 1218 | /* no need to call tx completion for NULL pointers */ |
1245 | if (!skb) | 1219 | if (!skb) |
1246 | continue; | 1220 | continue; |
@@ -1513,6 +1487,7 @@ static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar) | |||
1513 | switch (ar->hw_rev) { | 1487 | switch (ar->hw_rev) { |
1514 | case ATH10K_HW_QCA988X: | 1488 | case ATH10K_HW_QCA988X: |
1515 | case ATH10K_HW_QCA6174: | 1489 | case ATH10K_HW_QCA6174: |
1490 | case ATH10K_HW_QCA9377: | ||
1516 | val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + | 1491 | val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + |
1517 | CORE_CTRL_ADDRESS); | 1492 | CORE_CTRL_ADDRESS); |
1518 | val &= ~CORE_CTRL_PCIE_REG_31_MASK; | 1493 | val &= ~CORE_CTRL_PCIE_REG_31_MASK; |
@@ -1534,6 +1509,7 @@ static void ath10k_pci_irq_msi_fw_unmask(struct ath10k *ar) | |||
1534 | switch (ar->hw_rev) { | 1509 | switch (ar->hw_rev) { |
1535 | case ATH10K_HW_QCA988X: | 1510 | case ATH10K_HW_QCA988X: |
1536 | case ATH10K_HW_QCA6174: | 1511 | case ATH10K_HW_QCA6174: |
1512 | case ATH10K_HW_QCA9377: | ||
1537 | val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + | 1513 | val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + |
1538 | CORE_CTRL_ADDRESS); | 1514 | CORE_CTRL_ADDRESS); |
1539 | val |= CORE_CTRL_PCIE_REG_31_MASK; | 1515 | val |= CORE_CTRL_PCIE_REG_31_MASK; |
@@ -1624,7 +1600,6 @@ static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe) | |||
1624 | struct ath10k_pci *ar_pci; | 1600 | struct ath10k_pci *ar_pci; |
1625 | struct ath10k_ce_pipe *ce_pipe; | 1601 | struct ath10k_ce_pipe *ce_pipe; |
1626 | struct ath10k_ce_ring *ce_ring; | 1602 | struct ath10k_ce_ring *ce_ring; |
1627 | struct ce_desc *ce_desc; | ||
1628 | struct sk_buff *skb; | 1603 | struct sk_buff *skb; |
1629 | int i; | 1604 | int i; |
1630 | 1605 | ||
@@ -1639,10 +1614,6 @@ static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe) | |||
1639 | if (!pci_pipe->buf_sz) | 1614 | if (!pci_pipe->buf_sz) |
1640 | return; | 1615 | return; |
1641 | 1616 | ||
1642 | ce_desc = ce_ring->shadow_base; | ||
1643 | if (WARN_ON(!ce_desc)) | ||
1644 | return; | ||
1645 | |||
1646 | for (i = 0; i < ce_ring->nentries; i++) { | 1617 | for (i = 0; i < ce_ring->nentries; i++) { |
1647 | skb = ce_ring->per_transfer_context[i]; | 1618 | skb = ce_ring->per_transfer_context[i]; |
1648 | if (!skb) | 1619 | if (!skb) |
@@ -1816,12 +1787,8 @@ err_dma: | |||
1816 | static void ath10k_pci_bmi_send_done(struct ath10k_ce_pipe *ce_state) | 1787 | static void ath10k_pci_bmi_send_done(struct ath10k_ce_pipe *ce_state) |
1817 | { | 1788 | { |
1818 | struct bmi_xfer *xfer; | 1789 | struct bmi_xfer *xfer; |
1819 | u32 ce_data; | ||
1820 | unsigned int nbytes; | ||
1821 | unsigned int transfer_id; | ||
1822 | 1790 | ||
1823 | if (ath10k_ce_completed_send_next(ce_state, (void **)&xfer, &ce_data, | 1791 | if (ath10k_ce_completed_send_next(ce_state, (void **)&xfer)) |
1824 | &nbytes, &transfer_id)) | ||
1825 | return; | 1792 | return; |
1826 | 1793 | ||
1827 | xfer->tx_done = true; | 1794 | xfer->tx_done = true; |
@@ -1911,6 +1878,8 @@ static int ath10k_pci_get_num_banks(struct ath10k *ar) | |||
1911 | return 9; | 1878 | return 9; |
1912 | } | 1879 | } |
1913 | break; | 1880 | break; |
1881 | case QCA9377_1_0_DEVICE_ID: | ||
1882 | return 2; | ||
1914 | } | 1883 | } |
1915 | 1884 | ||
1916 | ath10k_warn(ar, "unknown number of banks, assuming 1\n"); | 1885 | ath10k_warn(ar, "unknown number of banks, assuming 1\n"); |
@@ -2371,6 +2340,8 @@ static int ath10k_pci_chip_reset(struct ath10k *ar) | |||
2371 | return ath10k_pci_qca988x_chip_reset(ar); | 2340 | return ath10k_pci_qca988x_chip_reset(ar); |
2372 | else if (QCA_REV_6174(ar)) | 2341 | else if (QCA_REV_6174(ar)) |
2373 | return ath10k_pci_qca6174_chip_reset(ar); | 2342 | return ath10k_pci_qca6174_chip_reset(ar); |
2343 | else if (QCA_REV_9377(ar)) | ||
2344 | return ath10k_pci_qca6174_chip_reset(ar); | ||
2374 | else if (QCA_REV_99X0(ar)) | 2345 | else if (QCA_REV_99X0(ar)) |
2375 | return ath10k_pci_qca99x0_chip_reset(ar); | 2346 | return ath10k_pci_qca99x0_chip_reset(ar); |
2376 | else | 2347 | else |
@@ -3003,6 +2974,10 @@ static int ath10k_pci_probe(struct pci_dev *pdev, | |||
3003 | hw_rev = ATH10K_HW_QCA99X0; | 2974 | hw_rev = ATH10K_HW_QCA99X0; |
3004 | pci_ps = false; | 2975 | pci_ps = false; |
3005 | break; | 2976 | break; |
2977 | case QCA9377_1_0_DEVICE_ID: | ||
2978 | hw_rev = ATH10K_HW_QCA9377; | ||
2979 | pci_ps = true; | ||
2980 | break; | ||
3006 | default: | 2981 | default: |
3007 | WARN_ON(1); | 2982 | WARN_ON(1); |
3008 | return -ENOTSUPP; | 2983 | return -ENOTSUPP; |
@@ -3204,3 +3179,7 @@ MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_FW_API4_FILE); | |||
3204 | MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_FW_API5_FILE); | 3179 | MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_FW_API5_FILE); |
3205 | MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" QCA6174_HW_3_0_BOARD_DATA_FILE); | 3180 | MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" QCA6174_HW_3_0_BOARD_DATA_FILE); |
3206 | MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_BOARD_API2_FILE); | 3181 | MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_BOARD_API2_FILE); |
3182 | |||
3183 | /* QCA9377 1.0 firmware files */ | ||
3184 | MODULE_FIRMWARE(QCA9377_HW_1_0_FW_DIR "/" ATH10K_FW_API5_FILE); | ||
3185 | MODULE_FIRMWARE(QCA9377_HW_1_0_FW_DIR "/" QCA9377_HW_1_0_BOARD_DATA_FILE); | ||
diff --git a/drivers/net/wireless/ath/ath10k/targaddrs.h b/drivers/net/wireless/ath/ath10k/targaddrs.h index 768bef629099..05a421bc322a 100644 --- a/drivers/net/wireless/ath/ath10k/targaddrs.h +++ b/drivers/net/wireless/ath/ath10k/targaddrs.h | |||
@@ -450,6 +450,9 @@ Fw Mode/SubMode Mask | |||
450 | #define QCA6174_BOARD_DATA_SZ 8192 | 450 | #define QCA6174_BOARD_DATA_SZ 8192 |
451 | #define QCA6174_BOARD_EXT_DATA_SZ 0 | 451 | #define QCA6174_BOARD_EXT_DATA_SZ 0 |
452 | 452 | ||
453 | #define QCA9377_BOARD_DATA_SZ QCA6174_BOARD_DATA_SZ | ||
454 | #define QCA9377_BOARD_EXT_DATA_SZ 0 | ||
455 | |||
453 | #define QCA99X0_BOARD_DATA_SZ 12288 | 456 | #define QCA99X0_BOARD_DATA_SZ 12288 |
454 | #define QCA99X0_BOARD_EXT_DATA_SZ 0 | 457 | #define QCA99X0_BOARD_EXT_DATA_SZ 0 |
455 | 458 | ||
diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c index b084f88da102..1d5a2fdcbf56 100644 --- a/drivers/net/wireless/ath/ath10k/testmode.c +++ b/drivers/net/wireless/ath/ath10k/testmode.c | |||
@@ -139,11 +139,181 @@ static int ath10k_tm_cmd_get_version(struct ath10k *ar, struct nlattr *tb[]) | |||
139 | return cfg80211_testmode_reply(skb); | 139 | return cfg80211_testmode_reply(skb); |
140 | } | 140 | } |
141 | 141 | ||
142 | static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) | 142 | static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar) |
143 | { | ||
144 | size_t len, magic_len, ie_len; | ||
145 | struct ath10k_fw_ie *hdr; | ||
146 | char filename[100]; | ||
147 | __le32 *version; | ||
148 | const u8 *data; | ||
149 | int ie_id, ret; | ||
150 | |||
151 | snprintf(filename, sizeof(filename), "%s/%s", | ||
152 | ar->hw_params.fw.dir, ATH10K_FW_UTF_API2_FILE); | ||
153 | |||
154 | /* load utf firmware image */ | ||
155 | ret = request_firmware(&ar->testmode.utf, filename, ar->dev); | ||
156 | if (ret) { | ||
157 | ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n", | ||
158 | filename, ret); | ||
159 | return ret; | ||
160 | } | ||
161 | |||
162 | data = ar->testmode.utf->data; | ||
163 | len = ar->testmode.utf->size; | ||
164 | |||
165 | /* FIXME: call release_firmware() in error cases */ | ||
166 | |||
167 | /* magic also includes the null byte, check that as well */ | ||
168 | magic_len = strlen(ATH10K_FIRMWARE_MAGIC) + 1; | ||
169 | |||
170 | if (len < magic_len) { | ||
171 | ath10k_err(ar, "utf firmware file is too small to contain magic\n"); | ||
172 | ret = -EINVAL; | ||
173 | goto err; | ||
174 | } | ||
175 | |||
176 | if (memcmp(data, ATH10K_FIRMWARE_MAGIC, magic_len) != 0) { | ||
177 | ath10k_err(ar, "invalid firmware magic\n"); | ||
178 | ret = -EINVAL; | ||
179 | goto err; | ||
180 | } | ||
181 | |||
182 | /* jump over the padding */ | ||
183 | magic_len = ALIGN(magic_len, 4); | ||
184 | |||
185 | len -= magic_len; | ||
186 | data += magic_len; | ||
187 | |||
188 | /* loop elements */ | ||
189 | while (len > sizeof(struct ath10k_fw_ie)) { | ||
190 | hdr = (struct ath10k_fw_ie *)data; | ||
191 | |||
192 | ie_id = le32_to_cpu(hdr->id); | ||
193 | ie_len = le32_to_cpu(hdr->len); | ||
194 | |||
195 | len -= sizeof(*hdr); | ||
196 | data += sizeof(*hdr); | ||
197 | |||
198 | if (len < ie_len) { | ||
199 | ath10k_err(ar, "invalid length for FW IE %d (%zu < %zu)\n", | ||
200 | ie_id, len, ie_len); | ||
201 | ret = -EINVAL; | ||
202 | goto err; | ||
203 | } | ||
204 | |||
205 | switch (ie_id) { | ||
206 | case ATH10K_FW_IE_FW_VERSION: | ||
207 | if (ie_len > sizeof(ar->testmode.utf_version) - 1) | ||
208 | break; | ||
209 | |||
210 | memcpy(ar->testmode.utf_version, data, ie_len); | ||
211 | ar->testmode.utf_version[ie_len] = '\0'; | ||
212 | |||
213 | ath10k_dbg(ar, ATH10K_DBG_TESTMODE, | ||
214 | "testmode found fw utf version %s\n", | ||
215 | ar->testmode.utf_version); | ||
216 | break; | ||
217 | case ATH10K_FW_IE_TIMESTAMP: | ||
218 | /* ignore timestamp, but don't warn about it either */ | ||
219 | break; | ||
220 | case ATH10K_FW_IE_FW_IMAGE: | ||
221 | ath10k_dbg(ar, ATH10K_DBG_TESTMODE, | ||
222 | "testmode found fw image ie (%zd B)\n", | ||
223 | ie_len); | ||
224 | |||
225 | ar->testmode.utf_firmware_data = data; | ||
226 | ar->testmode.utf_firmware_len = ie_len; | ||
227 | break; | ||
228 | case ATH10K_FW_IE_WMI_OP_VERSION: | ||
229 | if (ie_len != sizeof(u32)) | ||
230 | break; | ||
231 | version = (__le32 *)data; | ||
232 | ar->testmode.op_version = le32_to_cpup(version); | ||
233 | ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode found fw ie wmi op version %d\n", | ||
234 | ar->testmode.op_version); | ||
235 | break; | ||
236 | default: | ||
237 | ath10k_warn(ar, "Unknown testmode FW IE: %u\n", | ||
238 | le32_to_cpu(hdr->id)); | ||
239 | break; | ||
240 | } | ||
241 | /* jump over the padding */ | ||
242 | ie_len = ALIGN(ie_len, 4); | ||
243 | |||
244 | len -= ie_len; | ||
245 | data += ie_len; | ||
246 | } | ||
247 | |||
248 | if (!ar->testmode.utf_firmware_data || !ar->testmode.utf_firmware_len) { | ||
249 | ath10k_err(ar, "No ATH10K_FW_IE_FW_IMAGE found\n"); | ||
250 | ret = -EINVAL; | ||
251 | goto err; | ||
252 | } | ||
253 | |||
254 | return 0; | ||
255 | |||
256 | err: | ||
257 | release_firmware(ar->testmode.utf); | ||
258 | |||
259 | return ret; | ||
260 | } | ||
261 | |||
262 | static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar) | ||
143 | { | 263 | { |
144 | char filename[100]; | 264 | char filename[100]; |
145 | int ret; | 265 | int ret; |
146 | 266 | ||
267 | snprintf(filename, sizeof(filename), "%s/%s", | ||
268 | ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE); | ||
269 | |||
270 | /* load utf firmware image */ | ||
271 | ret = request_firmware(&ar->testmode.utf, filename, ar->dev); | ||
272 | if (ret) { | ||
273 | ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n", | ||
274 | filename, ret); | ||
275 | return ret; | ||
276 | } | ||
277 | |||
278 | /* We didn't find FW UTF API 1 ("utf.bin") does not advertise | ||
279 | * firmware features. Do an ugly hack where we force the firmware | ||
280 | * features to match with 10.1 branch so that wmi.c will use the | ||
281 | * correct WMI interface. | ||
282 | */ | ||
283 | |||
284 | ar->testmode.op_version = ATH10K_FW_WMI_OP_VERSION_10_1; | ||
285 | ar->testmode.utf_firmware_data = ar->testmode.utf->data; | ||
286 | ar->testmode.utf_firmware_len = ar->testmode.utf->size; | ||
287 | |||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | static int ath10k_tm_fetch_firmware(struct ath10k *ar) | ||
292 | { | ||
293 | int ret; | ||
294 | |||
295 | ret = ath10k_tm_fetch_utf_firmware_api_2(ar); | ||
296 | if (ret == 0) { | ||
297 | ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using fw utf api 2"); | ||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | ret = ath10k_tm_fetch_utf_firmware_api_1(ar); | ||
302 | if (ret) { | ||
303 | ath10k_err(ar, "failed to fetch utf firmware binary: %d", ret); | ||
304 | return ret; | ||
305 | } | ||
306 | |||
307 | ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using utf api 1"); | ||
308 | |||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) | ||
313 | { | ||
314 | const char *ver; | ||
315 | int ret; | ||
316 | |||
147 | ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf start\n"); | 317 | ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf start\n"); |
148 | 318 | ||
149 | mutex_lock(&ar->conf_mutex); | 319 | mutex_lock(&ar->conf_mutex); |
@@ -165,36 +335,27 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) | |||
165 | goto err; | 335 | goto err; |
166 | } | 336 | } |
167 | 337 | ||
168 | snprintf(filename, sizeof(filename), "%s/%s", | 338 | ret = ath10k_tm_fetch_firmware(ar); |
169 | ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE); | ||
170 | |||
171 | /* load utf firmware image */ | ||
172 | ret = request_firmware(&ar->testmode.utf, filename, ar->dev); | ||
173 | if (ret) { | 339 | if (ret) { |
174 | ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n", | 340 | ath10k_err(ar, "failed to fetch UTF firmware: %d", ret); |
175 | filename, ret); | ||
176 | goto err; | 341 | goto err; |
177 | } | 342 | } |
178 | 343 | ||
179 | spin_lock_bh(&ar->data_lock); | 344 | spin_lock_bh(&ar->data_lock); |
180 | |||
181 | ar->testmode.utf_monitor = true; | 345 | ar->testmode.utf_monitor = true; |
182 | |||
183 | spin_unlock_bh(&ar->data_lock); | 346 | spin_unlock_bh(&ar->data_lock); |
184 | |||
185 | BUILD_BUG_ON(sizeof(ar->fw_features) != | 347 | BUILD_BUG_ON(sizeof(ar->fw_features) != |
186 | sizeof(ar->testmode.orig_fw_features)); | 348 | sizeof(ar->testmode.orig_fw_features)); |
187 | 349 | ||
188 | memcpy(ar->testmode.orig_fw_features, ar->fw_features, | 350 | memcpy(ar->testmode.orig_fw_features, ar->fw_features, |
189 | sizeof(ar->fw_features)); | 351 | sizeof(ar->fw_features)); |
190 | ar->testmode.orig_wmi_op_version = ar->wmi.op_version; | 352 | ar->testmode.orig_wmi_op_version = ar->wmi.op_version; |
191 | |||
192 | /* utf.bin firmware image does not advertise firmware features. Do | ||
193 | * an ugly hack where we force the firmware features so that wmi.c | ||
194 | * will use the correct WMI interface. | ||
195 | */ | ||
196 | memset(ar->fw_features, 0, sizeof(ar->fw_features)); | 353 | memset(ar->fw_features, 0, sizeof(ar->fw_features)); |
197 | ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_1; | 354 | |
355 | ar->wmi.op_version = ar->testmode.op_version; | ||
356 | |||
357 | ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode wmi version %d\n", | ||
358 | ar->wmi.op_version); | ||
198 | 359 | ||
199 | ret = ath10k_hif_power_up(ar); | 360 | ret = ath10k_hif_power_up(ar); |
200 | if (ret) { | 361 | if (ret) { |
@@ -212,7 +373,12 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) | |||
212 | 373 | ||
213 | ar->state = ATH10K_STATE_UTF; | 374 | ar->state = ATH10K_STATE_UTF; |
214 | 375 | ||
215 | ath10k_info(ar, "UTF firmware started\n"); | 376 | if (strlen(ar->testmode.utf_version) > 0) |
377 | ver = ar->testmode.utf_version; | ||
378 | else | ||
379 | ver = "API 1"; | ||
380 | |||
381 | ath10k_info(ar, "UTF firmware %s started\n", ver); | ||
216 | 382 | ||
217 | mutex_unlock(&ar->conf_mutex); | 383 | mutex_unlock(&ar->conf_mutex); |
218 | 384 | ||
diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h index b54aa08cb25c..8f4f6a892581 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-ops.h +++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h | |||
@@ -182,6 +182,10 @@ struct wmi_ops { | |||
182 | void (*fw_stats_fill)(struct ath10k *ar, | 182 | void (*fw_stats_fill)(struct ath10k *ar, |
183 | struct ath10k_fw_stats *fw_stats, | 183 | struct ath10k_fw_stats *fw_stats, |
184 | char *buf); | 184 | char *buf); |
185 | struct sk_buff *(*gen_pdev_enable_adaptive_cca)(struct ath10k *ar, | ||
186 | u8 enable, | ||
187 | u32 detect_level, | ||
188 | u32 detect_margin); | ||
185 | }; | 189 | }; |
186 | 190 | ||
187 | int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id); | 191 | 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, | |||
1302 | ar->wmi.ops->fw_stats_fill(ar, fw_stats, buf); | 1306 | ar->wmi.ops->fw_stats_fill(ar, fw_stats, buf); |
1303 | return 0; | 1307 | return 0; |
1304 | } | 1308 | } |
1309 | |||
1310 | static inline int | ||
1311 | ath10k_wmi_pdev_enable_adaptive_cca(struct ath10k *ar, u8 enable, | ||
1312 | u32 detect_level, u32 detect_margin) | ||
1313 | { | ||
1314 | struct sk_buff *skb; | ||
1315 | |||
1316 | if (!ar->wmi.ops->gen_pdev_enable_adaptive_cca) | ||
1317 | return -EOPNOTSUPP; | ||
1318 | |||
1319 | skb = ar->wmi.ops->gen_pdev_enable_adaptive_cca(ar, enable, | ||
1320 | detect_level, | ||
1321 | detect_margin); | ||
1322 | |||
1323 | if (IS_ERR(skb)) | ||
1324 | return PTR_ERR(skb); | ||
1325 | |||
1326 | return ath10k_wmi_cmd_send(ar, skb, | ||
1327 | ar->wmi.cmd->pdev_enable_adaptive_cca_cmdid); | ||
1328 | } | ||
1329 | |||
1305 | #endif | 1330 | #endif |
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 8f835480a62c..6fbd17b69469 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include "wmi-ops.h" | 23 | #include "wmi-ops.h" |
24 | #include "wmi-tlv.h" | 24 | #include "wmi-tlv.h" |
25 | #include "p2p.h" | 25 | #include "p2p.h" |
26 | #include "testmode.h" | ||
26 | 27 | ||
27 | /***************/ | 28 | /***************/ |
28 | /* TLV helpers */ | 29 | /* TLV helpers */ |
@@ -419,6 +420,7 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb) | |||
419 | { | 420 | { |
420 | struct wmi_cmd_hdr *cmd_hdr; | 421 | struct wmi_cmd_hdr *cmd_hdr; |
421 | enum wmi_tlv_event_id id; | 422 | enum wmi_tlv_event_id id; |
423 | bool consumed; | ||
422 | 424 | ||
423 | cmd_hdr = (struct wmi_cmd_hdr *)skb->data; | 425 | cmd_hdr = (struct wmi_cmd_hdr *)skb->data; |
424 | id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); | 426 | 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) | |||
428 | 430 | ||
429 | trace_ath10k_wmi_event(ar, id, skb->data, skb->len); | 431 | trace_ath10k_wmi_event(ar, id, skb->data, skb->len); |
430 | 432 | ||
433 | consumed = ath10k_tm_event_wmi(ar, id, skb); | ||
434 | |||
435 | /* Ready event must be handled normally also in UTF mode so that we | ||
436 | * know the UTF firmware has booted, others we are just bypass WMI | ||
437 | * events to testmode. | ||
438 | */ | ||
439 | if (consumed && id != WMI_TLV_READY_EVENTID) { | ||
440 | ath10k_dbg(ar, ATH10K_DBG_WMI, | ||
441 | "wmi tlv testmode consumed 0x%x\n", id); | ||
442 | goto out; | ||
443 | } | ||
444 | |||
431 | switch (id) { | 445 | switch (id) { |
432 | case WMI_TLV_MGMT_RX_EVENTID: | 446 | case WMI_TLV_MGMT_RX_EVENTID: |
433 | ath10k_wmi_event_mgmt_rx(ar, skb); | 447 | ath10k_wmi_event_mgmt_rx(ar, skb); |
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 6e7d7a7f6a97..7569db0f69b5 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c | |||
@@ -148,6 +148,7 @@ static struct wmi_cmd_map wmi_cmd_map = { | |||
148 | .gpio_config_cmdid = WMI_GPIO_CONFIG_CMDID, | 148 | .gpio_config_cmdid = WMI_GPIO_CONFIG_CMDID, |
149 | .gpio_output_cmdid = WMI_GPIO_OUTPUT_CMDID, | 149 | .gpio_output_cmdid = WMI_GPIO_OUTPUT_CMDID, |
150 | .pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED, | 150 | .pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED, |
151 | .pdev_enable_adaptive_cca_cmdid = WMI_CMD_UNSUPPORTED, | ||
151 | .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED, | 152 | .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED, |
152 | .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED, | 153 | .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED, |
153 | .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED, | 154 | .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED, |
@@ -313,6 +314,7 @@ static struct wmi_cmd_map wmi_10x_cmd_map = { | |||
313 | .gpio_config_cmdid = WMI_10X_GPIO_CONFIG_CMDID, | 314 | .gpio_config_cmdid = WMI_10X_GPIO_CONFIG_CMDID, |
314 | .gpio_output_cmdid = WMI_10X_GPIO_OUTPUT_CMDID, | 315 | .gpio_output_cmdid = WMI_10X_GPIO_OUTPUT_CMDID, |
315 | .pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED, | 316 | .pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED, |
317 | .pdev_enable_adaptive_cca_cmdid = WMI_CMD_UNSUPPORTED, | ||
316 | .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED, | 318 | .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED, |
317 | .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED, | 319 | .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED, |
318 | .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED, | 320 | .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED, |
@@ -477,6 +479,7 @@ static struct wmi_cmd_map wmi_10_2_4_cmd_map = { | |||
477 | .gpio_config_cmdid = WMI_10_2_GPIO_CONFIG_CMDID, | 479 | .gpio_config_cmdid = WMI_10_2_GPIO_CONFIG_CMDID, |
478 | .gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID, | 480 | .gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID, |
479 | .pdev_get_temperature_cmdid = WMI_10_2_PDEV_GET_TEMPERATURE_CMDID, | 481 | .pdev_get_temperature_cmdid = WMI_10_2_PDEV_GET_TEMPERATURE_CMDID, |
482 | .pdev_enable_adaptive_cca_cmdid = WMI_10_2_SET_CCA_PARAMS, | ||
480 | .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED, | 483 | .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED, |
481 | .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED, | 484 | .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED, |
482 | .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED, | 485 | .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED, |
@@ -1407,6 +1410,7 @@ static struct wmi_cmd_map wmi_10_2_cmd_map = { | |||
1407 | .gpio_config_cmdid = WMI_10_2_GPIO_CONFIG_CMDID, | 1410 | .gpio_config_cmdid = WMI_10_2_GPIO_CONFIG_CMDID, |
1408 | .gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID, | 1411 | .gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID, |
1409 | .pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED, | 1412 | .pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED, |
1413 | .pdev_enable_adaptive_cca_cmdid = WMI_CMD_UNSUPPORTED, | ||
1410 | .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED, | 1414 | .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED, |
1411 | .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED, | 1415 | .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED, |
1412 | .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED, | 1416 | .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, | |||
2475 | dst->txop_ovf = __le32_to_cpu(src->txop_ovf); | 2479 | dst->txop_ovf = __le32_to_cpu(src->txop_ovf); |
2476 | } | 2480 | } |
2477 | 2481 | ||
2482 | static void | ||
2483 | ath10k_wmi_10_4_pull_pdev_stats_tx(const struct wmi_10_4_pdev_stats_tx *src, | ||
2484 | struct ath10k_fw_stats_pdev *dst) | ||
2485 | { | ||
2486 | dst->comp_queued = __le32_to_cpu(src->comp_queued); | ||
2487 | dst->comp_delivered = __le32_to_cpu(src->comp_delivered); | ||
2488 | dst->msdu_enqued = __le32_to_cpu(src->msdu_enqued); | ||
2489 | dst->mpdu_enqued = __le32_to_cpu(src->mpdu_enqued); | ||
2490 | dst->wmm_drop = __le32_to_cpu(src->wmm_drop); | ||
2491 | dst->local_enqued = __le32_to_cpu(src->local_enqued); | ||
2492 | dst->local_freed = __le32_to_cpu(src->local_freed); | ||
2493 | dst->hw_queued = __le32_to_cpu(src->hw_queued); | ||
2494 | dst->hw_reaped = __le32_to_cpu(src->hw_reaped); | ||
2495 | dst->underrun = __le32_to_cpu(src->underrun); | ||
2496 | dst->tx_abort = __le32_to_cpu(src->tx_abort); | ||
2497 | dst->mpdus_requed = __le32_to_cpu(src->mpdus_requed); | ||
2498 | dst->tx_ko = __le32_to_cpu(src->tx_ko); | ||
2499 | dst->data_rc = __le32_to_cpu(src->data_rc); | ||
2500 | dst->self_triggers = __le32_to_cpu(src->self_triggers); | ||
2501 | dst->sw_retry_failure = __le32_to_cpu(src->sw_retry_failure); | ||
2502 | dst->illgl_rate_phy_err = __le32_to_cpu(src->illgl_rate_phy_err); | ||
2503 | dst->pdev_cont_xretry = __le32_to_cpu(src->pdev_cont_xretry); | ||
2504 | dst->pdev_tx_timeout = __le32_to_cpu(src->pdev_tx_timeout); | ||
2505 | dst->pdev_resets = __le32_to_cpu(src->pdev_resets); | ||
2506 | dst->phy_underrun = __le32_to_cpu(src->phy_underrun); | ||
2507 | dst->txop_ovf = __le32_to_cpu(src->txop_ovf); | ||
2508 | dst->hw_paused = __le32_to_cpu(src->hw_paused); | ||
2509 | dst->seq_posted = __le32_to_cpu(src->seq_posted); | ||
2510 | dst->seq_failed_queueing = | ||
2511 | __le32_to_cpu(src->seq_failed_queueing); | ||
2512 | dst->seq_completed = __le32_to_cpu(src->seq_completed); | ||
2513 | dst->seq_restarted = __le32_to_cpu(src->seq_restarted); | ||
2514 | dst->mu_seq_posted = __le32_to_cpu(src->mu_seq_posted); | ||
2515 | dst->mpdus_sw_flush = __le32_to_cpu(src->mpdus_sw_flush); | ||
2516 | dst->mpdus_hw_filter = __le32_to_cpu(src->mpdus_hw_filter); | ||
2517 | dst->mpdus_truncated = __le32_to_cpu(src->mpdus_truncated); | ||
2518 | dst->mpdus_ack_failed = __le32_to_cpu(src->mpdus_ack_failed); | ||
2519 | dst->mpdus_hw_filter = __le32_to_cpu(src->mpdus_hw_filter); | ||
2520 | dst->mpdus_expired = __le32_to_cpu(src->mpdus_expired); | ||
2521 | } | ||
2522 | |||
2478 | void ath10k_wmi_pull_pdev_stats_rx(const struct wmi_pdev_stats_rx *src, | 2523 | void ath10k_wmi_pull_pdev_stats_rx(const struct wmi_pdev_stats_rx *src, |
2479 | struct ath10k_fw_stats_pdev *dst) | 2524 | struct ath10k_fw_stats_pdev *dst) |
2480 | { | 2525 | { |
@@ -2785,6 +2830,86 @@ static int ath10k_wmi_10_2_4_op_pull_fw_stats(struct ath10k *ar, | |||
2785 | return 0; | 2830 | return 0; |
2786 | } | 2831 | } |
2787 | 2832 | ||
2833 | static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar, | ||
2834 | struct sk_buff *skb, | ||
2835 | struct ath10k_fw_stats *stats) | ||
2836 | { | ||
2837 | const struct wmi_10_2_stats_event *ev = (void *)skb->data; | ||
2838 | u32 num_pdev_stats; | ||
2839 | u32 num_pdev_ext_stats; | ||
2840 | u32 num_vdev_stats; | ||
2841 | u32 num_peer_stats; | ||
2842 | int i; | ||
2843 | |||
2844 | if (!skb_pull(skb, sizeof(*ev))) | ||
2845 | return -EPROTO; | ||
2846 | |||
2847 | num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats); | ||
2848 | num_pdev_ext_stats = __le32_to_cpu(ev->num_pdev_ext_stats); | ||
2849 | num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats); | ||
2850 | num_peer_stats = __le32_to_cpu(ev->num_peer_stats); | ||
2851 | |||
2852 | for (i = 0; i < num_pdev_stats; i++) { | ||
2853 | const struct wmi_10_4_pdev_stats *src; | ||
2854 | struct ath10k_fw_stats_pdev *dst; | ||
2855 | |||
2856 | src = (void *)skb->data; | ||
2857 | if (!skb_pull(skb, sizeof(*src))) | ||
2858 | return -EPROTO; | ||
2859 | |||
2860 | dst = kzalloc(sizeof(*dst), GFP_ATOMIC); | ||
2861 | if (!dst) | ||
2862 | continue; | ||
2863 | |||
2864 | ath10k_wmi_pull_pdev_stats_base(&src->base, dst); | ||
2865 | ath10k_wmi_10_4_pull_pdev_stats_tx(&src->tx, dst); | ||
2866 | ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst); | ||
2867 | dst->rx_ovfl_errs = __le32_to_cpu(src->rx_ovfl_errs); | ||
2868 | ath10k_wmi_pull_pdev_stats_extra(&src->extra, dst); | ||
2869 | |||
2870 | list_add_tail(&dst->list, &stats->pdevs); | ||
2871 | } | ||
2872 | |||
2873 | for (i = 0; i < num_pdev_ext_stats; i++) { | ||
2874 | const struct wmi_10_2_pdev_ext_stats *src; | ||
2875 | |||
2876 | src = (void *)skb->data; | ||
2877 | if (!skb_pull(skb, sizeof(*src))) | ||
2878 | return -EPROTO; | ||
2879 | |||
2880 | /* FIXME: expose values to userspace | ||
2881 | * | ||
2882 | * Note: Even though this loop seems to do nothing it is | ||
2883 | * required to parse following sub-structures properly. | ||
2884 | */ | ||
2885 | } | ||
2886 | |||
2887 | /* fw doesn't implement vdev stats */ | ||
2888 | |||
2889 | for (i = 0; i < num_peer_stats; i++) { | ||
2890 | const struct wmi_10_4_peer_stats *src; | ||
2891 | struct ath10k_fw_stats_peer *dst; | ||
2892 | |||
2893 | src = (void *)skb->data; | ||
2894 | if (!skb_pull(skb, sizeof(*src))) | ||
2895 | return -EPROTO; | ||
2896 | |||
2897 | dst = kzalloc(sizeof(*dst), GFP_ATOMIC); | ||
2898 | if (!dst) | ||
2899 | continue; | ||
2900 | |||
2901 | ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr); | ||
2902 | dst->peer_rssi = __le32_to_cpu(src->peer_rssi); | ||
2903 | dst->peer_tx_rate = __le32_to_cpu(src->peer_tx_rate); | ||
2904 | dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate); | ||
2905 | /* FIXME: expose 10.4 specific values */ | ||
2906 | |||
2907 | list_add_tail(&dst->list, &stats->peers); | ||
2908 | } | ||
2909 | |||
2910 | return 0; | ||
2911 | } | ||
2912 | |||
2788 | void ath10k_wmi_event_update_stats(struct ath10k *ar, struct sk_buff *skb) | 2913 | void ath10k_wmi_event_update_stats(struct ath10k *ar, struct sk_buff *skb) |
2789 | { | 2914 | { |
2790 | ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_UPDATE_STATS_EVENTID\n"); | 2915 | 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) | |||
4335 | ar->num_rf_chains = ar->max_spatial_stream; | 4460 | ar->num_rf_chains = ar->max_spatial_stream; |
4336 | } | 4461 | } |
4337 | 4462 | ||
4338 | ar->supp_tx_chainmask = (1 << ar->num_rf_chains) - 1; | 4463 | if (!ar->cfg_tx_chainmask) { |
4339 | ar->supp_rx_chainmask = (1 << ar->num_rf_chains) - 1; | 4464 | ar->cfg_tx_chainmask = (1 << ar->num_rf_chains) - 1; |
4465 | ar->cfg_rx_chainmask = (1 << ar->num_rf_chains) - 1; | ||
4466 | } | ||
4340 | 4467 | ||
4341 | if (strlen(ar->hw->wiphy->fw_version) == 0) { | 4468 | if (strlen(ar->hw->wiphy->fw_version) == 0) { |
4342 | snprintf(ar->hw->wiphy->fw_version, | 4469 | 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) | |||
4931 | ath10k_dbg(ar, ATH10K_DBG_WMI, | 5058 | ath10k_dbg(ar, ATH10K_DBG_WMI, |
4932 | "received event id %d not implemented\n", id); | 5059 | "received event id %d not implemented\n", id); |
4933 | break; | 5060 | break; |
5061 | case WMI_10_4_UPDATE_STATS_EVENTID: | ||
5062 | ath10k_wmi_event_update_stats(ar, skb); | ||
5063 | break; | ||
4934 | default: | 5064 | default: |
4935 | ath10k_warn(ar, "Unknown eventid: %d\n", id); | 5065 | ath10k_warn(ar, "Unknown eventid: %d\n", id); |
4936 | break; | 5066 | break; |
@@ -6996,6 +7126,112 @@ unlock: | |||
6996 | buf[len] = 0; | 7126 | buf[len] = 0; |
6997 | } | 7127 | } |
6998 | 7128 | ||
7129 | static struct sk_buff * | ||
7130 | ath10k_wmi_op_gen_pdev_enable_adaptive_cca(struct ath10k *ar, u8 enable, | ||
7131 | u32 detect_level, u32 detect_margin) | ||
7132 | { | ||
7133 | struct wmi_pdev_set_adaptive_cca_params *cmd; | ||
7134 | struct sk_buff *skb; | ||
7135 | |||
7136 | skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); | ||
7137 | if (!skb) | ||
7138 | return ERR_PTR(-ENOMEM); | ||
7139 | |||
7140 | cmd = (struct wmi_pdev_set_adaptive_cca_params *)skb->data; | ||
7141 | cmd->enable = __cpu_to_le32(enable); | ||
7142 | cmd->cca_detect_level = __cpu_to_le32(detect_level); | ||
7143 | cmd->cca_detect_margin = __cpu_to_le32(detect_margin); | ||
7144 | |||
7145 | ath10k_dbg(ar, ATH10K_DBG_WMI, | ||
7146 | "wmi pdev set adaptive cca params enable:%d detection level:%d detection margin:%d\n", | ||
7147 | enable, detect_level, detect_margin); | ||
7148 | return skb; | ||
7149 | } | ||
7150 | |||
7151 | void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar, | ||
7152 | struct ath10k_fw_stats *fw_stats, | ||
7153 | char *buf) | ||
7154 | { | ||
7155 | u32 len = 0; | ||
7156 | u32 buf_len = ATH10K_FW_STATS_BUF_SIZE; | ||
7157 | const struct ath10k_fw_stats_pdev *pdev; | ||
7158 | const struct ath10k_fw_stats_vdev *vdev; | ||
7159 | const struct ath10k_fw_stats_peer *peer; | ||
7160 | size_t num_peers; | ||
7161 | size_t num_vdevs; | ||
7162 | |||
7163 | spin_lock_bh(&ar->data_lock); | ||
7164 | |||
7165 | pdev = list_first_entry_or_null(&fw_stats->pdevs, | ||
7166 | struct ath10k_fw_stats_pdev, list); | ||
7167 | if (!pdev) { | ||
7168 | ath10k_warn(ar, "failed to get pdev stats\n"); | ||
7169 | goto unlock; | ||
7170 | } | ||
7171 | |||
7172 | num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers); | ||
7173 | num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs); | ||
7174 | |||
7175 | ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len); | ||
7176 | ath10k_wmi_fw_pdev_extra_stats_fill(pdev, buf, &len); | ||
7177 | ath10k_wmi_fw_pdev_tx_stats_fill(pdev, buf, &len); | ||
7178 | |||
7179 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | ||
7180 | "HW paused", pdev->hw_paused); | ||
7181 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | ||
7182 | "Seqs posted", pdev->seq_posted); | ||
7183 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | ||
7184 | "Seqs failed queueing", pdev->seq_failed_queueing); | ||
7185 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | ||
7186 | "Seqs completed", pdev->seq_completed); | ||
7187 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | ||
7188 | "Seqs restarted", pdev->seq_restarted); | ||
7189 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | ||
7190 | "MU Seqs posted", pdev->mu_seq_posted); | ||
7191 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | ||
7192 | "MPDUs SW flushed", pdev->mpdus_sw_flush); | ||
7193 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | ||
7194 | "MPDUs HW filtered", pdev->mpdus_hw_filter); | ||
7195 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | ||
7196 | "MPDUs truncated", pdev->mpdus_truncated); | ||
7197 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | ||
7198 | "MPDUs receive no ACK", pdev->mpdus_ack_failed); | ||
7199 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | ||
7200 | "MPDUs expired", pdev->mpdus_expired); | ||
7201 | |||
7202 | ath10k_wmi_fw_pdev_rx_stats_fill(pdev, buf, &len); | ||
7203 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | ||
7204 | "Num Rx Overflow errors", pdev->rx_ovfl_errs); | ||
7205 | |||
7206 | len += scnprintf(buf + len, buf_len - len, "\n"); | ||
7207 | len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n", | ||
7208 | "ath10k VDEV stats", num_vdevs); | ||
7209 | len += scnprintf(buf + len, buf_len - len, "%30s\n\n", | ||
7210 | "================="); | ||
7211 | |||
7212 | list_for_each_entry(vdev, &fw_stats->vdevs, list) { | ||
7213 | ath10k_wmi_fw_vdev_stats_fill(vdev, buf, &len); | ||
7214 | } | ||
7215 | |||
7216 | len += scnprintf(buf + len, buf_len - len, "\n"); | ||
7217 | len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n", | ||
7218 | "ath10k PEER stats", num_peers); | ||
7219 | len += scnprintf(buf + len, buf_len - len, "%30s\n\n", | ||
7220 | "================="); | ||
7221 | |||
7222 | list_for_each_entry(peer, &fw_stats->peers, list) { | ||
7223 | ath10k_wmi_fw_peer_stats_fill(peer, buf, &len); | ||
7224 | } | ||
7225 | |||
7226 | unlock: | ||
7227 | spin_unlock_bh(&ar->data_lock); | ||
7228 | |||
7229 | if (len >= buf_len) | ||
7230 | buf[len - 1] = 0; | ||
7231 | else | ||
7232 | buf[len] = 0; | ||
7233 | } | ||
7234 | |||
6999 | static const struct wmi_ops wmi_ops = { | 7235 | static const struct wmi_ops wmi_ops = { |
7000 | .rx = ath10k_wmi_op_rx, | 7236 | .rx = ath10k_wmi_op_rx, |
7001 | .map_svc = wmi_main_svc_map, | 7237 | .map_svc = wmi_main_svc_map, |
@@ -7059,6 +7295,7 @@ static const struct wmi_ops wmi_ops = { | |||
7059 | /* .gen_prb_tmpl not implemented */ | 7295 | /* .gen_prb_tmpl not implemented */ |
7060 | /* .gen_p2p_go_bcn_ie not implemented */ | 7296 | /* .gen_p2p_go_bcn_ie not implemented */ |
7061 | /* .gen_adaptive_qcs not implemented */ | 7297 | /* .gen_adaptive_qcs not implemented */ |
7298 | /* .gen_pdev_enable_adaptive_cca not implemented */ | ||
7062 | }; | 7299 | }; |
7063 | 7300 | ||
7064 | static const struct wmi_ops wmi_10_1_ops = { | 7301 | static const struct wmi_ops wmi_10_1_ops = { |
@@ -7125,6 +7362,7 @@ static const struct wmi_ops wmi_10_1_ops = { | |||
7125 | /* .gen_prb_tmpl not implemented */ | 7362 | /* .gen_prb_tmpl not implemented */ |
7126 | /* .gen_p2p_go_bcn_ie not implemented */ | 7363 | /* .gen_p2p_go_bcn_ie not implemented */ |
7127 | /* .gen_adaptive_qcs not implemented */ | 7364 | /* .gen_adaptive_qcs not implemented */ |
7365 | /* .gen_pdev_enable_adaptive_cca not implemented */ | ||
7128 | }; | 7366 | }; |
7129 | 7367 | ||
7130 | static const struct wmi_ops wmi_10_2_ops = { | 7368 | static const struct wmi_ops wmi_10_2_ops = { |
@@ -7188,6 +7426,7 @@ static const struct wmi_ops wmi_10_2_ops = { | |||
7188 | .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, | 7426 | .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, |
7189 | .gen_delba_send = ath10k_wmi_op_gen_delba_send, | 7427 | .gen_delba_send = ath10k_wmi_op_gen_delba_send, |
7190 | .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, | 7428 | .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, |
7429 | /* .gen_pdev_enable_adaptive_cca not implemented */ | ||
7191 | }; | 7430 | }; |
7192 | 7431 | ||
7193 | static const struct wmi_ops wmi_10_2_4_ops = { | 7432 | static const struct wmi_ops wmi_10_2_4_ops = { |
@@ -7251,6 +7490,8 @@ static const struct wmi_ops wmi_10_2_4_ops = { | |||
7251 | .gen_delba_send = ath10k_wmi_op_gen_delba_send, | 7490 | .gen_delba_send = ath10k_wmi_op_gen_delba_send, |
7252 | .gen_pdev_get_tpc_config = ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config, | 7491 | .gen_pdev_get_tpc_config = ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config, |
7253 | .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, | 7492 | .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, |
7493 | .gen_pdev_enable_adaptive_cca = | ||
7494 | ath10k_wmi_op_gen_pdev_enable_adaptive_cca, | ||
7254 | /* .gen_bcn_tmpl not implemented */ | 7495 | /* .gen_bcn_tmpl not implemented */ |
7255 | /* .gen_prb_tmpl not implemented */ | 7496 | /* .gen_prb_tmpl not implemented */ |
7256 | /* .gen_p2p_go_bcn_ie not implemented */ | 7497 | /* .gen_p2p_go_bcn_ie not implemented */ |
@@ -7261,6 +7502,7 @@ static const struct wmi_ops wmi_10_4_ops = { | |||
7261 | .rx = ath10k_wmi_10_4_op_rx, | 7502 | .rx = ath10k_wmi_10_4_op_rx, |
7262 | .map_svc = wmi_10_4_svc_map, | 7503 | .map_svc = wmi_10_4_svc_map, |
7263 | 7504 | ||
7505 | .pull_fw_stats = ath10k_wmi_10_4_op_pull_fw_stats, | ||
7264 | .pull_scan = ath10k_wmi_op_pull_scan_ev, | 7506 | .pull_scan = ath10k_wmi_op_pull_scan_ev, |
7265 | .pull_mgmt_rx = ath10k_wmi_10_4_op_pull_mgmt_rx_ev, | 7507 | .pull_mgmt_rx = ath10k_wmi_10_4_op_pull_mgmt_rx_ev, |
7266 | .pull_ch_info = ath10k_wmi_10_4_op_pull_ch_info_ev, | 7508 | .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 = { | |||
7310 | .gen_addba_send = ath10k_wmi_op_gen_addba_send, | 7552 | .gen_addba_send = ath10k_wmi_op_gen_addba_send, |
7311 | .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, | 7553 | .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, |
7312 | .gen_delba_send = ath10k_wmi_op_gen_delba_send, | 7554 | .gen_delba_send = ath10k_wmi_op_gen_delba_send, |
7555 | .fw_stats_fill = ath10k_wmi_10_4_op_fw_stats_fill, | ||
7313 | 7556 | ||
7314 | /* shared with 10.2 */ | 7557 | /* shared with 10.2 */ |
7315 | .gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc, | 7558 | .gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc, |
7559 | .gen_request_stats = ath10k_wmi_op_gen_request_stats, | ||
7316 | }; | 7560 | }; |
7317 | 7561 | ||
7318 | int ath10k_wmi_attach(struct ath10k *ar) | 7562 | int ath10k_wmi_attach(struct ath10k *ar) |
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 6e84d1c1a6ca..72a4ef709577 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h | |||
@@ -772,6 +772,7 @@ struct wmi_cmd_map { | |||
772 | u32 mu_cal_start_cmdid; | 772 | u32 mu_cal_start_cmdid; |
773 | u32 set_cca_params_cmdid; | 773 | u32 set_cca_params_cmdid; |
774 | u32 pdev_bss_chan_info_request_cmdid; | 774 | u32 pdev_bss_chan_info_request_cmdid; |
775 | u32 pdev_enable_adaptive_cca_cmdid; | ||
775 | }; | 776 | }; |
776 | 777 | ||
777 | /* | 778 | /* |
@@ -1381,6 +1382,9 @@ enum wmi_10_2_cmd_id { | |||
1381 | WMI_10_2_VDEV_ATF_REQUEST_CMDID, | 1382 | WMI_10_2_VDEV_ATF_REQUEST_CMDID, |
1382 | WMI_10_2_PEER_ATF_REQUEST_CMDID, | 1383 | WMI_10_2_PEER_ATF_REQUEST_CMDID, |
1383 | WMI_10_2_PDEV_GET_TEMPERATURE_CMDID, | 1384 | WMI_10_2_PDEV_GET_TEMPERATURE_CMDID, |
1385 | WMI_10_2_MU_CAL_START_CMDID, | ||
1386 | WMI_10_2_SET_LTEU_CONFIG_CMDID, | ||
1387 | WMI_10_2_SET_CCA_PARAMS, | ||
1384 | WMI_10_2_PDEV_UTF_CMDID = WMI_10_2_END_CMDID - 1, | 1388 | WMI_10_2_PDEV_UTF_CMDID = WMI_10_2_END_CMDID - 1, |
1385 | }; | 1389 | }; |
1386 | 1390 | ||
@@ -3862,6 +3866,111 @@ struct wmi_pdev_stats_tx { | |||
3862 | __le32 txop_ovf; | 3866 | __le32 txop_ovf; |
3863 | } __packed; | 3867 | } __packed; |
3864 | 3868 | ||
3869 | struct wmi_10_4_pdev_stats_tx { | ||
3870 | /* Num HTT cookies queued to dispatch list */ | ||
3871 | __le32 comp_queued; | ||
3872 | |||
3873 | /* Num HTT cookies dispatched */ | ||
3874 | __le32 comp_delivered; | ||
3875 | |||
3876 | /* Num MSDU queued to WAL */ | ||
3877 | __le32 msdu_enqued; | ||
3878 | |||
3879 | /* Num MPDU queue to WAL */ | ||
3880 | __le32 mpdu_enqued; | ||
3881 | |||
3882 | /* Num MSDUs dropped by WMM limit */ | ||
3883 | __le32 wmm_drop; | ||
3884 | |||
3885 | /* Num Local frames queued */ | ||
3886 | __le32 local_enqued; | ||
3887 | |||
3888 | /* Num Local frames done */ | ||
3889 | __le32 local_freed; | ||
3890 | |||
3891 | /* Num queued to HW */ | ||
3892 | __le32 hw_queued; | ||
3893 | |||
3894 | /* Num PPDU reaped from HW */ | ||
3895 | __le32 hw_reaped; | ||
3896 | |||
3897 | /* Num underruns */ | ||
3898 | __le32 underrun; | ||
3899 | |||
3900 | /* HW Paused. */ | ||
3901 | __le32 hw_paused; | ||
3902 | |||
3903 | /* Num PPDUs cleaned up in TX abort */ | ||
3904 | __le32 tx_abort; | ||
3905 | |||
3906 | /* Num MPDUs requed by SW */ | ||
3907 | __le32 mpdus_requed; | ||
3908 | |||
3909 | /* excessive retries */ | ||
3910 | __le32 tx_ko; | ||
3911 | |||
3912 | /* data hw rate code */ | ||
3913 | __le32 data_rc; | ||
3914 | |||
3915 | /* Scheduler self triggers */ | ||
3916 | __le32 self_triggers; | ||
3917 | |||
3918 | /* frames dropped due to excessive sw retries */ | ||
3919 | __le32 sw_retry_failure; | ||
3920 | |||
3921 | /* illegal rate phy errors */ | ||
3922 | __le32 illgl_rate_phy_err; | ||
3923 | |||
3924 | /* wal pdev continuous xretry */ | ||
3925 | __le32 pdev_cont_xretry; | ||
3926 | |||
3927 | /* wal pdev tx timeouts */ | ||
3928 | __le32 pdev_tx_timeout; | ||
3929 | |||
3930 | /* wal pdev resets */ | ||
3931 | __le32 pdev_resets; | ||
3932 | |||
3933 | /* frames dropped due to non-availability of stateless TIDs */ | ||
3934 | __le32 stateless_tid_alloc_failure; | ||
3935 | |||
3936 | __le32 phy_underrun; | ||
3937 | |||
3938 | /* MPDU is more than txop limit */ | ||
3939 | __le32 txop_ovf; | ||
3940 | |||
3941 | /* Number of Sequences posted */ | ||
3942 | __le32 seq_posted; | ||
3943 | |||
3944 | /* Number of Sequences failed queueing */ | ||
3945 | __le32 seq_failed_queueing; | ||
3946 | |||
3947 | /* Number of Sequences completed */ | ||
3948 | __le32 seq_completed; | ||
3949 | |||
3950 | /* Number of Sequences restarted */ | ||
3951 | __le32 seq_restarted; | ||
3952 | |||
3953 | /* Number of MU Sequences posted */ | ||
3954 | __le32 mu_seq_posted; | ||
3955 | |||
3956 | /* Num MPDUs flushed by SW, HWPAUSED,SW TXABORT(Reset,channel change) */ | ||
3957 | __le32 mpdus_sw_flush; | ||
3958 | |||
3959 | /* Num MPDUs filtered by HW, all filter condition (TTL expired) */ | ||
3960 | __le32 mpdus_hw_filter; | ||
3961 | |||
3962 | /* Num MPDUs truncated by PDG | ||
3963 | * (TXOP, TBTT, PPDU_duration based on rate, dyn_bw) | ||
3964 | */ | ||
3965 | __le32 mpdus_truncated; | ||
3966 | |||
3967 | /* Num MPDUs that was tried but didn't receive ACK or BA */ | ||
3968 | __le32 mpdus_ack_failed; | ||
3969 | |||
3970 | /* Num MPDUs that was dropped due to expiry. */ | ||
3971 | __le32 mpdus_expired; | ||
3972 | } __packed; | ||
3973 | |||
3865 | struct wmi_pdev_stats_rx { | 3974 | struct wmi_pdev_stats_rx { |
3866 | /* Cnts any change in ring routing mid-ppdu */ | 3975 | /* Cnts any change in ring routing mid-ppdu */ |
3867 | __le32 mid_ppdu_route_change; | 3976 | __le32 mid_ppdu_route_change; |
@@ -4035,6 +4144,16 @@ struct wmi_10_2_pdev_stats { | |||
4035 | struct wmi_pdev_stats_extra extra; | 4144 | struct wmi_pdev_stats_extra extra; |
4036 | } __packed; | 4145 | } __packed; |
4037 | 4146 | ||
4147 | struct wmi_10_4_pdev_stats { | ||
4148 | struct wmi_pdev_stats_base base; | ||
4149 | struct wmi_10_4_pdev_stats_tx tx; | ||
4150 | struct wmi_pdev_stats_rx rx; | ||
4151 | __le32 rx_ovfl_errs; | ||
4152 | struct wmi_pdev_stats_mem mem; | ||
4153 | __le32 sram_free_size; | ||
4154 | struct wmi_pdev_stats_extra extra; | ||
4155 | } __packed; | ||
4156 | |||
4038 | /* | 4157 | /* |
4039 | * VDEV statistics | 4158 | * VDEV statistics |
4040 | * TODO: add all VDEV stats here | 4159 | * TODO: add all VDEV stats here |
@@ -4076,6 +4195,23 @@ struct wmi_10_2_4_peer_stats { | |||
4076 | __le32 unknown_value; /* FIXME: what is this word? */ | 4195 | __le32 unknown_value; /* FIXME: what is this word? */ |
4077 | } __packed; | 4196 | } __packed; |
4078 | 4197 | ||
4198 | struct wmi_10_4_peer_stats { | ||
4199 | struct wmi_mac_addr peer_macaddr; | ||
4200 | __le32 peer_rssi; | ||
4201 | __le32 peer_rssi_seq_num; | ||
4202 | __le32 peer_tx_rate; | ||
4203 | __le32 peer_rx_rate; | ||
4204 | __le32 current_per; | ||
4205 | __le32 retries; | ||
4206 | __le32 tx_rate_count; | ||
4207 | __le32 max_4ms_frame_len; | ||
4208 | __le32 total_sub_frames; | ||
4209 | __le32 tx_bytes; | ||
4210 | __le32 num_pkt_loss_overflow[4]; | ||
4211 | __le32 num_pkt_loss_excess_retry[4]; | ||
4212 | __le32 peer_rssi_changed; | ||
4213 | } __packed; | ||
4214 | |||
4079 | struct wmi_10_2_pdev_ext_stats { | 4215 | struct wmi_10_2_pdev_ext_stats { |
4080 | __le32 rx_rssi_comb; | 4216 | __le32 rx_rssi_comb; |
4081 | __le32 rx_rssi[4]; | 4217 | __le32 rx_rssi[4]; |
@@ -6094,6 +6230,15 @@ enum wmi_txbf_conf { | |||
6094 | WMI_TXBF_CONF_AFTER_ASSOC, | 6230 | WMI_TXBF_CONF_AFTER_ASSOC, |
6095 | }; | 6231 | }; |
6096 | 6232 | ||
6233 | #define WMI_CCA_DETECT_LEVEL_AUTO 0 | ||
6234 | #define WMI_CCA_DETECT_MARGIN_AUTO 0 | ||
6235 | |||
6236 | struct wmi_pdev_set_adaptive_cca_params { | ||
6237 | __le32 enable; | ||
6238 | __le32 cca_detect_level; | ||
6239 | __le32 cca_detect_margin; | ||
6240 | } __packed; | ||
6241 | |||
6097 | struct ath10k; | 6242 | struct ath10k; |
6098 | struct ath10k_vif; | 6243 | struct ath10k_vif; |
6099 | struct ath10k_fw_stats_pdev; | 6244 | struct ath10k_fw_stats_pdev; |
@@ -6188,5 +6333,8 @@ void ath10k_wmi_10x_op_fw_stats_fill(struct ath10k *ar, | |||
6188 | char *buf); | 6333 | char *buf); |
6189 | size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head); | 6334 | size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head); |
6190 | size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head); | 6335 | size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head); |
6336 | void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar, | ||
6337 | struct ath10k_fw_stats *fw_stats, | ||
6338 | char *buf); | ||
6191 | 6339 | ||
6192 | #endif /* _WMI_H_ */ | 6340 | #endif /* _WMI_H_ */ |
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 76b682e566ab..81ac8c59f0ec 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -3231,6 +3231,15 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
3231 | wait, buf, len, no_cck); | 3231 | wait, buf, len, no_cck); |
3232 | } | 3232 | } |
3233 | 3233 | ||
3234 | static int ath6kl_get_antenna(struct wiphy *wiphy, | ||
3235 | u32 *tx_ant, u32 *rx_ant) | ||
3236 | { | ||
3237 | struct ath6kl *ar = wiphy_priv(wiphy); | ||
3238 | *tx_ant = ar->hw.tx_ant; | ||
3239 | *rx_ant = ar->hw.rx_ant; | ||
3240 | return 0; | ||
3241 | } | ||
3242 | |||
3234 | static void ath6kl_mgmt_frame_register(struct wiphy *wiphy, | 3243 | static void ath6kl_mgmt_frame_register(struct wiphy *wiphy, |
3235 | struct wireless_dev *wdev, | 3244 | struct wireless_dev *wdev, |
3236 | u16 frame_type, bool reg) | 3245 | u16 frame_type, bool reg) |
@@ -3447,6 +3456,7 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = { | |||
3447 | .cancel_remain_on_channel = ath6kl_cancel_remain_on_channel, | 3456 | .cancel_remain_on_channel = ath6kl_cancel_remain_on_channel, |
3448 | .mgmt_tx = ath6kl_mgmt_tx, | 3457 | .mgmt_tx = ath6kl_mgmt_tx, |
3449 | .mgmt_frame_register = ath6kl_mgmt_frame_register, | 3458 | .mgmt_frame_register = ath6kl_mgmt_frame_register, |
3459 | .get_antenna = ath6kl_get_antenna, | ||
3450 | .sched_scan_start = ath6kl_cfg80211_sscan_start, | 3460 | .sched_scan_start = ath6kl_cfg80211_sscan_start, |
3451 | .sched_scan_stop = ath6kl_cfg80211_sscan_stop, | 3461 | .sched_scan_stop = ath6kl_cfg80211_sscan_stop, |
3452 | .set_bitrate_mask = ath6kl_cfg80211_set_bitrate, | 3462 | .set_bitrate_mask = ath6kl_cfg80211_set_bitrate, |
@@ -3634,6 +3644,127 @@ void ath6kl_cfg80211_vif_cleanup(struct ath6kl_vif *vif) | |||
3634 | ar->num_vif--; | 3644 | ar->num_vif--; |
3635 | } | 3645 | } |
3636 | 3646 | ||
3647 | static const char ath6kl_gstrings_sta_stats[][ETH_GSTRING_LEN] = { | ||
3648 | /* Common stats names used by many drivers. */ | ||
3649 | "tx_pkts_nic", "tx_bytes_nic", "rx_pkts_nic", "rx_bytes_nic", | ||
3650 | |||
3651 | /* TX stats. */ | ||
3652 | "d_tx_ucast_pkts", "d_tx_bcast_pkts", | ||
3653 | "d_tx_ucast_bytes", "d_tx_bcast_bytes", | ||
3654 | "d_tx_rts_ok", "d_tx_error", "d_tx_fail", | ||
3655 | "d_tx_retry", "d_tx_multi_retry", "d_tx_rts_fail", | ||
3656 | "d_tx_tkip_counter_measures", | ||
3657 | |||
3658 | /* RX Stats. */ | ||
3659 | "d_rx_ucast_pkts", "d_rx_ucast_rate", "d_rx_bcast_pkts", | ||
3660 | "d_rx_ucast_bytes", "d_rx_bcast_bytes", "d_rx_frag_pkt", | ||
3661 | "d_rx_error", "d_rx_crc_err", "d_rx_keycache_miss", | ||
3662 | "d_rx_decrypt_crc_err", "d_rx_duplicate_frames", | ||
3663 | "d_rx_mic_err", "d_rx_tkip_format_err", "d_rx_ccmp_format_err", | ||
3664 | "d_rx_ccmp_replay_err", | ||
3665 | |||
3666 | /* Misc stats. */ | ||
3667 | "d_beacon_miss", "d_num_connects", "d_num_disconnects", | ||
3668 | "d_beacon_avg_rssi", "d_arp_received", "d_arp_matched", | ||
3669 | "d_arp_replied" | ||
3670 | }; | ||
3671 | |||
3672 | #define ATH6KL_STATS_LEN ARRAY_SIZE(ath6kl_gstrings_sta_stats) | ||
3673 | |||
3674 | static int ath6kl_get_sset_count(struct net_device *dev, int sset) | ||
3675 | { | ||
3676 | int rv = 0; | ||
3677 | |||
3678 | if (sset == ETH_SS_STATS) | ||
3679 | rv += ATH6KL_STATS_LEN; | ||
3680 | |||
3681 | if (rv == 0) | ||
3682 | return -EOPNOTSUPP; | ||
3683 | return rv; | ||
3684 | } | ||
3685 | |||
3686 | static void ath6kl_get_stats(struct net_device *dev, | ||
3687 | struct ethtool_stats *stats, | ||
3688 | u64 *data) | ||
3689 | { | ||
3690 | struct ath6kl_vif *vif = netdev_priv(dev); | ||
3691 | struct ath6kl *ar = vif->ar; | ||
3692 | int i = 0; | ||
3693 | struct target_stats *tgt_stats; | ||
3694 | |||
3695 | memset(data, 0, sizeof(u64) * ATH6KL_STATS_LEN); | ||
3696 | |||
3697 | ath6kl_read_tgt_stats(ar, vif); | ||
3698 | |||
3699 | tgt_stats = &vif->target_stats; | ||
3700 | |||
3701 | data[i++] = tgt_stats->tx_ucast_pkt + tgt_stats->tx_bcast_pkt; | ||
3702 | data[i++] = tgt_stats->tx_ucast_byte + tgt_stats->tx_bcast_byte; | ||
3703 | data[i++] = tgt_stats->rx_ucast_pkt + tgt_stats->rx_bcast_pkt; | ||
3704 | data[i++] = tgt_stats->rx_ucast_byte + tgt_stats->rx_bcast_byte; | ||
3705 | |||
3706 | data[i++] = tgt_stats->tx_ucast_pkt; | ||
3707 | data[i++] = tgt_stats->tx_bcast_pkt; | ||
3708 | data[i++] = tgt_stats->tx_ucast_byte; | ||
3709 | data[i++] = tgt_stats->tx_bcast_byte; | ||
3710 | data[i++] = tgt_stats->tx_rts_success_cnt; | ||
3711 | data[i++] = tgt_stats->tx_err; | ||
3712 | data[i++] = tgt_stats->tx_fail_cnt; | ||
3713 | data[i++] = tgt_stats->tx_retry_cnt; | ||
3714 | data[i++] = tgt_stats->tx_mult_retry_cnt; | ||
3715 | data[i++] = tgt_stats->tx_rts_fail_cnt; | ||
3716 | data[i++] = tgt_stats->tkip_cnter_measures_invoked; | ||
3717 | |||
3718 | data[i++] = tgt_stats->rx_ucast_pkt; | ||
3719 | data[i++] = tgt_stats->rx_ucast_rate; | ||
3720 | data[i++] = tgt_stats->rx_bcast_pkt; | ||
3721 | data[i++] = tgt_stats->rx_ucast_byte; | ||
3722 | data[i++] = tgt_stats->rx_bcast_byte; | ||
3723 | data[i++] = tgt_stats->rx_frgment_pkt; | ||
3724 | data[i++] = tgt_stats->rx_err; | ||
3725 | data[i++] = tgt_stats->rx_crc_err; | ||
3726 | data[i++] = tgt_stats->rx_key_cache_miss; | ||
3727 | data[i++] = tgt_stats->rx_decrypt_err; | ||
3728 | data[i++] = tgt_stats->rx_dupl_frame; | ||
3729 | data[i++] = tgt_stats->tkip_local_mic_fail; | ||
3730 | data[i++] = tgt_stats->tkip_fmt_err; | ||
3731 | data[i++] = tgt_stats->ccmp_fmt_err; | ||
3732 | data[i++] = tgt_stats->ccmp_replays; | ||
3733 | |||
3734 | data[i++] = tgt_stats->cs_bmiss_cnt; | ||
3735 | data[i++] = tgt_stats->cs_connect_cnt; | ||
3736 | data[i++] = tgt_stats->cs_discon_cnt; | ||
3737 | data[i++] = tgt_stats->cs_ave_beacon_rssi; | ||
3738 | data[i++] = tgt_stats->arp_received; | ||
3739 | data[i++] = tgt_stats->arp_matched; | ||
3740 | data[i++] = tgt_stats->arp_replied; | ||
3741 | |||
3742 | if (i != ATH6KL_STATS_LEN) { | ||
3743 | WARN_ON_ONCE(1); | ||
3744 | ath6kl_err("ethtool stats error, i: %d STATS_LEN: %d\n", | ||
3745 | i, (int)ATH6KL_STATS_LEN); | ||
3746 | } | ||
3747 | } | ||
3748 | |||
3749 | /* These stats are per NIC, not really per vdev, so we just ignore dev. */ | ||
3750 | static void ath6kl_get_strings(struct net_device *dev, u32 sset, u8 *data) | ||
3751 | { | ||
3752 | int sz_sta_stats = 0; | ||
3753 | |||
3754 | if (sset == ETH_SS_STATS) { | ||
3755 | sz_sta_stats = sizeof(ath6kl_gstrings_sta_stats); | ||
3756 | memcpy(data, ath6kl_gstrings_sta_stats, sz_sta_stats); | ||
3757 | } | ||
3758 | } | ||
3759 | |||
3760 | static const struct ethtool_ops ath6kl_ethtool_ops = { | ||
3761 | .get_drvinfo = cfg80211_get_drvinfo, | ||
3762 | .get_link = ethtool_op_get_link, | ||
3763 | .get_strings = ath6kl_get_strings, | ||
3764 | .get_ethtool_stats = ath6kl_get_stats, | ||
3765 | .get_sset_count = ath6kl_get_sset_count, | ||
3766 | }; | ||
3767 | |||
3637 | struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name, | 3768 | struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name, |
3638 | unsigned char name_assign_type, | 3769 | unsigned char name_assign_type, |
3639 | enum nl80211_iftype type, | 3770 | enum nl80211_iftype type, |
@@ -3679,6 +3810,8 @@ struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name, | |||
3679 | if (ath6kl_cfg80211_vif_init(vif)) | 3810 | if (ath6kl_cfg80211_vif_init(vif)) |
3680 | goto err; | 3811 | goto err; |
3681 | 3812 | ||
3813 | netdev_set_default_ethtool_ops(ndev, &ath6kl_ethtool_ops); | ||
3814 | |||
3682 | if (register_netdevice(ndev)) | 3815 | if (register_netdevice(ndev)) |
3683 | goto err; | 3816 | goto err; |
3684 | 3817 | ||
@@ -3786,6 +3919,9 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) | |||
3786 | ath6kl_band_2ghz.ht_cap.ht_supported = false; | 3919 | ath6kl_band_2ghz.ht_cap.ht_supported = false; |
3787 | ath6kl_band_5ghz.ht_cap.cap = 0; | 3920 | ath6kl_band_5ghz.ht_cap.cap = 0; |
3788 | ath6kl_band_5ghz.ht_cap.ht_supported = false; | 3921 | ath6kl_band_5ghz.ht_cap.ht_supported = false; |
3922 | |||
3923 | if (ht) | ||
3924 | ath6kl_err("Firmware lacks RSN-CAP-OVERRIDE, so HT (802.11n) is disabled."); | ||
3789 | } | 3925 | } |
3790 | 3926 | ||
3791 | if (test_bit(ATH6KL_FW_CAPABILITY_64BIT_RATES, | 3927 | if (test_bit(ATH6KL_FW_CAPABILITY_64BIT_RATES, |
@@ -3794,11 +3930,18 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) | |||
3794 | ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff; | 3930 | ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff; |
3795 | ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff; | 3931 | ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff; |
3796 | ath6kl_band_5ghz.ht_cap.mcs.rx_mask[1] = 0xff; | 3932 | ath6kl_band_5ghz.ht_cap.mcs.rx_mask[1] = 0xff; |
3933 | ar->hw.tx_ant = 2; | ||
3934 | ar->hw.rx_ant = 2; | ||
3797 | } else { | 3935 | } else { |
3798 | ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff; | 3936 | ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff; |
3799 | ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff; | 3937 | ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff; |
3938 | ar->hw.tx_ant = 1; | ||
3939 | ar->hw.rx_ant = 1; | ||
3800 | } | 3940 | } |
3801 | 3941 | ||
3942 | wiphy->available_antennas_tx = ar->hw.tx_ant; | ||
3943 | wiphy->available_antennas_rx = ar->hw.rx_ant; | ||
3944 | |||
3802 | if (band_2gig) | 3945 | if (band_2gig) |
3803 | wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; | 3946 | wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; |
3804 | if (band_5gig) | 3947 | if (band_5gig) |
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 2b78c863d030..5f3acfe6015e 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h | |||
@@ -782,6 +782,8 @@ struct ath6kl { | |||
782 | u32 refclk_hz; | 782 | u32 refclk_hz; |
783 | u32 uarttx_pin; | 783 | u32 uarttx_pin; |
784 | u32 testscript_addr; | 784 | u32 testscript_addr; |
785 | u8 tx_ant; | ||
786 | u8 rx_ant; | ||
785 | enum wmi_phy_cap cap; | 787 | enum wmi_phy_cap cap; |
786 | 788 | ||
787 | u32 flags; | 789 | u32 flags; |
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index 81ba48d2938b..e2b7809d7886 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c | |||
@@ -98,6 +98,33 @@ void ath6kl_warn(const char *fmt, ...) | |||
98 | } | 98 | } |
99 | EXPORT_SYMBOL(ath6kl_warn); | 99 | EXPORT_SYMBOL(ath6kl_warn); |
100 | 100 | ||
101 | int ath6kl_read_tgt_stats(struct ath6kl *ar, struct ath6kl_vif *vif) | ||
102 | { | ||
103 | long left; | ||
104 | |||
105 | if (down_interruptible(&ar->sem)) | ||
106 | return -EBUSY; | ||
107 | |||
108 | set_bit(STATS_UPDATE_PEND, &vif->flags); | ||
109 | |||
110 | if (ath6kl_wmi_get_stats_cmd(ar->wmi, 0)) { | ||
111 | up(&ar->sem); | ||
112 | return -EIO; | ||
113 | } | ||
114 | |||
115 | left = wait_event_interruptible_timeout(ar->event_wq, | ||
116 | !test_bit(STATS_UPDATE_PEND, | ||
117 | &vif->flags), WMI_TIMEOUT); | ||
118 | |||
119 | up(&ar->sem); | ||
120 | |||
121 | if (left <= 0) | ||
122 | return -ETIMEDOUT; | ||
123 | |||
124 | return 0; | ||
125 | } | ||
126 | EXPORT_SYMBOL(ath6kl_read_tgt_stats); | ||
127 | |||
101 | #ifdef CONFIG_ATH6KL_DEBUG | 128 | #ifdef CONFIG_ATH6KL_DEBUG |
102 | 129 | ||
103 | void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...) | 130 | 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, | |||
544 | char *buf; | 571 | char *buf; |
545 | unsigned int len = 0, buf_len = 1500; | 572 | unsigned int len = 0, buf_len = 1500; |
546 | int i; | 573 | int i; |
547 | long left; | ||
548 | ssize_t ret_cnt; | 574 | ssize_t ret_cnt; |
575 | int rv; | ||
549 | 576 | ||
550 | vif = ath6kl_vif_first(ar); | 577 | vif = ath6kl_vif_first(ar); |
551 | if (!vif) | 578 | if (!vif) |
552 | return -EIO; | 579 | return -EIO; |
553 | 580 | ||
554 | tgt_stats = &vif->target_stats; | ||
555 | |||
556 | buf = kzalloc(buf_len, GFP_KERNEL); | 581 | buf = kzalloc(buf_len, GFP_KERNEL); |
557 | if (!buf) | 582 | if (!buf) |
558 | return -ENOMEM; | 583 | return -ENOMEM; |
559 | 584 | ||
560 | if (down_interruptible(&ar->sem)) { | 585 | rv = ath6kl_read_tgt_stats(ar, vif); |
586 | if (rv < 0) { | ||
561 | kfree(buf); | 587 | kfree(buf); |
562 | return -EBUSY; | 588 | return rv; |
563 | } | 589 | } |
564 | 590 | ||
565 | set_bit(STATS_UPDATE_PEND, &vif->flags); | 591 | tgt_stats = &vif->target_stats; |
566 | |||
567 | if (ath6kl_wmi_get_stats_cmd(ar->wmi, 0)) { | ||
568 | up(&ar->sem); | ||
569 | kfree(buf); | ||
570 | return -EIO; | ||
571 | } | ||
572 | |||
573 | left = wait_event_interruptible_timeout(ar->event_wq, | ||
574 | !test_bit(STATS_UPDATE_PEND, | ||
575 | &vif->flags), WMI_TIMEOUT); | ||
576 | |||
577 | up(&ar->sem); | ||
578 | |||
579 | if (left <= 0) { | ||
580 | kfree(buf); | ||
581 | return -ETIMEDOUT; | ||
582 | } | ||
583 | 592 | ||
584 | len += scnprintf(buf + len, buf_len - len, "\n"); | 593 | len += scnprintf(buf + len, buf_len - len, "\n"); |
585 | len += scnprintf(buf + len, buf_len - len, "%25s\n", | 594 | len += scnprintf(buf + len, buf_len - len, "%25s\n", |
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h index 19106ed28961..0614393dd7ae 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.h +++ b/drivers/net/wireless/ath/ath6kl/debug.h | |||
@@ -59,6 +59,8 @@ enum ath6kl_war { | |||
59 | ATH6KL_WAR_INVALID_RATE, | 59 | ATH6KL_WAR_INVALID_RATE, |
60 | }; | 60 | }; |
61 | 61 | ||
62 | int ath6kl_read_tgt_stats(struct ath6kl *ar, struct ath6kl_vif *vif); | ||
63 | |||
62 | #ifdef CONFIG_ATH6KL_DEBUG | 64 | #ifdef CONFIG_ATH6KL_DEBUG |
63 | 65 | ||
64 | void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...); | 66 | void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...); |
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 6e473fa4b13c..e3f3a6ae0c0a 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c | |||
@@ -994,7 +994,7 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) | |||
994 | switch (ie_id) { | 994 | switch (ie_id) { |
995 | case ATH6KL_FW_IE_FW_VERSION: | 995 | case ATH6KL_FW_IE_FW_VERSION: |
996 | strlcpy(ar->wiphy->fw_version, data, | 996 | strlcpy(ar->wiphy->fw_version, data, |
997 | sizeof(ar->wiphy->fw_version)); | 997 | min(sizeof(ar->wiphy->fw_version), ie_len+1)); |
998 | 998 | ||
999 | ath6kl_dbg(ATH6KL_DBG_BOOT, | 999 | ath6kl_dbg(ATH6KL_DBG_BOOT, |
1000 | "found fw version %s\n", | 1000 | "found fw version %s\n", |
diff --git a/drivers/net/wireless/ath/ath9k/common-debug.c b/drivers/net/wireless/ath/ath9k/common-debug.c index 3b289f933405..84afcf78151f 100644 --- a/drivers/net/wireless/ath/ath9k/common-debug.c +++ b/drivers/net/wireless/ath/ath9k/common-debug.c | |||
@@ -207,6 +207,7 @@ static ssize_t read_file_phy_err(struct file *file, char __user *user_buf, | |||
207 | PHY_ERR("RADAR ERR", ATH9K_PHYERR_RADAR); | 207 | PHY_ERR("RADAR ERR", ATH9K_PHYERR_RADAR); |
208 | PHY_ERR("SERVICE ERR", ATH9K_PHYERR_SERVICE); | 208 | PHY_ERR("SERVICE ERR", ATH9K_PHYERR_SERVICE); |
209 | PHY_ERR("TOR ERR", ATH9K_PHYERR_TOR); | 209 | PHY_ERR("TOR ERR", ATH9K_PHYERR_TOR); |
210 | |||
210 | PHY_ERR("OFDM-TIMING ERR", ATH9K_PHYERR_OFDM_TIMING); | 211 | PHY_ERR("OFDM-TIMING ERR", ATH9K_PHYERR_OFDM_TIMING); |
211 | PHY_ERR("OFDM-SIGNAL-PARITY ERR", ATH9K_PHYERR_OFDM_SIGNAL_PARITY); | 212 | PHY_ERR("OFDM-SIGNAL-PARITY ERR", ATH9K_PHYERR_OFDM_SIGNAL_PARITY); |
212 | PHY_ERR("OFDM-RATE ERR", ATH9K_PHYERR_OFDM_RATE_ILLEGAL); | 213 | 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, | |||
214 | PHY_ERR("OFDM-POWER-DROP ERR", ATH9K_PHYERR_OFDM_POWER_DROP); | 215 | PHY_ERR("OFDM-POWER-DROP ERR", ATH9K_PHYERR_OFDM_POWER_DROP); |
215 | PHY_ERR("OFDM-SERVICE ERR", ATH9K_PHYERR_OFDM_SERVICE); | 216 | PHY_ERR("OFDM-SERVICE ERR", ATH9K_PHYERR_OFDM_SERVICE); |
216 | PHY_ERR("OFDM-RESTART ERR", ATH9K_PHYERR_OFDM_RESTART); | 217 | PHY_ERR("OFDM-RESTART ERR", ATH9K_PHYERR_OFDM_RESTART); |
217 | PHY_ERR("FALSE-RADAR-EXT ERR", ATH9K_PHYERR_FALSE_RADAR_EXT); | 218 | |
219 | PHY_ERR("CCK-BLOCKER ERR", ATH9K_PHYERR_CCK_BLOCKER); | ||
218 | PHY_ERR("CCK-TIMING ERR", ATH9K_PHYERR_CCK_TIMING); | 220 | PHY_ERR("CCK-TIMING ERR", ATH9K_PHYERR_CCK_TIMING); |
219 | PHY_ERR("CCK-HEADER-CRC ERR", ATH9K_PHYERR_CCK_HEADER_CRC); | 221 | PHY_ERR("CCK-HEADER-CRC ERR", ATH9K_PHYERR_CCK_HEADER_CRC); |
220 | PHY_ERR("CCK-RATE ERR", ATH9K_PHYERR_CCK_RATE_ILLEGAL); | 222 | PHY_ERR("CCK-RATE ERR", ATH9K_PHYERR_CCK_RATE_ILLEGAL); |
221 | PHY_ERR("CCK-SERVICE ERR", ATH9K_PHYERR_CCK_SERVICE); | ||
222 | PHY_ERR("CCK-RESTART ERR", ATH9K_PHYERR_CCK_RESTART); | ||
223 | PHY_ERR("CCK-LENGTH ERR", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL); | 223 | PHY_ERR("CCK-LENGTH ERR", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL); |
224 | PHY_ERR("CCK-POWER-DROP ERR", ATH9K_PHYERR_CCK_POWER_DROP); | 224 | PHY_ERR("CCK-POWER-DROP ERR", ATH9K_PHYERR_CCK_POWER_DROP); |
225 | PHY_ERR("CCK-SERVICE ERR", ATH9K_PHYERR_CCK_SERVICE); | ||
226 | PHY_ERR("CCK-RESTART ERR", ATH9K_PHYERR_CCK_RESTART); | ||
227 | |||
225 | PHY_ERR("HT-CRC ERR", ATH9K_PHYERR_HT_CRC_ERROR); | 228 | PHY_ERR("HT-CRC ERR", ATH9K_PHYERR_HT_CRC_ERROR); |
226 | PHY_ERR("HT-LENGTH ERR", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); | 229 | PHY_ERR("HT-LENGTH ERR", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); |
227 | PHY_ERR("HT-RATE ERR", ATH9K_PHYERR_HT_RATE_ILLEGAL); | 230 | PHY_ERR("HT-RATE ERR", ATH9K_PHYERR_HT_RATE_ILLEGAL); |
231 | PHY_ERR("HT-ZLF ERR", ATH9K_PHYERR_HT_ZLF); | ||
232 | |||
233 | PHY_ERR("FALSE-RADAR-EXT ERR", ATH9K_PHYERR_FALSE_RADAR_EXT); | ||
234 | PHY_ERR("GREEN-FIELD ERR", ATH9K_PHYERR_GREEN_FIELD); | ||
235 | PHY_ERR("SPECTRAL ERR", ATH9K_PHYERR_SPECTRAL); | ||
228 | 236 | ||
229 | if (len > size) | 237 | if (len > size) |
230 | len = size; | 238 | len = size; |
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index e55fa11894b6..7fbf7f965f61 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h | |||
@@ -209,21 +209,25 @@ enum ath9k_phyerr { | |||
209 | ATH9K_PHYERR_OFDM_POWER_DROP = 21, | 209 | ATH9K_PHYERR_OFDM_POWER_DROP = 21, |
210 | ATH9K_PHYERR_OFDM_SERVICE = 22, | 210 | ATH9K_PHYERR_OFDM_SERVICE = 22, |
211 | ATH9K_PHYERR_OFDM_RESTART = 23, | 211 | ATH9K_PHYERR_OFDM_RESTART = 23, |
212 | ATH9K_PHYERR_FALSE_RADAR_EXT = 24, | ||
213 | 212 | ||
213 | ATH9K_PHYERR_CCK_BLOCKER = 24, | ||
214 | ATH9K_PHYERR_CCK_TIMING = 25, | 214 | ATH9K_PHYERR_CCK_TIMING = 25, |
215 | ATH9K_PHYERR_CCK_HEADER_CRC = 26, | 215 | ATH9K_PHYERR_CCK_HEADER_CRC = 26, |
216 | ATH9K_PHYERR_CCK_RATE_ILLEGAL = 27, | 216 | ATH9K_PHYERR_CCK_RATE_ILLEGAL = 27, |
217 | ATH9K_PHYERR_CCK_LENGTH_ILLEGAL = 28, | ||
218 | ATH9K_PHYERR_CCK_POWER_DROP = 29, | ||
217 | ATH9K_PHYERR_CCK_SERVICE = 30, | 219 | ATH9K_PHYERR_CCK_SERVICE = 30, |
218 | ATH9K_PHYERR_CCK_RESTART = 31, | 220 | ATH9K_PHYERR_CCK_RESTART = 31, |
219 | ATH9K_PHYERR_CCK_LENGTH_ILLEGAL = 32, | ||
220 | ATH9K_PHYERR_CCK_POWER_DROP = 33, | ||
221 | 221 | ||
222 | ATH9K_PHYERR_HT_CRC_ERROR = 34, | 222 | ATH9K_PHYERR_HT_CRC_ERROR = 32, |
223 | ATH9K_PHYERR_HT_LENGTH_ILLEGAL = 35, | 223 | ATH9K_PHYERR_HT_LENGTH_ILLEGAL = 33, |
224 | ATH9K_PHYERR_HT_RATE_ILLEGAL = 36, | 224 | ATH9K_PHYERR_HT_RATE_ILLEGAL = 34, |
225 | ATH9K_PHYERR_HT_ZLF = 35, | ||
226 | |||
227 | ATH9K_PHYERR_FALSE_RADAR_EXT = 36, | ||
228 | ATH9K_PHYERR_GREEN_FIELD = 37, | ||
229 | ATH9K_PHYERR_SPECTRAL = 38, | ||
225 | 230 | ||
226 | ATH9K_PHYERR_SPECTRAL = 38, | ||
227 | ATH9K_PHYERR_MAX = 39, | 231 | ATH9K_PHYERR_MAX = 39, |
228 | }; | 232 | }; |
229 | 233 | ||
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c index 086549b732b9..f8dfa05b290a 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.c +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c | |||
@@ -79,6 +79,7 @@ static int wcn36xx_dxe_allocate_ctl_block(struct wcn36xx_dxe_ch *ch) | |||
79 | struct wcn36xx_dxe_ctl *cur_ctl = NULL; | 79 | struct wcn36xx_dxe_ctl *cur_ctl = NULL; |
80 | int i; | 80 | int i; |
81 | 81 | ||
82 | spin_lock_init(&ch->lock); | ||
82 | for (i = 0; i < ch->desc_num; i++) { | 83 | for (i = 0; i < ch->desc_num; i++) { |
83 | cur_ctl = kzalloc(sizeof(*cur_ctl), GFP_KERNEL); | 84 | cur_ctl = kzalloc(sizeof(*cur_ctl), GFP_KERNEL); |
84 | if (!cur_ctl) | 85 | if (!cur_ctl) |
@@ -169,7 +170,7 @@ void wcn36xx_dxe_free_ctl_blks(struct wcn36xx *wcn) | |||
169 | wcn36xx_dxe_free_ctl_block(&wcn->dxe_rx_h_ch); | 170 | wcn36xx_dxe_free_ctl_block(&wcn->dxe_rx_h_ch); |
170 | } | 171 | } |
171 | 172 | ||
172 | static int wcn36xx_dxe_init_descs(struct wcn36xx_dxe_ch *wcn_ch) | 173 | static int wcn36xx_dxe_init_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn_ch) |
173 | { | 174 | { |
174 | struct wcn36xx_dxe_desc *cur_dxe = NULL; | 175 | struct wcn36xx_dxe_desc *cur_dxe = NULL; |
175 | struct wcn36xx_dxe_desc *prev_dxe = NULL; | 176 | struct wcn36xx_dxe_desc *prev_dxe = NULL; |
@@ -178,7 +179,7 @@ static int wcn36xx_dxe_init_descs(struct wcn36xx_dxe_ch *wcn_ch) | |||
178 | int i; | 179 | int i; |
179 | 180 | ||
180 | size = wcn_ch->desc_num * sizeof(struct wcn36xx_dxe_desc); | 181 | size = wcn_ch->desc_num * sizeof(struct wcn36xx_dxe_desc); |
181 | wcn_ch->cpu_addr = dma_alloc_coherent(NULL, size, &wcn_ch->dma_addr, | 182 | wcn_ch->cpu_addr = dma_alloc_coherent(dev, size, &wcn_ch->dma_addr, |
182 | GFP_KERNEL); | 183 | GFP_KERNEL); |
183 | if (!wcn_ch->cpu_addr) | 184 | if (!wcn_ch->cpu_addr) |
184 | return -ENOMEM; | 185 | return -ENOMEM; |
@@ -270,7 +271,7 @@ static int wcn36xx_dxe_enable_ch_int(struct wcn36xx *wcn, u16 wcn_ch) | |||
270 | return 0; | 271 | return 0; |
271 | } | 272 | } |
272 | 273 | ||
273 | static int wcn36xx_dxe_fill_skb(struct wcn36xx_dxe_ctl *ctl) | 274 | static int wcn36xx_dxe_fill_skb(struct device *dev, struct wcn36xx_dxe_ctl *ctl) |
274 | { | 275 | { |
275 | struct wcn36xx_dxe_desc *dxe = ctl->desc; | 276 | struct wcn36xx_dxe_desc *dxe = ctl->desc; |
276 | struct sk_buff *skb; | 277 | struct sk_buff *skb; |
@@ -279,7 +280,7 @@ static int wcn36xx_dxe_fill_skb(struct wcn36xx_dxe_ctl *ctl) | |||
279 | if (skb == NULL) | 280 | if (skb == NULL) |
280 | return -ENOMEM; | 281 | return -ENOMEM; |
281 | 282 | ||
282 | dxe->dst_addr_l = dma_map_single(NULL, | 283 | dxe->dst_addr_l = dma_map_single(dev, |
283 | skb_tail_pointer(skb), | 284 | skb_tail_pointer(skb), |
284 | WCN36XX_PKT_SIZE, | 285 | WCN36XX_PKT_SIZE, |
285 | DMA_FROM_DEVICE); | 286 | DMA_FROM_DEVICE); |
@@ -297,7 +298,7 @@ static int wcn36xx_dxe_ch_alloc_skb(struct wcn36xx *wcn, | |||
297 | cur_ctl = wcn_ch->head_blk_ctl; | 298 | cur_ctl = wcn_ch->head_blk_ctl; |
298 | 299 | ||
299 | for (i = 0; i < wcn_ch->desc_num; i++) { | 300 | for (i = 0; i < wcn_ch->desc_num; i++) { |
300 | wcn36xx_dxe_fill_skb(cur_ctl); | 301 | wcn36xx_dxe_fill_skb(wcn->dev, cur_ctl); |
301 | cur_ctl = cur_ctl->next; | 302 | cur_ctl = cur_ctl->next; |
302 | } | 303 | } |
303 | 304 | ||
@@ -345,7 +346,7 @@ void wcn36xx_dxe_tx_ack_ind(struct wcn36xx *wcn, u32 status) | |||
345 | 346 | ||
346 | static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch) | 347 | static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch) |
347 | { | 348 | { |
348 | struct wcn36xx_dxe_ctl *ctl = ch->tail_blk_ctl; | 349 | struct wcn36xx_dxe_ctl *ctl; |
349 | struct ieee80211_tx_info *info; | 350 | struct ieee80211_tx_info *info; |
350 | unsigned long flags; | 351 | unsigned long flags; |
351 | 352 | ||
@@ -354,23 +355,25 @@ static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch) | |||
354 | * completely full head and tail are pointing to the same element | 355 | * completely full head and tail are pointing to the same element |
355 | * and while-do will not make any cycles. | 356 | * and while-do will not make any cycles. |
356 | */ | 357 | */ |
358 | spin_lock_irqsave(&ch->lock, flags); | ||
359 | ctl = ch->tail_blk_ctl; | ||
357 | do { | 360 | do { |
358 | if (ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK) | 361 | if (ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK) |
359 | break; | 362 | break; |
360 | if (ctl->skb) { | 363 | if (ctl->skb) { |
361 | dma_unmap_single(NULL, ctl->desc->src_addr_l, | 364 | dma_unmap_single(wcn->dev, ctl->desc->src_addr_l, |
362 | ctl->skb->len, DMA_TO_DEVICE); | 365 | ctl->skb->len, DMA_TO_DEVICE); |
363 | info = IEEE80211_SKB_CB(ctl->skb); | 366 | info = IEEE80211_SKB_CB(ctl->skb); |
364 | if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) { | 367 | if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) { |
365 | /* Keep frame until TX status comes */ | 368 | /* Keep frame until TX status comes */ |
366 | ieee80211_free_txskb(wcn->hw, ctl->skb); | 369 | ieee80211_free_txskb(wcn->hw, ctl->skb); |
367 | } | 370 | } |
368 | spin_lock_irqsave(&ctl->skb_lock, flags); | 371 | spin_lock(&ctl->skb_lock); |
369 | if (wcn->queues_stopped) { | 372 | if (wcn->queues_stopped) { |
370 | wcn->queues_stopped = false; | 373 | wcn->queues_stopped = false; |
371 | ieee80211_wake_queues(wcn->hw); | 374 | ieee80211_wake_queues(wcn->hw); |
372 | } | 375 | } |
373 | spin_unlock_irqrestore(&ctl->skb_lock, flags); | 376 | spin_unlock(&ctl->skb_lock); |
374 | 377 | ||
375 | ctl->skb = NULL; | 378 | ctl->skb = NULL; |
376 | } | 379 | } |
@@ -379,6 +382,7 @@ static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch) | |||
379 | !(ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)); | 382 | !(ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)); |
380 | 383 | ||
381 | ch->tail_blk_ctl = ctl; | 384 | ch->tail_blk_ctl = ctl; |
385 | spin_unlock_irqrestore(&ch->lock, flags); | ||
382 | } | 386 | } |
383 | 387 | ||
384 | static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev) | 388 | static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev) |
@@ -474,7 +478,7 @@ static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn, | |||
474 | while (!(dxe->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)) { | 478 | while (!(dxe->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)) { |
475 | skb = ctl->skb; | 479 | skb = ctl->skb; |
476 | dma_addr = dxe->dst_addr_l; | 480 | dma_addr = dxe->dst_addr_l; |
477 | wcn36xx_dxe_fill_skb(ctl); | 481 | wcn36xx_dxe_fill_skb(wcn->dev, ctl); |
478 | 482 | ||
479 | switch (ch->ch_type) { | 483 | switch (ch->ch_type) { |
480 | case WCN36XX_DXE_CH_RX_L: | 484 | case WCN36XX_DXE_CH_RX_L: |
@@ -491,7 +495,7 @@ static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn, | |||
491 | wcn36xx_warn("Unknown channel\n"); | 495 | wcn36xx_warn("Unknown channel\n"); |
492 | } | 496 | } |
493 | 497 | ||
494 | dma_unmap_single(NULL, dma_addr, WCN36XX_PKT_SIZE, | 498 | dma_unmap_single(wcn->dev, dma_addr, WCN36XX_PKT_SIZE, |
495 | DMA_FROM_DEVICE); | 499 | DMA_FROM_DEVICE); |
496 | wcn36xx_rx_skb(wcn, skb); | 500 | wcn36xx_rx_skb(wcn, skb); |
497 | ctl = ctl->next; | 501 | ctl = ctl->next; |
@@ -540,7 +544,7 @@ int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn) | |||
540 | 16 - (WCN36XX_BD_CHUNK_SIZE % 8); | 544 | 16 - (WCN36XX_BD_CHUNK_SIZE % 8); |
541 | 545 | ||
542 | s = wcn->mgmt_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_H; | 546 | s = wcn->mgmt_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_H; |
543 | cpu_addr = dma_alloc_coherent(NULL, s, &wcn->mgmt_mem_pool.phy_addr, | 547 | cpu_addr = dma_alloc_coherent(wcn->dev, s, &wcn->mgmt_mem_pool.phy_addr, |
544 | GFP_KERNEL); | 548 | GFP_KERNEL); |
545 | if (!cpu_addr) | 549 | if (!cpu_addr) |
546 | goto out_err; | 550 | goto out_err; |
@@ -555,7 +559,7 @@ int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn) | |||
555 | 16 - (WCN36XX_BD_CHUNK_SIZE % 8); | 559 | 16 - (WCN36XX_BD_CHUNK_SIZE % 8); |
556 | 560 | ||
557 | s = wcn->data_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_L; | 561 | s = wcn->data_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_L; |
558 | cpu_addr = dma_alloc_coherent(NULL, s, &wcn->data_mem_pool.phy_addr, | 562 | cpu_addr = dma_alloc_coherent(wcn->dev, s, &wcn->data_mem_pool.phy_addr, |
559 | GFP_KERNEL); | 563 | GFP_KERNEL); |
560 | if (!cpu_addr) | 564 | if (!cpu_addr) |
561 | goto out_err; | 565 | goto out_err; |
@@ -574,13 +578,13 @@ out_err: | |||
574 | void wcn36xx_dxe_free_mem_pools(struct wcn36xx *wcn) | 578 | void wcn36xx_dxe_free_mem_pools(struct wcn36xx *wcn) |
575 | { | 579 | { |
576 | if (wcn->mgmt_mem_pool.virt_addr) | 580 | if (wcn->mgmt_mem_pool.virt_addr) |
577 | dma_free_coherent(NULL, wcn->mgmt_mem_pool.chunk_size * | 581 | dma_free_coherent(wcn->dev, wcn->mgmt_mem_pool.chunk_size * |
578 | WCN36XX_DXE_CH_DESC_NUMB_TX_H, | 582 | WCN36XX_DXE_CH_DESC_NUMB_TX_H, |
579 | wcn->mgmt_mem_pool.virt_addr, | 583 | wcn->mgmt_mem_pool.virt_addr, |
580 | wcn->mgmt_mem_pool.phy_addr); | 584 | wcn->mgmt_mem_pool.phy_addr); |
581 | 585 | ||
582 | if (wcn->data_mem_pool.virt_addr) { | 586 | if (wcn->data_mem_pool.virt_addr) { |
583 | dma_free_coherent(NULL, wcn->data_mem_pool.chunk_size * | 587 | dma_free_coherent(wcn->dev, wcn->data_mem_pool.chunk_size * |
584 | WCN36XX_DXE_CH_DESC_NUMB_TX_L, | 588 | WCN36XX_DXE_CH_DESC_NUMB_TX_L, |
585 | wcn->data_mem_pool.virt_addr, | 589 | wcn->data_mem_pool.virt_addr, |
586 | wcn->data_mem_pool.phy_addr); | 590 | wcn->data_mem_pool.phy_addr); |
@@ -596,12 +600,14 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, | |||
596 | struct wcn36xx_dxe_desc *desc = NULL; | 600 | struct wcn36xx_dxe_desc *desc = NULL; |
597 | struct wcn36xx_dxe_ch *ch = NULL; | 601 | struct wcn36xx_dxe_ch *ch = NULL; |
598 | unsigned long flags; | 602 | unsigned long flags; |
603 | int ret; | ||
599 | 604 | ||
600 | ch = is_low ? &wcn->dxe_tx_l_ch : &wcn->dxe_tx_h_ch; | 605 | ch = is_low ? &wcn->dxe_tx_l_ch : &wcn->dxe_tx_h_ch; |
601 | 606 | ||
607 | spin_lock_irqsave(&ch->lock, flags); | ||
602 | ctl = ch->head_blk_ctl; | 608 | ctl = ch->head_blk_ctl; |
603 | 609 | ||
604 | spin_lock_irqsave(&ctl->next->skb_lock, flags); | 610 | spin_lock(&ctl->next->skb_lock); |
605 | 611 | ||
606 | /* | 612 | /* |
607 | * If skb is not null that means that we reached the tail of the ring | 613 | * 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, | |||
611 | if (NULL != ctl->next->skb) { | 617 | if (NULL != ctl->next->skb) { |
612 | ieee80211_stop_queues(wcn->hw); | 618 | ieee80211_stop_queues(wcn->hw); |
613 | wcn->queues_stopped = true; | 619 | wcn->queues_stopped = true; |
614 | spin_unlock_irqrestore(&ctl->next->skb_lock, flags); | 620 | spin_unlock(&ctl->next->skb_lock); |
621 | spin_unlock_irqrestore(&ch->lock, flags); | ||
615 | return -EBUSY; | 622 | return -EBUSY; |
616 | } | 623 | } |
617 | spin_unlock_irqrestore(&ctl->next->skb_lock, flags); | 624 | spin_unlock(&ctl->next->skb_lock); |
618 | 625 | ||
619 | ctl->skb = NULL; | 626 | ctl->skb = NULL; |
620 | desc = ctl->desc; | 627 | desc = ctl->desc; |
@@ -640,10 +647,11 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, | |||
640 | desc = ctl->desc; | 647 | desc = ctl->desc; |
641 | if (ctl->bd_cpu_addr) { | 648 | if (ctl->bd_cpu_addr) { |
642 | wcn36xx_err("bd_cpu_addr cannot be NULL for skb DXE\n"); | 649 | wcn36xx_err("bd_cpu_addr cannot be NULL for skb DXE\n"); |
643 | return -EINVAL; | 650 | ret = -EINVAL; |
651 | goto unlock; | ||
644 | } | 652 | } |
645 | 653 | ||
646 | desc->src_addr_l = dma_map_single(NULL, | 654 | desc->src_addr_l = dma_map_single(wcn->dev, |
647 | ctl->skb->data, | 655 | ctl->skb->data, |
648 | ctl->skb->len, | 656 | ctl->skb->len, |
649 | DMA_TO_DEVICE); | 657 | DMA_TO_DEVICE); |
@@ -679,7 +687,10 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, | |||
679 | ch->reg_ctrl, ch->def_ctrl); | 687 | ch->reg_ctrl, ch->def_ctrl); |
680 | } | 688 | } |
681 | 689 | ||
682 | return 0; | 690 | ret = 0; |
691 | unlock: | ||
692 | spin_unlock_irqrestore(&ch->lock, flags); | ||
693 | return ret; | ||
683 | } | 694 | } |
684 | 695 | ||
685 | int wcn36xx_dxe_init(struct wcn36xx *wcn) | 696 | int wcn36xx_dxe_init(struct wcn36xx *wcn) |
@@ -696,7 +707,7 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) | |||
696 | /***************************************/ | 707 | /***************************************/ |
697 | /* Init descriptors for TX LOW channel */ | 708 | /* Init descriptors for TX LOW channel */ |
698 | /***************************************/ | 709 | /***************************************/ |
699 | wcn36xx_dxe_init_descs(&wcn->dxe_tx_l_ch); | 710 | wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_l_ch); |
700 | wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_l_ch, &wcn->data_mem_pool); | 711 | wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_l_ch, &wcn->data_mem_pool); |
701 | 712 | ||
702 | /* Write channel head to a NEXT register */ | 713 | /* Write channel head to a NEXT register */ |
@@ -714,7 +725,7 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) | |||
714 | /***************************************/ | 725 | /***************************************/ |
715 | /* Init descriptors for TX HIGH channel */ | 726 | /* Init descriptors for TX HIGH channel */ |
716 | /***************************************/ | 727 | /***************************************/ |
717 | wcn36xx_dxe_init_descs(&wcn->dxe_tx_h_ch); | 728 | wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_tx_h_ch); |
718 | wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_h_ch, &wcn->mgmt_mem_pool); | 729 | wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_h_ch, &wcn->mgmt_mem_pool); |
719 | 730 | ||
720 | /* Write channel head to a NEXT register */ | 731 | /* Write channel head to a NEXT register */ |
@@ -734,7 +745,7 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) | |||
734 | /***************************************/ | 745 | /***************************************/ |
735 | /* Init descriptors for RX LOW channel */ | 746 | /* Init descriptors for RX LOW channel */ |
736 | /***************************************/ | 747 | /***************************************/ |
737 | wcn36xx_dxe_init_descs(&wcn->dxe_rx_l_ch); | 748 | wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_l_ch); |
738 | 749 | ||
739 | /* For RX we need to preallocated buffers */ | 750 | /* For RX we need to preallocated buffers */ |
740 | wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_l_ch); | 751 | wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_l_ch); |
@@ -764,7 +775,7 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) | |||
764 | /***************************************/ | 775 | /***************************************/ |
765 | /* Init descriptors for RX HIGH channel */ | 776 | /* Init descriptors for RX HIGH channel */ |
766 | /***************************************/ | 777 | /***************************************/ |
767 | wcn36xx_dxe_init_descs(&wcn->dxe_rx_h_ch); | 778 | wcn36xx_dxe_init_descs(wcn->dev, &wcn->dxe_rx_h_ch); |
768 | 779 | ||
769 | /* For RX we need to prealocat buffers */ | 780 | /* For RX we need to prealocat buffers */ |
770 | wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_h_ch); | 781 | wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_h_ch); |
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.h b/drivers/net/wireless/ath/wcn36xx/dxe.h index 35ee7e966bd2..3eca4f9594f2 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.h +++ b/drivers/net/wireless/ath/wcn36xx/dxe.h | |||
@@ -243,6 +243,7 @@ struct wcn36xx_dxe_ctl { | |||
243 | }; | 243 | }; |
244 | 244 | ||
245 | struct wcn36xx_dxe_ch { | 245 | struct wcn36xx_dxe_ch { |
246 | spinlock_t lock; /* protects head/tail ptrs */ | ||
246 | enum wcn36xx_dxe_ch_type ch_type; | 247 | enum wcn36xx_dxe_ch_type ch_type; |
247 | void *cpu_addr; | 248 | void *cpu_addr; |
248 | dma_addr_t dma_addr; | 249 | dma_addr_t dma_addr; |
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index 06fc46f85c85..50c136e843c4 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c | |||
@@ -236,7 +236,7 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie) | |||
236 | 236 | ||
237 | isr &= ~(BIT_DMA_EP_RX_ICR_RX_DONE | | 237 | isr &= ~(BIT_DMA_EP_RX_ICR_RX_DONE | |
238 | BIT_DMA_EP_RX_ICR_RX_HTRSH); | 238 | BIT_DMA_EP_RX_ICR_RX_HTRSH); |
239 | if (likely(test_bit(wil_status_reset_done, wil->status))) { | 239 | if (likely(test_bit(wil_status_fwready, wil->status))) { |
240 | if (likely(test_bit(wil_status_napi_en, wil->status))) { | 240 | if (likely(test_bit(wil_status_napi_en, wil->status))) { |
241 | wil_dbg_txrx(wil, "NAPI(Rx) schedule\n"); | 241 | wil_dbg_txrx(wil, "NAPI(Rx) schedule\n"); |
242 | need_unmask = false; | 242 | need_unmask = false; |
@@ -286,7 +286,7 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie) | |||
286 | isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE; | 286 | isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE; |
287 | /* clear also all VRING interrupts */ | 287 | /* clear also all VRING interrupts */ |
288 | isr &= ~(BIT(25) - 1UL); | 288 | isr &= ~(BIT(25) - 1UL); |
289 | if (likely(test_bit(wil_status_reset_done, wil->status))) { | 289 | if (likely(test_bit(wil_status_fwready, wil->status))) { |
290 | wil_dbg_txrx(wil, "NAPI(Tx) schedule\n"); | 290 | wil_dbg_txrx(wil, "NAPI(Tx) schedule\n"); |
291 | need_unmask = false; | 291 | need_unmask = false; |
292 | napi_schedule(&wil->napi_tx); | 292 | napi_schedule(&wil->napi_tx); |
@@ -364,7 +364,7 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) | |||
364 | if (isr & ISR_MISC_FW_READY) { | 364 | if (isr & ISR_MISC_FW_READY) { |
365 | wil_dbg_irq(wil, "IRQ: FW ready\n"); | 365 | wil_dbg_irq(wil, "IRQ: FW ready\n"); |
366 | wil_cache_mbox_regs(wil); | 366 | wil_cache_mbox_regs(wil); |
367 | set_bit(wil_status_reset_done, wil->status); | 367 | set_bit(wil_status_mbox_ready, wil->status); |
368 | /** | 368 | /** |
369 | * Actual FW ready indicated by the | 369 | * Actual FW ready indicated by the |
370 | * WMI_FW_READY_EVENTID | 370 | * WMI_FW_READY_EVENTID |
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index aade16b126c4..bb69a5949aea 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c | |||
@@ -422,7 +422,7 @@ static void wil_connect_worker(struct work_struct *work) | |||
422 | wil->sta[cid].status = wil_sta_connected; | 422 | wil->sta[cid].status = wil_sta_connected; |
423 | netif_tx_wake_all_queues(ndev); | 423 | netif_tx_wake_all_queues(ndev); |
424 | } else { | 424 | } else { |
425 | wil->sta[cid].status = wil_sta_unused; | 425 | wil_disconnect_cid(wil, cid, WLAN_REASON_UNSPECIFIED, true); |
426 | } | 426 | } |
427 | } | 427 | } |
428 | 428 | ||
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 0f8b6877497e..3bc9bc0efbac 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c | |||
@@ -1242,6 +1242,7 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring, | |||
1242 | int tcp_hdr_len; | 1242 | int tcp_hdr_len; |
1243 | int skb_net_hdr_len; | 1243 | int skb_net_hdr_len; |
1244 | int gso_type; | 1244 | int gso_type; |
1245 | int rc = -EINVAL; | ||
1245 | 1246 | ||
1246 | wil_dbg_txrx(wil, "%s() %d bytes to vring %d\n", | 1247 | wil_dbg_txrx(wil, "%s() %d bytes to vring %d\n", |
1247 | __func__, skb->len, vring_index); | 1248 | __func__, skb->len, vring_index); |
@@ -1333,8 +1334,9 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring, | |||
1333 | len, rem_data, descs_used); | 1334 | len, rem_data, descs_used); |
1334 | 1335 | ||
1335 | if (descs_used == avail) { | 1336 | if (descs_used == avail) { |
1336 | wil_err(wil, "TSO: ring overflow\n"); | 1337 | wil_err_ratelimited(wil, "TSO: ring overflow\n"); |
1337 | goto dma_error; | 1338 | rc = -ENOMEM; |
1339 | goto mem_error; | ||
1338 | } | 1340 | } |
1339 | 1341 | ||
1340 | lenmss = min_t(int, rem_data, len); | 1342 | lenmss = min_t(int, rem_data, len); |
@@ -1356,8 +1358,10 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring, | |||
1356 | headlen -= lenmss; | 1358 | headlen -= lenmss; |
1357 | } | 1359 | } |
1358 | 1360 | ||
1359 | if (unlikely(dma_mapping_error(dev, pa))) | 1361 | if (unlikely(dma_mapping_error(dev, pa))) { |
1360 | goto dma_error; | 1362 | wil_err(wil, "TSO: DMA map page error\n"); |
1363 | goto mem_error; | ||
1364 | } | ||
1361 | 1365 | ||
1362 | _desc = &vring->va[i].tx; | 1366 | _desc = &vring->va[i].tx; |
1363 | 1367 | ||
@@ -1456,8 +1460,8 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring, | |||
1456 | } | 1460 | } |
1457 | 1461 | ||
1458 | /* advance swhead */ | 1462 | /* advance swhead */ |
1459 | wil_dbg_txrx(wil, "TSO: Tx swhead %d -> %d\n", swhead, vring->swhead); | ||
1460 | wil_vring_advance_head(vring, descs_used); | 1463 | wil_vring_advance_head(vring, descs_used); |
1464 | wil_dbg_txrx(wil, "TSO: Tx swhead %d -> %d\n", swhead, vring->swhead); | ||
1461 | 1465 | ||
1462 | /* make sure all writes to descriptors (shared memory) are done before | 1466 | /* make sure all writes to descriptors (shared memory) are done before |
1463 | * committing them to HW | 1467 | * committing them to HW |
@@ -1467,8 +1471,7 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring, | |||
1467 | wil_w(wil, vring->hwtail, vring->swhead); | 1471 | wil_w(wil, vring->hwtail, vring->swhead); |
1468 | return 0; | 1472 | return 0; |
1469 | 1473 | ||
1470 | dma_error: | 1474 | mem_error: |
1471 | wil_err(wil, "TSO: DMA map page error\n"); | ||
1472 | while (descs_used > 0) { | 1475 | while (descs_used > 0) { |
1473 | struct wil_ctx *ctx; | 1476 | struct wil_ctx *ctx; |
1474 | 1477 | ||
@@ -1479,14 +1482,11 @@ dma_error: | |||
1479 | _desc->dma.status = TX_DMA_STATUS_DU; | 1482 | _desc->dma.status = TX_DMA_STATUS_DU; |
1480 | ctx = &vring->ctx[i]; | 1483 | ctx = &vring->ctx[i]; |
1481 | wil_txdesc_unmap(dev, d, ctx); | 1484 | wil_txdesc_unmap(dev, d, ctx); |
1482 | if (ctx->skb) | ||
1483 | dev_kfree_skb_any(ctx->skb); | ||
1484 | memset(ctx, 0, sizeof(*ctx)); | 1485 | memset(ctx, 0, sizeof(*ctx)); |
1485 | descs_used--; | 1486 | descs_used--; |
1486 | } | 1487 | } |
1487 | |||
1488 | err_exit: | 1488 | err_exit: |
1489 | return -EINVAL; | 1489 | return rc; |
1490 | } | 1490 | } |
1491 | 1491 | ||
1492 | static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | 1492 | 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, | |||
1562 | _d = &vring->va[i].tx; | 1562 | _d = &vring->va[i].tx; |
1563 | pa = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag), | 1563 | pa = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag), |
1564 | DMA_TO_DEVICE); | 1564 | DMA_TO_DEVICE); |
1565 | if (unlikely(dma_mapping_error(dev, pa))) | 1565 | if (unlikely(dma_mapping_error(dev, pa))) { |
1566 | wil_err(wil, "Tx[%2d] failed to map fragment\n", | ||
1567 | vring_index); | ||
1566 | goto dma_error; | 1568 | goto dma_error; |
1569 | } | ||
1567 | vring->ctx[i].mapped_as = wil_mapped_as_page; | 1570 | vring->ctx[i].mapped_as = wil_mapped_as_page; |
1568 | wil_tx_desc_map(d, pa, len, vring_index); | 1571 | wil_tx_desc_map(d, pa, len, vring_index); |
1569 | /* no need to check return code - | 1572 | /* no need to check return code - |
@@ -1623,9 +1626,6 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | |||
1623 | _d->dma.status = TX_DMA_STATUS_DU; | 1626 | _d->dma.status = TX_DMA_STATUS_DU; |
1624 | wil_txdesc_unmap(dev, d, ctx); | 1627 | wil_txdesc_unmap(dev, d, ctx); |
1625 | 1628 | ||
1626 | if (ctx->skb) | ||
1627 | dev_kfree_skb_any(ctx->skb); | ||
1628 | |||
1629 | memset(ctx, 0, sizeof(*ctx)); | 1629 | memset(ctx, 0, sizeof(*ctx)); |
1630 | } | 1630 | } |
1631 | 1631 | ||
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index f619bf234353..ade5f3b8274b 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h | |||
@@ -402,11 +402,11 @@ struct vring_tx_data { | |||
402 | }; | 402 | }; |
403 | 403 | ||
404 | enum { /* for wil6210_priv.status */ | 404 | enum { /* for wil6210_priv.status */ |
405 | wil_status_fwready = 0, | 405 | wil_status_fwready = 0, /* FW operational */ |
406 | wil_status_fwconnecting, | 406 | wil_status_fwconnecting, |
407 | wil_status_fwconnected, | 407 | wil_status_fwconnected, |
408 | wil_status_dontscan, | 408 | wil_status_dontscan, |
409 | wil_status_reset_done, | 409 | wil_status_mbox_ready, /* MBOX structures ready */ |
410 | wil_status_irqen, /* FIXME: interrupts enabled - for debug */ | 410 | wil_status_irqen, /* FIXME: interrupts enabled - for debug */ |
411 | wil_status_napi_en, /* NAPI enabled protected by wil->mutex */ | 411 | wil_status_napi_en, /* NAPI enabled protected by wil->mutex */ |
412 | wil_status_resetting, /* reset in progress */ | 412 | wil_status_resetting, /* reset in progress */ |
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 61121892c6ca..6ed26baca0e5 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c | |||
@@ -293,12 +293,6 @@ static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len) | |||
293 | /* ignore MAC address, we already have it from the boot loader */ | 293 | /* ignore MAC address, we already have it from the boot loader */ |
294 | snprintf(wdev->wiphy->fw_version, sizeof(wdev->wiphy->fw_version), | 294 | snprintf(wdev->wiphy->fw_version, sizeof(wdev->wiphy->fw_version), |
295 | "%d", wil->fw_version); | 295 | "%d", wil->fw_version); |
296 | } | ||
297 | |||
298 | static void wmi_evt_fw_ready(struct wil6210_priv *wil, int id, void *d, | ||
299 | int len) | ||
300 | { | ||
301 | wil_dbg_wmi(wil, "WMI: got FW ready event\n"); | ||
302 | 296 | ||
303 | wil_set_recovery_state(wil, fw_recovery_idle); | 297 | wil_set_recovery_state(wil, fw_recovery_idle); |
304 | set_bit(wil_status_fwready, wil->status); | 298 | set_bit(wil_status_fwready, wil->status); |
@@ -684,13 +678,22 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) | |||
684 | spin_unlock_bh(&sta->tid_rx_lock); | 678 | spin_unlock_bh(&sta->tid_rx_lock); |
685 | } | 679 | } |
686 | 680 | ||
681 | /** | ||
682 | * Some events are ignored for purpose; and need not be interpreted as | ||
683 | * "unhandled events" | ||
684 | */ | ||
685 | static void wmi_evt_ignore(struct wil6210_priv *wil, int id, void *d, int len) | ||
686 | { | ||
687 | wil_dbg_wmi(wil, "Ignore event 0x%04x len %d\n", id, len); | ||
688 | } | ||
689 | |||
687 | static const struct { | 690 | static const struct { |
688 | int eventid; | 691 | int eventid; |
689 | void (*handler)(struct wil6210_priv *wil, int eventid, | 692 | void (*handler)(struct wil6210_priv *wil, int eventid, |
690 | void *data, int data_len); | 693 | void *data, int data_len); |
691 | } wmi_evt_handlers[] = { | 694 | } wmi_evt_handlers[] = { |
692 | {WMI_READY_EVENTID, wmi_evt_ready}, | 695 | {WMI_READY_EVENTID, wmi_evt_ready}, |
693 | {WMI_FW_READY_EVENTID, wmi_evt_fw_ready}, | 696 | {WMI_FW_READY_EVENTID, wmi_evt_ignore}, |
694 | {WMI_RX_MGMT_PACKET_EVENTID, wmi_evt_rx_mgmt}, | 697 | {WMI_RX_MGMT_PACKET_EVENTID, wmi_evt_rx_mgmt}, |
695 | {WMI_TX_MGMT_PACKET_EVENTID, wmi_evt_tx_mgmt}, | 698 | {WMI_TX_MGMT_PACKET_EVENTID, wmi_evt_tx_mgmt}, |
696 | {WMI_SCAN_COMPLETE_EVENTID, wmi_evt_scan_complete}, | 699 | {WMI_SCAN_COMPLETE_EVENTID, wmi_evt_scan_complete}, |
@@ -701,6 +704,7 @@ static const struct { | |||
701 | {WMI_RCP_ADDBA_REQ_EVENTID, wmi_evt_addba_rx_req}, | 704 | {WMI_RCP_ADDBA_REQ_EVENTID, wmi_evt_addba_rx_req}, |
702 | {WMI_DELBA_EVENTID, wmi_evt_delba}, | 705 | {WMI_DELBA_EVENTID, wmi_evt_delba}, |
703 | {WMI_VRING_EN_EVENTID, wmi_evt_vring_en}, | 706 | {WMI_VRING_EN_EVENTID, wmi_evt_vring_en}, |
707 | {WMI_DATA_PORT_OPEN_EVENTID, wmi_evt_ignore}, | ||
704 | }; | 708 | }; |
705 | 709 | ||
706 | /* | 710 | /* |
@@ -720,7 +724,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil) | |||
720 | ulong flags; | 724 | ulong flags; |
721 | unsigned n; | 725 | unsigned n; |
722 | 726 | ||
723 | if (!test_bit(wil_status_reset_done, wil->status)) { | 727 | if (!test_bit(wil_status_mbox_ready, wil->status)) { |
724 | wil_err(wil, "Reset in progress. Cannot handle WMI event\n"); | 728 | wil_err(wil, "Reset in progress. Cannot handle WMI event\n"); |
725 | return; | 729 | return; |
726 | } | 730 | } |
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 759fb8d41fc9..fba856032ca5 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig | |||
@@ -71,26 +71,6 @@ config B43_PCICORE_AUTOSELECT | |||
71 | select SSB_DRIVER_PCICORE | 71 | select SSB_DRIVER_PCICORE |
72 | default y | 72 | default y |
73 | 73 | ||
74 | config B43_PCMCIA | ||
75 | bool "Broadcom 43xx PCMCIA device support" | ||
76 | depends on B43 && B43_SSB && SSB_PCMCIAHOST_POSSIBLE | ||
77 | select SSB_PCMCIAHOST | ||
78 | ---help--- | ||
79 | Broadcom 43xx PCMCIA device support. | ||
80 | |||
81 | Support for 16bit PCMCIA devices. | ||
82 | Please note that most PC-CARD devices are _NOT_ 16bit PCMCIA | ||
83 | devices, but 32bit CardBUS devices. CardBUS devices are supported | ||
84 | out of the box by b43. | ||
85 | |||
86 | With this config option you can drive b43 cards in | ||
87 | CompactFlash formfactor in a PCMCIA adaptor. | ||
88 | CF b43 cards can sometimes be found in handheld PCs. | ||
89 | |||
90 | It's safe to select Y here, even if you don't have a B43 PCMCIA device. | ||
91 | |||
92 | If unsure, say N. | ||
93 | |||
94 | config B43_SDIO | 74 | config B43_SDIO |
95 | bool "Broadcom 43xx SDIO device support" | 75 | bool "Broadcom 43xx SDIO device support" |
96 | depends on B43 && B43_SSB && SSB_SDIOHOST_POSSIBLE | 76 | depends on B43 && B43_SSB && SSB_SDIOHOST_POSSIBLE |
diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile index c624d4d90e4f..ddc4df46656f 100644 --- a/drivers/net/wireless/b43/Makefile +++ b/drivers/net/wireless/b43/Makefile | |||
@@ -21,7 +21,6 @@ b43-y += pio.o | |||
21 | b43-y += rfkill.o | 21 | b43-y += rfkill.o |
22 | b43-y += ppr.o | 22 | b43-y += ppr.o |
23 | b43-$(CONFIG_B43_LEDS) += leds.o | 23 | b43-$(CONFIG_B43_LEDS) += leds.o |
24 | b43-$(CONFIG_B43_PCMCIA) += pcmcia.o | ||
25 | b43-$(CONFIG_B43_SDIO) += sdio.o | 24 | b43-$(CONFIG_B43_SDIO) += sdio.o |
26 | b43-$(CONFIG_B43_DEBUG) += debugfs.o | 25 | b43-$(CONFIG_B43_DEBUG) += debugfs.o |
27 | 26 | ||
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 71d3e9adbf3c..ec013fbd6a81 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -56,7 +56,6 @@ | |||
56 | #include "sysfs.h" | 56 | #include "sysfs.h" |
57 | #include "xmit.h" | 57 | #include "xmit.h" |
58 | #include "lo.h" | 58 | #include "lo.h" |
59 | #include "pcmcia.h" | ||
60 | #include "sdio.h" | 59 | #include "sdio.h" |
61 | #include <linux/mmc/sdio_func.h> | 60 | #include <linux/mmc/sdio_func.h> |
62 | 61 | ||
@@ -5850,12 +5849,9 @@ static int __init b43_init(void) | |||
5850 | int err; | 5849 | int err; |
5851 | 5850 | ||
5852 | b43_debugfs_init(); | 5851 | b43_debugfs_init(); |
5853 | err = b43_pcmcia_init(); | ||
5854 | if (err) | ||
5855 | goto err_dfs_exit; | ||
5856 | err = b43_sdio_init(); | 5852 | err = b43_sdio_init(); |
5857 | if (err) | 5853 | if (err) |
5858 | goto err_pcmcia_exit; | 5854 | goto err_dfs_exit; |
5859 | #ifdef CONFIG_B43_BCMA | 5855 | #ifdef CONFIG_B43_BCMA |
5860 | err = bcma_driver_register(&b43_bcma_driver); | 5856 | err = bcma_driver_register(&b43_bcma_driver); |
5861 | if (err) | 5857 | if (err) |
@@ -5878,8 +5874,6 @@ err_bcma_driver_exit: | |||
5878 | err_sdio_exit: | 5874 | err_sdio_exit: |
5879 | #endif | 5875 | #endif |
5880 | b43_sdio_exit(); | 5876 | b43_sdio_exit(); |
5881 | err_pcmcia_exit: | ||
5882 | b43_pcmcia_exit(); | ||
5883 | err_dfs_exit: | 5877 | err_dfs_exit: |
5884 | b43_debugfs_exit(); | 5878 | b43_debugfs_exit(); |
5885 | return err; | 5879 | return err; |
@@ -5894,7 +5888,6 @@ static void __exit b43_exit(void) | |||
5894 | bcma_driver_unregister(&b43_bcma_driver); | 5888 | bcma_driver_unregister(&b43_bcma_driver); |
5895 | #endif | 5889 | #endif |
5896 | b43_sdio_exit(); | 5890 | b43_sdio_exit(); |
5897 | b43_pcmcia_exit(); | ||
5898 | b43_debugfs_exit(); | 5891 | b43_debugfs_exit(); |
5899 | } | 5892 | } |
5900 | 5893 | ||
diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c deleted file mode 100644 index 55f2bd7f8f74..000000000000 --- a/drivers/net/wireless/b43/pcmcia.c +++ /dev/null | |||
@@ -1,145 +0,0 @@ | |||
1 | /* | ||
2 | |||
3 | Broadcom B43 wireless driver | ||
4 | |||
5 | Copyright (c) 2007 Michael Buesch <m@bues.ch> | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation; either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; see the file COPYING. If not, write to | ||
19 | the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, | ||
20 | Boston, MA 02110-1301, USA. | ||
21 | |||
22 | */ | ||
23 | |||
24 | #include "pcmcia.h" | ||
25 | |||
26 | #include <linux/ssb/ssb.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/module.h> | ||
29 | |||
30 | #include <pcmcia/cistpl.h> | ||
31 | #include <pcmcia/ciscode.h> | ||
32 | #include <pcmcia/ds.h> | ||
33 | #include <pcmcia/cisreg.h> | ||
34 | |||
35 | |||
36 | static const struct pcmcia_device_id b43_pcmcia_tbl[] = { | ||
37 | PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448), | ||
38 | PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476), | ||
39 | PCMCIA_DEVICE_NULL, | ||
40 | }; | ||
41 | |||
42 | MODULE_DEVICE_TABLE(pcmcia, b43_pcmcia_tbl); | ||
43 | |||
44 | #ifdef CONFIG_PM | ||
45 | static int b43_pcmcia_suspend(struct pcmcia_device *dev) | ||
46 | { | ||
47 | struct ssb_bus *ssb = dev->priv; | ||
48 | |||
49 | return ssb_bus_suspend(ssb); | ||
50 | } | ||
51 | |||
52 | static int b43_pcmcia_resume(struct pcmcia_device *dev) | ||
53 | { | ||
54 | struct ssb_bus *ssb = dev->priv; | ||
55 | |||
56 | return ssb_bus_resume(ssb); | ||
57 | } | ||
58 | #else /* CONFIG_PM */ | ||
59 | # define b43_pcmcia_suspend NULL | ||
60 | # define b43_pcmcia_resume NULL | ||
61 | #endif /* CONFIG_PM */ | ||
62 | |||
63 | static int b43_pcmcia_probe(struct pcmcia_device *dev) | ||
64 | { | ||
65 | struct ssb_bus *ssb; | ||
66 | int err = -ENOMEM; | ||
67 | int res = 0; | ||
68 | |||
69 | ssb = kzalloc(sizeof(*ssb), GFP_KERNEL); | ||
70 | if (!ssb) | ||
71 | goto out_error; | ||
72 | |||
73 | err = -ENODEV; | ||
74 | |||
75 | dev->config_flags |= CONF_ENABLE_IRQ; | ||
76 | |||
77 | dev->resource[2]->flags |= WIN_ENABLE | WIN_DATA_WIDTH_16 | | ||
78 | WIN_USE_WAIT; | ||
79 | dev->resource[2]->start = 0; | ||
80 | dev->resource[2]->end = SSB_CORE_SIZE; | ||
81 | res = pcmcia_request_window(dev, dev->resource[2], 250); | ||
82 | if (res != 0) | ||
83 | goto err_kfree_ssb; | ||
84 | |||
85 | res = pcmcia_map_mem_page(dev, dev->resource[2], 0); | ||
86 | if (res != 0) | ||
87 | goto err_disable; | ||
88 | |||
89 | if (!dev->irq) | ||
90 | goto err_disable; | ||
91 | |||
92 | res = pcmcia_enable_device(dev); | ||
93 | if (res != 0) | ||
94 | goto err_disable; | ||
95 | |||
96 | err = ssb_bus_pcmciabus_register(ssb, dev, dev->resource[2]->start); | ||
97 | if (err) | ||
98 | goto err_disable; | ||
99 | dev->priv = ssb; | ||
100 | |||
101 | return 0; | ||
102 | |||
103 | err_disable: | ||
104 | pcmcia_disable_device(dev); | ||
105 | err_kfree_ssb: | ||
106 | kfree(ssb); | ||
107 | out_error: | ||
108 | printk(KERN_ERR "b43-pcmcia: Initialization failed (%d, %d)\n", | ||
109 | res, err); | ||
110 | return err; | ||
111 | } | ||
112 | |||
113 | static void b43_pcmcia_remove(struct pcmcia_device *dev) | ||
114 | { | ||
115 | struct ssb_bus *ssb = dev->priv; | ||
116 | |||
117 | ssb_bus_unregister(ssb); | ||
118 | pcmcia_disable_device(dev); | ||
119 | kfree(ssb); | ||
120 | dev->priv = NULL; | ||
121 | } | ||
122 | |||
123 | static struct pcmcia_driver b43_pcmcia_driver = { | ||
124 | .owner = THIS_MODULE, | ||
125 | .name = "b43-pcmcia", | ||
126 | .id_table = b43_pcmcia_tbl, | ||
127 | .probe = b43_pcmcia_probe, | ||
128 | .remove = b43_pcmcia_remove, | ||
129 | .suspend = b43_pcmcia_suspend, | ||
130 | .resume = b43_pcmcia_resume, | ||
131 | }; | ||
132 | |||
133 | /* | ||
134 | * These are not module init/exit functions! | ||
135 | * The module_pcmcia_driver() helper cannot be used here. | ||
136 | */ | ||
137 | int b43_pcmcia_init(void) | ||
138 | { | ||
139 | return pcmcia_register_driver(&b43_pcmcia_driver); | ||
140 | } | ||
141 | |||
142 | void b43_pcmcia_exit(void) | ||
143 | { | ||
144 | pcmcia_unregister_driver(&b43_pcmcia_driver); | ||
145 | } | ||
diff --git a/drivers/net/wireless/b43/pcmcia.h b/drivers/net/wireless/b43/pcmcia.h deleted file mode 100644 index 85f120a67cbe..000000000000 --- a/drivers/net/wireless/b43/pcmcia.h +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | #ifndef B43_PCMCIA_H_ | ||
2 | #define B43_PCMCIA_H_ | ||
3 | |||
4 | #ifdef CONFIG_B43_PCMCIA | ||
5 | |||
6 | int b43_pcmcia_init(void); | ||
7 | void b43_pcmcia_exit(void); | ||
8 | |||
9 | #else /* CONFIG_B43_PCMCIA */ | ||
10 | |||
11 | static inline int b43_pcmcia_init(void) | ||
12 | { | ||
13 | return 0; | ||
14 | } | ||
15 | static inline void b43_pcmcia_exit(void) | ||
16 | { | ||
17 | } | ||
18 | |||
19 | #endif /* CONFIG_B43_PCMCIA */ | ||
20 | #endif /* B43_PCMCIA_H_ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h index af5b3201492c..9dbe19cbb4dd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h | |||
@@ -86,6 +86,8 @@ | |||
86 | * Structured as &struct iwl_fw_error_dump_trigger_desc. | 86 | * Structured as &struct iwl_fw_error_dump_trigger_desc. |
87 | * @IWL_FW_ERROR_DUMP_RB: the content of an RB structured as | 87 | * @IWL_FW_ERROR_DUMP_RB: the content of an RB structured as |
88 | * &struct iwl_fw_error_dump_rb | 88 | * &struct iwl_fw_error_dump_rb |
89 | * @IWL_FW_ERROR_PAGING: UMAC's image memory segments which were | ||
90 | * paged to the DRAM. | ||
89 | */ | 91 | */ |
90 | enum iwl_fw_error_dump_type { | 92 | enum iwl_fw_error_dump_type { |
91 | /* 0 is deprecated */ | 93 | /* 0 is deprecated */ |
@@ -100,6 +102,7 @@ enum iwl_fw_error_dump_type { | |||
100 | IWL_FW_ERROR_DUMP_MEM = 9, | 102 | IWL_FW_ERROR_DUMP_MEM = 9, |
101 | IWL_FW_ERROR_DUMP_ERROR_INFO = 10, | 103 | IWL_FW_ERROR_DUMP_ERROR_INFO = 10, |
102 | IWL_FW_ERROR_DUMP_RB = 11, | 104 | IWL_FW_ERROR_DUMP_RB = 11, |
105 | IWL_FW_ERROR_DUMP_PAGING = 12, | ||
103 | 106 | ||
104 | IWL_FW_ERROR_DUMP_MAX, | 107 | IWL_FW_ERROR_DUMP_MAX, |
105 | }; | 108 | }; |
@@ -240,6 +243,19 @@ struct iwl_fw_error_dump_rb { | |||
240 | }; | 243 | }; |
241 | 244 | ||
242 | /** | 245 | /** |
246 | * struct iwl_fw_error_dump_paging - content of the UMAC's image page | ||
247 | * block on DRAM | ||
248 | * @index: the index of the page block | ||
249 | * @reserved: | ||
250 | * @data: the content of the page block | ||
251 | */ | ||
252 | struct iwl_fw_error_dump_paging { | ||
253 | __le32 index; | ||
254 | __le32 reserved; | ||
255 | u8 data[]; | ||
256 | }; | ||
257 | |||
258 | /** | ||
243 | * iwl_fw_error_next_data - advance fw error dump data pointer | 259 | * iwl_fw_error_next_data - advance fw error dump data pointer |
244 | * @data: previous data block | 260 | * @data: previous data block |
245 | * Returns: next data block | 261 | * Returns: next data block |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h index 72ddd4a163e6..08303db0000f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h | |||
@@ -306,6 +306,8 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t; | |||
306 | * is supported. | 306 | * is supported. |
307 | * @IWL_UCODE_TLV_CAPA_BT_COEX_RRC: supports BT Coex RRC | 307 | * @IWL_UCODE_TLV_CAPA_BT_COEX_RRC: supports BT Coex RRC |
308 | * @IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT: supports gscan | 308 | * @IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT: supports gscan |
309 | * @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement | ||
310 | * @IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS: supports short PM timeouts | ||
309 | * | 311 | * |
310 | * @NUM_IWL_UCODE_TLV_CAPA: number of bits used | 312 | * @NUM_IWL_UCODE_TLV_CAPA: number of bits used |
311 | */ | 313 | */ |
@@ -330,6 +332,8 @@ enum iwl_ucode_tlv_capa { | |||
330 | IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC = (__force iwl_ucode_tlv_capa_t)29, | 332 | IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC = (__force iwl_ucode_tlv_capa_t)29, |
331 | IWL_UCODE_TLV_CAPA_BT_COEX_RRC = (__force iwl_ucode_tlv_capa_t)30, | 333 | IWL_UCODE_TLV_CAPA_BT_COEX_RRC = (__force iwl_ucode_tlv_capa_t)30, |
332 | IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)31, | 334 | IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)31, |
335 | IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64, | ||
336 | IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65, | ||
333 | 337 | ||
334 | NUM_IWL_UCODE_TLV_CAPA | 338 | NUM_IWL_UCODE_TLV_CAPA |
335 | #ifdef __CHECKER__ | 339 | #ifdef __CHECKER__ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index bb51b6f8002c..6f76525088f0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -409,6 +409,7 @@ enum iwl_d3_status { | |||
409 | * @STATUS_TRANS_GOING_IDLE: shutting down the trans, only special commands | 409 | * @STATUS_TRANS_GOING_IDLE: shutting down the trans, only special commands |
410 | * are sent | 410 | * are sent |
411 | * @STATUS_TRANS_IDLE: the trans is idle - general commands are not to be sent | 411 | * @STATUS_TRANS_IDLE: the trans is idle - general commands are not to be sent |
412 | * @STATUS_TRANS_DEAD: trans is dead - avoid any read/write operation | ||
412 | */ | 413 | */ |
413 | enum iwl_trans_status { | 414 | enum iwl_trans_status { |
414 | STATUS_SYNC_HCMD_ACTIVE, | 415 | STATUS_SYNC_HCMD_ACTIVE, |
@@ -419,6 +420,7 @@ enum iwl_trans_status { | |||
419 | STATUS_FW_ERROR, | 420 | STATUS_FW_ERROR, |
420 | STATUS_TRANS_GOING_IDLE, | 421 | STATUS_TRANS_GOING_IDLE, |
421 | STATUS_TRANS_IDLE, | 422 | STATUS_TRANS_IDLE, |
423 | STATUS_TRANS_DEAD, | ||
422 | }; | 424 | }; |
423 | 425 | ||
424 | /** | 426 | /** |
diff --git a/drivers/net/wireless/iwlwifi/mvm/constants.h b/drivers/net/wireless/iwlwifi/mvm/constants.h index a3ca6db0f303..5c21231e195d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/iwlwifi/mvm/constants.h | |||
@@ -71,6 +71,9 @@ | |||
71 | #define IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT (100 * USEC_PER_MSEC) | 71 | #define IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT (100 * USEC_PER_MSEC) |
72 | #define IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT (10 * USEC_PER_MSEC) | 72 | #define IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT (10 * USEC_PER_MSEC) |
73 | #define IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT (10 * USEC_PER_MSEC) | 73 | #define IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT (10 * USEC_PER_MSEC) |
74 | #define IWL_MVM_SHORT_PS_TX_DATA_TIMEOUT (2 * 1024) /* defined in TU */ | ||
75 | #define IWL_MVM_SHORT_PS_RX_DATA_TIMEOUT (40 * 1024) /* defined in TU */ | ||
76 | #define IWL_MVM_P2P_LOWLATENCY_PS_ENABLE 0 | ||
74 | #define IWL_MVM_UAPSD_RX_DATA_TIMEOUT (50 * USEC_PER_MSEC) | 77 | #define IWL_MVM_UAPSD_RX_DATA_TIMEOUT (50 * USEC_PER_MSEC) |
75 | #define IWL_MVM_UAPSD_TX_DATA_TIMEOUT (50 * USEC_PER_MSEC) | 78 | #define IWL_MVM_UAPSD_TX_DATA_TIMEOUT (50 * USEC_PER_MSEC) |
76 | #define IWL_MVM_UAPSD_QUEUES (IEEE80211_WMM_IE_STA_QOSINFO_AC_VO |\ | 79 | #define IWL_MVM_UAPSD_QUEUES (IEEE80211_WMM_IE_STA_QOSINFO_AC_VO |\ |
@@ -101,7 +104,6 @@ | |||
101 | #define IWL_MVM_FW_BCAST_FILTER_PASS_ALL 0 | 104 | #define IWL_MVM_FW_BCAST_FILTER_PASS_ALL 0 |
102 | #define IWL_MVM_QUOTA_THRESHOLD 4 | 105 | #define IWL_MVM_QUOTA_THRESHOLD 4 |
103 | #define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0 | 106 | #define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0 |
104 | #define IWL_MVM_RS_DISABLE_P2P_MIMO 0 | ||
105 | #define IWL_MVM_RS_80_20_FAR_RANGE_TWEAK 1 | 107 | #define IWL_MVM_RS_80_20_FAR_RANGE_TWEAK 1 |
106 | #define IWL_MVM_TOF_IS_RESPONDER 0 | 108 | #define IWL_MVM_TOF_IS_RESPONDER 0 |
107 | #define IWL_MVM_RS_NUM_TRY_BEFORE_ANT_TOGGLE 1 | 109 | #define IWL_MVM_RS_NUM_TRY_BEFORE_ANT_TOGGLE 1 |
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c index 398bef6f4f61..7904b41a04c6 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c | |||
@@ -715,11 +715,30 @@ static ssize_t iwl_dbgfs_tof_responder_params_write(struct ieee80211_vif *vif, | |||
715 | goto out; | 715 | goto out; |
716 | } | 716 | } |
717 | 717 | ||
718 | data = iwl_dbgfs_is_match("ctrl_ch_position=", buf); | 718 | data = iwl_dbgfs_is_match("center_freq=", buf); |
719 | if (data) { | 719 | if (data) { |
720 | struct iwl_tof_responder_config_cmd *cmd = | ||
721 | &mvm->tof_data.responder_cfg; | ||
722 | |||
720 | ret = kstrtou32(data, 10, &value); | 723 | ret = kstrtou32(data, 10, &value); |
721 | if (ret == 0) | 724 | if (ret == 0 && value) { |
722 | mvm->tof_data.responder_cfg.ctrl_ch_position = value; | 725 | enum ieee80211_band band = (cmd->channel_num <= 14) ? |
726 | IEEE80211_BAND_2GHZ : | ||
727 | IEEE80211_BAND_5GHZ; | ||
728 | struct ieee80211_channel chn = { | ||
729 | .band = band, | ||
730 | .center_freq = ieee80211_channel_to_frequency( | ||
731 | cmd->channel_num, band), | ||
732 | }; | ||
733 | struct cfg80211_chan_def chandef = { | ||
734 | .chan = &chn, | ||
735 | .center_freq1 = | ||
736 | ieee80211_channel_to_frequency(value, | ||
737 | band), | ||
738 | }; | ||
739 | |||
740 | cmd->ctrl_ch_position = iwl_mvm_get_ctrl_pos(&chandef); | ||
741 | } | ||
723 | goto out; | 742 | goto out; |
724 | } | 743 | } |
725 | 744 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index 9b4fbb8b483a..05928fb4021d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c | |||
@@ -85,7 +85,7 @@ static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf, | |||
85 | IWL_ERR(mvm, "FLUSHING queues: scd_q_msk = 0x%x\n", scd_q_msk); | 85 | IWL_ERR(mvm, "FLUSHING queues: scd_q_msk = 0x%x\n", scd_q_msk); |
86 | 86 | ||
87 | mutex_lock(&mvm->mutex); | 87 | mutex_lock(&mvm->mutex); |
88 | ret = iwl_mvm_flush_tx_path(mvm, scd_q_msk, true) ? : count; | 88 | ret = iwl_mvm_flush_tx_path(mvm, scd_q_msk, 0) ? : count; |
89 | mutex_unlock(&mvm->mutex); | 89 | mutex_unlock(&mvm->mutex); |
90 | 90 | ||
91 | return ret; | 91 | return ret; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h index 660cc1c93e19..3a657e4b60ac 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h | |||
@@ -101,6 +101,7 @@ struct iwl_ssid_ie { | |||
101 | 101 | ||
102 | #define IWL_FULL_SCAN_MULTIPLIER 5 | 102 | #define IWL_FULL_SCAN_MULTIPLIER 5 |
103 | #define IWL_FAST_SCHED_SCAN_ITERATIONS 3 | 103 | #define IWL_FAST_SCHED_SCAN_ITERATIONS 3 |
104 | #define IWL_MAX_SCHED_SCAN_PLANS 2 | ||
104 | 105 | ||
105 | enum scan_framework_client { | 106 | enum scan_framework_client { |
106 | SCAN_CLIENT_SCHED_SCAN = BIT(0), | 107 | SCAN_CLIENT_SCHED_SCAN = BIT(0), |
@@ -359,7 +360,7 @@ struct iwl_scan_req_lmac { | |||
359 | /* SCAN_REQ_PERIODIC_PARAMS_API_S */ | 360 | /* SCAN_REQ_PERIODIC_PARAMS_API_S */ |
360 | __le32 iter_num; | 361 | __le32 iter_num; |
361 | __le32 delay; | 362 | __le32 delay; |
362 | struct iwl_scan_schedule_lmac schedule[2]; | 363 | struct iwl_scan_schedule_lmac schedule[IWL_MAX_SCHED_SCAN_PLANS]; |
363 | struct iwl_scan_channel_opt channel_opt[2]; | 364 | struct iwl_scan_channel_opt channel_opt[2]; |
364 | u8 data[]; | 365 | u8 data[]; |
365 | } __packed; | 366 | } __packed; |
@@ -582,7 +583,7 @@ struct iwl_scan_umac_schedule { | |||
582 | */ | 583 | */ |
583 | struct iwl_scan_req_umac_tail { | 584 | struct iwl_scan_req_umac_tail { |
584 | /* SCAN_PERIODIC_PARAMS_API_S_VER_1 */ | 585 | /* SCAN_PERIODIC_PARAMS_API_S_VER_1 */ |
585 | struct iwl_scan_umac_schedule schedule[2]; | 586 | struct iwl_scan_umac_schedule schedule[IWL_MAX_SCHED_SCAN_PLANS]; |
586 | __le16 delay; | 587 | __le16 delay; |
587 | __le16 reserved; | 588 | __le16 reserved; |
588 | /* SCAN_PROBE_PARAMS_API_S_VER_1 */ | 589 | /* SCAN_PROBE_PARAMS_API_S_VER_1 */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index 44ff6849b7a5..181590fbd3b3 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h | |||
@@ -1524,6 +1524,69 @@ struct iwl_dts_measurement_cmd { | |||
1524 | } __packed; /* TEMPERATURE_MEASUREMENT_TRIGGER_CMD_S */ | 1524 | } __packed; /* TEMPERATURE_MEASUREMENT_TRIGGER_CMD_S */ |
1525 | 1525 | ||
1526 | /** | 1526 | /** |
1527 | * enum iwl_dts_control_measurement_mode - DTS measurement type | ||
1528 | * @DTS_AUTOMATIC: Automatic mode (full SW control). Provide temperature read | ||
1529 | * back (latest value. Not waiting for new value). Use automatic | ||
1530 | * SW DTS configuration. | ||
1531 | * @DTS_REQUEST_READ: Request DTS read. Configure DTS with manual settings, | ||
1532 | * trigger DTS reading and provide read back temperature read | ||
1533 | * when available. | ||
1534 | * @DTS_OVER_WRITE: over-write the DTS temperatures in the SW until next read | ||
1535 | * @DTS_DIRECT_WITHOUT_MEASURE: DTS returns its latest temperature result, | ||
1536 | * without measurement trigger. | ||
1537 | */ | ||
1538 | enum iwl_dts_control_measurement_mode { | ||
1539 | DTS_AUTOMATIC = 0, | ||
1540 | DTS_REQUEST_READ = 1, | ||
1541 | DTS_OVER_WRITE = 2, | ||
1542 | DTS_DIRECT_WITHOUT_MEASURE = 3, | ||
1543 | }; | ||
1544 | |||
1545 | /** | ||
1546 | * enum iwl_dts_used - DTS to use or used for measurement in the DTS request | ||
1547 | * @DTS_USE_TOP: Top | ||
1548 | * @DTS_USE_CHAIN_A: chain A | ||
1549 | * @DTS_USE_CHAIN_B: chain B | ||
1550 | * @DTS_USE_CHAIN_C: chain C | ||
1551 | * @XTAL_TEMPERATURE - read temperature from xtal | ||
1552 | */ | ||
1553 | enum iwl_dts_used { | ||
1554 | DTS_USE_TOP = 0, | ||
1555 | DTS_USE_CHAIN_A = 1, | ||
1556 | DTS_USE_CHAIN_B = 2, | ||
1557 | DTS_USE_CHAIN_C = 3, | ||
1558 | XTAL_TEMPERATURE = 4, | ||
1559 | }; | ||
1560 | |||
1561 | /** | ||
1562 | * enum iwl_dts_bit_mode - bit-mode to use in DTS request read mode | ||
1563 | * @DTS_BIT6_MODE: bit 6 mode | ||
1564 | * @DTS_BIT8_MODE: bit 8 mode | ||
1565 | */ | ||
1566 | enum iwl_dts_bit_mode { | ||
1567 | DTS_BIT6_MODE = 0, | ||
1568 | DTS_BIT8_MODE = 1, | ||
1569 | }; | ||
1570 | |||
1571 | /** | ||
1572 | * iwl_ext_dts_measurement_cmd - request extended DTS temperature measurements | ||
1573 | * @control_mode: see &enum iwl_dts_control_measurement_mode | ||
1574 | * @temperature: used when over write DTS mode is selected | ||
1575 | * @sensor: set temperature sensor to use. See &enum iwl_dts_used | ||
1576 | * @avg_factor: average factor to DTS in request DTS read mode | ||
1577 | * @bit_mode: value defines the DTS bit mode to use. See &enum iwl_dts_bit_mode | ||
1578 | * @step_duration: step duration for the DTS | ||
1579 | */ | ||
1580 | struct iwl_ext_dts_measurement_cmd { | ||
1581 | __le32 control_mode; | ||
1582 | __le32 temperature; | ||
1583 | __le32 sensor; | ||
1584 | __le32 avg_factor; | ||
1585 | __le32 bit_mode; | ||
1586 | __le32 step_duration; | ||
1587 | } __packed; /* XVT_FW_DTS_CONTROL_MEASUREMENT_REQUEST_API_S */ | ||
1588 | |||
1589 | /** | ||
1527 | * iwl_dts_measurement_notif - notification received with the measurements | 1590 | * iwl_dts_measurement_notif - notification received with the measurements |
1528 | * | 1591 | * |
1529 | * @temp: the measured temperature | 1592 | * @temp: the measured temperature |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index 9d36ba7295a5..ad7ad720d2e7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | |||
@@ -843,6 +843,9 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm, | |||
843 | ctxt_sta->listen_interval = cpu_to_le32(mvm->hw->conf.listen_interval); | 843 | ctxt_sta->listen_interval = cpu_to_le32(mvm->hw->conf.listen_interval); |
844 | ctxt_sta->assoc_id = cpu_to_le32(vif->bss_conf.aid); | 844 | ctxt_sta->assoc_id = cpu_to_le32(vif->bss_conf.aid); |
845 | 845 | ||
846 | if (vif->probe_req_reg && vif->bss_conf.assoc && vif->p2p) | ||
847 | cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST); | ||
848 | |||
846 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); | 849 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); |
847 | } | 850 | } |
848 | 851 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index a38e07bb137f..1fb684693040 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -572,6 +572,14 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
572 | /* we create the 802.11 header and zero length SSID IE. */ | 572 | /* we create the 802.11 header and zero length SSID IE. */ |
573 | hw->wiphy->max_sched_scan_ie_len = | 573 | hw->wiphy->max_sched_scan_ie_len = |
574 | SCAN_OFFLOAD_PROBE_REQ_SIZE - 24 - 2; | 574 | SCAN_OFFLOAD_PROBE_REQ_SIZE - 24 - 2; |
575 | hw->wiphy->max_sched_scan_plans = IWL_MAX_SCHED_SCAN_PLANS; | ||
576 | hw->wiphy->max_sched_scan_plan_interval = U16_MAX; | ||
577 | |||
578 | /* | ||
579 | * the firmware uses u8 for num of iterations, but 0xff is saved for | ||
580 | * infinite loop, so the maximum number of iterations is actually 254. | ||
581 | */ | ||
582 | hw->wiphy->max_sched_scan_plan_iterations = 254; | ||
575 | 583 | ||
576 | hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN | | 584 | hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN | |
577 | NL80211_FEATURE_LOW_PRIORITY_SCAN | | 585 | NL80211_FEATURE_LOW_PRIORITY_SCAN | |
@@ -1129,6 +1137,12 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | |||
1129 | 1137 | ||
1130 | lockdep_assert_held(&mvm->mutex); | 1138 | lockdep_assert_held(&mvm->mutex); |
1131 | 1139 | ||
1140 | /* there's no point in fw dump if the bus is dead */ | ||
1141 | if (test_bit(STATUS_TRANS_DEAD, &mvm->trans->status)) { | ||
1142 | IWL_ERR(mvm, "Skip fw error dump since bus is dead\n"); | ||
1143 | return; | ||
1144 | } | ||
1145 | |||
1132 | if (mvm->fw_dump_trig && | 1146 | if (mvm->fw_dump_trig && |
1133 | mvm->fw_dump_trig->mode & IWL_FW_DBG_TRIGGER_MONITOR_ONLY) | 1147 | mvm->fw_dump_trig->mode & IWL_FW_DBG_TRIGGER_MONITOR_ONLY) |
1134 | monitor_dump_only = true; | 1148 | monitor_dump_only = true; |
@@ -1192,6 +1206,13 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | |||
1192 | if (sram2_len) | 1206 | if (sram2_len) |
1193 | file_len += sizeof(*dump_data) + sizeof(*dump_mem) + sram2_len; | 1207 | file_len += sizeof(*dump_data) + sizeof(*dump_mem) + sram2_len; |
1194 | 1208 | ||
1209 | /* Make room for fw's virtual image pages, if it exists */ | ||
1210 | if (mvm->fw->img[mvm->cur_ucode].paging_mem_size) | ||
1211 | file_len += mvm->num_of_paging_blk * | ||
1212 | (sizeof(*dump_data) + | ||
1213 | sizeof(struct iwl_fw_error_dump_paging) + | ||
1214 | PAGING_BLOCK_SIZE); | ||
1215 | |||
1195 | /* If we only want a monitor dump, reset the file length */ | 1216 | /* If we only want a monitor dump, reset the file length */ |
1196 | if (monitor_dump_only) { | 1217 | if (monitor_dump_only) { |
1197 | file_len = sizeof(*dump_file) + sizeof(*dump_data) + | 1218 | file_len = sizeof(*dump_file) + sizeof(*dump_data) + |
@@ -1302,6 +1323,26 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | |||
1302 | dump_mem->data, IWL8260_ICCM_LEN); | 1323 | dump_mem->data, IWL8260_ICCM_LEN); |
1303 | } | 1324 | } |
1304 | 1325 | ||
1326 | /* Dump fw's virtual image */ | ||
1327 | if (mvm->fw->img[mvm->cur_ucode].paging_mem_size) { | ||
1328 | u32 i; | ||
1329 | |||
1330 | for (i = 1; i < mvm->num_of_paging_blk + 1; i++) { | ||
1331 | struct iwl_fw_error_dump_paging *paging; | ||
1332 | struct page *pages = | ||
1333 | mvm->fw_paging_db[i].fw_paging_block; | ||
1334 | |||
1335 | dump_data = iwl_fw_error_next_data(dump_data); | ||
1336 | dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PAGING); | ||
1337 | dump_data->len = cpu_to_le32(sizeof(*paging) + | ||
1338 | PAGING_BLOCK_SIZE); | ||
1339 | paging = (void *)dump_data->data; | ||
1340 | paging->index = cpu_to_le32(i); | ||
1341 | memcpy(paging->data, page_address(pages), | ||
1342 | PAGING_BLOCK_SIZE); | ||
1343 | } | ||
1344 | } | ||
1345 | |||
1305 | dump_trans_data: | 1346 | dump_trans_data: |
1306 | fw_error_dump->trans_ptr = iwl_trans_dump_data(mvm->trans, | 1347 | fw_error_dump->trans_ptr = iwl_trans_dump_data(mvm->trans, |
1307 | mvm->fw_dump_trig); | 1348 | mvm->fw_dump_trig); |
@@ -1754,7 +1795,7 @@ static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm, | |||
1754 | * Flush them here. | 1795 | * Flush them here. |
1755 | */ | 1796 | */ |
1756 | mutex_lock(&mvm->mutex); | 1797 | mutex_lock(&mvm->mutex); |
1757 | iwl_mvm_flush_tx_path(mvm, tfd_msk, true); | 1798 | iwl_mvm_flush_tx_path(mvm, tfd_msk, 0); |
1758 | mutex_unlock(&mvm->mutex); | 1799 | mutex_unlock(&mvm->mutex); |
1759 | 1800 | ||
1760 | /* | 1801 | /* |
@@ -1955,6 +1996,27 @@ out: | |||
1955 | *total_flags = 0; | 1996 | *total_flags = 0; |
1956 | } | 1997 | } |
1957 | 1998 | ||
1999 | static void iwl_mvm_config_iface_filter(struct ieee80211_hw *hw, | ||
2000 | struct ieee80211_vif *vif, | ||
2001 | unsigned int filter_flags, | ||
2002 | unsigned int changed_flags) | ||
2003 | { | ||
2004 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
2005 | |||
2006 | /* We support only filter for probe requests */ | ||
2007 | if (!(changed_flags & FIF_PROBE_REQ)) | ||
2008 | return; | ||
2009 | |||
2010 | /* Supported only for p2p client interfaces */ | ||
2011 | if (vif->type != NL80211_IFTYPE_STATION || !vif->bss_conf.assoc || | ||
2012 | !vif->p2p) | ||
2013 | return; | ||
2014 | |||
2015 | mutex_lock(&mvm->mutex); | ||
2016 | iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); | ||
2017 | mutex_unlock(&mvm->mutex); | ||
2018 | } | ||
2019 | |||
1958 | #ifdef CONFIG_IWLWIFI_BCAST_FILTERING | 2020 | #ifdef CONFIG_IWLWIFI_BCAST_FILTERING |
1959 | struct iwl_bcast_iter_data { | 2021 | struct iwl_bcast_iter_data { |
1960 | struct iwl_mvm *mvm; | 2022 | struct iwl_mvm *mvm; |
@@ -3898,7 +3960,7 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw, | |||
3898 | } | 3960 | } |
3899 | 3961 | ||
3900 | if (drop) { | 3962 | if (drop) { |
3901 | if (iwl_mvm_flush_tx_path(mvm, msk, true)) | 3963 | if (iwl_mvm_flush_tx_path(mvm, msk, 0)) |
3902 | IWL_ERR(mvm, "flush request fail\n"); | 3964 | IWL_ERR(mvm, "flush request fail\n"); |
3903 | mutex_unlock(&mvm->mutex); | 3965 | mutex_unlock(&mvm->mutex); |
3904 | } else { | 3966 | } else { |
@@ -4135,6 +4197,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = { | |||
4135 | .config = iwl_mvm_mac_config, | 4197 | .config = iwl_mvm_mac_config, |
4136 | .prepare_multicast = iwl_mvm_prepare_multicast, | 4198 | .prepare_multicast = iwl_mvm_prepare_multicast, |
4137 | .configure_filter = iwl_mvm_configure_filter, | 4199 | .configure_filter = iwl_mvm_configure_filter, |
4200 | .config_iface_filter = iwl_mvm_config_iface_filter, | ||
4138 | .bss_info_changed = iwl_mvm_bss_info_changed, | 4201 | .bss_info_changed = iwl_mvm_bss_info_changed, |
4139 | .hw_scan = iwl_mvm_mac_hw_scan, | 4202 | .hw_scan = iwl_mvm_mac_hw_scan, |
4140 | .cancel_hw_scan = iwl_mvm_mac_cancel_hw_scan, | 4203 | .cancel_hw_scan = iwl_mvm_mac_cancel_hw_scan, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 16c5a6d7e0c9..c6327cd1d071 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -1036,7 +1036,7 @@ const char *iwl_mvm_get_tx_fail_reason(u32 status); | |||
1036 | #else | 1036 | #else |
1037 | static inline const char *iwl_mvm_get_tx_fail_reason(u32 status) { return ""; } | 1037 | static inline const char *iwl_mvm_get_tx_fail_reason(u32 status) { return ""; } |
1038 | #endif | 1038 | #endif |
1039 | int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, bool sync); | 1039 | int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, u32 flags); |
1040 | void iwl_mvm_async_handlers_purge(struct iwl_mvm *mvm); | 1040 | void iwl_mvm_async_handlers_purge(struct iwl_mvm *mvm); |
1041 | 1041 | ||
1042 | static inline void iwl_mvm_set_tx_cmd_ccmp(struct ieee80211_tx_info *info, | 1042 | static inline void iwl_mvm_set_tx_cmd_ccmp(struct ieee80211_tx_info *info, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index 4e4a680f274a..2ee0f6fe56a1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c | |||
@@ -483,6 +483,7 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm) | |||
483 | ret = -ENOMEM; | 483 | ret = -ENOMEM; |
484 | break; | 484 | break; |
485 | } | 485 | } |
486 | kfree(mvm->nvm_sections[section_id].data); | ||
486 | mvm->nvm_sections[section_id].data = temp; | 487 | mvm->nvm_sections[section_id].data = temp; |
487 | mvm->nvm_sections[section_id].length = section_size; | 488 | mvm->nvm_sections[section_id].length = section_size; |
488 | 489 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index 723b537341c4..bed9696ee410 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c | |||
@@ -348,7 +348,8 @@ static void iwl_mvm_power_config_skip_dtim(struct iwl_mvm *mvm, | |||
348 | 348 | ||
349 | static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, | 349 | static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, |
350 | struct ieee80211_vif *vif, | 350 | struct ieee80211_vif *vif, |
351 | struct iwl_mac_power_cmd *cmd) | 351 | struct iwl_mac_power_cmd *cmd, |
352 | bool host_awake) | ||
352 | { | 353 | { |
353 | int dtimper, bi; | 354 | int dtimper, bi; |
354 | int keep_alive; | 355 | int keep_alive; |
@@ -376,8 +377,13 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, | |||
376 | 377 | ||
377 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); | 378 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); |
378 | 379 | ||
379 | if (!vif->bss_conf.ps || !mvmvif->pm_enabled || | 380 | if (!vif->bss_conf.ps || !mvmvif->pm_enabled) |
380 | (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p)) | 381 | return; |
382 | |||
383 | if (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p && | ||
384 | (!fw_has_capa(&mvm->fw->ucode_capa, | ||
385 | IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS) || | ||
386 | !IWL_MVM_P2P_LOWLATENCY_PS_ENABLE)) | ||
381 | return; | 387 | return; |
382 | 388 | ||
383 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK); | 389 | 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, | |||
389 | cmd->lprx_rssi_threshold = POWER_LPRX_RSSI_THRESHOLD; | 395 | cmd->lprx_rssi_threshold = POWER_LPRX_RSSI_THRESHOLD; |
390 | } | 396 | } |
391 | 397 | ||
392 | iwl_mvm_power_config_skip_dtim(mvm, vif, cmd, | 398 | iwl_mvm_power_config_skip_dtim(mvm, vif, cmd, host_awake); |
393 | mvm->cur_ucode != IWL_UCODE_WOWLAN); | ||
394 | 399 | ||
395 | if (mvm->cur_ucode != IWL_UCODE_WOWLAN) { | 400 | if (!host_awake) { |
396 | cmd->rx_data_timeout = | 401 | cmd->rx_data_timeout = |
397 | cpu_to_le32(IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT); | 402 | cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT); |
398 | cmd->tx_data_timeout = | 403 | cmd->tx_data_timeout = |
399 | cpu_to_le32(IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT); | 404 | cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT); |
405 | } else if (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p && | ||
406 | fw_has_capa(&mvm->fw->ucode_capa, | ||
407 | IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS)) { | ||
408 | cmd->tx_data_timeout = | ||
409 | cpu_to_le32(IWL_MVM_SHORT_PS_TX_DATA_TIMEOUT); | ||
410 | cmd->rx_data_timeout = | ||
411 | cpu_to_le32(IWL_MVM_SHORT_PS_RX_DATA_TIMEOUT); | ||
400 | } else { | 412 | } else { |
401 | cmd->rx_data_timeout = | 413 | cmd->rx_data_timeout = |
402 | cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT); | 414 | cpu_to_le32(IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT); |
403 | cmd->tx_data_timeout = | 415 | cmd->tx_data_timeout = |
404 | cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT); | 416 | cpu_to_le32(IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT); |
405 | } | 417 | } |
406 | 418 | ||
407 | if (iwl_mvm_power_allow_uapsd(mvm, vif)) | 419 | if (iwl_mvm_power_allow_uapsd(mvm, vif)) |
@@ -458,7 +470,8 @@ static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm, | |||
458 | { | 470 | { |
459 | struct iwl_mac_power_cmd cmd = {}; | 471 | struct iwl_mac_power_cmd cmd = {}; |
460 | 472 | ||
461 | iwl_mvm_power_build_cmd(mvm, vif, &cmd); | 473 | iwl_mvm_power_build_cmd(mvm, vif, &cmd, |
474 | mvm->cur_ucode != IWL_UCODE_WOWLAN); | ||
462 | iwl_mvm_power_log(mvm, &cmd); | 475 | iwl_mvm_power_log(mvm, &cmd); |
463 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 476 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
464 | memcpy(&iwl_mvm_vif_from_mac80211(vif)->mac_pwr_cmd, &cmd, sizeof(cmd)); | 477 | 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, | |||
994 | if (!vif->bss_conf.assoc) | 1007 | if (!vif->bss_conf.assoc) |
995 | return 0; | 1008 | return 0; |
996 | 1009 | ||
997 | iwl_mvm_power_build_cmd(mvm, vif, &cmd); | 1010 | iwl_mvm_power_build_cmd(mvm, vif, &cmd, !enable); |
998 | |||
999 | /* when enabling D0i3, override the skip-over-dtim configuration */ | ||
1000 | if (enable) | ||
1001 | iwl_mvm_power_config_skip_dtim(mvm, vif, &cmd, false); | ||
1002 | 1011 | ||
1003 | iwl_mvm_power_log(mvm, &cmd); | 1012 | iwl_mvm_power_log(mvm, &cmd); |
1004 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 1013 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 34d98b26a215..d1ad10391b47 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c | |||
@@ -177,9 +177,6 @@ static bool rs_mimo_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
177 | 177 | ||
178 | mvmsta = iwl_mvm_sta_from_mac80211(sta); | 178 | mvmsta = iwl_mvm_sta_from_mac80211(sta); |
179 | mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif); | 179 | mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif); |
180 | if (IWL_MVM_RS_DISABLE_P2P_MIMO && | ||
181 | iwl_mvm_vif_low_latency(mvmvif) && mvmsta->vif->p2p) | ||
182 | return false; | ||
183 | 180 | ||
184 | if (mvm->nvm_data->sku_cap_mimo_disabled) | 181 | if (mvm->nvm_data->sku_cap_mimo_disabled) |
185 | return false; | 182 | return false; |
@@ -3071,9 +3068,6 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
3071 | else | 3068 | else |
3072 | rs_vht_init(mvm, sta, lq_sta, vht_cap); | 3069 | rs_vht_init(mvm, sta, lq_sta, vht_cap); |
3073 | 3070 | ||
3074 | if (IWL_MVM_RS_DISABLE_P2P_MIMO && sta_priv->vif->p2p) | ||
3075 | lq_sta->active_mimo2_rate = 0; | ||
3076 | |||
3077 | lq_sta->max_legacy_rate_idx = | 3071 | lq_sta->max_legacy_rate_idx = |
3078 | rs_get_max_rate_from_mask(lq_sta->active_legacy_rate); | 3072 | rs_get_max_rate_from_mask(lq_sta->active_legacy_rate); |
3079 | lq_sta->max_siso_rate_idx = | 3073 | lq_sta->max_siso_rate_idx = |
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index cee4f267ca66..d6e0c1b5c20c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c | |||
@@ -131,7 +131,6 @@ struct iwl_mvm_scan_params { | |||
131 | int n_ssids; | 131 | int n_ssids; |
132 | struct cfg80211_ssid *ssids; | 132 | struct cfg80211_ssid *ssids; |
133 | struct ieee80211_channel **channels; | 133 | struct ieee80211_channel **channels; |
134 | u16 interval; /* interval between scans (in secs) */ | ||
135 | u32 flags; | 134 | u32 flags; |
136 | u8 *mac_addr; | 135 | u8 *mac_addr; |
137 | u8 *mac_addr_mask; | 136 | u8 *mac_addr_mask; |
@@ -140,7 +139,8 @@ struct iwl_mvm_scan_params { | |||
140 | int n_match_sets; | 139 | int n_match_sets; |
141 | struct iwl_scan_probe_req preq; | 140 | struct iwl_scan_probe_req preq; |
142 | struct cfg80211_match_set *match_sets; | 141 | struct cfg80211_match_set *match_sets; |
143 | u8 iterations[2]; | 142 | int n_scan_plans; |
143 | struct cfg80211_sched_scan_plan *scan_plans; | ||
144 | }; | 144 | }; |
145 | 145 | ||
146 | static u8 iwl_mvm_scan_rx_ant(struct iwl_mvm *mvm) | 146 | 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, | |||
474 | int ret; | 474 | int ret; |
475 | 475 | ||
476 | if (WARN_ON(req->n_match_sets > IWL_SCAN_MAX_PROFILES)) | 476 | if (WARN_ON(req->n_match_sets > IWL_SCAN_MAX_PROFILES)) |
477 | return -EIO; | 477 | return -EIO; |
478 | 478 | ||
479 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SHORT_BL) | 479 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SHORT_BL) |
480 | blacklist_len = IWL_SCAN_SHORT_BLACKLIST_LEN; | 480 | 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, | |||
737 | } | 737 | } |
738 | 738 | ||
739 | static inline bool iwl_mvm_scan_use_ebs(struct iwl_mvm *mvm, | 739 | static inline bool iwl_mvm_scan_use_ebs(struct iwl_mvm *mvm, |
740 | struct ieee80211_vif *vif, | 740 | struct ieee80211_vif *vif) |
741 | int n_iterations) | ||
742 | { | 741 | { |
743 | const struct iwl_ucode_capabilities *capa = &mvm->fw->ucode_capa; | 742 | const struct iwl_ucode_capabilities *capa = &mvm->fw->ucode_capa; |
744 | 743 | ||
@@ -753,11 +752,6 @@ static inline bool iwl_mvm_scan_use_ebs(struct iwl_mvm *mvm, | |||
753 | vif->type != NL80211_IFTYPE_P2P_DEVICE); | 752 | vif->type != NL80211_IFTYPE_P2P_DEVICE); |
754 | } | 753 | } |
755 | 754 | ||
756 | static int iwl_mvm_scan_total_iterations(struct iwl_mvm_scan_params *params) | ||
757 | { | ||
758 | return params->iterations[0] + params->iterations[1]; | ||
759 | } | ||
760 | |||
761 | static int iwl_mvm_scan_lmac_flags(struct iwl_mvm *mvm, | 755 | static int iwl_mvm_scan_lmac_flags(struct iwl_mvm *mvm, |
762 | struct iwl_mvm_scan_params *params) | 756 | struct iwl_mvm_scan_params *params) |
763 | { | 757 | { |
@@ -796,12 +790,15 @@ static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
796 | (void *)(cmd->data + sizeof(struct iwl_scan_channel_cfg_lmac) * | 790 | (void *)(cmd->data + sizeof(struct iwl_scan_channel_cfg_lmac) * |
797 | mvm->fw->ucode_capa.n_scan_channels); | 791 | mvm->fw->ucode_capa.n_scan_channels); |
798 | u32 ssid_bitmap = 0; | 792 | u32 ssid_bitmap = 0; |
799 | int n_iterations = iwl_mvm_scan_total_iterations(params); | 793 | int i; |
800 | 794 | ||
801 | lockdep_assert_held(&mvm->mutex); | 795 | lockdep_assert_held(&mvm->mutex); |
802 | 796 | ||
803 | memset(cmd, 0, ksize(cmd)); | 797 | memset(cmd, 0, ksize(cmd)); |
804 | 798 | ||
799 | if (WARN_ON(params->n_scan_plans > IWL_MAX_SCHED_SCAN_PLANS)) | ||
800 | return -EINVAL; | ||
801 | |||
805 | iwl_mvm_scan_lmac_dwell(mvm, cmd, params); | 802 | iwl_mvm_scan_lmac_dwell(mvm, cmd, params); |
806 | 803 | ||
807 | cmd->rx_chain_select = iwl_mvm_scan_rx_chain(mvm); | 804 | 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, | |||
821 | /* this API uses bits 1-20 instead of 0-19 */ | 818 | /* this API uses bits 1-20 instead of 0-19 */ |
822 | ssid_bitmap <<= 1; | 819 | ssid_bitmap <<= 1; |
823 | 820 | ||
824 | cmd->schedule[0].delay = cpu_to_le16(params->interval); | 821 | for (i = 0; i < params->n_scan_plans; i++) { |
825 | cmd->schedule[0].iterations = params->iterations[0]; | 822 | struct cfg80211_sched_scan_plan *scan_plan = |
826 | cmd->schedule[0].full_scan_mul = 1; | 823 | ¶ms->scan_plans[i]; |
827 | cmd->schedule[1].delay = cpu_to_le16(params->interval); | 824 | |
828 | cmd->schedule[1].iterations = params->iterations[1]; | 825 | cmd->schedule[i].delay = |
829 | cmd->schedule[1].full_scan_mul = 1; | 826 | cpu_to_le16(scan_plan->interval); |
827 | cmd->schedule[i].iterations = scan_plan->iterations; | ||
828 | cmd->schedule[i].full_scan_mul = 1; | ||
829 | } | ||
830 | |||
831 | /* | ||
832 | * If the number of iterations of the last scan plan is set to | ||
833 | * zero, it should run infinitely. However, this is not always the case. | ||
834 | * For example, when regular scan is requested the driver sets one scan | ||
835 | * plan with one iteration. | ||
836 | */ | ||
837 | if (!cmd->schedule[i - 1].iterations) | ||
838 | cmd->schedule[i - 1].iterations = 0xff; | ||
830 | 839 | ||
831 | if (iwl_mvm_scan_use_ebs(mvm, vif, n_iterations)) { | 840 | if (iwl_mvm_scan_use_ebs(mvm, vif)) { |
832 | cmd->channel_opt[0].flags = | 841 | cmd->channel_opt[0].flags = |
833 | cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS | | 842 | cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS | |
834 | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | | 843 | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | |
@@ -892,7 +901,6 @@ static __le32 iwl_mvm_scan_config_rates(struct iwl_mvm *mvm) | |||
892 | 901 | ||
893 | int iwl_mvm_config_scan(struct iwl_mvm *mvm) | 902 | int iwl_mvm_config_scan(struct iwl_mvm *mvm) |
894 | { | 903 | { |
895 | |||
896 | struct iwl_scan_config *scan_config; | 904 | struct iwl_scan_config *scan_config; |
897 | struct ieee80211_supported_band *band; | 905 | struct ieee80211_supported_band *band; |
898 | int num_channels = | 906 | int num_channels = |
@@ -968,6 +976,12 @@ static int iwl_mvm_scan_uid_by_status(struct iwl_mvm *mvm, int status) | |||
968 | return -ENOENT; | 976 | return -ENOENT; |
969 | } | 977 | } |
970 | 978 | ||
979 | static inline bool iwl_mvm_is_regular_scan(struct iwl_mvm_scan_params *params) | ||
980 | { | ||
981 | return params->n_scan_plans == 1 && | ||
982 | params->scan_plans[0].iterations == 1; | ||
983 | } | ||
984 | |||
971 | static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm, | 985 | static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm, |
972 | struct iwl_scan_req_umac *cmd, | 986 | struct iwl_scan_req_umac *cmd, |
973 | struct iwl_mvm_scan_params *params) | 987 | struct iwl_mvm_scan_params *params) |
@@ -980,7 +994,7 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm, | |||
980 | cmd->scan_priority = | 994 | cmd->scan_priority = |
981 | iwl_mvm_scan_priority(mvm, IWL_SCAN_PRIORITY_EXT_6); | 995 | iwl_mvm_scan_priority(mvm, IWL_SCAN_PRIORITY_EXT_6); |
982 | 996 | ||
983 | if (iwl_mvm_scan_total_iterations(params) == 1) | 997 | if (iwl_mvm_is_regular_scan(params)) |
984 | cmd->ooc_priority = | 998 | cmd->ooc_priority = |
985 | iwl_mvm_scan_priority(mvm, IWL_SCAN_PRIORITY_EXT_6); | 999 | iwl_mvm_scan_priority(mvm, IWL_SCAN_PRIORITY_EXT_6); |
986 | else | 1000 | else |
@@ -1027,7 +1041,7 @@ static u32 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm, | |||
1027 | else | 1041 | else |
1028 | flags |= IWL_UMAC_SCAN_GEN_FLAGS_MATCH; | 1042 | flags |= IWL_UMAC_SCAN_GEN_FLAGS_MATCH; |
1029 | 1043 | ||
1030 | if (iwl_mvm_scan_total_iterations(params) > 1) | 1044 | if (!iwl_mvm_is_regular_scan(params)) |
1031 | flags |= IWL_UMAC_SCAN_GEN_FLAGS_PERIODIC; | 1045 | flags |= IWL_UMAC_SCAN_GEN_FLAGS_PERIODIC; |
1032 | 1046 | ||
1033 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 1047 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
@@ -1045,12 +1059,14 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1045 | struct iwl_scan_req_umac_tail *sec_part = (void *)&cmd->data + | 1059 | struct iwl_scan_req_umac_tail *sec_part = (void *)&cmd->data + |
1046 | sizeof(struct iwl_scan_channel_cfg_umac) * | 1060 | sizeof(struct iwl_scan_channel_cfg_umac) * |
1047 | mvm->fw->ucode_capa.n_scan_channels; | 1061 | mvm->fw->ucode_capa.n_scan_channels; |
1048 | int uid; | 1062 | int uid, i; |
1049 | u32 ssid_bitmap = 0; | 1063 | u32 ssid_bitmap = 0; |
1050 | int n_iterations = iwl_mvm_scan_total_iterations(params); | ||
1051 | 1064 | ||
1052 | lockdep_assert_held(&mvm->mutex); | 1065 | lockdep_assert_held(&mvm->mutex); |
1053 | 1066 | ||
1067 | if (WARN_ON(params->n_scan_plans > IWL_MAX_SCHED_SCAN_PLANS)) | ||
1068 | return -EINVAL; | ||
1069 | |||
1054 | uid = iwl_mvm_scan_uid_by_status(mvm, 0); | 1070 | uid = iwl_mvm_scan_uid_by_status(mvm, 0); |
1055 | if (uid < 0) | 1071 | if (uid < 0) |
1056 | return uid; | 1072 | return uid; |
@@ -1067,7 +1083,7 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1067 | if (type == IWL_MVM_SCAN_SCHED) | 1083 | if (type == IWL_MVM_SCAN_SCHED) |
1068 | cmd->flags = cpu_to_le32(IWL_UMAC_SCAN_FLAG_PREEMPTIVE); | 1084 | cmd->flags = cpu_to_le32(IWL_UMAC_SCAN_FLAG_PREEMPTIVE); |
1069 | 1085 | ||
1070 | if (iwl_mvm_scan_use_ebs(mvm, vif, n_iterations)) | 1086 | if (iwl_mvm_scan_use_ebs(mvm, vif)) |
1071 | cmd->channel_flags = IWL_SCAN_CHANNEL_FLAG_EBS | | 1087 | cmd->channel_flags = IWL_SCAN_CHANNEL_FLAG_EBS | |
1072 | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | | 1088 | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | |
1073 | IWL_SCAN_CHANNEL_FLAG_CACHE_ADD; | 1089 | IWL_SCAN_CHANNEL_FLAG_CACHE_ADD; |
@@ -1079,12 +1095,23 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1079 | iwl_mvm_umac_scan_cfg_channels(mvm, params->channels, | 1095 | iwl_mvm_umac_scan_cfg_channels(mvm, params->channels, |
1080 | params->n_channels, ssid_bitmap, cmd); | 1096 | params->n_channels, ssid_bitmap, cmd); |
1081 | 1097 | ||
1082 | /* With UMAC we use only one schedule for now, so use the sum | 1098 | for (i = 0; i < params->n_scan_plans; i++) { |
1083 | * of the iterations (with a a maximum of 255). | 1099 | struct cfg80211_sched_scan_plan *scan_plan = |
1100 | ¶ms->scan_plans[i]; | ||
1101 | |||
1102 | sec_part->schedule[i].iter_count = scan_plan->iterations; | ||
1103 | sec_part->schedule[i].interval = | ||
1104 | cpu_to_le16(scan_plan->interval); | ||
1105 | } | ||
1106 | |||
1107 | /* | ||
1108 | * If the number of iterations of the last scan plan is set to | ||
1109 | * zero, it should run infinitely. However, this is not always the case. | ||
1110 | * For example, when regular scan is requested the driver sets one scan | ||
1111 | * plan with one iteration. | ||
1084 | */ | 1112 | */ |
1085 | sec_part->schedule[0].iter_count = | 1113 | if (!sec_part->schedule[i - 1].iter_count) |
1086 | (n_iterations > 255) ? 255 : n_iterations; | 1114 | sec_part->schedule[i - 1].iter_count = 0xff; |
1087 | sec_part->schedule[0].interval = cpu_to_le16(params->interval); | ||
1088 | 1115 | ||
1089 | sec_part->delay = cpu_to_le16(params->delay); | 1116 | sec_part->delay = cpu_to_le16(params->delay); |
1090 | sec_part->preq = params->preq; | 1117 | sec_part->preq = params->preq; |
@@ -1150,6 +1177,7 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1150 | }; | 1177 | }; |
1151 | struct iwl_mvm_scan_params params = {}; | 1178 | struct iwl_mvm_scan_params params = {}; |
1152 | int ret; | 1179 | int ret; |
1180 | struct cfg80211_sched_scan_plan scan_plan = { .iterations = 1 }; | ||
1153 | 1181 | ||
1154 | lockdep_assert_held(&mvm->mutex); | 1182 | lockdep_assert_held(&mvm->mutex); |
1155 | 1183 | ||
@@ -1162,8 +1190,6 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1162 | if (ret) | 1190 | if (ret) |
1163 | return ret; | 1191 | return ret; |
1164 | 1192 | ||
1165 | iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN); | ||
1166 | |||
1167 | /* we should have failed registration if scan_cmd was NULL */ | 1193 | /* we should have failed registration if scan_cmd was NULL */ |
1168 | if (WARN_ON(!mvm->scan_cmd)) | 1194 | if (WARN_ON(!mvm->scan_cmd)) |
1169 | return -ENOMEM; | 1195 | return -ENOMEM; |
@@ -1175,7 +1201,6 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1175 | params.flags = req->flags; | 1201 | params.flags = req->flags; |
1176 | params.n_channels = req->n_channels; | 1202 | params.n_channels = req->n_channels; |
1177 | params.delay = 0; | 1203 | params.delay = 0; |
1178 | params.interval = 0; | ||
1179 | params.ssids = req->ssids; | 1204 | params.ssids = req->ssids; |
1180 | params.channels = req->channels; | 1205 | params.channels = req->channels; |
1181 | params.mac_addr = req->mac_addr; | 1206 | params.mac_addr = req->mac_addr; |
@@ -1185,8 +1210,8 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1185 | params.n_match_sets = 0; | 1210 | params.n_match_sets = 0; |
1186 | params.match_sets = NULL; | 1211 | params.match_sets = NULL; |
1187 | 1212 | ||
1188 | params.iterations[0] = 1; | 1213 | params.scan_plans = &scan_plan; |
1189 | params.iterations[1] = 0; | 1214 | params.n_scan_plans = 1; |
1190 | 1215 | ||
1191 | params.type = iwl_mvm_get_scan_type(mvm, vif, ¶ms); | 1216 | params.type = iwl_mvm_get_scan_type(mvm, vif, ¶ms); |
1192 | 1217 | ||
@@ -1205,21 +1230,20 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1205 | return ret; | 1230 | return ret; |
1206 | 1231 | ||
1207 | ret = iwl_mvm_send_cmd(mvm, &hcmd); | 1232 | ret = iwl_mvm_send_cmd(mvm, &hcmd); |
1208 | if (!ret) { | 1233 | if (ret) { |
1209 | IWL_DEBUG_SCAN(mvm, "Scan request was sent successfully\n"); | ||
1210 | mvm->scan_status |= IWL_MVM_SCAN_REGULAR; | ||
1211 | } else { | ||
1212 | /* If the scan failed, it usually means that the FW was unable | 1234 | /* If the scan failed, it usually means that the FW was unable |
1213 | * to allocate the time events. Warn on it, but maybe we | 1235 | * to allocate the time events. Warn on it, but maybe we |
1214 | * should try to send the command again with different params. | 1236 | * should try to send the command again with different params. |
1215 | */ | 1237 | */ |
1216 | IWL_ERR(mvm, "Scan failed! ret %d\n", ret); | 1238 | IWL_ERR(mvm, "Scan failed! ret %d\n", ret); |
1239 | return ret; | ||
1217 | } | 1240 | } |
1218 | 1241 | ||
1219 | if (ret) | 1242 | IWL_DEBUG_SCAN(mvm, "Scan request was sent successfully\n"); |
1220 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); | 1243 | mvm->scan_status |= IWL_MVM_SCAN_REGULAR; |
1244 | iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN); | ||
1221 | 1245 | ||
1222 | return ret; | 1246 | return 0; |
1223 | } | 1247 | } |
1224 | 1248 | ||
1225 | int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, | 1249 | int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, |
@@ -1265,20 +1289,14 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, | |||
1265 | params.pass_all = iwl_mvm_scan_pass_all(mvm, req); | 1289 | params.pass_all = iwl_mvm_scan_pass_all(mvm, req); |
1266 | params.n_match_sets = req->n_match_sets; | 1290 | params.n_match_sets = req->n_match_sets; |
1267 | params.match_sets = req->match_sets; | 1291 | params.match_sets = req->match_sets; |
1292 | if (!req->n_scan_plans) | ||
1293 | return -EINVAL; | ||
1268 | 1294 | ||
1269 | params.iterations[0] = 0; | 1295 | params.n_scan_plans = req->n_scan_plans; |
1270 | params.iterations[1] = 0xff; | 1296 | params.scan_plans = req->scan_plans; |
1271 | 1297 | ||
1272 | params.type = iwl_mvm_get_scan_type(mvm, vif, ¶ms); | 1298 | params.type = iwl_mvm_get_scan_type(mvm, vif, ¶ms); |
1273 | 1299 | ||
1274 | if (req->scan_plans[0].interval > U16_MAX) { | ||
1275 | IWL_DEBUG_SCAN(mvm, | ||
1276 | "interval value is > 16-bits, set to max possible\n"); | ||
1277 | params.interval = U16_MAX; | ||
1278 | } else { | ||
1279 | params.interval = req->scan_plans[0].interval; | ||
1280 | } | ||
1281 | |||
1282 | /* In theory, LMAC scans can handle a 32-bit delay, but since | 1300 | /* In theory, LMAC scans can handle a 32-bit delay, but since |
1283 | * waiting for over 18 hours to start the scan is a bit silly | 1301 | * waiting for over 18 hours to start the scan is a bit silly |
1284 | * and to keep it aligned with UMAC scans (which only support | 1302 | * and to keep it aligned with UMAC scans (which only support |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index a9a3eb6a1f8a..300a249486e4 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c | |||
@@ -255,7 +255,7 @@ static void iwl_mvm_tdls_sta_deinit(struct iwl_mvm *mvm, | |||
255 | /* disable the TDLS STA-specific queues */ | 255 | /* disable the TDLS STA-specific queues */ |
256 | sta_msk = mvmsta->tfd_queue_msk; | 256 | sta_msk = mvmsta->tfd_queue_msk; |
257 | for_each_set_bit(i, &sta_msk, sizeof(sta_msk) * BITS_PER_BYTE) | 257 | for_each_set_bit(i, &sta_msk, sizeof(sta_msk) * BITS_PER_BYTE) |
258 | iwl_mvm_disable_txq(mvm, i, i, 0, 0); | 258 | iwl_mvm_disable_txq(mvm, i, i, IWL_MAX_TID_COUNT, 0); |
259 | } | 259 | } |
260 | 260 | ||
261 | int iwl_mvm_add_sta(struct iwl_mvm *mvm, | 261 | int iwl_mvm_add_sta(struct iwl_mvm *mvm, |
@@ -474,7 +474,8 @@ void iwl_mvm_sta_drained_wk(struct work_struct *wk) | |||
474 | unsigned long i, msk = mvm->tfd_drained[sta_id]; | 474 | unsigned long i, msk = mvm->tfd_drained[sta_id]; |
475 | 475 | ||
476 | for_each_set_bit(i, &msk, sizeof(msk) * BITS_PER_BYTE) | 476 | for_each_set_bit(i, &msk, sizeof(msk) * BITS_PER_BYTE) |
477 | iwl_mvm_disable_txq(mvm, i, i, 0, 0); | 477 | iwl_mvm_disable_txq(mvm, i, i, |
478 | IWL_MAX_TID_COUNT, 0); | ||
478 | 479 | ||
479 | mvm->tfd_drained[sta_id] = 0; | 480 | mvm->tfd_drained[sta_id] = 0; |
480 | IWL_DEBUG_TDLS(mvm, "Drained sta %d, with queues %ld\n", | 481 | IWL_DEBUG_TDLS(mvm, "Drained sta %d, with queues %ld\n", |
@@ -501,7 +502,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, | |||
501 | if (ret) | 502 | if (ret) |
502 | return ret; | 503 | return ret; |
503 | /* flush its queues here since we are freeing mvm_sta */ | 504 | /* flush its queues here since we are freeing mvm_sta */ |
504 | ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, true); | 505 | ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, 0); |
505 | if (ret) | 506 | if (ret) |
506 | return ret; | 507 | return ret; |
507 | ret = iwl_trans_wait_tx_queue_empty(mvm->trans, | 508 | 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, | |||
1155 | 1156 | ||
1156 | if (old_state >= IWL_AGG_ON) { | 1157 | if (old_state >= IWL_AGG_ON) { |
1157 | iwl_mvm_drain_sta(mvm, mvmsta, true); | 1158 | iwl_mvm_drain_sta(mvm, mvmsta, true); |
1158 | if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), true)) | 1159 | if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), 0)) |
1159 | IWL_ERR(mvm, "Couldn't flush the AGG queue\n"); | 1160 | IWL_ERR(mvm, "Couldn't flush the AGG queue\n"); |
1160 | iwl_trans_wait_tx_queue_empty(mvm->trans, | 1161 | iwl_trans_wait_tx_queue_empty(mvm->trans, |
1161 | mvmsta->tfd_queue_msk); | 1162 | mvmsta->tfd_queue_msk); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c index dbd7d544575d..7530eb23035d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c | |||
@@ -129,7 +129,7 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk) | |||
129 | * issue as it will have to complete before the next command is | 129 | * issue as it will have to complete before the next command is |
130 | * executed, and a new time event means a new command. | 130 | * executed, and a new time event means a new command. |
131 | */ | 131 | */ |
132 | iwl_mvm_flush_tx_path(mvm, queues, false); | 132 | iwl_mvm_flush_tx_path(mvm, queues, CMD_ASYNC); |
133 | } | 133 | } |
134 | 134 | ||
135 | static void iwl_mvm_roc_finished(struct iwl_mvm *mvm) | 135 | static void iwl_mvm_roc_finished(struct iwl_mvm *mvm) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c index 58b762f1e0b5..cadfc0460597 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tt.c +++ b/drivers/net/wireless/iwlwifi/mvm/tt.c | |||
@@ -176,6 +176,9 @@ static int iwl_mvm_get_temp_cmd(struct iwl_mvm *mvm) | |||
176 | struct iwl_dts_measurement_cmd cmd = { | 176 | struct iwl_dts_measurement_cmd cmd = { |
177 | .flags = cpu_to_le32(DTS_TRIGGER_CMD_FLAGS_TEMP), | 177 | .flags = cpu_to_le32(DTS_TRIGGER_CMD_FLAGS_TEMP), |
178 | }; | 178 | }; |
179 | struct iwl_ext_dts_measurement_cmd extcmd = { | ||
180 | .control_mode = cpu_to_le32(DTS_AUTOMATIC), | ||
181 | }; | ||
179 | u32 cmdid; | 182 | u32 cmdid; |
180 | 183 | ||
181 | if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_WIDE_CMD_HDR)) | 184 | 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) | |||
183 | PHY_OPS_GROUP, 0); | 186 | PHY_OPS_GROUP, 0); |
184 | else | 187 | else |
185 | cmdid = CMD_DTS_MEASUREMENT_TRIGGER; | 188 | cmdid = CMD_DTS_MEASUREMENT_TRIGGER; |
186 | return iwl_mvm_send_cmd_pdu(mvm, cmdid, 0, | 189 | |
187 | sizeof(cmd), &cmd); | 190 | if (!fw_has_capa(&mvm->fw->ucode_capa, |
191 | IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE)) | ||
192 | return iwl_mvm_send_cmd_pdu(mvm, cmdid, 0, sizeof(cmd), &cmd); | ||
193 | |||
194 | return iwl_mvm_send_cmd_pdu(mvm, cmdid, 0, sizeof(extcmd), &extcmd); | ||
188 | } | 195 | } |
189 | 196 | ||
190 | int iwl_mvm_get_temp(struct iwl_mvm *mvm) | 197 | int iwl_mvm_get_temp(struct iwl_mvm *mvm) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index ff8b9bdef7e8..c652a66be803 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c | |||
@@ -1099,7 +1099,7 @@ out: | |||
1099 | * 2) flush the Tx path | 1099 | * 2) flush the Tx path |
1100 | * 3) wait for the transport queues to be empty | 1100 | * 3) wait for the transport queues to be empty |
1101 | */ | 1101 | */ |
1102 | int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, bool sync) | 1102 | int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, u32 flags) |
1103 | { | 1103 | { |
1104 | int ret; | 1104 | int ret; |
1105 | struct iwl_tx_path_flush_cmd flush_cmd = { | 1105 | 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) | |||
1107 | .flush_ctl = cpu_to_le16(DUMP_TX_FIFO_FLUSH), | 1107 | .flush_ctl = cpu_to_le16(DUMP_TX_FIFO_FLUSH), |
1108 | }; | 1108 | }; |
1109 | 1109 | ||
1110 | u32 flags = sync ? 0 : CMD_ASYNC; | ||
1111 | |||
1112 | ret = iwl_mvm_send_cmd_pdu(mvm, TXPATH_FLUSH, flags, | 1110 | ret = iwl_mvm_send_cmd_pdu(mvm, TXPATH_FLUSH, flags, |
1113 | sizeof(flush_cmd), &flush_cmd); | 1111 | sizeof(flush_cmd), &flush_cmd); |
1114 | if (ret) | 1112 | if (ret) |
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 6ba7d300b08f..90283453073c 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
@@ -592,10 +592,8 @@ static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans) | |||
592 | 592 | ||
593 | do { | 593 | do { |
594 | ret = iwl_pcie_set_hw_ready(trans); | 594 | ret = iwl_pcie_set_hw_ready(trans); |
595 | if (ret >= 0) { | 595 | if (ret >= 0) |
596 | ret = 0; | 596 | return 0; |
597 | goto out; | ||
598 | } | ||
599 | 597 | ||
600 | usleep_range(200, 1000); | 598 | usleep_range(200, 1000); |
601 | t += 200; | 599 | t += 200; |
@@ -605,10 +603,6 @@ static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans) | |||
605 | 603 | ||
606 | IWL_ERR(trans, "Couldn't prepare the card\n"); | 604 | IWL_ERR(trans, "Couldn't prepare the card\n"); |
607 | 605 | ||
608 | out: | ||
609 | iwl_clear_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG, | ||
610 | CSR_RESET_LINK_PWR_MGMT_DISABLED); | ||
611 | |||
612 | return ret; | 606 | return ret; |
613 | } | 607 | } |
614 | 608 | ||
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index b7ac45f324d7..4073116e6e9f 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -1821,6 +1821,10 @@ static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
1821 | return -1; | 1821 | return -1; |
1822 | } | 1822 | } |
1823 | 1823 | ||
1824 | if (netif_carrier_ok(priv->netdev)) | ||
1825 | netif_carrier_off(priv->netdev); | ||
1826 | mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter); | ||
1827 | |||
1824 | return 0; | 1828 | return 0; |
1825 | } | 1829 | } |
1826 | 1830 | ||
@@ -1925,6 +1929,10 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, | |||
1925 | if (mwifiex_set_mgmt_ies(priv, ¶ms->beacon)) | 1929 | if (mwifiex_set_mgmt_ies(priv, ¶ms->beacon)) |
1926 | return -1; | 1930 | return -1; |
1927 | 1931 | ||
1932 | if (!netif_carrier_ok(priv->netdev)) | ||
1933 | netif_carrier_on(priv->netdev); | ||
1934 | mwifiex_wake_up_net_dev_queue(priv->netdev, priv->adapter); | ||
1935 | |||
1928 | memcpy(&priv->bss_cfg, bss_cfg, sizeof(priv->bss_cfg)); | 1936 | memcpy(&priv->bss_cfg, bss_cfg, sizeof(priv->bss_cfg)); |
1929 | kfree(bss_cfg); | 1937 | kfree(bss_cfg); |
1930 | return 0; | 1938 | return 0; |
diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c index 078834cf1251..86ff54296f39 100644 --- a/drivers/net/wireless/mwifiex/uap_event.c +++ b/drivers/net/wireless/mwifiex/uap_event.c | |||
@@ -179,19 +179,12 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) | |||
179 | case EVENT_UAP_BSS_IDLE: | 179 | case EVENT_UAP_BSS_IDLE: |
180 | priv->media_connected = false; | 180 | priv->media_connected = false; |
181 | priv->port_open = false; | 181 | priv->port_open = false; |
182 | if (netif_carrier_ok(priv->netdev)) | ||
183 | netif_carrier_off(priv->netdev); | ||
184 | mwifiex_stop_net_dev_queue(priv->netdev, adapter); | ||
185 | |||
186 | mwifiex_clean_txrx(priv); | 182 | mwifiex_clean_txrx(priv); |
187 | mwifiex_del_all_sta_list(priv); | 183 | mwifiex_del_all_sta_list(priv); |
188 | break; | 184 | break; |
189 | case EVENT_UAP_BSS_ACTIVE: | 185 | case EVENT_UAP_BSS_ACTIVE: |
190 | priv->media_connected = true; | 186 | priv->media_connected = true; |
191 | priv->port_open = true; | 187 | priv->port_open = true; |
192 | if (!netif_carrier_ok(priv->netdev)) | ||
193 | netif_carrier_on(priv->netdev); | ||
194 | mwifiex_wake_up_net_dev_queue(priv->netdev, adapter); | ||
195 | break; | 188 | break; |
196 | case EVENT_UAP_BSS_START: | 189 | case EVENT_UAP_BSS_START: |
197 | mwifiex_dbg(adapter, EVENT, | 190 | mwifiex_dbg(adapter, EVENT, |
diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c index 26a57d773d30..f2cd513d54b2 100644 --- a/drivers/net/wireless/orinoco/orinoco_usb.c +++ b/drivers/net/wireless/orinoco/orinoco_usb.c | |||
@@ -1576,6 +1576,7 @@ static int ezusb_probe(struct usb_interface *interface, | |||
1576 | ezusb_hard_reset, NULL); | 1576 | ezusb_hard_reset, NULL); |
1577 | if (!priv) { | 1577 | if (!priv) { |
1578 | err("Couldn't allocate orinocodev"); | 1578 | err("Couldn't allocate orinocodev"); |
1579 | retval = -ENOMEM; | ||
1579 | goto exit; | 1580 | goto exit; |
1580 | } | 1581 | } |
1581 | 1582 | ||
diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig index f0d22cdb51cd..149214beeda9 100644 --- a/drivers/ssb/Kconfig +++ b/drivers/ssb/Kconfig | |||
@@ -80,6 +80,15 @@ config SSB_SDIOHOST | |||
80 | 80 | ||
81 | If unsure, say N | 81 | If unsure, say N |
82 | 82 | ||
83 | config SSB_HOST_SOC | ||
84 | bool "Support for SSB bus on SoC" | ||
85 | depends on SSB | ||
86 | help | ||
87 | Host interface for a SSB directly mapped into memory. This is | ||
88 | for some Broadcom SoCs from the BCM47xx and BCM53xx lines. | ||
89 | |||
90 | If unsure, say N | ||
91 | |||
83 | config SSB_SILENT | 92 | config SSB_SILENT |
84 | bool "No SSB kernel messages" | 93 | bool "No SSB kernel messages" |
85 | depends on SSB && EXPERT | 94 | depends on SSB && EXPERT |
diff --git a/drivers/ssb/Makefile b/drivers/ssb/Makefile index b1ddc116d387..64a09681cee0 100644 --- a/drivers/ssb/Makefile +++ b/drivers/ssb/Makefile | |||
@@ -5,8 +5,9 @@ ssb-$(CONFIG_SSB_SPROM) += sprom.o | |||
5 | 5 | ||
6 | # host support | 6 | # host support |
7 | ssb-$(CONFIG_SSB_PCIHOST) += pci.o pcihost_wrapper.o | 7 | ssb-$(CONFIG_SSB_PCIHOST) += pci.o pcihost_wrapper.o |
8 | ssb-$(CONFIG_SSB_PCMCIAHOST) += pcmcia.o | 8 | ssb-$(CONFIG_SSB_PCMCIAHOST) += pcmcia.o bridge_pcmcia_80211.o |
9 | ssb-$(CONFIG_SSB_SDIOHOST) += sdio.o | 9 | ssb-$(CONFIG_SSB_SDIOHOST) += sdio.o |
10 | ssb-$(CONFIG_SSB_HOST_SOC) += host_soc.o | ||
10 | 11 | ||
11 | # built-in drivers | 12 | # built-in drivers |
12 | ssb-y += driver_chipcommon.o | 13 | ssb-y += driver_chipcommon.o |
diff --git a/drivers/ssb/bridge_pcmcia_80211.c b/drivers/ssb/bridge_pcmcia_80211.c new file mode 100644 index 000000000000..d70568ea02d5 --- /dev/null +++ b/drivers/ssb/bridge_pcmcia_80211.c | |||
@@ -0,0 +1,128 @@ | |||
1 | /* | ||
2 | * Broadcom 43xx PCMCIA-SSB bridge module | ||
3 | * | ||
4 | * Copyright (c) 2007 Michael Buesch <m@bues.ch> | ||
5 | * | ||
6 | * Licensed under the GNU/GPL. See COPYING for details. | ||
7 | */ | ||
8 | |||
9 | #include <linux/ssb/ssb.h> | ||
10 | #include <linux/slab.h> | ||
11 | #include <linux/module.h> | ||
12 | |||
13 | #include <pcmcia/cistpl.h> | ||
14 | #include <pcmcia/ciscode.h> | ||
15 | #include <pcmcia/ds.h> | ||
16 | #include <pcmcia/cisreg.h> | ||
17 | |||
18 | #include "ssb_private.h" | ||
19 | |||
20 | static const struct pcmcia_device_id ssb_host_pcmcia_tbl[] = { | ||
21 | PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448), | ||
22 | PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476), | ||
23 | PCMCIA_DEVICE_NULL, | ||
24 | }; | ||
25 | |||
26 | MODULE_DEVICE_TABLE(pcmcia, ssb_host_pcmcia_tbl); | ||
27 | |||
28 | static int ssb_host_pcmcia_probe(struct pcmcia_device *dev) | ||
29 | { | ||
30 | struct ssb_bus *ssb; | ||
31 | int err = -ENOMEM; | ||
32 | int res = 0; | ||
33 | |||
34 | ssb = kzalloc(sizeof(*ssb), GFP_KERNEL); | ||
35 | if (!ssb) | ||
36 | goto out_error; | ||
37 | |||
38 | err = -ENODEV; | ||
39 | |||
40 | dev->config_flags |= CONF_ENABLE_IRQ; | ||
41 | |||
42 | dev->resource[2]->flags |= WIN_ENABLE | WIN_DATA_WIDTH_16 | | ||
43 | WIN_USE_WAIT; | ||
44 | dev->resource[2]->start = 0; | ||
45 | dev->resource[2]->end = SSB_CORE_SIZE; | ||
46 | res = pcmcia_request_window(dev, dev->resource[2], 250); | ||
47 | if (res != 0) | ||
48 | goto err_kfree_ssb; | ||
49 | |||
50 | res = pcmcia_map_mem_page(dev, dev->resource[2], 0); | ||
51 | if (res != 0) | ||
52 | goto err_disable; | ||
53 | |||
54 | if (!dev->irq) | ||
55 | goto err_disable; | ||
56 | |||
57 | res = pcmcia_enable_device(dev); | ||
58 | if (res != 0) | ||
59 | goto err_disable; | ||
60 | |||
61 | err = ssb_bus_pcmciabus_register(ssb, dev, dev->resource[2]->start); | ||
62 | if (err) | ||
63 | goto err_disable; | ||
64 | dev->priv = ssb; | ||
65 | |||
66 | return 0; | ||
67 | |||
68 | err_disable: | ||
69 | pcmcia_disable_device(dev); | ||
70 | err_kfree_ssb: | ||
71 | kfree(ssb); | ||
72 | out_error: | ||
73 | ssb_err("Initialization failed (%d, %d)\n", res, err); | ||
74 | return err; | ||
75 | } | ||
76 | |||
77 | static void ssb_host_pcmcia_remove(struct pcmcia_device *dev) | ||
78 | { | ||
79 | struct ssb_bus *ssb = dev->priv; | ||
80 | |||
81 | ssb_bus_unregister(ssb); | ||
82 | pcmcia_disable_device(dev); | ||
83 | kfree(ssb); | ||
84 | dev->priv = NULL; | ||
85 | } | ||
86 | |||
87 | #ifdef CONFIG_PM | ||
88 | static int ssb_host_pcmcia_suspend(struct pcmcia_device *dev) | ||
89 | { | ||
90 | struct ssb_bus *ssb = dev->priv; | ||
91 | |||
92 | return ssb_bus_suspend(ssb); | ||
93 | } | ||
94 | |||
95 | static int ssb_host_pcmcia_resume(struct pcmcia_device *dev) | ||
96 | { | ||
97 | struct ssb_bus *ssb = dev->priv; | ||
98 | |||
99 | return ssb_bus_resume(ssb); | ||
100 | } | ||
101 | #else /* CONFIG_PM */ | ||
102 | # define ssb_host_pcmcia_suspend NULL | ||
103 | # define ssb_host_pcmcia_resume NULL | ||
104 | #endif /* CONFIG_PM */ | ||
105 | |||
106 | static struct pcmcia_driver ssb_host_pcmcia_driver = { | ||
107 | .owner = THIS_MODULE, | ||
108 | .name = "ssb-pcmcia", | ||
109 | .id_table = ssb_host_pcmcia_tbl, | ||
110 | .probe = ssb_host_pcmcia_probe, | ||
111 | .remove = ssb_host_pcmcia_remove, | ||
112 | .suspend = ssb_host_pcmcia_suspend, | ||
113 | .resume = ssb_host_pcmcia_resume, | ||
114 | }; | ||
115 | |||
116 | /* | ||
117 | * These are not module init/exit functions! | ||
118 | * The module_pcmcia_driver() helper cannot be used here. | ||
119 | */ | ||
120 | int ssb_host_pcmcia_init(void) | ||
121 | { | ||
122 | return pcmcia_register_driver(&ssb_host_pcmcia_driver); | ||
123 | } | ||
124 | |||
125 | void ssb_host_pcmcia_exit(void) | ||
126 | { | ||
127 | pcmcia_unregister_driver(&ssb_host_pcmcia_driver); | ||
128 | } | ||
diff --git a/drivers/ssb/host_soc.c b/drivers/ssb/host_soc.c new file mode 100644 index 000000000000..c809f255af34 --- /dev/null +++ b/drivers/ssb/host_soc.c | |||
@@ -0,0 +1,173 @@ | |||
1 | /* | ||
2 | * Sonics Silicon Backplane SoC host related functions. | ||
3 | * Subsystem core | ||
4 | * | ||
5 | * Copyright 2005, Broadcom Corporation | ||
6 | * Copyright 2006, 2007, Michael Buesch <m@bues.ch> | ||
7 | * | ||
8 | * Licensed under the GNU/GPL. See COPYING for details. | ||
9 | */ | ||
10 | |||
11 | #include <linux/ssb/ssb.h> | ||
12 | |||
13 | #include "ssb_private.h" | ||
14 | |||
15 | static u8 ssb_host_soc_read8(struct ssb_device *dev, u16 offset) | ||
16 | { | ||
17 | struct ssb_bus *bus = dev->bus; | ||
18 | |||
19 | offset += dev->core_index * SSB_CORE_SIZE; | ||
20 | return readb(bus->mmio + offset); | ||
21 | } | ||
22 | |||
23 | static u16 ssb_host_soc_read16(struct ssb_device *dev, u16 offset) | ||
24 | { | ||
25 | struct ssb_bus *bus = dev->bus; | ||
26 | |||
27 | offset += dev->core_index * SSB_CORE_SIZE; | ||
28 | return readw(bus->mmio + offset); | ||
29 | } | ||
30 | |||
31 | static u32 ssb_host_soc_read32(struct ssb_device *dev, u16 offset) | ||
32 | { | ||
33 | struct ssb_bus *bus = dev->bus; | ||
34 | |||
35 | offset += dev->core_index * SSB_CORE_SIZE; | ||
36 | return readl(bus->mmio + offset); | ||
37 | } | ||
38 | |||
39 | #ifdef CONFIG_SSB_BLOCKIO | ||
40 | static void ssb_host_soc_block_read(struct ssb_device *dev, void *buffer, | ||
41 | size_t count, u16 offset, u8 reg_width) | ||
42 | { | ||
43 | struct ssb_bus *bus = dev->bus; | ||
44 | void __iomem *addr; | ||
45 | |||
46 | offset += dev->core_index * SSB_CORE_SIZE; | ||
47 | addr = bus->mmio + offset; | ||
48 | |||
49 | switch (reg_width) { | ||
50 | case sizeof(u8): { | ||
51 | u8 *buf = buffer; | ||
52 | |||
53 | while (count) { | ||
54 | *buf = __raw_readb(addr); | ||
55 | buf++; | ||
56 | count--; | ||
57 | } | ||
58 | break; | ||
59 | } | ||
60 | case sizeof(u16): { | ||
61 | __le16 *buf = buffer; | ||
62 | |||
63 | SSB_WARN_ON(count & 1); | ||
64 | while (count) { | ||
65 | *buf = (__force __le16)__raw_readw(addr); | ||
66 | buf++; | ||
67 | count -= 2; | ||
68 | } | ||
69 | break; | ||
70 | } | ||
71 | case sizeof(u32): { | ||
72 | __le32 *buf = buffer; | ||
73 | |||
74 | SSB_WARN_ON(count & 3); | ||
75 | while (count) { | ||
76 | *buf = (__force __le32)__raw_readl(addr); | ||
77 | buf++; | ||
78 | count -= 4; | ||
79 | } | ||
80 | break; | ||
81 | } | ||
82 | default: | ||
83 | SSB_WARN_ON(1); | ||
84 | } | ||
85 | } | ||
86 | #endif /* CONFIG_SSB_BLOCKIO */ | ||
87 | |||
88 | static void ssb_host_soc_write8(struct ssb_device *dev, u16 offset, u8 value) | ||
89 | { | ||
90 | struct ssb_bus *bus = dev->bus; | ||
91 | |||
92 | offset += dev->core_index * SSB_CORE_SIZE; | ||
93 | writeb(value, bus->mmio + offset); | ||
94 | } | ||
95 | |||
96 | static void ssb_host_soc_write16(struct ssb_device *dev, u16 offset, u16 value) | ||
97 | { | ||
98 | struct ssb_bus *bus = dev->bus; | ||
99 | |||
100 | offset += dev->core_index * SSB_CORE_SIZE; | ||
101 | writew(value, bus->mmio + offset); | ||
102 | } | ||
103 | |||
104 | static void ssb_host_soc_write32(struct ssb_device *dev, u16 offset, u32 value) | ||
105 | { | ||
106 | struct ssb_bus *bus = dev->bus; | ||
107 | |||
108 | offset += dev->core_index * SSB_CORE_SIZE; | ||
109 | writel(value, bus->mmio + offset); | ||
110 | } | ||
111 | |||
112 | #ifdef CONFIG_SSB_BLOCKIO | ||
113 | static void ssb_host_soc_block_write(struct ssb_device *dev, const void *buffer, | ||
114 | size_t count, u16 offset, u8 reg_width) | ||
115 | { | ||
116 | struct ssb_bus *bus = dev->bus; | ||
117 | void __iomem *addr; | ||
118 | |||
119 | offset += dev->core_index * SSB_CORE_SIZE; | ||
120 | addr = bus->mmio + offset; | ||
121 | |||
122 | switch (reg_width) { | ||
123 | case sizeof(u8): { | ||
124 | const u8 *buf = buffer; | ||
125 | |||
126 | while (count) { | ||
127 | __raw_writeb(*buf, addr); | ||
128 | buf++; | ||
129 | count--; | ||
130 | } | ||
131 | break; | ||
132 | } | ||
133 | case sizeof(u16): { | ||
134 | const __le16 *buf = buffer; | ||
135 | |||
136 | SSB_WARN_ON(count & 1); | ||
137 | while (count) { | ||
138 | __raw_writew((__force u16)(*buf), addr); | ||
139 | buf++; | ||
140 | count -= 2; | ||
141 | } | ||
142 | break; | ||
143 | } | ||
144 | case sizeof(u32): { | ||
145 | const __le32 *buf = buffer; | ||
146 | |||
147 | SSB_WARN_ON(count & 3); | ||
148 | while (count) { | ||
149 | __raw_writel((__force u32)(*buf), addr); | ||
150 | buf++; | ||
151 | count -= 4; | ||
152 | } | ||
153 | break; | ||
154 | } | ||
155 | default: | ||
156 | SSB_WARN_ON(1); | ||
157 | } | ||
158 | } | ||
159 | #endif /* CONFIG_SSB_BLOCKIO */ | ||
160 | |||
161 | /* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */ | ||
162 | const struct ssb_bus_ops ssb_host_soc_ops = { | ||
163 | .read8 = ssb_host_soc_read8, | ||
164 | .read16 = ssb_host_soc_read16, | ||
165 | .read32 = ssb_host_soc_read32, | ||
166 | .write8 = ssb_host_soc_write8, | ||
167 | .write16 = ssb_host_soc_write16, | ||
168 | .write32 = ssb_host_soc_write32, | ||
169 | #ifdef CONFIG_SSB_BLOCKIO | ||
170 | .block_read = ssb_host_soc_block_read, | ||
171 | .block_write = ssb_host_soc_block_write, | ||
172 | #endif | ||
173 | }; | ||
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index 8cf23a2468ba..5d1e9a0fc389 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c | |||
@@ -596,166 +596,6 @@ error: | |||
596 | return err; | 596 | return err; |
597 | } | 597 | } |
598 | 598 | ||
599 | static u8 ssb_ssb_read8(struct ssb_device *dev, u16 offset) | ||
600 | { | ||
601 | struct ssb_bus *bus = dev->bus; | ||
602 | |||
603 | offset += dev->core_index * SSB_CORE_SIZE; | ||
604 | return readb(bus->mmio + offset); | ||
605 | } | ||
606 | |||
607 | static u16 ssb_ssb_read16(struct ssb_device *dev, u16 offset) | ||
608 | { | ||
609 | struct ssb_bus *bus = dev->bus; | ||
610 | |||
611 | offset += dev->core_index * SSB_CORE_SIZE; | ||
612 | return readw(bus->mmio + offset); | ||
613 | } | ||
614 | |||
615 | static u32 ssb_ssb_read32(struct ssb_device *dev, u16 offset) | ||
616 | { | ||
617 | struct ssb_bus *bus = dev->bus; | ||
618 | |||
619 | offset += dev->core_index * SSB_CORE_SIZE; | ||
620 | return readl(bus->mmio + offset); | ||
621 | } | ||
622 | |||
623 | #ifdef CONFIG_SSB_BLOCKIO | ||
624 | static void ssb_ssb_block_read(struct ssb_device *dev, void *buffer, | ||
625 | size_t count, u16 offset, u8 reg_width) | ||
626 | { | ||
627 | struct ssb_bus *bus = dev->bus; | ||
628 | void __iomem *addr; | ||
629 | |||
630 | offset += dev->core_index * SSB_CORE_SIZE; | ||
631 | addr = bus->mmio + offset; | ||
632 | |||
633 | switch (reg_width) { | ||
634 | case sizeof(u8): { | ||
635 | u8 *buf = buffer; | ||
636 | |||
637 | while (count) { | ||
638 | *buf = __raw_readb(addr); | ||
639 | buf++; | ||
640 | count--; | ||
641 | } | ||
642 | break; | ||
643 | } | ||
644 | case sizeof(u16): { | ||
645 | __le16 *buf = buffer; | ||
646 | |||
647 | SSB_WARN_ON(count & 1); | ||
648 | while (count) { | ||
649 | *buf = (__force __le16)__raw_readw(addr); | ||
650 | buf++; | ||
651 | count -= 2; | ||
652 | } | ||
653 | break; | ||
654 | } | ||
655 | case sizeof(u32): { | ||
656 | __le32 *buf = buffer; | ||
657 | |||
658 | SSB_WARN_ON(count & 3); | ||
659 | while (count) { | ||
660 | *buf = (__force __le32)__raw_readl(addr); | ||
661 | buf++; | ||
662 | count -= 4; | ||
663 | } | ||
664 | break; | ||
665 | } | ||
666 | default: | ||
667 | SSB_WARN_ON(1); | ||
668 | } | ||
669 | } | ||
670 | #endif /* CONFIG_SSB_BLOCKIO */ | ||
671 | |||
672 | static void ssb_ssb_write8(struct ssb_device *dev, u16 offset, u8 value) | ||
673 | { | ||
674 | struct ssb_bus *bus = dev->bus; | ||
675 | |||
676 | offset += dev->core_index * SSB_CORE_SIZE; | ||
677 | writeb(value, bus->mmio + offset); | ||
678 | } | ||
679 | |||
680 | static void ssb_ssb_write16(struct ssb_device *dev, u16 offset, u16 value) | ||
681 | { | ||
682 | struct ssb_bus *bus = dev->bus; | ||
683 | |||
684 | offset += dev->core_index * SSB_CORE_SIZE; | ||
685 | writew(value, bus->mmio + offset); | ||
686 | } | ||
687 | |||
688 | static void ssb_ssb_write32(struct ssb_device *dev, u16 offset, u32 value) | ||
689 | { | ||
690 | struct ssb_bus *bus = dev->bus; | ||
691 | |||
692 | offset += dev->core_index * SSB_CORE_SIZE; | ||
693 | writel(value, bus->mmio + offset); | ||
694 | } | ||
695 | |||
696 | #ifdef CONFIG_SSB_BLOCKIO | ||
697 | static void ssb_ssb_block_write(struct ssb_device *dev, const void *buffer, | ||
698 | size_t count, u16 offset, u8 reg_width) | ||
699 | { | ||
700 | struct ssb_bus *bus = dev->bus; | ||
701 | void __iomem *addr; | ||
702 | |||
703 | offset += dev->core_index * SSB_CORE_SIZE; | ||
704 | addr = bus->mmio + offset; | ||
705 | |||
706 | switch (reg_width) { | ||
707 | case sizeof(u8): { | ||
708 | const u8 *buf = buffer; | ||
709 | |||
710 | while (count) { | ||
711 | __raw_writeb(*buf, addr); | ||
712 | buf++; | ||
713 | count--; | ||
714 | } | ||
715 | break; | ||
716 | } | ||
717 | case sizeof(u16): { | ||
718 | const __le16 *buf = buffer; | ||
719 | |||
720 | SSB_WARN_ON(count & 1); | ||
721 | while (count) { | ||
722 | __raw_writew((__force u16)(*buf), addr); | ||
723 | buf++; | ||
724 | count -= 2; | ||
725 | } | ||
726 | break; | ||
727 | } | ||
728 | case sizeof(u32): { | ||
729 | const __le32 *buf = buffer; | ||
730 | |||
731 | SSB_WARN_ON(count & 3); | ||
732 | while (count) { | ||
733 | __raw_writel((__force u32)(*buf), addr); | ||
734 | buf++; | ||
735 | count -= 4; | ||
736 | } | ||
737 | break; | ||
738 | } | ||
739 | default: | ||
740 | SSB_WARN_ON(1); | ||
741 | } | ||
742 | } | ||
743 | #endif /* CONFIG_SSB_BLOCKIO */ | ||
744 | |||
745 | /* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */ | ||
746 | static const struct ssb_bus_ops ssb_ssb_ops = { | ||
747 | .read8 = ssb_ssb_read8, | ||
748 | .read16 = ssb_ssb_read16, | ||
749 | .read32 = ssb_ssb_read32, | ||
750 | .write8 = ssb_ssb_write8, | ||
751 | .write16 = ssb_ssb_write16, | ||
752 | .write32 = ssb_ssb_write32, | ||
753 | #ifdef CONFIG_SSB_BLOCKIO | ||
754 | .block_read = ssb_ssb_block_read, | ||
755 | .block_write = ssb_ssb_block_write, | ||
756 | #endif | ||
757 | }; | ||
758 | |||
759 | static int ssb_fetch_invariants(struct ssb_bus *bus, | 599 | static int ssb_fetch_invariants(struct ssb_bus *bus, |
760 | ssb_invariants_func_t get_invariants) | 600 | ssb_invariants_func_t get_invariants) |
761 | { | 601 | { |
@@ -897,7 +737,6 @@ int ssb_bus_pcmciabus_register(struct ssb_bus *bus, | |||
897 | 737 | ||
898 | return err; | 738 | return err; |
899 | } | 739 | } |
900 | EXPORT_SYMBOL(ssb_bus_pcmciabus_register); | ||
901 | #endif /* CONFIG_SSB_PCMCIAHOST */ | 740 | #endif /* CONFIG_SSB_PCMCIAHOST */ |
902 | 741 | ||
903 | #ifdef CONFIG_SSB_SDIOHOST | 742 | #ifdef CONFIG_SSB_SDIOHOST |
@@ -922,13 +761,14 @@ int ssb_bus_sdiobus_register(struct ssb_bus *bus, struct sdio_func *func, | |||
922 | EXPORT_SYMBOL(ssb_bus_sdiobus_register); | 761 | EXPORT_SYMBOL(ssb_bus_sdiobus_register); |
923 | #endif /* CONFIG_SSB_PCMCIAHOST */ | 762 | #endif /* CONFIG_SSB_PCMCIAHOST */ |
924 | 763 | ||
764 | #ifdef CONFIG_SSB_HOST_SOC | ||
925 | int ssb_bus_ssbbus_register(struct ssb_bus *bus, unsigned long baseaddr, | 765 | int ssb_bus_ssbbus_register(struct ssb_bus *bus, unsigned long baseaddr, |
926 | ssb_invariants_func_t get_invariants) | 766 | ssb_invariants_func_t get_invariants) |
927 | { | 767 | { |
928 | int err; | 768 | int err; |
929 | 769 | ||
930 | bus->bustype = SSB_BUSTYPE_SSB; | 770 | bus->bustype = SSB_BUSTYPE_SSB; |
931 | bus->ops = &ssb_ssb_ops; | 771 | bus->ops = &ssb_host_soc_ops; |
932 | 772 | ||
933 | err = ssb_bus_register(bus, get_invariants, baseaddr); | 773 | err = ssb_bus_register(bus, get_invariants, baseaddr); |
934 | if (!err) { | 774 | if (!err) { |
@@ -938,6 +778,7 @@ int ssb_bus_ssbbus_register(struct ssb_bus *bus, unsigned long baseaddr, | |||
938 | 778 | ||
939 | return err; | 779 | return err; |
940 | } | 780 | } |
781 | #endif | ||
941 | 782 | ||
942 | int __ssb_driver_register(struct ssb_driver *drv, struct module *owner) | 783 | int __ssb_driver_register(struct ssb_driver *drv, struct module *owner) |
943 | { | 784 | { |
@@ -1464,6 +1305,12 @@ static int __init ssb_modinit(void) | |||
1464 | /* don't fail SSB init because of this */ | 1305 | /* don't fail SSB init because of this */ |
1465 | err = 0; | 1306 | err = 0; |
1466 | } | 1307 | } |
1308 | err = ssb_host_pcmcia_init(); | ||
1309 | if (err) { | ||
1310 | ssb_err("PCMCIA host initialization failed\n"); | ||
1311 | /* don't fail SSB init because of this */ | ||
1312 | err = 0; | ||
1313 | } | ||
1467 | err = ssb_gige_init(); | 1314 | err = ssb_gige_init(); |
1468 | if (err) { | 1315 | if (err) { |
1469 | ssb_err("SSB Broadcom Gigabit Ethernet driver initialization failed\n"); | 1316 | ssb_err("SSB Broadcom Gigabit Ethernet driver initialization failed\n"); |
@@ -1481,6 +1328,7 @@ fs_initcall(ssb_modinit); | |||
1481 | static void __exit ssb_modexit(void) | 1328 | static void __exit ssb_modexit(void) |
1482 | { | 1329 | { |
1483 | ssb_gige_exit(); | 1330 | ssb_gige_exit(); |
1331 | ssb_host_pcmcia_exit(); | ||
1484 | b43_pci_ssb_bridge_exit(); | 1332 | b43_pci_ssb_bridge_exit(); |
1485 | bus_unregister(&ssb_bustype); | 1333 | bus_unregister(&ssb_bustype); |
1486 | } | 1334 | } |
diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h index 8a2ebc88c66f..15bfd5c7d2d7 100644 --- a/drivers/ssb/ssb_private.h +++ b/drivers/ssb/ssb_private.h | |||
@@ -94,6 +94,8 @@ extern int ssb_pcmcia_get_invariants(struct ssb_bus *bus, | |||
94 | extern int ssb_pcmcia_hardware_setup(struct ssb_bus *bus); | 94 | extern int ssb_pcmcia_hardware_setup(struct ssb_bus *bus); |
95 | extern void ssb_pcmcia_exit(struct ssb_bus *bus); | 95 | extern void ssb_pcmcia_exit(struct ssb_bus *bus); |
96 | extern int ssb_pcmcia_init(struct ssb_bus *bus); | 96 | extern int ssb_pcmcia_init(struct ssb_bus *bus); |
97 | extern int ssb_host_pcmcia_init(void); | ||
98 | extern void ssb_host_pcmcia_exit(void); | ||
97 | extern const struct ssb_bus_ops ssb_pcmcia_ops; | 99 | extern const struct ssb_bus_ops ssb_pcmcia_ops; |
98 | #else /* CONFIG_SSB_PCMCIAHOST */ | 100 | #else /* CONFIG_SSB_PCMCIAHOST */ |
99 | static inline int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus, | 101 | 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) | |||
117 | { | 119 | { |
118 | return 0; | 120 | return 0; |
119 | } | 121 | } |
122 | static inline int ssb_host_pcmcia_init(void) | ||
123 | { | ||
124 | return 0; | ||
125 | } | ||
126 | static inline void ssb_host_pcmcia_exit(void) | ||
127 | { | ||
128 | } | ||
120 | #endif /* CONFIG_SSB_PCMCIAHOST */ | 129 | #endif /* CONFIG_SSB_PCMCIAHOST */ |
121 | 130 | ||
122 | /* sdio.c */ | 131 | /* sdio.c */ |
@@ -148,6 +157,13 @@ static inline int ssb_sdio_init(struct ssb_bus *bus) | |||
148 | } | 157 | } |
149 | #endif /* CONFIG_SSB_SDIOHOST */ | 158 | #endif /* CONFIG_SSB_SDIOHOST */ |
150 | 159 | ||
160 | /************************************************** | ||
161 | * host_soc.c | ||
162 | **************************************************/ | ||
163 | |||
164 | #ifdef CONFIG_SSB_HOST_SOC | ||
165 | extern const struct ssb_bus_ops ssb_host_soc_ops; | ||
166 | #endif | ||
151 | 167 | ||
152 | /* scan.c */ | 168 | /* scan.c */ |
153 | extern const char *ssb_core_name(u16 coreid); | 169 | extern const char *ssb_core_name(u16 coreid); |