.. | .. |
---|
179 | 179 | if (!wcn_ch->cpu_addr) |
---|
180 | 180 | return -ENOMEM; |
---|
181 | 181 | |
---|
182 | | - memset(wcn_ch->cpu_addr, 0, size); |
---|
183 | | - |
---|
184 | 182 | cur_dxe = (struct wcn36xx_dxe_desc *)wcn_ch->cpu_addr; |
---|
185 | 183 | cur_ctl = wcn_ch->head_blk_ctl; |
---|
186 | 184 | |
---|
.. | .. |
---|
274 | 272 | return 0; |
---|
275 | 273 | } |
---|
276 | 274 | |
---|
| 275 | +static void wcn36xx_dxe_disable_ch_int(struct wcn36xx *wcn, u16 wcn_ch) |
---|
| 276 | +{ |
---|
| 277 | + int reg_data = 0; |
---|
| 278 | + |
---|
| 279 | + wcn36xx_dxe_read_register(wcn, |
---|
| 280 | + WCN36XX_DXE_INT_MASK_REG, |
---|
| 281 | + ®_data); |
---|
| 282 | + |
---|
| 283 | + reg_data &= ~wcn_ch; |
---|
| 284 | + |
---|
| 285 | + wcn36xx_dxe_write_register(wcn, |
---|
| 286 | + WCN36XX_DXE_INT_MASK_REG, |
---|
| 287 | + (int)reg_data); |
---|
| 288 | +} |
---|
| 289 | + |
---|
277 | 290 | static int wcn36xx_dxe_fill_skb(struct device *dev, |
---|
278 | 291 | struct wcn36xx_dxe_ctl *ctl, |
---|
279 | 292 | gfp_t gfp) |
---|
.. | .. |
---|
336 | 349 | spin_lock_irqsave(&wcn->dxe_lock, flags); |
---|
337 | 350 | skb = wcn->tx_ack_skb; |
---|
338 | 351 | wcn->tx_ack_skb = NULL; |
---|
| 352 | + del_timer(&wcn->tx_ack_timer); |
---|
339 | 353 | spin_unlock_irqrestore(&wcn->dxe_lock, flags); |
---|
340 | 354 | |
---|
341 | 355 | if (!skb) { |
---|
.. | .. |
---|
347 | 361 | |
---|
348 | 362 | if (status == 1) |
---|
349 | 363 | info->flags |= IEEE80211_TX_STAT_ACK; |
---|
| 364 | + else |
---|
| 365 | + info->flags &= ~IEEE80211_TX_STAT_ACK; |
---|
350 | 366 | |
---|
351 | 367 | wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ack status: %d\n", status); |
---|
| 368 | + |
---|
| 369 | + ieee80211_tx_status_irqsafe(wcn->hw, skb); |
---|
| 370 | + ieee80211_wake_queues(wcn->hw); |
---|
| 371 | +} |
---|
| 372 | + |
---|
| 373 | +static void wcn36xx_dxe_tx_timer(struct timer_list *t) |
---|
| 374 | +{ |
---|
| 375 | + struct wcn36xx *wcn = from_timer(wcn, t, tx_ack_timer); |
---|
| 376 | + struct ieee80211_tx_info *info; |
---|
| 377 | + unsigned long flags; |
---|
| 378 | + struct sk_buff *skb; |
---|
| 379 | + |
---|
| 380 | + /* TX Timeout */ |
---|
| 381 | + wcn36xx_dbg(WCN36XX_DBG_DXE, "TX timeout\n"); |
---|
| 382 | + |
---|
| 383 | + spin_lock_irqsave(&wcn->dxe_lock, flags); |
---|
| 384 | + skb = wcn->tx_ack_skb; |
---|
| 385 | + wcn->tx_ack_skb = NULL; |
---|
| 386 | + spin_unlock_irqrestore(&wcn->dxe_lock, flags); |
---|
| 387 | + |
---|
| 388 | + if (!skb) |
---|
| 389 | + return; |
---|
| 390 | + |
---|
| 391 | + info = IEEE80211_SKB_CB(skb); |
---|
| 392 | + info->flags &= ~IEEE80211_TX_STAT_ACK; |
---|
| 393 | + info->flags &= ~IEEE80211_TX_STAT_NOACK_TRANSMITTED; |
---|
352 | 394 | |
---|
353 | 395 | ieee80211_tx_status_irqsafe(wcn->hw, skb); |
---|
354 | 396 | ieee80211_wake_queues(wcn->hw); |
---|
.. | .. |
---|
376 | 418 | dma_unmap_single(wcn->dev, ctl->desc->src_addr_l, |
---|
377 | 419 | ctl->skb->len, DMA_TO_DEVICE); |
---|
378 | 420 | info = IEEE80211_SKB_CB(ctl->skb); |
---|
379 | | - if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) { |
---|
380 | | - /* Keep frame until TX status comes */ |
---|
| 421 | + if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) { |
---|
| 422 | + if (info->flags & IEEE80211_TX_CTL_NO_ACK) { |
---|
| 423 | + info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; |
---|
| 424 | + ieee80211_tx_status_irqsafe(wcn->hw, ctl->skb); |
---|
| 425 | + } else { |
---|
| 426 | + /* Wait for the TX ack indication or timeout... */ |
---|
| 427 | + spin_lock(&wcn->dxe_lock); |
---|
| 428 | + if (WARN_ON(wcn->tx_ack_skb)) |
---|
| 429 | + ieee80211_free_txskb(wcn->hw, wcn->tx_ack_skb); |
---|
| 430 | + wcn->tx_ack_skb = ctl->skb; /* Tracking ref */ |
---|
| 431 | + mod_timer(&wcn->tx_ack_timer, jiffies + HZ / 10); |
---|
| 432 | + spin_unlock(&wcn->dxe_lock); |
---|
| 433 | + } |
---|
| 434 | + /* do not free, ownership transferred to mac80211 status cb */ |
---|
| 435 | + } else { |
---|
381 | 436 | ieee80211_free_txskb(wcn->hw, ctl->skb); |
---|
382 | 437 | } |
---|
383 | 438 | |
---|
.. | .. |
---|
436 | 491 | int_reason); |
---|
437 | 492 | |
---|
438 | 493 | if (int_reason & (WCN36XX_CH_STAT_INT_DONE_MASK | |
---|
439 | | - WCN36XX_CH_STAT_INT_ED_MASK)) |
---|
| 494 | + WCN36XX_CH_STAT_INT_ED_MASK)) { |
---|
440 | 495 | reap_tx_dxes(wcn, &wcn->dxe_tx_h_ch); |
---|
| 496 | + } |
---|
441 | 497 | } |
---|
442 | 498 | |
---|
443 | 499 | if (int_src & WCN36XX_INT_MASK_CHAN_TX_L) { |
---|
.. | .. |
---|
448 | 504 | wcn36xx_dxe_write_register(wcn, |
---|
449 | 505 | WCN36XX_DXE_0_INT_CLR, |
---|
450 | 506 | WCN36XX_INT_MASK_CHAN_TX_L); |
---|
451 | | - |
---|
452 | 507 | |
---|
453 | 508 | if (int_reason & WCN36XX_CH_STAT_INT_ERR_MASK ) { |
---|
454 | 509 | wcn36xx_dxe_write_register(wcn, |
---|
.. | .. |
---|
475 | 530 | int_reason); |
---|
476 | 531 | |
---|
477 | 532 | if (int_reason & (WCN36XX_CH_STAT_INT_DONE_MASK | |
---|
478 | | - WCN36XX_CH_STAT_INT_ED_MASK)) |
---|
| 533 | + WCN36XX_CH_STAT_INT_ED_MASK)) { |
---|
479 | 534 | reap_tx_dxes(wcn, &wcn->dxe_tx_l_ch); |
---|
| 535 | + } |
---|
480 | 536 | } |
---|
481 | 537 | |
---|
482 | 538 | return IRQ_HANDLED; |
---|
.. | .. |
---|
638 | 694 | 16 - (WCN36XX_BD_CHUNK_SIZE % 8); |
---|
639 | 695 | |
---|
640 | 696 | s = wcn->mgmt_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_H; |
---|
641 | | - cpu_addr = dma_alloc_coherent(wcn->dev, s, &wcn->mgmt_mem_pool.phy_addr, |
---|
| 697 | + cpu_addr = dma_alloc_coherent(wcn->dev, s, |
---|
| 698 | + &wcn->mgmt_mem_pool.phy_addr, |
---|
642 | 699 | GFP_KERNEL); |
---|
643 | 700 | if (!cpu_addr) |
---|
644 | 701 | goto out_err; |
---|
645 | 702 | |
---|
646 | 703 | wcn->mgmt_mem_pool.virt_addr = cpu_addr; |
---|
647 | | - memset(cpu_addr, 0, s); |
---|
648 | 704 | |
---|
649 | 705 | /* Allocate BD headers for DATA frames */ |
---|
650 | 706 | |
---|
.. | .. |
---|
653 | 709 | 16 - (WCN36XX_BD_CHUNK_SIZE % 8); |
---|
654 | 710 | |
---|
655 | 711 | s = wcn->data_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_L; |
---|
656 | | - cpu_addr = dma_alloc_coherent(wcn->dev, s, &wcn->data_mem_pool.phy_addr, |
---|
| 712 | + cpu_addr = dma_alloc_coherent(wcn->dev, s, |
---|
| 713 | + &wcn->data_mem_pool.phy_addr, |
---|
657 | 714 | GFP_KERNEL); |
---|
658 | 715 | if (!cpu_addr) |
---|
659 | 716 | goto out_err; |
---|
660 | 717 | |
---|
661 | 718 | wcn->data_mem_pool.virt_addr = cpu_addr; |
---|
662 | | - memset(cpu_addr, 0, s); |
---|
663 | 719 | |
---|
664 | 720 | return 0; |
---|
665 | 721 | |
---|
.. | .. |
---|
828 | 884 | WCN36XX_DXE_WQ_TX_L); |
---|
829 | 885 | |
---|
830 | 886 | wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, ®_data); |
---|
831 | | - wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_L); |
---|
832 | 887 | |
---|
833 | 888 | /***************************************/ |
---|
834 | 889 | /* Init descriptors for TX HIGH channel */ |
---|
.. | .. |
---|
852 | 907 | |
---|
853 | 908 | wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, ®_data); |
---|
854 | 909 | |
---|
855 | | - /* Enable channel interrupts */ |
---|
856 | | - wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_H); |
---|
857 | | - |
---|
858 | 910 | /***************************************/ |
---|
859 | 911 | /* Init descriptors for RX LOW channel */ |
---|
860 | 912 | /***************************************/ |
---|
.. | .. |
---|
863 | 915 | dev_err(wcn->dev, "Error allocating descriptor\n"); |
---|
864 | 916 | goto out_err_rxl_ch; |
---|
865 | 917 | } |
---|
866 | | - |
---|
867 | 918 | |
---|
868 | 919 | /* For RX we need to preallocated buffers */ |
---|
869 | 920 | wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_l_ch); |
---|
.. | .. |
---|
886 | 937 | wcn36xx_dxe_write_register(wcn, |
---|
887 | 938 | WCN36XX_DXE_REG_CTL_RX_L, |
---|
888 | 939 | WCN36XX_DXE_CH_DEFAULT_CTL_RX_L); |
---|
889 | | - |
---|
890 | | - /* Enable channel interrupts */ |
---|
891 | | - wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_L); |
---|
892 | 940 | |
---|
893 | 941 | /***************************************/ |
---|
894 | 942 | /* Init descriptors for RX HIGH channel */ |
---|
.. | .. |
---|
921 | 969 | WCN36XX_DXE_REG_CTL_RX_H, |
---|
922 | 970 | WCN36XX_DXE_CH_DEFAULT_CTL_RX_H); |
---|
923 | 971 | |
---|
924 | | - /* Enable channel interrupts */ |
---|
925 | | - wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_H); |
---|
926 | | - |
---|
927 | 972 | ret = wcn36xx_dxe_request_irqs(wcn); |
---|
928 | 973 | if (ret < 0) |
---|
929 | 974 | goto out_err_irq; |
---|
| 975 | + |
---|
| 976 | + timer_setup(&wcn->tx_ack_timer, wcn36xx_dxe_tx_timer, 0); |
---|
| 977 | + |
---|
| 978 | + /* Enable channel interrupts */ |
---|
| 979 | + wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_L); |
---|
| 980 | + wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_H); |
---|
| 981 | + wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_L); |
---|
| 982 | + wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_H); |
---|
930 | 983 | |
---|
931 | 984 | return 0; |
---|
932 | 985 | |
---|
.. | .. |
---|
944 | 997 | |
---|
945 | 998 | void wcn36xx_dxe_deinit(struct wcn36xx *wcn) |
---|
946 | 999 | { |
---|
| 1000 | + int reg_data = 0; |
---|
| 1001 | + |
---|
| 1002 | + /* Disable channel interrupts */ |
---|
| 1003 | + wcn36xx_dxe_disable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_H); |
---|
| 1004 | + wcn36xx_dxe_disable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_L); |
---|
| 1005 | + wcn36xx_dxe_disable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_H); |
---|
| 1006 | + wcn36xx_dxe_disable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_L); |
---|
| 1007 | + |
---|
947 | 1008 | free_irq(wcn->tx_irq, wcn); |
---|
948 | 1009 | free_irq(wcn->rx_irq, wcn); |
---|
| 1010 | + del_timer(&wcn->tx_ack_timer); |
---|
949 | 1011 | |
---|
950 | 1012 | if (wcn->tx_ack_skb) { |
---|
951 | 1013 | ieee80211_tx_status_irqsafe(wcn->hw, wcn->tx_ack_skb); |
---|
952 | 1014 | wcn->tx_ack_skb = NULL; |
---|
953 | 1015 | } |
---|
954 | 1016 | |
---|
| 1017 | + /* Put the DXE block into reset before freeing memory */ |
---|
| 1018 | + reg_data = WCN36XX_DXE_REG_RESET; |
---|
| 1019 | + wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_REG_CSR_RESET, reg_data); |
---|
| 1020 | + |
---|
955 | 1021 | wcn36xx_dxe_ch_free_skbs(wcn, &wcn->dxe_rx_l_ch); |
---|
956 | 1022 | wcn36xx_dxe_ch_free_skbs(wcn, &wcn->dxe_rx_h_ch); |
---|
957 | 1023 | |
---|