Re: [RFC v2 02/12] rtw88: core files

2018-10-04 Thread Stanislaw Gruszka
On Thu, Oct 04, 2018 at 01:42:35PM +0200, Stanislaw Gruszka wrote:
> On Wed, Oct 03, 2018 at 04:02:18PM +0800, yhchu...@realtek.com wrote:
> > +static void rtw_restore_port_cfg(struct rtw_dev *rtwdev)
> > +{
> > +   struct rtw_vif *rtwvif;
> > +   u32 config = ~0;
> > +
> > +   rcu_read_lock();
> > +   list_for_each_entry(rtwvif, &rtwdev->vif_list, list)
> list_for_each_entry_rcu
> 
> > +void rtw_lps_enter_check(struct rtw_dev *rtwdev)
> > +{
> > +   struct rtw_vif *rtwvif, *lps_if;
> > +   u8 assoc_cnt = 0;
> > +
> > +   rcu_read_lock();
> > +   list_for_each_entry(rtwvif, &rtwdev->vif_list, list) {
> list_for_each_entry_rcu

Ok fixed in v3 , I just realized that I'm reviewing v2.



Re: [PATCH 01/12] rtwlan: main files

2018-10-04 Thread Stanislaw Gruszka
On Thu, Oct 04, 2018 at 03:39:55PM +0300, Kalle Valo wrote:
> >> Can we put the configuration file in the firmware directory?
> >> Should we package them into binary files? Or just put the raw data.
> >>
> >> We can test the performance for it. After we got the result, we will make 
> >> a decision
> >> about it. And if we decide to put them in the firmware directory, will 
> >> send a patch.
> >> For now, I think we can just leave them in the .c.
> >
> > Yes, you could put the configuration files in the firmware directory.
> > I would put them in binary form, not as text files. That way the size
> > would be smaller, and it would not be possible to alter them,
> > particularly if the binary file is checksummed.
> >
> > It would likely be OK if only the agc table was stored in this way.
> > That would take away about half of the lines in the 8822b table file.
> 
> So what's the worry here? The lines of source code, binary size or what?
> 
>  .../net/wireless/realtek/rtw88/rtw8822b_table.c| 20783 
> +++
> 
> Looking at the diffstat rtw8822b_table.c seems to be 20 kLOC, IMHO it's
> not that bad as it's just data. But of course I might be missing
> something as I haven't checked patches yet.

My concern was it's plenty of redundant data, for example:

0x81C, 0xFF03,
0x81C, 0xFE03,
0x81C, 0xFD020003,
0x81C, 0xFC040003,
0x81C, 0xFB060003,
0x81C, 0xFA080003,
0x81C, 0xF90A0003,
0x81C, 0xF80C0003,
0x81C, 0xF70E0003,
0x81C, 0xF613,

Approx 1 lines like this, braked by lines like this

0x9012, 0x, 0x4000, 0x,

in more or less regular way.

Not big deal, but perhaps this could be coded in much more compact way.

Regards
Stanislaw



Re: [RFC v2 03/12] rtw88: hci files

2018-10-04 Thread Stanislaw Gruszka
On Thu, Oct 04, 2018 at 03:02:13PM +0200, Stanislaw Gruszka wrote:
> > +   WARN(flag, "DBI write fail");
> We always print WARN, there is other return point in this function.
> 
> > +static void rtw_mdio_write(struct rtw_dev *rtwdev, u8 addr, u16 data, bool 
> > g1)
> 
> > +   WARN(wflag, "MDIO write fail");
> The same.

This is ok, I missed that WARN is printed only conditionally.


Re: [RFC v2 04/12] rtw88: trx files

2018-10-04 Thread Stanislaw Gruszka
On Wed, Oct 03, 2018 at 04:02:20PM +0800, yhchu...@realtek.com wrote:
> +static void rtw_rx_rssi_add(struct rtw_dev *rtwdev,
> + struct rtw_rx_pkt_stat *pkt_stat,
> + struct ieee80211_hdr *hdr)
> +{
> + struct ieee80211_vif *vif;
> + struct rtw_vif *rtwvif;
> + struct rtw_sta_info *si;
> + __le16 fc = hdr->frame_control;
> + u8 *bssid;
> + u8 macid = RTW_BC_MC_MACID;
> + bool match_bssid = false;
> + bool is_packet_match_bssid;
> + bool if_addr_match;
> + bool hw_err;
> + bool ctl;
> +
> + rcu_read_lock();
> +
> + bssid = get_hdr_bssid(hdr);
> + rtwvif = get_hdr_vif(rtwdev, hdr);
> + vif = rtwvif ? rtwvif->vif : NULL;
> + pkt_stat->vif = vif;
> + if (unlikely(is_broadcast_ether_addr(hdr->addr1) ||
> +  is_multicast_ether_addr(hdr->addr1)))
> + match_bssid = get_hdr_match_bssid(rtwdev, hdr, bssid);
> + else if (vif)
> + match_bssid = ether_addr_equal(vif->bss_conf.bssid, bssid);
> + si = get_hdr_sta(rtwdev, vif, hdr);
> + macid = si ? si->mac_id : RTW_BC_MC_MACID;
> + pkt_stat->mac_id = macid;
> + pkt_stat->si = si;
> +
> + if_addr_match = !!vif;
> + hw_err = pkt_stat->crc_err || pkt_stat->icv_err;
> + ctl = ieee80211_is_ctl(fc);
> + is_packet_match_bssid = !hw_err && !ctl && match_bssid;
> +
> + if (((match_bssid && if_addr_match) || ieee80211_is_beacon(fc)) &&
> + (!hw_err && !ctl) && (pkt_stat->phy_status && pkt_stat->si))
> + ewma_rssi_add(&pkt_stat->si->avg_rssi, pkt_stat->rssi);
> +
> + rcu_read_unlock();

What for rcu_read_lock/unlock is here ? Maybe is needed,
but perhaps not to protect entire function ?

> +static u8 get_tx_ampdu_factor(struct ieee80211_sta *sta)
> +{
> + u8 exp = sta->ht_cap.ampdu_factor;
> +
> + /* the least ampdu factor is 8K, and the value in the tx desc is the
> +  * max aggregation num, which represents val * 2 packets can be
> +  * aggregated in an AMPDU, so here we should use 8/2=4 as the base
> +  */
> + return (BIT(2) << exp) - 1;
Using 4 whould be much more readable.

> +static void rtw_tx_data_pkt_info_update(struct rtw_dev *rtwdev,
> + struct rtw_tx_pkt_info *pkt_info,
> + struct ieee80211_tx_control *control,
> + struct sk_buff *skb)
> +{

> + if (sta->vht_cap.vht_supported)
> + rate = get_highest_vht_tx_rate(rtwdev, sta);
> + else if (sta->ht_cap.ht_supported)
> + rate = get_highest_ht_tx_rate(rtwdev, sta);
> + else if (sta->supp_rates[0] <= 0xf)
> + rate = DESC_RATE11M;
> + else
> + rate = DESC_RATE54M;
No rate control, just use highest possible rate for each standard ?

> +
> + pkt_info->bmc = bmc;
> + pkt_info->sec_type = sec_type;
> + pkt_info->tx_pkt_size = skb->len;
> + pkt_info->offset = chip->tx_pkt_desc_sz;
> + pkt_info->qsel = skb->priority;

Shouldn't be qsel somehow mapped from skb->priority ?

Thanks
Stanislaw


Re: [RFC v2 03/12] rtw88: hci files

2018-10-04 Thread Stanislaw Gruszka
On Wed, Oct 03, 2018 at 04:02:19PM +0800, yhchu...@realtek.com wrote:
> +static inline u32
> +rtw_read_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
> + u32 addr, u32 mask)
> +{
> + unsigned long flags;
> + u32 val;
> +
> + spin_lock_irqsave(&rtwdev->rf_lock, flags);
> + val = rtwdev->chip->ops->read_rf(rtwdev, rf_path, addr, mask);
> + spin_unlock_irqrestore(&rtwdev->rf_lock, flags);

What for is rtwdev->rf_lock lock ? Is possible to call
rtw_read_rf() or rtw_write_rf() in some simultanious way ?

> +static int rtw_pci_reset_rx_desc(struct rtw_dev *rtwdev, struct sk_buff *skb,
> +  struct rtw_pci_rx_ring *rx_ring,
> +  u32 idx, u32 desc_sz)
> +{
> + struct pci_dev *pdev = to_pci_dev(rtwdev->dev);
> + struct rtw_pci_rx_buffer_desc *buf_desc;
> + int buf_sz = RTK_PCI_RX_BUF_SIZE;
> + dma_addr_t dma;
> +
> + if (!skb)
> + return -EINVAL;
Too late, see below.

> +
> + dma = pci_map_single(pdev, skb->data, buf_sz, PCI_DMA_FROMDEVICE);
> + if (pci_dma_mapping_error(pdev, dma))
> + return -EBUSY;
> +
> + *((dma_addr_t *)skb->cb) = dma;
> + buf_desc = (struct rtw_pci_rx_buffer_desc *)(rx_ring->r.head +
> +  idx * desc_sz);
> + memset(buf_desc, 0, sizeof(*buf_desc));
> + buf_desc->buf_size = cpu_to_le16(8216);

Why the difference between RTK_PCI_RX_BUF_SIZE = 9100 and this 8216 ? 

> +static int rtw_pci_init_rx_ring(struct rtw_dev *rtwdev,
> + struct rtw_pci_rx_ring *rx_ring,
> + u8 desc_size, u32 len)
> +{
> + struct pci_dev *pdev = to_pci_dev(rtwdev->dev);
> + struct sk_buff *skb = NULL;
> + dma_addr_t dma;
> + u8 *head;
> + int ring_sz = desc_size * len;
> + int buf_sz = RTK_PCI_RX_BUF_SIZE;
> + int i, allocated;
> + int ret = 0;
> +
> + head = pci_zalloc_consistent(pdev, ring_sz, &dma);
> + if (!head) {
> + rtw_err(rtwdev, "failed to allocate rx ring\n");
> + return -ENOMEM;
> + }
> + rx_ring->r.head = head;
> +
> + for (i = 0; i < len; i++) {
> + skb = dev_alloc_skb(buf_sz);
> + memset(skb->data, 0, buf_sz);
No error check. Also I think you should use different version to 
allow specify GPF_KERNEL flag, this is not atomic context.

> +static void rtw_pci_dma_check(struct rtw_dev *rtwdev,
> +   struct rtw_pci_rx_ring *rx_ring,
> +   u32 idx)
> +{
> + struct rtw_chip_info *chip = rtwdev->chip;
> + struct rtw_pci_rx_buffer_desc *buf_desc;
> + u32 desc_sz = chip->rx_buf_desc_sz;
> + u16 total_pkt_size;
> + int i;
> +
> + buf_desc = (struct rtw_pci_rx_buffer_desc *)(rx_ring->r.head +
> +  idx * desc_sz);
> + for (i = 0; i < 20; i++) {
> + total_pkt_size = le16_to_cpu(buf_desc->total_pkt_size);
> + if (total_pkt_size)
> + return;
> + }
> +
> + if (i >= 20)
> + rtw_warn(rtwdev, "pci bus timeout, drop packet\n");
This is not right, most likely you need to use
dma_sync_single_for_cpu() .

> +static int rtw_pci_tx(struct rtw_dev *rtwdev,
> +   struct rtw_tx_pkt_info *pkt_info,
> +   struct sk_buff *skb)
> +{
> + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
> + struct rtw_pci_tx_ring *ring;
> + u8 queue = rtw_hw_queue_mapping(skb);
> + int ret;
> +
> + ret = rtw_pci_xmit(rtwdev, pkt_info, skb, queue);
> + if (ret)
> + return ret;
> +
> + ring = &rtwpci->tx_rings[queue];
> + if (avail_desc(ring->r.wp, ring->r.rp, ring->r.len) < 2) {
> + ieee80211_stop_queue(rtwdev->hw, skb_get_queue_mapping(skb));
> + ring->queue_stopped = true;
I think here is race condition with below code that wakes queue...

> + if (ring->queue_stopped &&
> + avail_desc(ring->r.wp, ring->r.rp, ring->r.len) > 4) {
> + q_map = skb_get_queue_mapping(skb);
> + ieee80211_wake_queue(hw, q_map);
> + ring->queue_stopped = false;

... here. This should be somehow synchronized.
> + }
> +
> + info = IEEE80211_SKB_CB(skb);
> + ieee80211_tx_info_clear_status(info);
> + info->flags |= IEEE80211_TX_STAT_ACK;
> + ieee80211_tx_status_irqsafe(hw, skb);

Always report ACK ?
> +
> +static irqreturn_t rtw_pci_interrupt_handler(int irq, void *dev)
> +{
> + struct rtw_dev *rtwdev = dev;
> + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
> + u32 irq_status[4];
> + unsigned long flags;
> +
> + spin_lock_irqsave(&rtwpci->irq_lock, flags);

flags not needed, interrupts are disabled in IRQ.

> + rtw_pci_disable_interrupt(rtwdev, rtwpci);

This seems

Re: [RFC v2 02/12] rtw88: core files

2018-10-04 Thread Stanislaw Gruszka
On Wed, Oct 03, 2018 at 04:02:18PM +0800, yhchu...@realtek.com wrote:
> +static void rtw_restore_port_cfg(struct rtw_dev *rtwdev)
> +{
> + struct rtw_vif *rtwvif;
> + u32 config = ~0;
> +
> + rcu_read_lock();
> + list_for_each_entry(rtwvif, &rtwdev->vif_list, list)
list_for_each_entry_rcu

> +void rtw_lps_enter_check(struct rtw_dev *rtwdev)
> +{
> + struct rtw_vif *rtwvif, *lps_if;
> + u8 assoc_cnt = 0;
> +
> + rcu_read_lock();
> + list_for_each_entry(rtwvif, &rtwdev->vif_list, list) {
list_for_each_entry_rcu

> +static struct country_code_to_enum_rd all_countries[] = {
> + {COUNTRY_CODE_FCC, "US"},
> + {COUNTRY_CODE_IC, "US"},
> + {COUNTRY_CODE_ETSI, "EC"},
> + {COUNTRY_CODE_SPAIN, "EC"},
> + {COUNTRY_CODE_FRANCE, "EC"},
> + {COUNTRY_CODE_MKK, "JP"},
> + {COUNTRY_CODE_MKK1, "JP"},
> + {COUNTRY_CODE_ISRAEL, "EC"},
> + {COUNTRY_CODE_TELEC, "JP"},
> + {COUNTRY_CODE_MIC, "JP"},
> + {COUNTRY_CODE_GLOBAL_DOMAIN, "JP"},
> + {COUNTRY_CODE_WORLD_WIDE_13, "EC"},
> + {COUNTRY_CODE_TELEC_NETGEAR, "EC"},
> + {COUNTRY_CODE_WORLD_WIDE_13_5G_ALL, "US"},
> +};
> +
> +/* Only these channels allow active
> + * scan on all world regulatory domains
> + */
> +#define RTW_2GHZ_CH01_11 \
> + REG_RULE(2412 - 10, 2462 + 10, 40, 0, 20, 0)

> +static const
> +struct ieee80211_regdomain *rtw_regdomain_select(struct rtw_regulatory *reg)
> +{
> + switch (reg->country_code) {
> + case COUNTRY_CODE_FCC:
> + return &rtw_regdom_no_midband;
> + case COUNTRY_CODE_IC:
> + return &rtw_regdom_11;
> + case COUNTRY_CODE_TELEC_NETGEAR:
> + return &rtw_regdom_60_64;
> + case COUNTRY_CODE_ETSI:
> + case COUNTRY_CODE_SPAIN:
> + case COUNTRY_CODE_FRANCE:
> + case COUNTRY_CODE_ISRAEL:
> + return &rtw_regdom_12_13;
> + case COUNTRY_CODE_MKK:
> + case COUNTRY_CODE_MKK1:
> + case COUNTRY_CODE_TELEC:
> + case COUNTRY_CODE_MIC:
> + return &rtw_regdom_14_60_64;
> + case COUNTRY_CODE_GLOBAL_DOMAIN:
> + return &rtw_regdom_14;
> + case COUNTRY_CODE_WORLD_WIDE_13:
> + case COUNTRY_CODE_WORLD_WIDE_13_5G_ALL:
> + return &rtw_regdom_12_13_5g_all;
> + default:
> + return &rtw_regdom_no_midband;
> + }

I'm not an expert on this, but I wonder if this is really needed
and standard linux regd stuff can not be used and regulatory
rules read from wireless-regd data-base.

Thanks
Stanislaw


Re: [RFC v2 06/12] rtw88: fw and efuse files

2018-10-04 Thread Stanislaw Gruszka
Hi

On Wed, Oct 03, 2018 at 04:02:22PM +0800, yhchu...@realtek.com wrote:
> +void rtw_fw_do_iqk(struct rtw_dev *rtwdev, struct rtw_iqk_para *para)
> +{
> + u8 h2c_pkt[H2C_PKT_SIZE] = {0};

Not sure if '= {0}' work as expected for arrays, you
want to nulify first byte or whole h2c_pkt ?

> +void rtw_add_rsvd_page(struct rtw_dev *rtwdev, enum rtw_rsvd_packet_type 
> type,
> +bool txdesc)
> +{
> + struct rtw_rsvd_page *rsvd_pkt;
> +
> + list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) {
> + if (rsvd_pkt->type == type)
> + return;
> + }
> +
> + rsvd_pkt = kmalloc(sizeof(*rsvd_pkt),
> +in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);

It's never called from interrupt. You have to check kmalloc output value.

> + rsvd_pkt->type = type;
> + rsvd_pkt->add_txdesc = txdesc;
> + list_add_tail(&rsvd_pkt->list, &rtwdev->rsvd_page_list);

> +
> +void rtw_reset_rsvd_page(struct rtw_dev *rtwdev)
> +{
> + struct rtw_rsvd_page *rsvd_pkt, *tmp;
> +
> + list_for_each_entry_safe(rsvd_pkt, tmp, &rtwdev->rsvd_page_list, list) {
> + if (rsvd_pkt->type == RSVD_BEACON)
> + continue;
> + list_del(&rsvd_pkt->list);
> + kfree(rsvd_pkt);
> + }

It also not clear how the list is protected agains concurrent access.
However seems like much simpler solution would be use array instead of
the list. For example above code could be replaced by:

for (i = RSVD_BEACON + 1; i <= RSVD_QOS_NULL ; i++) {
kfree(rwdev->rsvd_page_arr[i]));
rsvd_page_arr[i] = NULL;
}

And other operations like adding / removing / checking if present could
be simplified as well.

Also RSVD_PROBE_RESP page is never created.

> + *size = (total_page - 1) * page_size + page_margin;
> + buf = kzalloc(*size, GFP_KERNEL | GFP_ATOMIC);

Those GPF flags contradict to each other :-)
and buf not checked agains NULL.

Thanks
Stanislaw


[PATCH 1/5] mt76x0: print BBP version only for debug

2018-10-04 Thread Stanislaw Gruszka
Use dev_dbg to print BBP version.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/phy.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
index ba3b5847af48..cbbfd5193d9c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
@@ -186,7 +186,6 @@ int mt76x0_wait_bbp_ready(struct mt76x02_dev *dev)
 
do {
val = mt76_rr(dev, MT_BBP(CORE, 0));
-   printk("BBP version %08x\n", val);
if (val && ~val)
break;
} while (--i);
@@ -196,6 +195,7 @@ int mt76x0_wait_bbp_ready(struct mt76x02_dev *dev)
return -EIO;
}
 
+   dev_dbg(dev->mt76.dev, "BBP version %08x\n", val);
return 0;
 }
 
-- 
1.9.3



[PATCH 2/5] mt76x0: correct RF access via RF_CSR regiser.

2018-10-04 Thread Stanislaw Gruszka
PCIe version don't use MCU for RF regsisters access. We need
to correct RF CSR method to support up to 127 RF registers.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/phy.c   | 6 ++
 drivers/net/wireless/mediatek/mt76/mt76x02_regs.h | 4 ++--
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
index cbbfd5193d9c..da4569f00794 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
@@ -37,7 +37,7 @@
bank = MT_RF_BANK(offset);
reg = MT_RF_REG(offset);
 
-   if (WARN_ON_ONCE(reg > 64) || WARN_ON_ONCE(bank) > 8)
+   if (WARN_ON_ONCE(reg > 127) || WARN_ON_ONCE(bank) > 8)
return -EINVAL;
 
mutex_lock(&dev->phy_mutex);
@@ -76,7 +76,7 @@ static int mt76x0_rf_csr_rr(struct mt76x02_dev *dev, u32 
offset)
bank = MT_RF_BANK(offset);
reg = MT_RF_REG(offset);
 
-   if (WARN_ON_ONCE(reg > 64) || WARN_ON_ONCE(bank) > 8)
+   if (WARN_ON_ONCE(reg > 127) || WARN_ON_ONCE(bank) > 8)
return -EINVAL;
 
mutex_lock(&dev->phy_mutex);
@@ -119,7 +119,6 @@ static int mt76x0_rf_csr_rr(struct mt76x02_dev *dev, u32 
offset)
 
return mt76_wr_rp(dev, MT_MCU_MEMMAP_RF, &pair, 1);
} else {
-   WARN_ON_ONCE(1);
return mt76x0_rf_csr_wr(dev, offset, val);
}
 }
@@ -138,7 +137,6 @@ static int mt76x0_rf_csr_rr(struct mt76x02_dev *dev, u32 
offset)
ret = mt76_rd_rp(dev, MT_MCU_MEMMAP_RF, &pair, 1);
val = pair.value;
} else {
-   WARN_ON_ONCE(1);
ret = val = mt76x0_rf_csr_rr(dev, offset);
}
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h 
b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h
index 24d1e6d747dd..f7de77d09d28 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h
@@ -205,8 +205,8 @@
 #define MT_TXQ_STA 0x0434
 #defineMT_RF_CSR_CFG   0x0500
 #define MT_RF_CSR_CFG_DATA GENMASK(7, 0)
-#define MT_RF_CSR_CFG_REG_ID   GENMASK(13, 8)
-#define MT_RF_CSR_CFG_REG_BANK GENMASK(17, 14)
+#define MT_RF_CSR_CFG_REG_ID   GENMASK(14, 8)
+#define MT_RF_CSR_CFG_REG_BANK GENMASK(17, 15)
 #define MT_RF_CSR_CFG_WR   BIT(30)
 #define MT_RF_CSR_CFG_KICK BIT(31)
 
-- 
1.9.3



[PATCH 4/5] mt76x0: correct RF reg pairs write for PCIe

2018-10-04 Thread Stanislaw Gruszka
We have to use RF CSR method for PCIe.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/phy.c | 19 ---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
index da4569f00794..8e4194e59398 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
@@ -173,9 +173,22 @@ static int mt76x0_rf_csr_rr(struct mt76x02_dev *dev, u32 
offset)
 }
 #endif
 
-#define RF_RANDOM_WRITE(dev, tab)  \
-   mt76_wr_rp(dev, MT_MCU_MEMMAP_RF,   \
-  tab, ARRAY_SIZE(tab))
+static void
+mt76x0_rf_csr_wr_rp(struct mt76x02_dev *dev, const struct mt76_reg_pair *data,
+   int n)
+{
+   while (n-- > 0) {
+   mt76x0_rf_csr_wr(dev, data->reg, data->value);
+   data++;
+   }
+}
+
+#define RF_RANDOM_WRITE(dev, tab) do { \
+   if (mt76_is_mmio(dev))  \
+   mt76x0_rf_csr_wr_rp(dev, tab, ARRAY_SIZE(tab)); \
+   else\
+   mt76_wr_rp(dev, MT_MCU_MEMMAP_RF, tab, ARRAY_SIZE(tab));\
+} while (0)
 
 int mt76x0_wait_bbp_ready(struct mt76x02_dev *dev)
 {
-- 
1.9.3



[PATCH 5/5] mt76x0: use bus helper to identify rf access method

2018-10-04 Thread Stanislaw Gruszka
Use mt76_is_usb() to identify RF access method instead of
MT76_STATE_MCU_RUNNING flag and add warning since MCU has
to be initialized before we can access RF registers via MCU.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/phy.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
index 8e4194e59398..202f436eb358 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
@@ -111,12 +111,14 @@ static int mt76x0_rf_csr_rr(struct mt76x02_dev *dev, u32 
offset)
 static int
 rf_wr(struct mt76x02_dev *dev, u32 offset, u8 val)
 {
-   if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state)) {
+   if (mt76_is_usb(dev)) {
struct mt76_reg_pair pair = {
.reg = offset,
.value = val,
};
 
+   WARN_ON_ONCE(!test_bit(MT76_STATE_MCU_RUNNING,
+&dev->mt76.state));
return mt76_wr_rp(dev, MT_MCU_MEMMAP_RF, &pair, 1);
} else {
return mt76x0_rf_csr_wr(dev, offset, val);
@@ -129,11 +131,13 @@ static int mt76x0_rf_csr_rr(struct mt76x02_dev *dev, u32 
offset)
int ret;
u32 val;
 
-   if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state)) {
+   if (mt76_is_usb(dev)) {
struct mt76_reg_pair pair = {
.reg = offset,
};
 
+   WARN_ON_ONCE(!test_bit(MT76_STATE_MCU_RUNNING,
+&dev->mt76.state));
ret = mt76_rd_rp(dev, MT_MCU_MEMMAP_RF, &pair, 1);
val = pair.value;
} else {
-- 
1.9.3



[PATCH 3/5] mt76: allow to identify bus

2018-10-04 Thread Stanislaw Gruszka
Add helpers to identify bus type.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mmio.c | 1 +
 drivers/net/wireless/mediatek/mt76/mt76.h | 9 +
 drivers/net/wireless/mediatek/mt76/usb.c  | 1 +
 3 files changed, 11 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mmio.c 
b/drivers/net/wireless/mediatek/mt76/mmio.c
index 30a5d928e655..1d6bbce76041 100644
--- a/drivers/net/wireless/mediatek/mt76/mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mmio.c
@@ -79,6 +79,7 @@ void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs)
.copy = mt76_mmio_copy,
.wr_rp = mt76_mmio_wr_rp,
.rd_rp = mt76_mmio_rd_rp,
+   .type = MT76_BUS_MMIO,
};
 
dev->bus = &mt76_mmio_ops;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h 
b/drivers/net/wireless/mediatek/mt76/mt76.h
index f723a07cab29..3bfa7f5e3513 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -38,6 +38,11 @@ struct mt76_reg_pair {
u32 value;
 };
 
+enum mt76_bus_type {
+   MT76_BUS_MMIO,
+   MT76_BUS_USB,
+};
+
 struct mt76_bus_ops {
u32 (*rr)(struct mt76_dev *dev, u32 offset);
void (*wr)(struct mt76_dev *dev, u32 offset, u32 val);
@@ -48,8 +53,12 @@ struct mt76_bus_ops {
 const struct mt76_reg_pair *rp, int len);
int (*rd_rp)(struct mt76_dev *dev, u32 base,
 struct mt76_reg_pair *rp, int len);
+   enum mt76_bus_type type;
 };
 
+#define mt76_is_usb(dev) ((dev)->mt76.bus->type == MT76_BUS_USB)
+#define mt76_is_mmio(dev) ((dev)->mt76.bus->type == MT76_BUS_MMIO)
+
 enum mt76_txq_id {
MT_TXQ_VO = IEEE80211_AC_VO,
MT_TXQ_VI = IEEE80211_AC_VI,
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c 
b/drivers/net/wireless/mediatek/mt76/usb.c
index 6b643ea701e3..cccb143e57b0 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -862,6 +862,7 @@ int mt76u_init(struct mt76_dev *dev,
.copy = mt76u_copy,
.wr_rp = mt76u_wr_rp,
.rd_rp = mt76u_rd_rp,
+   .type = MT76_BUS_USB,
};
struct mt76_usb *usb = &dev->usb;
 
-- 
1.9.3



[PATCH 0/5] mt76x0: phy/rf fixups for PCIe

2018-10-04 Thread Stanislaw Gruszka
Changes since RFC:
- regbase on top of mt76x02_dev change
- add patch to choose single reg RF access via mt76_is_usb()

Stanislaw Gruszka (5):
  mt76x0: print BBP version only for debug
  mt76x0: correct RF access via RF_CSR regiser.
  mt76: allow to identify bus
  mt76x0: correct RF reg pairs write for PCIe
  mt76x0: use bus helper to identify rf access method

 drivers/net/wireless/mediatek/mt76/mmio.c |  1 +
 drivers/net/wireless/mediatek/mt76/mt76.h |  9 ++
 drivers/net/wireless/mediatek/mt76/mt76x0/phy.c   | 35 ---
 drivers/net/wireless/mediatek/mt76/mt76x02_regs.h |  4 +--
 drivers/net/wireless/mediatek/mt76/usb.c  |  1 +
 5 files changed, 38 insertions(+), 12 deletions(-)

-- 
1.9.3



Re: [PATCH] net: wireless: iwlegacy: Fix possible data races in il4965_send_rxon_assoc()

2018-10-04 Thread Stanislaw Gruszka
On Wed, Oct 03, 2018 at 10:07:45PM +0800, Jia-Ju Bai wrote:
> These possible races are detected by a runtime testing. 
> To fix these races, the mutex lock is used in il4965_send_rxon_assoc() 
> to protect the data.

Really ? I'm surprised by that, see below.

> @@ -1297,6 +1297,7 @@ il4965_send_rxon_assoc(struct il_priv *il)
>   const struct il_rxon_cmd *rxon1 = &il->staging;
>   const struct il_rxon_cmd *rxon2 = &il->active;
>  
> + mutex_lock(&il->mutex);
>   if (rxon1->flags == rxon2->flags &&

For 4965 driver il4965_send_rxon_assoc() is only called by
il_mac_bss_info_changed() and il4965_commit_rxon().

il_mac_bss_info_changed() acquire il->mutex and
callers of  il4965_commit_rxon() acquire il->mutex
(but I did not check all of them).

So I wonder how this patch did not cause the deadlock ?
  
Anyway what can be done is adding:

lockdep_assert_held(&il->mutex);

il4965_commit_rxon() to check if we hold the mutex.

Thanks
Stanislaw


Re: new mt76 usb crashes on device removal

2018-10-03 Thread Stanislaw Gruszka
On Wed, Oct 03, 2018 at 04:09:06PM +0200, Lorenzo Bianconi wrote:
> > It still crashes. You can not reproduce the problem ?
> > It's 100% reproducible for me, when I unplug mt76x0u or mt76x2 device.
> 
> Hi Stanislaw,
> 
> any news about the latest patchset I sent to fix that issue?

It fixed the problem, I thought you tested that by yourself.

Regards
Stanislaw


Re: [PATCH 06/10] mt76x2: move mt76x2_dev in mt76x02_util.h

2018-10-03 Thread Stanislaw Gruszka
On Wed, Oct 03, 2018 at 03:51:32PM +0200, Felix Fietkau wrote:
> >> > }
> >> > 
> >> > put them into mt76xN_dev and still remove dupicated code ?
> >> Quite often, mt76_dev would be needed as well for register access, which 
> >> means extra parameters for a lot of functions.
> >> I think Lorenzo’s approach makes the code a lot more concise, and makes it 
> >> easier to share more code between mt76x0 and mt76x2.
> > 
> > I think this could be solved very easly by container_of() macro if
> > there will be one mt76x02_dev struct just after mt76_dev.
> That's possible, yes. But given how much code can still be unified
> between mt76x0 and mt76x2, I don't think there will be much need for a
> x0 or x2 specific device struct. And in that case, the code will be more
> readable if we avoid putting a lot of unnecessary &dev->mt76x02 or
> container_of in the code.

Ok, I guess can live with mt76x02_dev :-)

Thanks
Stanislaw


Re: [PATCH 06/10] mt76x2: move mt76x2_dev in mt76x02_util.h

2018-10-03 Thread Stanislaw Gruszka
On Wed, Oct 03, 2018 at 01:49:23PM +0200, Felix Fietkau wrote:
> 
> 
> > On 3. Oct 2018, at 13:12, Stanislaw Gruszka  wrote:
> > 
> > On Wed, Oct 03, 2018 at 01:01:40PM +0200, Lorenzo Bianconi wrote:
> >>> 
> >>> On Tue, Oct 02, 2018 at 12:19:04AM +0200, Lorenzo Bianconi wrote:
> >>>> Move mt76x2_dev in mt76x02_util.h and rename it in mt76x02_dev
> >>>> in order to be shared between mt76x2 and mt76x0 driver
> >>> 
> >>>> +struct mt76x02_dev {
> >>>> + struct mt76_dev mt76; /* must be first */
> >>>> +
> >>>> + struct mac_address macaddr_list[8];
> >>>> +
> >>>> + struct mutex mutex;
> >>>> +
> >>>> + u8 txdone_seq;
> >>>> + DECLARE_KFIFO_PTR(txstatus_fifo, struct mt76x02_tx_status);
> >>>> +
> >>>> + struct sk_buff *rx_head;
> >>>> +
> >>>> + struct tasklet_struct tx_tasklet;
> >>>> + struct tasklet_struct pre_tbtt_tasklet;
> >>>> + struct delayed_work cal_work;
> >>>> + struct delayed_work mac_work;
> >>>> +
> >>>> + u32 aggr_stats[32];
> >>>> +
> >>>> + struct sk_buff *beacons[8];
> >>>> + u8 beacon_mask;
> >>>> + u8 beacon_data_mask;
> >>>> +
> >>>> + u8 tbtt_count;
> >>>> + u16 beacon_int;
> >>>> +
> >>>> + struct mt76x02_calibration cal;
> >>>> +
> >>>> + s8 target_power;
> >>>> + s8 target_power_delta[2];
> >>>> + bool enable_tpc;
> >>>> +
> >>>> + u8 coverage_class;
> >>>> + u8 slottime;
> >>>> +
> >>>> + struct mt76x02_dfs_pattern_detector dfs_pd;
> >>>> +};
> >>>> +
> >>> 
> >>>> static bool
> >>>> -mt76x2_has_cal_free_data(struct mt76x2_dev *dev, u8 *efuse)
> >>>> +mt76x2_has_cal_free_data(struct mt76x02_dev *dev, u8 *efuse)
> >>> 
> >>> I don't think this is right approach. I would rather prefer to have
> >>> common data structures embeded in mt76x2_dev and mt76x0_dev
> >>> structures to have chip sepcific fields/data separated.
> >>> 
> >> 
> >> The reason of this patch is that mt76x0_dev fields are already in 
> >> mt76x2_dev
> >> so I guess there is no need to have different structures. Moreover in
> >> this way we can
> >> remove a lot of duplicated code between mt76x0 and mt76x2 drivers.
> > 
> > But you can still create additional structures i.e.
> > 
> > mt76x02_power {
> >s8 target_power;
> >s8 target_power_delta[2];
> >bool enable_tpc;
> > }
> > 
> > mt76x02_conf {
> >u8 coverage_class;
> > u8 slottime;
> > }
> > 
> > put them into mt76xN_dev and still remove dupicated code ?
> Quite often, mt76_dev would be needed as well for register access, which 
> means extra parameters for a lot of functions.
> I think Lorenzo’s approach makes the code a lot more concise, and makes it 
> easier to share more code between mt76x0 and mt76x2.

I think this could be solved very easly by container_of() macro if
there will be one mt76x02_dev struct just after mt76_dev.

Regerds
Stanislaw


Re: [PATCH 06/10] mt76x2: move mt76x2_dev in mt76x02_util.h

2018-10-03 Thread Stanislaw Gruszka
On Wed, Oct 03, 2018 at 01:01:40PM +0200, Lorenzo Bianconi wrote:
> >
> > On Tue, Oct 02, 2018 at 12:19:04AM +0200, Lorenzo Bianconi wrote:
> > > Move mt76x2_dev in mt76x02_util.h and rename it in mt76x02_dev
> > > in order to be shared between mt76x2 and mt76x0 driver
> > 
> > > +struct mt76x02_dev {
> > > + struct mt76_dev mt76; /* must be first */
> > > +
> > > + struct mac_address macaddr_list[8];
> > > +
> > > + struct mutex mutex;
> > > +
> > > + u8 txdone_seq;
> > > + DECLARE_KFIFO_PTR(txstatus_fifo, struct mt76x02_tx_status);
> > > +
> > > + struct sk_buff *rx_head;
> > > +
> > > + struct tasklet_struct tx_tasklet;
> > > + struct tasklet_struct pre_tbtt_tasklet;
> > > + struct delayed_work cal_work;
> > > + struct delayed_work mac_work;
> > > +
> > > + u32 aggr_stats[32];
> > > +
> > > + struct sk_buff *beacons[8];
> > > + u8 beacon_mask;
> > > + u8 beacon_data_mask;
> > > +
> > > + u8 tbtt_count;
> > > + u16 beacon_int;
> > > +
> > > + struct mt76x02_calibration cal;
> > > +
> > > + s8 target_power;
> > > + s8 target_power_delta[2];
> > > + bool enable_tpc;
> > > +
> > > + u8 coverage_class;
> > > + u8 slottime;
> > > +
> > > + struct mt76x02_dfs_pattern_detector dfs_pd;
> > > +};
> > > +
> > 
> > >  static bool
> > > -mt76x2_has_cal_free_data(struct mt76x2_dev *dev, u8 *efuse)
> > > +mt76x2_has_cal_free_data(struct mt76x02_dev *dev, u8 *efuse)
> >
> > I don't think this is right approach. I would rather prefer to have
> > common data structures embeded in mt76x2_dev and mt76x0_dev
> > structures to have chip sepcific fields/data separated.
> >
> 
> The reason of this patch is that mt76x0_dev fields are already in mt76x2_dev
> so I guess there is no need to have different structures. Moreover in
> this way we can
> remove a lot of duplicated code between mt76x0 and mt76x2 drivers.

But you can still create additional structures i.e.

mt76x02_power {
s8 target_power;
s8 target_power_delta[2];
bool enable_tpc;
}

mt76x02_conf {
u8 coverage_class;
u8 slottime;
}

put them into mt76xN_dev and still remove dupicated code ?

Thanks
Stanislaw



Re: [PATCH 06/10] mt76x2: move mt76x2_dev in mt76x02_util.h

2018-10-03 Thread Stanislaw Gruszka
On Tue, Oct 02, 2018 at 12:19:04AM +0200, Lorenzo Bianconi wrote:
> Move mt76x2_dev in mt76x02_util.h and rename it in mt76x02_dev
> in order to be shared between mt76x2 and mt76x0 driver

> +struct mt76x02_dev {
> + struct mt76_dev mt76; /* must be first */
> +
> + struct mac_address macaddr_list[8];
> +
> + struct mutex mutex;
> +
> + u8 txdone_seq;
> + DECLARE_KFIFO_PTR(txstatus_fifo, struct mt76x02_tx_status);
> +
> + struct sk_buff *rx_head;
> +
> + struct tasklet_struct tx_tasklet;
> + struct tasklet_struct pre_tbtt_tasklet;
> + struct delayed_work cal_work;
> + struct delayed_work mac_work;
> +
> + u32 aggr_stats[32];
> +
> + struct sk_buff *beacons[8];
> + u8 beacon_mask;
> + u8 beacon_data_mask;
> +
> + u8 tbtt_count;
> + u16 beacon_int;
> +
> + struct mt76x02_calibration cal;
> +
> + s8 target_power;
> + s8 target_power_delta[2];
> + bool enable_tpc;
> +
> + u8 coverage_class;
> + u8 slottime;
> +
> + struct mt76x02_dfs_pattern_detector dfs_pd;
> +};
> +
 
>  static bool
> -mt76x2_has_cal_free_data(struct mt76x2_dev *dev, u8 *efuse)
> +mt76x2_has_cal_free_data(struct mt76x02_dev *dev, u8 *efuse)

I don't think this is right approach. I would rather prefer to have
common data structures embeded in mt76x2_dev and mt76x0_dev
structures to have chip sepcific fields/data separated.

Regards
Stanislaw



Re: new mt76 usb crashes on device removal

2018-10-03 Thread Stanislaw Gruszka
On Wed, Oct 03, 2018 at 11:15:37AM +0200, Lorenzo Bianconi wrote:
> > After
> > 
> > b11e19694dc9 "mt76x0: add ieee80211_ops ops pointer to mt76x0_alloc_device 
> > signature"
> > 
> > I have new crashs when remove mt76x0u and mt76x2u devices. 
> > I can not provide calltrace because some other warning/traces
> > show up instantly after the problem happen and mask prints
> > for initall problem. Then the machine hungs.
> > 
> > Anyway bisection blame b11e19694dc9 commit and I confirm that problem
> > not happen before this commit. I also applied the fix with I just
> > posted, so this is diffrent issue.
> 
> Hi Stanislaw,
> 
> I do not know if it is related or not, but could you please try following 
> patch:
> 
> Regards,
> Lorenzo
> 
> --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
> @@ -179,11 +179,11 @@ static int mt76x0u_register_device(struct mt76x0_dev 
> *dev)
>   struct ieee80211_hw *hw = dev->mt76.hw;
>   int err;
>  
> - err = mt76u_mcu_init_rx(&dev->mt76);
> + err = mt76u_alloc_queues(&dev->mt76);
>   if (err < 0)
>   return err;
>  
> - err = mt76u_alloc_queues(&dev->mt76);
> + err = mt76u_mcu_init_rx(&dev->mt76);
>   if (err < 0)
>   return err;

It still crashes. You can not reproduce the problem ?
It's 100% reproducible for me, when I unplug mt76x0u or mt76x2 device.

Thanks
Stanislaw


Re: [RFC 2/2] mt76: make frag_cache global per cpu structure

2018-10-03 Thread Stanislaw Gruszka
On Wed, Oct 03, 2018 at 11:38:54AM +0200, Lorenzo Bianconi wrote:
> > +static DEFINE_PER_CPU(struct page_frag_cache, mt76_frag_cache);
> > +
> > +void *mt76_alloc_frag(unsigned int fragsz)
> > +{
> > +   struct page_frag_cache *fc;
> > +   unsigned long flags;
> > +   void *data;
> > +
> > +   local_irq_save(flags);
> 
> I like this approach since we will avoid a cache miss for the spinlock :)
> Do we still need to disable local_irq here since (not considering fw upload)
> I guess there is no contention for mt76_frag_cache

I think is needed if we have more than one device, but I think we can
change to local_irq_disable() / local_irq_enable() . 

Thanks
Stanislaw 


Re: [PATCH] mt76: fix frag length allocation for usb

2018-10-03 Thread Stanislaw Gruszka
On Wed, Oct 03, 2018 at 11:12:07AM +0200, Lorenzo Bianconi wrote:
> > This is correct fix for c12128ce44b0 ("mt76: use a per rx queue page
> > fragment cache"). We use wrong length when we allocate segments for
> > MCU transmissions, which require bigger segment size than e->buf_size.
> > 
> > Commit 481bb0432414 ("mt76: usb: make rx page_frag_cache access atomic")
> > partially solved the problem or actually mask it by changing
> > mt76u_mcu_init_rx() and mt76u_alloc_queues() sequence, so e->buf_size
> > become non zero any longer, but still not big enough to handle MCU data.
> 
> Hi Stanislaw,
> 
> I agree that we should use len in page_frag_alloc() instead of q->buf_size, so
> 
> Acked-by: Lorenzo Bianconi 
> 
> but reviewing the code I guess the real issue is not q->buf_size (since it 
> should
> be bigger than MCU_RESP_URB_SIZE) but it is the sequence of calls in

I added printk and there are allocations where len is bigger then
q->buf_size even with correct mt76u_alloc_queues, mt76u_mcu_init_rx
sequence for mt76x0u:

[16426.606090] q->buf_size 2048 len 2048 nsgs 8sglen 1728
[16426.606131] q->buf_size 2048 len 2048 nsgs 8sglen 1728
[16426.606134] q->buf_size 2048 len 2048 nsgs 8sglen 1728

[16426.606464] q->buf_size 2048 len 2048 nsgs 8sglen 1728
[16426.607517] q->buf_size 2048 len 1024 nsgs 1sglen 1024
[16426.939268] q->buf_size 2048 len 14584 nsgs 1sglen 14584
[16426.984955] q->buf_size 2048 len 14584 nsgs 1sglen 14584

Not sure where it come from, but it's after MCU init (which is 1024
third line from end).

> mt76x0u_register_device() since mt76u_alloc_queues need to be called before
> mt76u_mcu_init_rx()

Ok, so this was already fixed in 

commit 481bb0432414f790066205fe77226b7d1877385d
Author: Lorenzo Bianconi 
Date:   Wed Sep 26 13:07:39 2018 +0200

mt76: usb: make rx page_frag_cache access atomic

but then the sequence was changed again in

commit faa605bdfaa1322ea8e85791abdb3382a8cb4e0c
Author: Lorenzo Bianconi 
Date:   Fri Sep 28 13:39:00 2018 +0200

mt76x0: usb: move initialization code in usb.c

Thanks
Stanislaw
 


[RFC 2/2] mt76: make frag_cache global per cpu structure

2018-10-03 Thread Stanislaw Gruszka
Make mt76 frag cache similar to netdev frag cache. This should
make frag allocation safe regarding concurrent access and also
be more efficient since we will use pages that most likely are
hot on particular cpu.

And we don't need to clean up the cache up during device removal.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/dma.c  |  2 +-
 drivers/net/wireless/mediatek/mt76/usb.c  | 10 +-
 drivers/net/wireless/mediatek/mt76/util.c | 16 
 drivers/net/wireless/mediatek/mt76/util.h |  1 +
 4 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/dma.c 
b/drivers/net/wireless/mediatek/mt76/dma.c
index f7fbd7016403..59453a7781c5 100644
--- a/drivers/net/wireless/mediatek/mt76/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/dma.c
@@ -328,7 +328,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue 
*q, bool napi)
while (q->queued < q->ndesc - 1) {
struct mt76_queue_buf qbuf;
 
-   buf = page_frag_alloc(&q->rx_page, q->buf_size, GFP_ATOMIC);
+   buf = mt76_alloc_frag(q->buf_size);
if (!buf)
break;
 
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c 
b/drivers/net/wireless/mediatek/mt76/usb.c
index a103b77ae8c4..a892f59a32d8 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -276,7 +276,6 @@ static int
 mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76u_buf *buf,
 int nsgs, int len, int sglen)
 {
-   struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
struct urb *urb = buf->urb;
int i;
 
@@ -285,7 +284,7 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76u_buf 
*buf,
void *data;
int offset;
 
-   data = page_frag_alloc(&q->rx_page, len, GFP_ATOMIC);
+   data = mt76_alloc_frag(len);
if (!data)
break;
 
@@ -557,13 +556,6 @@ static void mt76u_free_rx(struct mt76_dev *dev)
 
for (i = 0; i < q->ndesc; i++)
mt76u_buf_free(&q->entry[i].ubuf);
-
-   if (!q->rx_page.va)
-   return;
-
-   page = virt_to_page(q->rx_page.va);
-   __page_frag_cache_drain(page, q->rx_page.pagecnt_bias);
-   memset(&q->rx_page, 0, sizeof(q->rx_page));
 }
 
 static void mt76u_stop_rx(struct mt76_dev *dev)
diff --git a/drivers/net/wireless/mediatek/mt76/util.c 
b/drivers/net/wireless/mediatek/mt76/util.c
index 0c35b8db58cd..def2a1b841b9 100644
--- a/drivers/net/wireless/mediatek/mt76/util.c
+++ b/drivers/net/wireless/mediatek/mt76/util.c
@@ -75,4 +75,20 @@ int mt76_wcid_alloc(unsigned long *mask, int size)
 }
 EXPORT_SYMBOL_GPL(mt76_wcid_alloc);
 
+static DEFINE_PER_CPU(struct page_frag_cache, mt76_frag_cache);
+
+void *mt76_alloc_frag(unsigned int fragsz)
+{
+   struct page_frag_cache *fc;
+   unsigned long flags;
+   void *data;
+
+   local_irq_save(flags);
+   fc = this_cpu_ptr(&mt76_frag_cache);
+   data = page_frag_alloc(fc, fragsz, GFP_ATOMIC);
+   local_irq_restore(flags);
+   return data;
+}
+EXPORT_SYMBOL_GPL(mt76_alloc_frag);
+
 MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/mediatek/mt76/util.h 
b/drivers/net/wireless/mediatek/mt76/util.h
index 018d475504a2..6cb6c0e993c4 100644
--- a/drivers/net/wireless/mediatek/mt76/util.h
+++ b/drivers/net/wireless/mediatek/mt76/util.h
@@ -41,4 +41,5 @@ mt76_skb_set_moredata(struct sk_buff *skb, bool enable)
hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_MOREDATA);
 }
 
+void *mt76_alloc_frag(unsigned int fragsz);
 #endif
-- 
2.7.5



[RFC 1/2] mt76: remove rx_page_lock

2018-10-03 Thread Stanislaw Gruszka
Extra serializaion for protecting q->rx_page is not needed,
we stop rx_tasklet before we nulify it in mt76u_free_rx().

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76.h | 1 -
 drivers/net/wireless/mediatek/mt76/usb.c  | 8 +---
 2 files changed, 1 insertion(+), 8 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h 
b/drivers/net/wireless/mediatek/mt76/mt76.h
index f2dd4d87e355..2ab524c8f14f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -122,7 +122,6 @@ struct mt76_queue {
dma_addr_t desc_dma;
struct sk_buff *rx_head;
struct page_frag_cache rx_page;
-   spinlock_t rx_page_lock;
 };
 
 struct mt76_mcu_ops {
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c 
b/drivers/net/wireless/mediatek/mt76/usb.c
index 6b643ea701e3..a103b77ae8c4 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -280,7 +280,6 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76u_buf 
*buf,
struct urb *urb = buf->urb;
int i;
 
-   spin_lock_bh(&q->rx_page_lock);
for (i = 0; i < nsgs; i++) {
struct page *page;
void *data;
@@ -294,7 +293,6 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76u_buf 
*buf,
offset = data - page_address(page);
sg_set_page(&urb->sg[i], page, sglen, offset);
}
-   spin_unlock_bh(&q->rx_page_lock);
 
if (i < nsgs) {
int j;
@@ -523,7 +521,6 @@ static int mt76u_alloc_rx(struct mt76_dev *dev)
struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
int i, err, nsgs;
 
-   spin_lock_init(&q->rx_page_lock);
spin_lock_init(&q->lock);
q->entry = devm_kzalloc(dev->dev,
MT_NUM_RX_ENTRIES * sizeof(*q->entry),
@@ -561,15 +558,12 @@ static void mt76u_free_rx(struct mt76_dev *dev)
for (i = 0; i < q->ndesc; i++)
mt76u_buf_free(&q->entry[i].ubuf);
 
-   spin_lock_bh(&q->rx_page_lock);
if (!q->rx_page.va)
-   goto out;
+   return;
 
page = virt_to_page(q->rx_page.va);
__page_frag_cache_drain(page, q->rx_page.pagecnt_bias);
memset(&q->rx_page, 0, sizeof(q->rx_page));
-out:
-   spin_unlock_bh(&q->rx_page_lock);
 }
 
 static void mt76u_stop_rx(struct mt76_dev *dev)
-- 
2.7.5



new mt76 usb crashes on device removal

2018-10-03 Thread Stanislaw Gruszka
After

b11e19694dc9 "mt76x0: add ieee80211_ops ops pointer to mt76x0_alloc_device 
signature"

I have new crashs when remove mt76x0u and mt76x2u devices. 
I can not provide calltrace because some other warning/traces
show up instantly after the problem happen and mask prints
for initall problem. Then the machine hungs.

Anyway bisection blame b11e19694dc9 commit and I confirm that problem
not happen before this commit. I also applied the fix with I just
posted, so this is diffrent issue.

Thanks
Stanislaw 


[PATCH] mt76: fix frag length allocation for usb

2018-10-03 Thread Stanislaw Gruszka
This is correct fix for c12128ce44b0 ("mt76: use a per rx queue page
fragment cache"). We use wrong length when we allocate segments for
MCU transmissions, which require bigger segment size than e->buf_size.

Commit 481bb0432414 ("mt76: usb: make rx page_frag_cache access atomic")
partially solved the problem or actually mask it by changing
mt76u_mcu_init_rx() and mt76u_alloc_queues() sequence, so e->buf_size
become non zero any longer, but still not big enough to handle MCU data.

Patch fixes memory corruption which can manifest itself as random,
not easy to reproduce crashes, during mt76 driver load or unload.

Fixes: c12128ce44b0 ("mt76: use a per rx queue page fragment cache")
Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/usb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/usb.c 
b/drivers/net/wireless/mediatek/mt76/usb.c
index de7785c4f6af..6b643ea701e3 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -286,7 +286,7 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76u_buf 
*buf,
void *data;
int offset;
 
-   data = page_frag_alloc(&q->rx_page, q->buf_size, GFP_ATOMIC);
+   data = page_frag_alloc(&q->rx_page, len, GFP_ATOMIC);
if (!data)
break;
 
-- 
2.7.5



Re: [PATCH 01/12] rtwlan: main files

2018-10-02 Thread Stanislaw Gruszka
On Wed, Oct 03, 2018 at 03:25:37AM +, Tony Chuang wrote:
> Can I add you as Reviewed-by in RFCv2 ?

Not yet :-) I'm going to review all (v2) patches in detail,
not just first one, but this will take time. I'll post
Reviewed-by tag when done and if I will have no remarks.

> You helped me a lot :)
You welcome ;-)

Thanks
Stanislaw


Re: [PATCH 01/12] rtwlan: main files

2018-10-02 Thread Stanislaw Gruszka
On Fri, Sep 28, 2018 at 11:32:41AM +, Tony Chuang wrote:
> > if (rtw_hci_tx(rtwdev, &pkt_info, skb))
> > dev_kfree_skb_any(skb)
> > 
> > just to remove 'return;' and out label.
> 
> 
> OK, but why not use ieee80211_free_txskb, should it be better for mac80211?

Yes, it is better as it also do some extra thing for dropped frame.

> > > OK, but I think this is needed, our tables have different forms 
> > 
> > Not sure if that is better solution, but could the tables be pre-prarsed
> > by user-space program and then embed in the driver in ready to send
> > to the hardware from ?
> > 
> > Also there are lot of redundancy in those tables, for example:
> > 
> > +   0x81C, 0xFF03,
> > +   0x81C, 0xF503,
> > +   0x81C, 0xF4020003,
> > +   0x81C, 0xF3040003,
> > +   0x81C, 0xF2060003,
> > +   0x81C, 0xF1080003,
> > +   0x81C, 0xF00A0003,
> > +   0x81C, 0xEF0C0003,
> > +   0x81C, 0xEE0E0003,
> > +   0x81C, 0xED13,
> > +   0x81C, 0xEC120003,
> > +   0x81C, 0xEB140003,
> > +   0x81C, 0xEA160003,
> > +   0x81C, 0xE9180003,
> > +   0x81C, 0xE81A0003,
> > +   0x81C, 0xE71C0003,
> > +   0x81C, 0xE61E0003,
> > +   0x81C, 0xE523,
> > 
> > 0x81C and 0003 repeats in many lines.
> > 
> > This seems to be parse data, not that we have to write 0x81C
> > register many times. Would be possible to remove the redundancy?
> 
> 
> No, they cannot be removed, the sequence matters.
> And it is really writing to 0x81C ...
> It is really magic, I cannot believe to this, too.

This is contradiction for what I asked you before, i.e. doing parsing
in user space, but since we have this parsing mechanism in the driver
perhaps the tables can be coded in some more compact way, for example:

{ prefix, suffix, len, {data} }

{ 0x81C, 0x0003, N ,
  { 0xFF02 , 0xF500 ,  , 0xE520 } }

The rtw8822b_table.c file is quite big. 

Thanks
Stanislaw
 


Re: [PATCH 01/12] rtwlan: main files

2018-10-02 Thread Stanislaw Gruszka
Hi

On Tue, Oct 02, 2018 at 09:35:35AM +, Tony Chuang wrote:
> 
> Hi Kale & Stanislaw,
> 
> I am working on the driver code and making some changes that Stanislaw
> have mentioned. And I expected that I will finish them tomorrow, what
> should I do after I finished them?
> 
> Should I send an RFCv2, or start a new RFC for it ? Because our driver will
> be renamed from rtwlan to rtw88 for 8822B/8822C

I think RFCv2 since this is is second iteration and name change is part
of it.

Thanks
Stanislaw


Re: [RFC 4/5] mt76: move mt76x02_mac_write_txwi in mt76x02-lib module

2018-10-01 Thread Stanislaw Gruszka
On Mon, Oct 01, 2018 at 12:06:56PM +0200, Lorenzo Bianconi wrote:
> > All above looks mt76x2 specific, maybe would be beter to place this in 
> > in setup_txwi() calback i.e:
> > 
> > if (dev->drv->setup_txwi)
> > drv->drv->setup_txwi(...)
> > 
> > or maybe you plan to implement get_tx_txpwr_adj() for mt76x0 as well,
> > is this feature supported by the MT76x0 chips ?
> 
> For the moment tpc is supported just for mt76x2 chipsets but tx power subfield
> is present in mt76x0_txwi as well. Moreover merging mt76x2_dev and mt76x0_dev
> in mt76x02_dev allows us to move mt76x2_get_tx_txpwr_adj() in mt76x02-lib
> module, remove get_tx_txpwr_adj callback and just make tpc disabled for mt76x0
> for the moment.
> As suggested by Felix, we can take into account chainmask for txstream
> configuration and remove is_mt76x2() check.
> Agree?

Yes, sounds reasonable.

Regards
Stanislaw


Re: [RFC] mt76x2: move mt76x2 source files to mt76x2 folder

2018-09-30 Thread Stanislaw Gruszka
On Sat, Sep 29, 2018 at 01:08:19PM +0200, Lorenzo Bianconi wrote:
> Move mt76x2 and mt76x2u drivers to mt76x2 subfolder and
> leave just shared code in mt76 root folder
I was waiting for that change :-)

> Signed-off-by: Lorenzo Bianconi 
Acked-by: Stanislaw Gruszka 



Re: [RFC 4/5] mt76: move mt76x02_mac_write_txwi in mt76x02-lib module

2018-09-30 Thread Stanislaw Gruszka
On Sat, Sep 29, 2018 at 07:44:55PM +0200, Lorenzo Bianconi wrote:
> + spin_lock_bh(&dev->lock);
> + if (wcid && (rate->idx < 0 || !rate->count)) {
> + txwi->rate = wcid->tx_rate;
> + max_txpwr_adj = wcid->max_txpwr_adj;
> + nss = wcid->tx_rate_nss;
> + } else {
> + txwi->rate = mt76x02_mac_tx_rate_val(dev, rate, &nss);
> + max_txpwr_adj = mt76x02_tx_get_max_txpwr_adj(dev, rate);
> + }
> + spin_unlock_bh(&dev->lock);
> +
> + if (dev->drv->get_tx_txpwr_adj) {
> + txpwr_adj = dev->drv->get_tx_txpwr_adj(dev, dev->txpower_conf,
> +max_txpwr_adj);
> + txwi->ctl2 = FIELD_PREP(MT_TX_PWR_ADJ, txpwr_adj);
> + }
> +
> + if (is_mt76x2(dev) && mt76_rev(dev) >= MT76XX_REV_E4)
> + txwi->txstream = 0x13;
> + else if (is_mt76x2(dev) && mt76_rev(dev) >= MT76XX_REV_E3 &&
> +  !(txwi->rate & cpu_to_le16(rate_ht_mask)))
> + txwi->txstream = 0x93;

All above looks mt76x2 specific, maybe would be beter to place this in 
in setup_txwi() calback i.e:

if (dev->drv->setup_txwi)
drv->drv->setup_txwi(...)

or maybe you plan to implement get_tx_txpwr_adj() for mt76x0 as well,
is this feature supported by the MT76x0 chips ?

Thanks
Stanislaw


Re: [PATCH] mt76x0: init: intrduce MT_H2M_* definitions

2018-09-30 Thread Stanislaw Gruszka
On Sat, Sep 29, 2018 at 07:30:32PM +0200, Lorenzo Bianconi wrote:
> Add MT_H2M_BBP_AGENT, MT_H2M_MAILBOX_CSR and MT_H2M_INT_SRC and
> remove magic numbers
> 
>  
>   /* TODO: Probably not needed */
> - mt76_wr(dev, 0x7028, 0);
> - mt76_wr(dev, 0x7010, 0);
> - mt76_wr(dev, 0x7024, 0);
> - msleep(10);
> + mt76_wr(dev, MT_H2M_BBP_AGENT, 0);
> + mt76_wr(dev, MT_H2M_MAILBOX_CSR, 0);
> + mt76_wr(dev, MT_H2M_INT_SRC, 0);

The same here, I think this should be just removed.

> + usleep_range(1, 2);

Why this change ?

Thanks
Stanislaw


Re: [PATCH] mt76x0: pci: add mt76x0e_cleanup routine

2018-09-30 Thread Stanislaw Gruszka
Hi

On Sat, Sep 29, 2018 at 07:26:41PM +0200, Lorenzo Bianconi wrote:
> Add mt76x0e_cleanup routine to tidy up the device
> during netdevice removal
> 
> Signed-off-by: Lorenzo Bianconi 
> + mt76_wr(dev, MT_H2M_MAILBOX_CID, ~0);
> + mt76_wr(dev, MT_H2M_MAILBOX_STATUS, ~0);

I don't think this is needed. Those are legacy communication registers,
most likely not used in new chips and stay in vendor driver, because
it wasn't cleaned up.

Regards
Stanislaw



Re: [PATCH 01/12] rtwlan: main files

2018-09-28 Thread Stanislaw Gruszka
Hi

On Fri, Sep 28, 2018 at 03:20:45AM +, Tony Chuang wrote:
> > > + rtw_tx_pkt_info_update(rtwdev, &pkt_info, control, skb);
> > > + if (rtw_hci_tx(rtwdev, &pkt_info, skb))
> > > + goto out;
> > > +
> > > + return;
> > > +
> > > +out:
> > > + dev_kfree_skb_any(skb);
> > This can be simplified by just do kfree after if ().
> 
> 
> OK, will replace them with ieee80211_free_txskb

I was thinking about:

if (rtw_hci_tx(rtwdev, &pkt_info, skb))
dev_kfree_skb_any(skb)

just to remove 'return;' and out label.

> Have not noticed so far, cause not we can only support on vif.
> 
> And only STA mode is tested, should first modify the iface_conbination.
> Then modify them back again if we submit patches support concurrents
> 
> I think that vif_list & sta_list could be protected by a single mutex that
> protects concurrent access against mac80211 callbacks, and further add
> some rcu locks to protect sta_info. You have some suggestions?

That's good solution, sync multiple possible writes via mutex and
reads of list against writes via RCU.

> I think mac80211 will do it "if the vif is different", but under the same vif,
> mac80211 will protect it with "sdata->wdev.mtx". Not sure if I am right.

I need to check that as well :-)

> Yes, we can. If we have TDLS peer in STA mode or in AP mode, we could have
> different bw_mode, by the sta_info mac80211 passed to us, and that sta_info is
> checked by mac80211 based on the capabilities (IE) of the peer.
How this work with respect we configure band-width when we change the channel?
If we set band-width per sta, should then setting band-width on channel
setup be droped ?

> > > +static inline void rtw_load_table(struct rtw_dev *rtwdev,
> > > +   const struct rtw_table *tbl)
> > > +{
> > > + (*tbl->parse)(rtwdev, tbl);
> > > +}
> > 
> > This interface of loading/processing tables of data looks very strange.
> > I don't think is incorrect, but seems to be somewhat not necessary
> > complicated. I'll try provide more detailed comment about that when
> > review other files.
> 
> 
> OK, but I think this is needed, our tables have different forms 

Not sure if that is better solution, but could the tables be pre-prarsed
by user-space program and then embed in the driver in ready to send
to the hardware from ?

Also there are lot of redundancy in those tables, for example:

+   0x81C, 0xFF03,
+   0x81C, 0xF503,
+   0x81C, 0xF4020003,
+   0x81C, 0xF3040003,
+   0x81C, 0xF2060003,
+   0x81C, 0xF1080003,
+   0x81C, 0xF00A0003,
+   0x81C, 0xEF0C0003,
+   0x81C, 0xEE0E0003,
+   0x81C, 0xED13,
+   0x81C, 0xEC120003,
+   0x81C, 0xEB140003,
+   0x81C, 0xEA160003,
+   0x81C, 0xE9180003,
+   0x81C, 0xE81A0003,
+   0x81C, 0xE71C0003,
+   0x81C, 0xE61E0003,
+   0x81C, 0xE523,

0x81C and 0003 repeats in many lines. 

This seems to be parse data, not that we have to write 0x81C
register many times. Would be possible to remove the redundancy?

Thanks
Stanislaw


Re: [PATCH 01/12] rtwlan: main files

2018-09-28 Thread Stanislaw Gruszka
On Thu, Sep 27, 2018 at 10:40:44AM -0500, Larry Finger wrote:
> On 9/27/18 8:50 AM, Stanislaw Gruszka wrote:
> --snip
> 
> > 
> > > +#define BIT_LEN_MASK_32(__bitlen) (0x >> (32 - (__bitlen)))
> > > +#define BIT_OFFSET_LEN_MASK_32(__bitoffset, __bitlen)
> > >   \
> > > + (BIT_LEN_MASK_32(__bitlen) << (__bitoffset))
> > > +#define LE_P4BYTE_TO_HOST_4BYTE(__start) (le32_to_cpu(*((__le32 
> > > *)(__start
> > > +#define LE_BITS_CLEARED_TO_4BYTE(__start, __bitoffset, __bitlen) 
> > >   \
> > > + (LE_P4BYTE_TO_HOST_4BYTE(__start) &\
> > > +  (~BIT_OFFSET_LEN_MASK_32(__bitoffset, __bitlen)))
> > > +#define LE_BITS_TO_4BYTE(__start, __bitoffset, __bitlen) 
> > >   \
> > > + ((LE_P4BYTE_TO_HOST_4BYTE(__start) >> (__bitoffset)) & \
> > > +  BIT_LEN_MASK_32(__bitlen))
> > > +#define SET_BITS_TO_LE_4BYTE(__start, __bitoffset, __bitlen, __value)
> > >   \
> > > + do {   \
> > > + *((__le32 *)(__start)) = \
> > > + cpu_to_le32( \
> > > + LE_BITS_CLEARED_TO_4BYTE(__start, __bitoffset, __bitlen) | \
> > > + u32)__value) & BIT_LEN_MASK_32(__bitlen)) << (__bitoffset))\
> > > + ); \
> > > + } while (0)
> 
> Stanislaw,
> 
> I have never loved these macros, and it took a lot of time to get them to be
> endian correct. Could you point me to a method that would overwrite a
> portion of a 32-bit little-endian word that would be correct for both
> little- and big-endian machines? Keep in mind that Kalle hates the use of
> compile tests on __LITTLE_ENDIAN.

Maybe something like this (not tested)

#define SET_LE32(reg, off, len, val) \
((reg & cpu_to_le32(~GENMASK(off + len - 1, off))) | cpu_to_le32(val << 
off))

?

There are plenty of bitops and endian primitives in kernel, it's
very very unlikly you need custom macros for handle that.

Thanks
Stanislaw


Re: [PATCH v2 08/24] mt76: move mt76x2_wait_for_bbp in mt76x02-lib module

2018-09-28 Thread Stanislaw Gruszka
On Fri, Sep 28, 2018 at 08:40:01AM +0200, Lorenzo Bianconi wrote:
> +static inline bool
> +mt76x02_wait_for_txrx_active(struct mt76_dev *dev)
> +{
> + return __mt76_poll_msec(dev, MT_MAC_STATUS,
> + MT_MAC_STATUS_TX | MT_MAC_STATUS_RX,
> + 0, 100);
> +}

The name is unfortunate, what we wait for is TX and RX become idle
i.e. hardware do not perform any RX or TX (see for example 
mt76x2_mac_stop() ).

I think this patch should be droped and we should just use
mt76_poll_msec(MT_MAC_STATUS) directly, there is no real benefit
for this function.

Thanks
Stanislaw



Re: [PATCH 01/12] rtwlan: main files

2018-09-27 Thread Stanislaw Gruszka
Hi,

Below is some more detailed review of first patch (with mostly
nitpicks).

On Fri, Sep 21, 2018 at 02:03:56PM +0800, yhchu...@realtek.com wrote:
> +static void rtw_ops_tx(struct ieee80211_hw *hw,
> +struct ieee80211_tx_control *control,
> +struct sk_buff *skb)
> +{
> + struct rtw_dev *rtwdev = hw->priv;
> + struct rtw_tx_pkt_info pkt_info;
> +
> + if (!rtw_flag_check(rtwdev, RTW_FLAG_RUNNING))
> + goto out;
> +
> + memset(&pkt_info, 0, sizeof(pkt_info));
> + rtw_tx_pkt_info_update(rtwdev, &pkt_info, control, skb);
> + if (rtw_hci_tx(rtwdev, &pkt_info, skb))
> + goto out;
> +
> + return;
> +
> +out:
> + dev_kfree_skb_any(skb);
This can be simplified by just do kfree after if ().
   
> +static int rtw_ops_add_interface(struct ieee80211_hw *hw,
> +  struct ieee80211_vif *vif)
> +{
> + struct rtw_dev *rtwdev = hw->priv;
> + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
> + enum rtw_net_type net_type;
> + u32 config = 0;
> + u8 port = 0;

> + list_add(&rtwvif->list, &rtwdev->vif_list);
How rtwdev->vif_list is protected agains concurent access ?

> + INIT_LIST_HEAD(&rtwvif->sta_list);
> +
> + rtwvif->conf = &rtw_vif_port[port];
port is always 0, this either should be fixes or max interfaces for
STA should be set to 1 (temporally).
 
> +static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
> +  struct ieee80211_vif *vif,
> +  struct ieee80211_bss_conf *conf,
> +  u32 changed)
> +{
> + struct rtw_dev *rtwdev = hw->priv;
> + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
> + u32 config = 0;
> +
> + if (changed & BSS_CHANGED_ASSOC) {
> + struct rtw_sta_info *ap;
> + struct rtw_chip_info *chip = rtwdev->chip;
> + enum rtw_net_type net_type;
> +
> + ap = list_first_entry(&rtwvif->sta_list,
> +   struct rtw_sta_info, list);
How rtlwvif->sta_list is protected against concurrent access ? 

> +static u8 rtw_acquire_macid(struct rtw_dev *rtwdev)
> +{
> + u8 i;
> +
> + for (i = 0; i < RTW_MAX_MAC_ID_NUM; i++) {
> + if (!rtwdev->macid_used[i]) {
> + rtwdev->macid_used[i] = true;
> + return i;
> + }
> + }
> +
> + return i;
> +}
> +
> +static void rtw_release_macid(struct rtw_dev *rtwdev, u8 mac_id)
> +{
> + rtwdev->macid_used[mac_id] = false;
> +}
> +
> +static int rtw_ops_sta_add(struct ieee80211_hw *hw,
> +struct ieee80211_vif *vif,
> +struct ieee80211_sta *sta)
> +{
> + struct rtw_dev *rtwdev = hw->priv;
> + struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
> + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
> +
> + si->mac_id = rtw_acquire_macid(rtwdev);

> +
> +static int rtw_ops_sta_remove(struct ieee80211_hw *hw,
> +   struct ieee80211_vif *vif,
> +   struct ieee80211_sta *sta)
> +{
> + struct rtw_dev *rtwdev = hw->priv;
> + struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
> +
> + rtw_release_macid(rtwdev, si->mac_id);
I'm not sure if mac80211 can not add one STA and remove another one
STA at the same time. This need to be verified.

> +static struct ieee80211_iface_limit rtw_5port_limits[] = {
> + { .max = 1, .types = BIT(NL80211_IFTYPE_AP) |
> +  BIT(NL80211_IFTYPE_ADHOC) |
> +  BIT(NL80211_IFTYPE_MESH_POINT), },
> + { .max = 5, .types = BIT(NL80211_IFTYPE_STATION), },

> +static struct ieee80211_iface_combination rtw_5port_if_combs[] = {
> + {
> + .limits = rtw_5port_limits,
> + .n_limits = ARRAY_SIZE(rtw_5port_limits),
> + .max_interfaces = 5,
> + .num_different_channels = 1,
> + },
Here: change to max interfaces to 1 or fix port in add/remove interface.

> +static void rtw_watch_dog_work(struct work_struct *work)
> +{
> + struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
> +   watch_dog_work.work);
> + struct rtw_vif *rtwvif;
> +
> + if (!rtw_flag_check(rtwdev, RTW_FLAG_RUNNING))
> + return;
> +
> + ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->watch_dog_work,
> +  RTW_WATCH_DOG_DELAY_TIME);
> +
> + /* check if we can enter lps */
> + rtw_lps_enter_check(rtwdev);
> +
> + /* reset tx/rx statictics */
> + rtwdev->stats.tx_unicast = 0;
> + rtwdev->stats.rx_unicast = 0;
> + rtwdev->stats.tx_cnt = 0;
> + rtwdev->stats.rx_cnt = 0;
> + list_for_each_entry(rtwvif, &rtwdev->vif_list, list) {
> + rtwvif->stats.tx_unicast = 0;
> +   

Re: [PATCH 19/26] mt76x0: pci: add hw initialization at bootstrap

2018-09-27 Thread Stanislaw Gruszka
On Thu, Sep 27, 2018 at 11:01:48AM +0200, Lorenzo Bianconi wrote:
> Add mt76x0e_register_device routine in pci_init.c
> to initialize the device during hw probe.
> 
> Signed-off-by: Lorenzo Bianconi 
> ---
>  .../wireless/mediatek/mt76/mt76x0/Makefile|  2 +-
>  .../net/wireless/mediatek/mt76/mt76x0/init.c  | 10 +--
>  .../wireless/mediatek/mt76/mt76x0/mt76x0.h|  2 +
>  .../net/wireless/mediatek/mt76/mt76x0/pci.c   |  2 +-
>  .../wireless/mediatek/mt76/mt76x0/pci_init.c  | 65 +++
>  .../wireless/mediatek/mt76/mt76x02_eeprom.h   |  1 +
>  6 files changed, 73 insertions(+), 9 deletions(-)
>  create mode 100644 drivers/net/wireless/mediatek/mt76/mt76x0/pci_init.c
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/Makefile 
> b/drivers/net/wireless/mediatek/mt76/mt76x0/Makefile
> index 30c84a557076..daa4929bdee6 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76x0/Makefile
> +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/Makefile
> @@ -6,7 +6,7 @@ mt76x0-common-y := \
>   init.o main.o trace.o eeprom.o phy.o \
>   mac.o debugfs.o tx.o
>  mt76x0u-y := usb.o usb_mcu.o usb_init.o
> -mt76x0e-y := pci.o pci_mcu.o
> +mt76x0e-y := pci.o pci_mcu.o pci_init.o

How much {pci,usb}_{init,mcu}.c files are expected to grow?
For now they are about between 100 and 200 lines of code
and I do not see reason to move code into separate files
so far. It could be easy placed in usb.c and pci.c files.
But if the files will grow, I'm ok with code moving.

Thanks
Stanislaw


Re: [PATCH 17/26] mt76: add mt76x02_mac_start routine

2018-09-27 Thread Stanislaw Gruszka
On Thu, Sep 27, 2018 at 11:01:46AM +0200, Lorenzo Bianconi wrote:
> Introduce mt76x02_mac_start since the mac start code is shared between
> mt76x0e and mt76x2 drivers.
> 
> Signed-off-by: Lorenzo Bianconi 
> ---
>  drivers/net/wireless/mediatek/mt76/mt76x02_mac.c | 15 +++
>  drivers/net/wireless/mediatek/mt76/mt76x02_mac.h |  1 +
>  drivers/net/wireless/mediatek/mt76/mt76x2_init.c | 12 +---
>  3 files changed, 17 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c 
> b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
> index df4366a702c9..5f120c1fa79f 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
> @@ -18,6 +18,8 @@
>  #include "mt76.h"
>  #include "mt76x02_regs.h"
>  #include "mt76x02_mac.h"
> +#include "mt76x02_dma.h"
> +#include "mt76x02_util.h"
>  
>  enum mt76x02_cipher_type
>  mt76x02_mac_get_key_info(struct ieee80211_key_conf *key, u8 *key_data)
> @@ -520,3 +522,16 @@ void mt76x02_mac_setaddr(struct mt76_dev *dev, u8 *addr)
> FIELD_PREP(MT_MAC_ADDR_DW1_U2ME_MASK, 0xff));
>  }
>  EXPORT_SYMBOL_GPL(mt76x02_mac_setaddr);
> +
> +void mt76x02_mac_start(struct mt76_dev *dev)
> +{
> + mt76x02_dma_enable(dev);
> + __mt76_wr(dev, MT_RX_FILTR_CFG, dev->rxfilter);
> + __mt76_wr(dev, MT_MAC_SYS_CTRL,
> +   MT_MAC_SYS_CTRL_ENABLE_TX |
> +   MT_MAC_SYS_CTRL_ENABLE_RX);
> + mt76x02_irq_enable(dev,
> +MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL |
> +MT_INT_TX_STAT);
> +}

irq_enable is PCIe specific (also mt76x02_dma_enable() seems to
be PCIe specifc). I think this should be not mixed within generic code
and perhaps the function name prefix should be mt76x02e_ .

Thanks
Stanislaw



Re: [PATCH 15/26] mt76x0: init: reset beacon offset during bootstrap

2018-09-27 Thread Stanislaw Gruszka
On Thu, Sep 27, 2018 at 11:01:44AM +0200, Lorenzo Bianconi wrote:
> Add beacon offset reset in mt76x0e_init_hardware routine
> 
> Signed-off-by: Lorenzo Bianconi 
> ---
>  drivers/net/wireless/mediatek/mt76/mt76x0/init.c | 8 +++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c 
> b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
> index 03211fd0db33..6600ee046800 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
> @@ -345,7 +345,7 @@ EXPORT_SYMBOL_GPL(mt76x0_mac_stop);
>  
>  int mt76x0_init_hardware(struct mt76x0_dev *dev)
>  {
> - int ret;
> + int ret, i, j, beacon_len;
>  
>   if (!mt76x02_wait_for_wpdma(&dev->mt76, 1000))
>   return -EIO;
> @@ -385,6 +385,12 @@ int mt76x0_init_hardware(struct mt76x0_dev *dev)
>MT_BEACON_TIME_CFG_TBTT_EN |
>MT_BEACON_TIME_CFG_BEACON_TX));
>  
> + beacon_len = mt76x02_beacon_offsets[1] - mt76x02_beacon_offsets[0];
> + for (i = 0; i < 8; i++) {
> + for (j = 0; j < beacon_len; j += 4)
> + mt76_wr(dev, mt76x02_beacon_offsets[i] + j, 0);
> + }
> +

This seems to ba fix for 

"mt76: move mt76x02_beacon_offset in mt76x02_core.c"

please add "Fixes:" tag or merge this patch into previous one.

Thanks
Stanislaw


Re: [PATCH 08/26] mt76: move mt76x2_wait_for_bbp in mt76x02-lib module

2018-09-27 Thread Stanislaw Gruszka
On Thu, Sep 27, 2018 at 11:01:37AM +0200, Lorenzo Bianconi wrote:
> Move mt76x2_wait_for_bbp utility routine in mt76x02_util.h
> in order to be resued by mt76x0 driver
> 
> Signed-off-by: Lorenzo Bianconi 
> ---
> +static inline bool mt76x02_wait_for_bbp(struct mt76_dev *dev)
> +{
> + return __mt76_poll_msec(dev, MT_MAC_STATUS,
> + MT_MAC_STATUS_TX | MT_MAC_STATUS_RX,
> + 0, 100);
> +}

I think this should be renamed to 

mt76x02_wait_for_txrx_busy()

or similar name, to avoid confusion and should be also used
in mt76x0 to replace:

if (!mt76_poll_msec(dev, MT_MAC_STATUS,
MT_MAC_STATUS_TX | MT_MAC_STATUS_RX, 0, 1000))


Regards
Stanislaw



Re: [PATCH 06/26] mt76: move mt76x02_beacon_offset in mt76x02_core.c

2018-09-27 Thread Stanislaw Gruszka
On Thu, Sep 27, 2018 at 11:01:35AM +0200, Lorenzo Bianconi wrote:
> Move mt76x02_beacon_offset utility routine in mt76x02-lib module
> since it is shared between mt76x0 and mt76x2 driver and remove
> duplicated code. Moreover move beacon_offset data structure in
> mt76x02-lib module since it is shared between mt76x0 and mt76x2
> drivers
> 
> Signed-off-by: Lorenzo Bianconi 


> +const u16 mt76x02_beacon_offsets[16] = {
> + /* 1024 byte per beacon */
> + 0xc000,
> + 0xc400,
> + 0xc800,
> + 0xcc00,
> + 0xd000,
> + 0xd400,
> + 0xd800,
> + 0xdc00,
> + /* BSS idx 8-15 not used for beacons */
> + 0xc000,
> + 0xc000,
> + 0xc000,
> + 0xc000,
> + 0xc000,
> + 0xc000,
> + 0xc000,
> + 0xc000,
> +};
> +EXPORT_SYMBOL_GPL(mt76x02_beacon_offsets);
I don't think this should be added to mt76x02_core.c with interrupt stuff.
Interrupts are mmio specific, and beaconing are generic for both buses.
Seems mt76x02_util is better place for beaconing.

Also maybe to avoid confusion mt76x02_core.c should be named
mt76x02_mmio.c and contain only code for PCIe i.e. mt76x0e, mt76x2e.

Thanks
Stanislaw


Re: [RFC 1/4] mt76x0: print BBP version only for debug

2018-09-27 Thread Stanislaw Gruszka
On Thu, Sep 27, 2018 at 11:34:39AM +0200, Lorenzo Bianconi wrote:
> Please drop the comment, it is a different register. Maybe we can
Too late :-)

> generalize mt76x02_wait_for_mac instead?

Seems BBP(CORE,0) is not used by mt76x2, so merging it into mt76x02
is not correct.

Thanks
Stanislaw


Re: [RFC 1/4] mt76x0: print BBP version only for debug

2018-09-27 Thread Stanislaw Gruszka
On Thu, Sep 27, 2018 at 11:26:30AM +0200, Lorenzo Bianconi wrote:
> > Use dev_dbg to print BBP version.
> > 
> > Signed-off-by: Stanislaw Gruszka 
> > ---
> >  drivers/net/wireless/mediatek/mt76/mt76x0/phy.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c 
> > b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
> > index 4fd2c65e196a..ca0a693654a3 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
> > +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
> > @@ -187,7 +187,6 @@ int mt76x0_wait_bbp_ready(struct mt76x0_dev *dev)
> >  
> > do {
> > val = mt76_rr(dev, MT_BBP(CORE, 0));
> > -   printk("BBP version %08x\n", val);
> > if (val && ~val)
> > break;
> > } while (--i);
> > @@ -197,6 +196,7 @@ int mt76x0_wait_bbp_ready(struct mt76x0_dev *dev)
> > return -EIO;
> > }
> >  
> > +   dev_dbg(dev->mt76.dev, "BBP version %08x\n", val);
> > return 0;
> >  }
> 
> I guess we can drop mt76x0_wait_bbp_ready and use mt76x02_wait_for_mac instead

Why? Wait for BBP is diffrent, we read MT_BBP(CORE, 0)=0x2000 register,
wait for MAC we read MT_MAC_CSR0=0x1000 ?

Baside this patch is about replacing printk by dev_dbg.

Thanks
Stanislaw


[RFC 4/4] mt76x0: correct RF reg pairs write for PCIe

2018-09-27 Thread Stanislaw Gruszka
We have to use RF CSR method for PCIe.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/phy.c | 19 ---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
index 33e0ea9707e3..4d4f8e7e5fe5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
@@ -174,9 +174,22 @@
 }
 #endif
 
-#define RF_RANDOM_WRITE(dev, tab)  \
-   mt76_wr_rp(dev, MT_MCU_MEMMAP_RF,   \
-  tab, ARRAY_SIZE(tab))
+static void
+mt76x0_rf_csr_wr_rp(struct mt76x0_dev *dev, const struct mt76_reg_pair *data,
+   int n)
+{
+   while (n-- > 0) {
+   mt76x0_rf_csr_wr(dev, data->reg, data->value);
+   data++;
+   }
+}
+
+#define RF_RANDOM_WRITE(dev, tab) do { \
+   if (mt76_is_mmio(dev))  \
+   mt76x0_rf_csr_wr_rp(dev, tab, ARRAY_SIZE(tab)); \
+   else\
+   mt76_wr_rp(dev, MT_MCU_MEMMAP_RF, tab, ARRAY_SIZE(tab));\
+} while (0)
 
 int mt76x0_wait_bbp_ready(struct mt76x0_dev *dev)
 {
-- 
1.9.3



[RFC 0/4] mt76x0: phy/rf fixups for PCIe

2018-09-27 Thread Stanislaw Gruszka
This is RFC for now, especially I'm interesting if patch 3 and 4
is direction we should go.

This is on top of Lorenzo github mt7610ev5 branch. 

Stanislaw Gruszka (4):
  mt76x0: print BBP version only for debug
  mt76x0: correct RF access via RF_CSR regiser.
  mt76: allow to identify bus
  mt76x0: correct RF reg pairs write for PCIe

 drivers/net/wireless/mediatek/mt76/mmio.c |  1 +
 drivers/net/wireless/mediatek/mt76/mt76.h |  9 
 drivers/net/wireless/mediatek/mt76/mt76x0/phy.c   | 27 ---
 drivers/net/wireless/mediatek/mt76/mt76x02_regs.h |  4 ++--
 drivers/net/wireless/mediatek/mt76/usb.c  |  1 +
 5 files changed, 32 insertions(+), 10 deletions(-)

-- 
1.9.3



[RFC 2/4] mt76x0: correct RF access via RF_CSR regiser.

2018-09-27 Thread Stanislaw Gruszka
PCIe version don't use MCU for RF regsisters access. We need
to correct RF CSR method to support up to 127 RF registers.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/phy.c   | 6 ++
 drivers/net/wireless/mediatek/mt76/mt76x02_regs.h | 4 ++--
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
index ca0a693654a3..33e0ea9707e3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
@@ -37,7 +37,7 @@
bank = MT_RF_BANK(offset);
reg = MT_RF_REG(offset);
 
-   if (WARN_ON_ONCE(reg > 64) || WARN_ON_ONCE(bank) > 8)
+   if (WARN_ON_ONCE(reg > 127) || WARN_ON_ONCE(bank) > 8)
return -EINVAL;
 
mutex_lock(&dev->reg_atomic_mutex);
@@ -77,7 +77,7 @@
bank = MT_RF_BANK(offset);
reg = MT_RF_REG(offset);
 
-   if (WARN_ON_ONCE(reg > 64) || WARN_ON_ONCE(bank) > 8)
+   if (WARN_ON_ONCE(reg > 127) || WARN_ON_ONCE(bank) > 8)
return -EINVAL;
 
mutex_lock(&dev->reg_atomic_mutex);
@@ -120,7 +120,6 @@
 
return mt76_wr_rp(dev, MT_MCU_MEMMAP_RF, &pair, 1);
} else {
-   WARN_ON_ONCE(1);
return mt76x0_rf_csr_wr(dev, offset, val);
}
 }
@@ -139,7 +138,6 @@
ret = mt76_rd_rp(dev, MT_MCU_MEMMAP_RF, &pair, 1);
val = pair.value;
} else {
-   WARN_ON_ONCE(1);
ret = val = mt76x0_rf_csr_rr(dev, offset);
}
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h 
b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h
index 24d1e6d747dd..f7de77d09d28 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_regs.h
@@ -205,8 +205,8 @@
 #define MT_TXQ_STA 0x0434
 #defineMT_RF_CSR_CFG   0x0500
 #define MT_RF_CSR_CFG_DATA GENMASK(7, 0)
-#define MT_RF_CSR_CFG_REG_ID   GENMASK(13, 8)
-#define MT_RF_CSR_CFG_REG_BANK GENMASK(17, 14)
+#define MT_RF_CSR_CFG_REG_ID   GENMASK(14, 8)
+#define MT_RF_CSR_CFG_REG_BANK GENMASK(17, 15)
 #define MT_RF_CSR_CFG_WR   BIT(30)
 #define MT_RF_CSR_CFG_KICK BIT(31)
 
-- 
1.9.3



[RFC 1/4] mt76x0: print BBP version only for debug

2018-09-27 Thread Stanislaw Gruszka
Use dev_dbg to print BBP version.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/phy.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
index 4fd2c65e196a..ca0a693654a3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c
@@ -187,7 +187,6 @@ int mt76x0_wait_bbp_ready(struct mt76x0_dev *dev)
 
do {
val = mt76_rr(dev, MT_BBP(CORE, 0));
-   printk("BBP version %08x\n", val);
if (val && ~val)
break;
} while (--i);
@@ -197,6 +196,7 @@ int mt76x0_wait_bbp_ready(struct mt76x0_dev *dev)
return -EIO;
}
 
+   dev_dbg(dev->mt76.dev, "BBP version %08x\n", val);
return 0;
 }
 
-- 
1.9.3



[RFC 3/4] mt76: allow to identify bus

2018-09-27 Thread Stanislaw Gruszka
Add helpers to identify bus type.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mmio.c | 1 +
 drivers/net/wireless/mediatek/mt76/mt76.h | 9 +
 drivers/net/wireless/mediatek/mt76/usb.c  | 1 +
 3 files changed, 11 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mmio.c 
b/drivers/net/wireless/mediatek/mt76/mmio.c
index 30a5d928e655..1d6bbce76041 100644
--- a/drivers/net/wireless/mediatek/mt76/mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mmio.c
@@ -79,6 +79,7 @@ void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs)
.copy = mt76_mmio_copy,
.wr_rp = mt76_mmio_wr_rp,
.rd_rp = mt76_mmio_rd_rp,
+   .type = MT76_BUS_MMIO,
};
 
dev->bus = &mt76_mmio_ops;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h 
b/drivers/net/wireless/mediatek/mt76/mt76.h
index f2dd4d87e355..b0e6215c67ec 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -38,6 +38,11 @@ struct mt76_reg_pair {
u32 value;
 };
 
+enum mt76_bus_type {
+   MT76_BUS_MMIO,
+   MT76_BUS_USB,
+};
+
 struct mt76_bus_ops {
u32 (*rr)(struct mt76_dev *dev, u32 offset);
void (*wr)(struct mt76_dev *dev, u32 offset, u32 val);
@@ -48,8 +53,12 @@ struct mt76_bus_ops {
 const struct mt76_reg_pair *rp, int len);
int (*rd_rp)(struct mt76_dev *dev, u32 base,
 struct mt76_reg_pair *rp, int len);
+   enum mt76_bus_type type;
 };
 
+#define mt76_is_usb(dev) ((dev)->mt76.bus->type == MT76_BUS_USB)
+#define mt76_is_mmio(dev) ((dev)->mt76.bus->type == MT76_BUS_MMIO)
+
 enum mt76_txq_id {
MT_TXQ_VO = IEEE80211_AC_VO,
MT_TXQ_VI = IEEE80211_AC_VI,
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c 
b/drivers/net/wireless/mediatek/mt76/usb.c
index de7785c4f6af..a7fc5db39b31 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -862,6 +862,7 @@ int mt76u_init(struct mt76_dev *dev,
.copy = mt76u_copy,
.wr_rp = mt76u_wr_rp,
.rd_rp = mt76u_rd_rp,
+   .type = MT76_BUS_USB,
};
struct mt76_usb *usb = &dev->usb;
 
-- 
1.9.3



Re: [PATCH] mt76: fix building without CONFIG_MT76x0U

2018-09-26 Thread Stanislaw Gruszka
On Wed, Sep 26, 2018 at 02:51:59PM +0200, Arnd Bergmann wrote:
> The recent rework of the mt76 driver caused build failures in
> configurations that leave the mt76x0u support disabled:
> 
> ERROR: "mt76u_mcu_deinit" 
> [drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0-common.ko] undefined!
> ERROR: "mt76x02u_set_txinfo" 
> [drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0-common.ko] undefined!
> ERROR: "mt76u_queues_deinit" 
> [drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0-common.ko] undefined!
> ERROR: "mt76u_stop_stat_wk" 
> [drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0-common.ko] undefined!
> 
> The mt76x0_push_txwi()/mt76x0_tx_prepare_skb()/mt76x0_cleanup() functions
> that cause some of these are only called from the usb portion, and can
> be hidden in an #ifdef in this case.
> 
> mt76u_stop_stat_wk() is called mt76x0_mac_stop(), which is in turn
> shared between multiple callers. Calling it only when the USB driver
> is enabled avoids the link error but it is not clear to me whether this
> can be called from a context where it would not do the right thing.

I think there not yet posted Lorenzo patches that fix this build
problem.

Regards
Stanislaw



[PATCH 5/5] rt2800: flush and txstatus rework for rt2800mmio

2018-09-26 Thread Stanislaw Gruszka
Implement custom rt2800mmio flush routine and change txstatus
routine to read TX_STA_FIFO also in the tasklet.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c  |  14 ++-
 drivers/net/wireless/ralink/rt2x00/rt2800mmio.c | 118 ++--
 drivers/net/wireless/ralink/rt2x00/rt2800mmio.h |   1 +
 drivers/net/wireless/ralink/rt2x00/rt2800pci.c  |   2 +-
 4 files changed, 97 insertions(+), 38 deletions(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c 
b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 595cb9c90b81..9e7b8933d30c 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -1147,7 +1147,7 @@ static inline bool rt2800_entry_txstatus_timeout(struct 
rt2x00_dev *rt2x00dev,
return false;
 
if (test_bit(DEVICE_STATE_FLUSHING, &rt2x00dev->flags))
-   tout = msecs_to_jiffies(100);
+   tout = msecs_to_jiffies(50);
else
tout = msecs_to_jiffies(2000);
 
@@ -1163,15 +1163,13 @@ bool rt2800_txstatus_timeout(struct rt2x00_dev 
*rt2x00dev)
 {
struct data_queue *queue;
struct queue_entry *entry;
-   unsigned long tout;
 
-   if (test_bit(DEVICE_STATE_FLUSHING, &rt2x00dev->flags))
-   tout = msecs_to_jiffies(50);
-   else
-   tout = msecs_to_jiffies(1000);
+   if (!test_bit(DEVICE_STATE_FLUSHING, &rt2x00dev->flags)) {
+   unsigned long tout = msecs_to_jiffies(1000);
 
-   if (time_before(jiffies, rt2x00dev->last_nostatus_check + tout))
-   return false;
+   if (time_before(jiffies, rt2x00dev->last_nostatus_check + tout))
+   return false;
+   }
 
rt2x00dev->last_nostatus_check = jiffies;
 
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c 
b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
index d0426314c2df..ddb88cfeace2 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
@@ -191,21 +191,6 @@ static inline void rt2800mmio_enable_interrupt(struct 
rt2x00_dev *rt2x00dev,
spin_unlock_irq(&rt2x00dev->irqmask_lock);
 }
 
-void rt2800mmio_txstatus_tasklet(unsigned long data)
-{
-   struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
-
-   rt2800_txdone(rt2x00dev);
-
-   if (rt2800_txstatus_timeout(rt2x00dev))
-   rt2800_txdone_nostatus(rt2x00dev);
-
-   if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-   rt2800mmio_enable_interrupt(rt2x00dev,
-   INT_SOURCE_CSR_TX_FIFO_STATUS);
-}
-EXPORT_SYMBOL_GPL(rt2800mmio_txstatus_tasklet);
-
 void rt2800mmio_pretbtt_tasklet(unsigned long data)
 {
struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
@@ -270,12 +255,26 @@ void rt2800mmio_autowake_tasklet(unsigned long data)
 }
 EXPORT_SYMBOL_GPL(rt2800mmio_autowake_tasklet);
 
-static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
+static void rt2800mmio_txdone(struct rt2x00_dev *rt2x00dev)
+{
+   bool timeout = false;
+
+   while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo) ||
+  (timeout = rt2800_txstatus_timeout(rt2x00dev))) {
+
+   rt2800_txdone(rt2x00dev);
+
+   if (timeout)
+   rt2800_txdone_nostatus(rt2x00dev);
+   }
+}
+
+static bool rt2800mmio_fetch_txstatus(struct rt2x00_dev *rt2x00dev)
 {
u32 status;
-   int i;
+   bool more = false;
 
-   /*
+   /* FIXEME: rewrite this comment
 * The TX_FIFO_STATUS interrupt needs special care. We should
 * read TX_STA_FIFO but we should do it immediately as otherwise
 * the register can overflow and we would lose status reports.
@@ -286,25 +285,37 @@ static void rt2800mmio_txstatus_interrupt(struct 
rt2x00_dev *rt2x00dev)
 * because we can schedule the tasklet multiple times (when the
 * interrupt fires again during tx status processing).
 *
-* Since we have only one producer and one consumer we don't
+* txstatus tasklet is called with INT_SOURCE_CSR_TX_FIFO_STATUS
+* disabled so have only one producer and one consumer - we don't
 * need to lock the kfifo.
 */
-   for (i = 0; i < rt2x00dev->tx->limit; i++) {
+   while (!kfifo_is_full(&rt2x00dev->txstatus_fifo)) {
status = rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO);
-
if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
break;
 
-   if (!kfifo_put(&rt2x00dev->txstatus_fifo, status)) {
-   rt2x00_warn(rt2x00dev, "TX status FIFO overrun, drop tx 
status report\n");
-   break;
-   }
+   kfifo_put(&a

[PATCH 2/5] rt2800mmio: use txdone/txstatus routines from lib

2018-09-26 Thread Stanislaw Gruszka
Use usb txdone/txstatus routines (now in rt2800libc) for mmio devices.

Note this also change how we handle INT_SOURCE_CSR_TX_FIFO_STATUS
interrupt. Now it is disabled since IRQ routine till end of the txstatus
tasklet (the same behaviour like others interrupts). Reason to do not
disable this interrupt was not to miss any tx status from 16 entries
FIFO register. Now, since we check for tx status timeout, we can
allow to miss some tx statuses. However this will be improved in further
patch where I also implement read status FIFO register in the tasklet.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/ralink/rt2x00/rt2800mmio.c  | 180 +--
 drivers/net/wireless/ralink/rt2x00/rt2x00queue.c |   1 +
 2 files changed, 9 insertions(+), 172 deletions(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c 
b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
index e1a7ed7e4892..aa8449a5e8fe 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
@@ -175,161 +175,6 @@ static void rt2800mmio_wakeup(struct rt2x00_dev 
*rt2x00dev)
rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
 }
 
-static bool rt2800mmio_txdone_entry_check(struct queue_entry *entry, u32 
status)
-{
-   __le32 *txwi;
-   u32 word;
-   int wcid, tx_wcid;
-
-   wcid = rt2x00_get_field32(status, TX_STA_FIFO_WCID);
-
-   txwi = rt2800_drv_get_txwi(entry);
-   word = rt2x00_desc_read(txwi, 1);
-   tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
-
-   return (tx_wcid == wcid);
-}
-
-static bool rt2800mmio_txdone_find_entry(struct queue_entry *entry, void *data)
-{
-   u32 status = *(u32 *)data;
-
-   /*
-* rt2800pci hardware might reorder frames when exchanging traffic
-* with multiple BA enabled STAs.
-*
-* For example, a tx queue
-*[ STA1 | STA2 | STA1 | STA2 ]
-* can result in tx status reports
-*[ STA1 | STA1 | STA2 | STA2 ]
-* when the hw decides to aggregate the frames for STA1 into one AMPDU.
-*
-* To mitigate this effect, associate the tx status to the first frame
-* in the tx queue with a matching wcid.
-*/
-   if (rt2800mmio_txdone_entry_check(entry, status) &&
-   !test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
-   /*
-* Got a matching frame, associate the tx status with
-* the frame
-*/
-   entry->status = status;
-   set_bit(ENTRY_DATA_STATUS_SET, &entry->flags);
-   return true;
-   }
-
-   /* Check the next frame */
-   return false;
-}
-
-static bool rt2800mmio_txdone_match_first(struct queue_entry *entry, void 
*data)
-{
-   u32 status = *(u32 *)data;
-
-   /*
-* Find the first frame without tx status and assign this status to it
-* regardless if it matches or not.
-*/
-   if (!test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
-   /*
-* Got a matching frame, associate the tx status with
-* the frame
-*/
-   entry->status = status;
-   set_bit(ENTRY_DATA_STATUS_SET, &entry->flags);
-   return true;
-   }
-
-   /* Check the next frame */
-   return false;
-}
-static bool rt2800mmio_txdone_release_entries(struct queue_entry *entry,
- void *data)
-{
-   if (test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) {
-   rt2800_txdone_entry(entry, entry->status,
-   rt2800mmio_get_txwi(entry), true);
-   return false;
-   }
-
-   /* No more frames to release */
-   return true;
-}
-
-static bool rt2800mmio_txdone(struct rt2x00_dev *rt2x00dev)
-{
-   struct data_queue *queue;
-   u32 status;
-   u8 qid;
-   int max_tx_done = 16;
-
-   while (kfifo_get(&rt2x00dev->txstatus_fifo, &status)) {
-   qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE);
-   if (unlikely(qid >= QID_RX)) {
-   /*
-* Unknown queue, this shouldn't happen. Just drop
-* this tx status.
-*/
-   rt2x00_warn(rt2x00dev, "Got TX status report with 
unexpected pid %u, dropping\n",
-   qid);
-   break;
-   }
-
-   queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
-   if (unlikely(queue == NULL)) {
-   /*
-* The queue is NULL, this shouldn't happen. Stop
-* processing here and drop the tx status
-*/
-   

[PATCH 3/5] rt2x00: do not check for txstatus timeout every time on tasklet

2018-09-26 Thread Stanislaw Gruszka
Do not check for tx status timeout everytime we perform txstatus tasklet.
Perform check once per half a second.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c   | 7 +++
 drivers/net/wireless/ralink/rt2x00/rt2800mmio.c  | 3 ++-
 drivers/net/wireless/ralink/rt2x00/rt2x00.h  | 2 ++
 drivers/net/wireless/ralink/rt2x00/rt2x00queue.c | 1 +
 4 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c 
b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 9f2835729016..0c56c7dca55f 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -1158,11 +1158,18 @@ bool rt2800_txstatus_timeout(struct rt2x00_dev 
*rt2x00dev)
struct data_queue *queue;
struct queue_entry *entry;
 
+   if (time_before(jiffies,
+   rt2x00dev->last_nostatus_check + msecs_to_jiffies(500)))
+   return false;
+
+   rt2x00dev->last_nostatus_check = jiffies;
+
tx_queue_for_each(rt2x00dev, queue) {
entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
if (rt2800_entry_txstatus_timeout(entry))
return true;
}
+
return false;
 }
 EXPORT_SYMBOL_GPL(rt2800_txstatus_timeout);
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c 
b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
index aa8449a5e8fe..d0426314c2df 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
@@ -197,7 +197,8 @@ void rt2800mmio_txstatus_tasklet(unsigned long data)
 
rt2800_txdone(rt2x00dev);
 
-   rt2800_txdone_nostatus(rt2x00dev);
+   if (rt2800_txstatus_timeout(rt2x00dev))
+   rt2800_txdone_nostatus(rt2x00dev);
 
if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
rt2800mmio_enable_interrupt(rt2x00dev,
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h 
b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
index a279a4363bc1..af062cda4a23 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
@@ -980,6 +980,8 @@ struct rt2x00_dev {
 */
DECLARE_KFIFO_PTR(txstatus_fifo, u32);
 
+   unsigned long last_nostatus_check;
+
/*
 * Timer to ensure tx status reports are read (rt2800usb).
 */
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c 
b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
index 6e8beb7ea350..92ddc19e7bf7 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
@@ -1039,6 +1039,7 @@ void rt2x00queue_start_queues(struct rt2x00_dev 
*rt2x00dev)
 */
tx_queue_for_each(rt2x00dev, queue)
rt2x00queue_start_queue(queue);
+   rt2x00dev->last_nostatus_check = jiffies;
 
rt2x00queue_start_queue(rt2x00dev->rx);
 }
-- 
2.7.5



[PATCH 1/5] rt2800: move usb specific txdone/txstatus routines to rt2800lib

2018-09-26 Thread Stanislaw Gruszka
In order to reuse usb txdone/txstatus routines for mmio, move them
to common rt2800lib.c file.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 138 
 drivers/net/wireless/ralink/rt2x00/rt2800lib.h |   3 +
 drivers/net/wireless/ralink/rt2x00/rt2800usb.c | 143 +
 3 files changed, 145 insertions(+), 139 deletions(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c 
b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index a567bc273ffc..9f2835729016 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -957,6 +957,47 @@ static void rt2800_rate_from_status(struct skb_frame_desc 
*skbdesc,
skbdesc->tx_rate_flags = flags;
 }
 
+static bool rt2800_txdone_entry_check(struct queue_entry *entry, u32 reg)
+{
+   __le32 *txwi;
+   u32 word;
+   int wcid, ack, pid;
+   int tx_wcid, tx_ack, tx_pid, is_agg;
+
+   /*
+* This frames has returned with an IO error,
+* so the status report is not intended for this
+* frame.
+*/
+   if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
+   return false;
+
+   wcid= rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
+   ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
+   pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
+   is_agg  = rt2x00_get_field32(reg, TX_STA_FIFO_TX_AGGRE);
+
+   /*
+* Validate if this TX status report is intended for
+* this entry by comparing the WCID/ACK/PID fields.
+*/
+   txwi = rt2800_drv_get_txwi(entry);
+
+   word = rt2x00_desc_read(txwi, 1);
+   tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID);
+   tx_ack  = rt2x00_get_field32(word, TXWI_W1_ACK);
+   tx_pid  = rt2x00_get_field32(word, TXWI_W1_PACKETID);
+
+   if (wcid != tx_wcid || ack != tx_ack || (!is_agg && pid != tx_pid)) {
+   rt2x00_dbg(entry->queue->rt2x00dev,
+  "TX status report missed for queue %d entry %d\n",
+  entry->queue->qid, entry->entry_idx);
+   return false;
+   }
+
+   return true;
+}
+
 void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi,
 bool match)
 {
@@ -1059,6 +1100,103 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 
status, __le32 *txwi,
 }
 EXPORT_SYMBOL_GPL(rt2800_txdone_entry);
 
+void rt2800_txdone(struct rt2x00_dev *rt2x00dev)
+{
+   struct data_queue *queue;
+   struct queue_entry *entry;
+   u32 reg;
+   u8 qid;
+   bool match;
+
+   while (kfifo_get(&rt2x00dev->txstatus_fifo, ®)) {
+   /*
+* TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus qid is
+* guaranteed to be one of the TX QIDs .
+*/
+   qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
+   queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
+
+   if (unlikely(rt2x00queue_empty(queue))) {
+   rt2x00_dbg(rt2x00dev, "Got TX status for an empty queue 
%u, dropping\n",
+  qid);
+   break;
+   }
+
+   entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+
+   if (unlikely(test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
+!test_bit(ENTRY_DATA_STATUS_PENDING, 
&entry->flags))) {
+   rt2x00_warn(rt2x00dev, "Data pending for entry %u in 
queue %u\n",
+   entry->entry_idx, qid);
+   break;
+   }
+
+   match = rt2800_txdone_entry_check(entry, reg);
+   rt2800_txdone_entry(entry, reg, rt2800_drv_get_txwi(entry), 
match);
+   }
+}
+EXPORT_SYMBOL_GPL(rt2800_txdone);
+
+static inline bool rt2800_entry_txstatus_timeout(struct queue_entry *entry)
+{
+   bool tout;
+
+   if (!test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
+   return false;
+
+   tout = time_after(jiffies, entry->last_action + msecs_to_jiffies(500));
+   if (unlikely(tout))
+   rt2x00_dbg(entry->queue->rt2x00dev,
+  "TX status timeout for entry %d in queue %d\n",
+  entry->entry_idx, entry->queue->qid);
+   return tout;
+
+}
+
+bool rt2800_txstatus_timeout(struct rt2x00_dev *rt2x00dev)
+{
+   struct data_queue *queue;
+   struct queue_entry *entry;
+
+   tx_queue_for_each(rt2x00dev, queue) {
+   entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+   if (rt2800_entry_txstatus_timeout(entry))
+   return true;
+   }
+   return false;
+}
+EXPORT_SYMBOL_GPL(

[PATCH 4/5] rt2x00: use different txstatus timeouts when flushing

2018-09-26 Thread Stanislaw Gruszka
Use different tx status timeouts for normal operation and when flushing.
This increase timeout to 2s for normal operation as when there are bad
radio conditions and frames are reposted many times device can not provide
the status for quite long. With new timeout we can still get valid status
on such bad conditions.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 31 +-
 drivers/net/wireless/ralink/rt2x00/rt2x00.h|  1 +
 drivers/net/wireless/ralink/rt2x00/rt2x00mac.c |  4 
 3 files changed, 26 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c 
b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 0c56c7dca55f..595cb9c90b81 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -1137,36 +1137,47 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev)
 }
 EXPORT_SYMBOL_GPL(rt2800_txdone);
 
-static inline bool rt2800_entry_txstatus_timeout(struct queue_entry *entry)
+static inline bool rt2800_entry_txstatus_timeout(struct rt2x00_dev *rt2x00dev,
+struct queue_entry *entry)
 {
-   bool tout;
+   bool ret;
+   unsigned long tout;
 
if (!test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
return false;
 
-   tout = time_after(jiffies, entry->last_action + msecs_to_jiffies(500));
-   if (unlikely(tout))
+   if (test_bit(DEVICE_STATE_FLUSHING, &rt2x00dev->flags))
+   tout = msecs_to_jiffies(100);
+   else
+   tout = msecs_to_jiffies(2000);
+
+   ret = time_after(jiffies, entry->last_action + tout);
+   if (unlikely(ret))
rt2x00_dbg(entry->queue->rt2x00dev,
   "TX status timeout for entry %d in queue %d\n",
   entry->entry_idx, entry->queue->qid);
-   return tout;
-
+   return ret;
 }
 
 bool rt2800_txstatus_timeout(struct rt2x00_dev *rt2x00dev)
 {
struct data_queue *queue;
struct queue_entry *entry;
+   unsigned long tout;
+
+   if (test_bit(DEVICE_STATE_FLUSHING, &rt2x00dev->flags))
+   tout = msecs_to_jiffies(50);
+   else
+   tout = msecs_to_jiffies(1000);
 
-   if (time_before(jiffies,
-   rt2x00dev->last_nostatus_check + msecs_to_jiffies(500)))
+   if (time_before(jiffies, rt2x00dev->last_nostatus_check + tout))
return false;
 
rt2x00dev->last_nostatus_check = jiffies;
 
tx_queue_for_each(rt2x00dev, queue) {
entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
-   if (rt2800_entry_txstatus_timeout(entry))
+   if (rt2800_entry_txstatus_timeout(rt2x00dev, entry))
return true;
}
 
@@ -1195,7 +1206,7 @@ void rt2800_txdone_nostatus(struct rt2x00_dev *rt2x00dev)
break;
 
if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags) ||
-   rt2800_entry_txstatus_timeout(entry))
+   rt2800_entry_txstatus_timeout(rt2x00dev, entry))
rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
else
break;
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h 
b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
index af062cda4a23..4b1744e9fb78 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
@@ -665,6 +665,7 @@ enum rt2x00_state_flags {
DEVICE_STATE_STARTED,
DEVICE_STATE_ENABLED_RADIO,
DEVICE_STATE_SCANNING,
+   DEVICE_STATE_FLUSHING,
 
/*
 * Driver configuration
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c 
b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
index fa2fd64084ac..2825560e2424 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
@@ -720,8 +720,12 @@ void rt2x00mac_flush(struct ieee80211_hw *hw, struct 
ieee80211_vif *vif,
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
return;
 
+   set_bit(DEVICE_STATE_FLUSHING, &rt2x00dev->flags);
+
tx_queue_for_each(rt2x00dev, queue)
rt2x00queue_flush_queue(queue, drop);
+
+   clear_bit(DEVICE_STATE_FLUSHING, &rt2x00dev->flags);
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_flush);
 
-- 
2.7.5



[PATCH 0/5] rt2800mmio txdone/interrupts/flush rework

2018-09-26 Thread Stanislaw Gruszka
This patchset make rt2800mmio txdone routines the same as rt2800usb.
It should address problems with TX status interrupt handling and
doing txdone for cases when we miss TX statuses from HW. We assume
that for PCIe/SOC we always read TX status in IRQ routine, but this
can be not true for example when CPU is busy with other interrupts.  

It was tested by  with positive feedback, some users report that
patches make MT7620 routers workable for them. This is documented
here: https://bugzilla.kernel.org/show_bug.cgi?id=82751

Stanislaw Gruszka (5):
  rt2800: move usb specific txdone/txstatus routines to rt2800lib
  rt2800mmio: use txdone/txstatus routines from lib
  rt2x00: do not check for txstatus timeout every time on tasklet
  rt2x00: use different txstatus timeouts when flushing
  rt2800: flush and txstatus rework for rt2800mmio

 drivers/net/wireless/ralink/rt2x00/rt2800lib.c   | 154 +
 drivers/net/wireless/ralink/rt2x00/rt2800lib.h   |   3 +
 drivers/net/wireless/ralink/rt2x00/rt2800mmio.c  | 277 +++
 drivers/net/wireless/ralink/rt2x00/rt2800mmio.h  |   1 +
 drivers/net/wireless/ralink/rt2x00/rt2800pci.c   |   2 +-
 drivers/net/wireless/ralink/rt2x00/rt2800usb.c   | 143 +---
 drivers/net/wireless/ralink/rt2x00/rt2x00.h  |   3 +
 drivers/net/wireless/ralink/rt2x00/rt2x00mac.c   |   4 +
 drivers/net/wireless/ralink/rt2x00/rt2x00queue.c |   2 +
 9 files changed, 259 insertions(+), 330 deletions(-)

-- 
2.7.5



Re: [PATCH] mt76x0: add quirk to disable 2.4GHz band for Archer T1U

2018-09-25 Thread Stanislaw Gruszka
On Tue, Sep 25, 2018 at 11:55:48AM +0200, Arend van Spriel wrote:
> On 9/25/2018 11:48 AM, Stanislaw Gruszka wrote:
> >On Tue, Sep 25, 2018 at 11:07:47AM +0200, Lorenzo Bianconi wrote:
> >>On Sep 25, Felix Fietkau wrote:
> >>>On 2018-09-25 09:54, Lorenzo Bianconi wrote:
> >>>>>
> >>>>>diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c 
> >>>>>b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
> >>>>>index 76d607f73758..b7a1069ecd0e 100644
> >>>>>--- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
> >>>>>+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
> >>>>>@@ -45,7 +45,8 @@
> >>>>> { USB_DEVICE(0x20f4, 0x806b) }, /* TRENDnet TEW-806UBH  */
> >>>>> { USB_DEVICE(0x7392, 0xc711) }, /* Devolo Wifi ac Stick */
> >>>>> { USB_DEVICE(0x0df6, 0x0079) }, /* Sitecom Europe B.V. ac  
> >>>>> Stick */
> >>>>>-{ USB_DEVICE(0x2357, 0x0105) }, /* TP-LINK Archer T1U */
> >>>>>+{ USB_DEVICE(0x2357, 0x0105),
> >>>>>+  .driver_info = 1,  }, /* TP-LINK Archer T1U */
> >>>>
> >>>>Hi Stanislaw,
> >>>>
> >>>>what about using 'ieee80211-freq-limit' OF property to limit available 
> >>>>wireless
> >>>>band? In this way we can take into account even the opposite case (no 
> >>>>5GHz).
> >>>That doesn't make sense for USB devices, which can be plugged into any
> >>>machine.
> >>
> >>Ack, right.
> >>What about a more general solution like adding an enum { NO_5GHz = 1, 
> >>NO_2GHz }?
> >>Does it worth to implement it now?
> >
> >I do not see reason for that. Basically band information should be
> >read from EEPROM, I do not expect need for more quirks like this.
> 
> Well. Never say never :-p And the phrase "quirks like this" does
> seem to leave the door open for other quirks. Or did you mean
> "quirks using driver_info"?

I mean quirks that mask out band. Anyway if the need for any other
quirk will show up then the things can be modified. Do not see point
for doing it now, when we don't know if new stuff will be used
at all.

Thanks
Stanislaw



Re: [PATCH] mt76x0: add quirk to disable 2.4GHz band for Archer T1U

2018-09-25 Thread Stanislaw Gruszka
On Tue, Sep 25, 2018 at 11:07:47AM +0200, Lorenzo Bianconi wrote:
> On Sep 25, Felix Fietkau wrote:
> > On 2018-09-25 09:54, Lorenzo Bianconi wrote:
> > >>  
> > >> diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c 
> > >> b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
> > >> index 76d607f73758..b7a1069ecd0e 100644
> > >> --- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
> > >> +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
> > >> @@ -45,7 +45,8 @@
> > >>  { USB_DEVICE(0x20f4, 0x806b) }, /* TRENDnet TEW-806UBH  */
> > >>  { USB_DEVICE(0x7392, 0xc711) }, /* Devolo Wifi ac Stick */
> > >>  { USB_DEVICE(0x0df6, 0x0079) }, /* Sitecom Europe B.V. ac  
> > >> Stick */
> > >> -{ USB_DEVICE(0x2357, 0x0105) }, /* TP-LINK Archer T1U */
> > >> +{ USB_DEVICE(0x2357, 0x0105),
> > >> +  .driver_info = 1,  }, /* TP-LINK Archer T1U */
> > > 
> > > Hi Stanislaw,
> > > 
> > > what about using 'ieee80211-freq-limit' OF property to limit available 
> > > wireless
> > > band? In this way we can take into account even the opposite case (no 
> > > 5GHz).
> > That doesn't make sense for USB devices, which can be plugged into any
> > machine.
> 
> Ack, right.
> What about a more general solution like adding an enum { NO_5GHz = 1, NO_2GHz 
> }?
> Does it worth to implement it now?

I do not see reason for that. Basically band information should be
read from EEPROM, I do not expect need for more quirks like this.

Thanks
Stanislaw 


[PATCH] mt76x0: add quirk to disable 2.4GHz band for Archer T1U

2018-09-24 Thread Stanislaw Gruszka
TP-LINK Archer T1U do not support 2.4GHz band despite EEPROM
reports that. Add quirk to mask out 2.4GHz support.

Reported-by: Sid Hayn 
Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c | 5 +
 drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h | 2 ++
 drivers/net/wireless/mediatek/mt76/mt76x0/usb.c| 7 ++-
 3 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
index 18bd80adbb51..3d712f6d7078 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
@@ -62,6 +62,11 @@ static void mt76x0_set_chip_cap(struct mt76x0_dev *dev)
dev_dbg(dev->mt76.dev, "2GHz %d 5GHz %d\n",
dev->mt76.cap.has_2ghz, dev->mt76.cap.has_5ghz);
 
+   if (dev->no_2ghz) {
+   dev->mt76.cap.has_2ghz = false;
+   dev_dbg(dev->mt76.dev, "mask out 2GHz support\n");
+   }
+
if (!mt76x02_field_valid(nic_conf1 & 0xff))
nic_conf1 &= 0xff00;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h 
b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
index 7e131241344b..242abab69cdb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
@@ -108,6 +108,8 @@ struct mt76x0_dev {
u8 agc_save;
u16 chainmask;
 
+   bool no_2ghz;
+
struct mac_stats stats;
 };
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
index 76d607f73758..b7a1069ecd0e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
@@ -45,7 +45,8 @@
{ USB_DEVICE(0x20f4, 0x806b) }, /* TRENDnet TEW-806UBH  */
{ USB_DEVICE(0x7392, 0xc711) }, /* Devolo Wifi ac Stick */
{ USB_DEVICE(0x0df6, 0x0079) }, /* Sitecom Europe B.V. ac  Stick */
-   { USB_DEVICE(0x2357, 0x0105) }, /* TP-LINK Archer T1U */
+   { USB_DEVICE(0x2357, 0x0105),
+ .driver_info = 1,  }, /* TP-LINK Archer T1U */
{ USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x7630, 0xff, 0x2, 0xff)}, /* 
MT7630U */
{ USB_DEVICE_AND_INTERFACE_INFO(0x0E8D, 0x7650, 0xff, 0x2, 0xff)}, /* 
MT7650U */
{ 0, }
@@ -222,6 +223,10 @@ static int mt76x0u_probe(struct usb_interface *usb_intf,
if (!dev)
return -ENOMEM;
 
+   /* Quirk for Archer T1U */
+   if (id->driver_info)
+   dev->no_2ghz = true;
+
usb_dev = usb_get_dev(usb_dev);
usb_reset_device(usb_dev);
 
-- 
1.9.3



Re: mt76x0 random crashes after c12128ce44b0

2018-09-24 Thread Stanislaw Gruszka
On Mon, Sep 24, 2018 at 04:27:59PM +0200, Lorenzo Bianconi wrote:
> >
> > hi
> >
> > On Mon, Sep 24, 2018 at 04:13:11PM +0200, Lorenzo Bianconi wrote:
> > > On Sep 24, Stanislaw Gruszka wrote:
> > > > Hi, after -next commit:
> > > >
> > > > commit c12128ce44b04a987c4eb0f733cc99c4dd50d45a
> > > > Author: Felix Fietkau 
> > > > Date:   Fri Jul 13 16:26:15 2018 +0200
> > > >
> > > > mt76: use a per rx queue page fragment cache
> > > >
> > > > I have random crashes when load or unlod mt76x0u module.
> > > >
> > >
> > > Hi Stanislaw,
> > >
> > > could you please try following patch (I am not 100% sure it fixes the 
> > > issue)
> >
> > Still crashes when module is unloaded.
> 
> ok, what are the steps to reproduce it? rmmod mt76x0?

modprobe -r mt76x0u

Not sure if that matter, but modprobe unload also other mt76 modules.

But also sometimes crashes after first modprobe or when unplug/plug
device .

Thanks
Stanislaw


Re: mt76x0 random crashes after c12128ce44b0

2018-09-24 Thread Stanislaw Gruszka
hi

On Mon, Sep 24, 2018 at 04:13:11PM +0200, Lorenzo Bianconi wrote:
> On Sep 24, Stanislaw Gruszka wrote:
> > Hi, after -next commit: 
> > 
> > commit c12128ce44b04a987c4eb0f733cc99c4dd50d45a
> > Author: Felix Fietkau 
> > Date:   Fri Jul 13 16:26:15 2018 +0200
> > 
> > mt76: use a per rx queue page fragment cache
> > 
> > I have random crashes when load or unlod mt76x0u module.
> > 
> 
> Hi Stanislaw,
> 
> could you please try following patch (I am not 100% sure it fixes the issue)

Still crashes when module is unloaded.

Regards
Stanislaw


mt76x0 random crashes after c12128ce44b0

2018-09-24 Thread Stanislaw Gruszka
Hi, after -next commit: 

commit c12128ce44b04a987c4eb0f733cc99c4dd50d45a
Author: Felix Fietkau 
Date:   Fri Jul 13 16:26:15 2018 +0200

mt76: use a per rx queue page fragment cache

I have random crashes when load or unlod mt76x0u module.

When loading, it looks like this:

[   40.238936] usb 1-1.1: new high-speed USB device number 3 using ehci-pci
[   40.333174] usb 1-1.1: New USB device found, idVendor=2357, idProduct=0105, 
bcdDevice= 1.00
[   40.333178] usb 1-1.1: New USB device strings: Mfr=1, Product=2, 
SerialNumber=3
[   40.333181] usb 1-1.1: Product: WiFi
[   40.333183] usb 1-1.1: Manufacturer: MediaTek
[   40.333185] usb 1-1.1: SerialNumber: 1.0
[   40.566944] usb 1-1.1: reset high-speed USB device number 3 using ehci-pci
[   40.651457] mt76x0u 1-1.1:1.0: ASIC revision: 7612 MAC revision: 76502000
[   40.982520] BUG: unable to handle kernel paging request at 9f8322e19000
[   40.982540] PGD 27ba01067 P4D 27ba01067 PUD 27ddba063 PMD 263b35063 PTE 
800262e19061
[   40.982555] Oops: 0003 [#1] SMP PTI
[   40.982563] CPU: 2 PID: 1766 Comm: systemd-udevd Not tainted 4.19.0-rc5+ #6
[   40.982570] Hardware name: ASUSTeK COMPUTER INC. ESC2000 G2/Z9PE-D8 WS, BIOS 
0405 03/19/2012
[   40.982587] RIP: 0010:__memcpy+0x12/0x20
[   40.982593] Code: 48 c1 e2 20 48 09 c2 48 31 d3 e9 68 ff ff ff 90 90 90 90 
90 90 90 90 90 66 66 90 66 90 48 89 f8 48 89 d1 48 c1 e9 03 83 e2 07  48 a5 
89 d1 f3 a4 c3 66 0f 1f 44 00 00 48 89 f8 48 89 d1 f3 a4
[   40.982608] RSP: 0018:ba13849b3ad8 EFLAGS: 00010246
[   40.982616] RAX: 9f8322e17004 RBX: 38f0 RCX: 031f
[   40.982626] RDX:  RSI: ba13844cf058 RDI: 9f8322e18ffc
[   40.982633] RBP: 00010c6c R08:  R09: 607ec000
[   40.982640] R10: 0003 R11: 3e2e R12: 9f8324cd9540
[   40.982648] R13:  R14: ba13849b3b30 R15: 9f8322e17000
[   40.982656] FS:  7fadec85b880() GS:9f833fa8() 
knlGS:
[   40.982664] CS:  0010 DS:  ES:  CR0: 80050033
[   40.982670] CR2: 9f8322e19000 CR3: 000263428001 CR4: 000606e0
[   40.982677] Call Trace:
[   40.982690]  mt76x02u_mcu_fw_send_data+0x16c/0x270 [mt76x02_usb]
[   40.982702]  mt76x0u_probe+0x35a/0x598 [mt76x0u]
[   40.982711]  ? __pm_runtime_set_status+0x149/0x210
[   40.982721]  usb_probe_interface+0x113/0x310
[   40.982730]  really_probe+0x1c8/0x400
[   40.982738]  driver_probe_device+0x5c/0x130
[   40.982745]  __driver_attach+0xec/0x110
[   40.982751]  ? driver_probe_device+0x130/0x130
[   40.982758]  bus_for_each_dev+0x50/0x90
[   40.982766]  bus_add_driver+0x1c0/0x280
[   40.982773]  driver_register+0x5b/0xe0
[   40.982780]  usb_register_driver+0x7c/0x140
[   40.982787]  ? 0xc0ad9000
[   40.982794]  do_one_initcall+0x44/0x19b
[   40.982802]  ? free_unref_page_commit+0x80/0xf0
[   40.982810]  ? _cond_resched+0x15/0x30
[   40.982818]  do_init_module+0x5a/0x210
[   40.982825]  load_module+0x175c/0x1bc0
[   40.982831]  ? m_show+0x190/0x190
[   40.982839]  ? kernel_read_file+0x161/0x1b0
[   40.982846]  ? kernel_read_file_from_fd+0x44/0x70
[   40.982855]  ? security_capable+0x39/0x50
[   40.982861]  __do_sys_finit_module+0x97/0xc0
[   40.982870]  do_syscall_64+0x3f/0xf0
[   40.982876]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
[   40.982883] RIP: 0033:0x7fadeb6f1809
[   40.982888] Code: 01 00 48 81 c4 80 00 00 00 e9 f1 fe ff ff 0f 1f 00 48 89 
f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 
f0 ff ff 73 01 c3 48 8b 0d 1f 86 2c 00 f7 d8 64 89 01 48
[   40.982904] RSP: 002b:7ffe548f9f38 EFLAGS: 0246 ORIG_RAX: 
0139
[   40.982913] RAX: ffda RBX: 7fadebdf0d89 RCX: 7fadeb6f1809
[   40.982920] RDX:  RSI: 7fadebdf0d89 RDI: 0006
[   40.982927] RBP:  R08:  R09: 
[   40.982934] R10: 0006 R11: 0246 R12: 560b9ef58ab0
[   40.982941] R13: 560b9ef29800 R14: 560b9ef59040 R15: 0002

However somethings module load correctly and crash happen when I unload it:

[  522.218992] BUG: Bad page state in process polkitd  pfn:264d20
[  522.218997] page:dae40860df00 count:-1 mapcount:0 
mapping: index:0x0
[  522.219000] flags: 0x20()
[  522.219004] raw: 0020 dead0100 dead0200 

[  522.219006] raw:   
[  522.219007] page dumped because: nonzero _refcount
[  522.219008] Modules linked in: mt76x0u mt76x0_common mt76x02_usb mt76_usb 
mt76x02_lib mt76 mac80211 cfg80211 ctr ccm arc4 bnep bluetooth ecdh_generic 
ip6table_filter ip6_tables iptable_filter ip_tables ebtable_nat ebtables rfkill 
snd_hda_codec_hdmi x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel kvm 
snd_hda_codec_realtek snd_hda_codec_generic snd_hda_intel snd_hda_codec 
irqb

Re: [RFC 00/12] rtwlan: mac80211 driver for Realtek 802.11ac wireless network chips

2018-09-21 Thread Stanislaw Gruszka
On Fri, Sep 21, 2018 at 02:03:55PM +0800, yhchu...@realtek.com wrote:
> From: Yan-Hsuan Chuang 
> 
> This is a new mac80211 driver for Realtek 802.11ac wireless network chips.
> rtwlan supports 8822BE and 8822CE chips, and will be able to support
> multi-vif combinations in run-time.
> 
> For now, only PCI bus is supported, but rtwlan was originally designed
> to optionally support three buses includes USB & SDIO. USB & SDIO modules
> will soon be supported by rtwlan, with configurable core module to fit
> with different bus modules in the same time.
> 
> For example, if we choose 8822BE and 8822CU, only PCI & USB modules will
> be selected, built, loaded into kernel. This is one of the major
> difference from rtlwifi, which can only support specific combinations.
> 
> Another difference from rtlwifi is that rtwlan is designed to support
> the latest Realtek 802.11ac wireless network chips like 8822B and
> 8822C series. Compared to the earlier chips supported by rtlwifi like
> the 802.11n 8192EE chipset or 802.11ac 8821AE/8812AE chips, newer ICs
> have different MAC & PHY settings, such as new multi-port feature for the
> MAC layer design and Jaguar2/Jaguar3 PHY layer IPs.
> 
> Multi-Port feature is also supported under rtwlan's software architecture.
> rtlwifi can only support one vif in the same time, most because of the
> hardware limitations for early chips, hence the original design of it
> also restricts the usage of multi-vif support, so latest chipset seems not
> take advantages from its new MAC engine.
> 
> However, rtwlan can run multiple vifs concurrently by holding them on
> hardware ports provided by MAC engine, so we can easily start different
> roles on a single device.
> 
> Based on the reasons mentioned before, we implemented rtwlan. It had many
> authors, they are listed here alphabetically:
> 
> Ping-Ke Shih 
> Tzu-En Huang 
> Yan-Hsuan Chuang 

I didn't do detailed review, but my general impression is very very
positive. New driver looks great!

Just 2 generic remarks:
- please add MAINTAINERS file entry
- please post a patch or request to remove staging/rtlwifi driver
  since this one is replace for it (8822BE PCI-ID is the same)

Thanks
Stanislaw


Re: [PATCH 1/5] rt2x00: set registers based on current band

2018-09-19 Thread Stanislaw Gruszka
On Wed, Sep 19, 2018 at 02:47:18PM +0200, Stanislaw Gruszka wrote:
> > Can you show us how will the problem trigger on dual band devices?
> 
> When you switch from some 2.4GHz channel to 5GHz channel (or vice versa)
> ->curr_band will point to old band not the new one. To fix that you 
> have to move curr_band assignemt before ->config() in
> rt2x00lib_config() i.e:
> 
> rt2x00dev->curr_band = conf->chandef.chan->band; 
> rt2x00dev->ops->lib->config(rt2x00dev, &libconf, ieee80211_flags);
> 
> However I do not see the point of replacyng rf->channel check 
> to ->curr_band check. What you can do is oposite thing, replace
> wrong usage of ->curr_band in very few places in rt2800_config()
> subroutines to rf->channel check.

Actually ->curr_band is used in rt2800_config_ant() subroutines
not in rt2800_config() subroutines so things looks ok.

Stanislaw


Re: [PATCH 1/5] rt2x00: set registers based on current band

2018-09-19 Thread Stanislaw Gruszka
On Wed, Sep 19, 2018 at 02:17:30PM +0200, Tomislav Požega wrote:
> On Wed, 19 Sep 2018 13:05:41 +0200, Stanislaw Gruszka wrote:
> 
> >Driver should provide on what channels are supported to mac80211, but
> >user space decide what channel to use and that imply band 2.4GHz or
> >5GHz. ->curr_band is just shortcut for band of current channel. Is set 
> >in rt2x00lib_config() after we call rt2x00dev->ops->lib->config()
> >[rt2800_config() for rt2800] . So patch is wrong. Either ->curr_band 
> >should be set before ->config call or we need to consistently use
> >rf->channel <= 14 for band check in any rt2800_config() function and
> >all it's subroutines. I prefer the second solution (i.e. rf->channel)
> >and now I can see few places when we use ->curr_band, what is a bug.
> 
> Works fine, no any kind of regression, especially not performance ones.
Did you test on dual band devices ?

> So I don't see a reason to claim it is wrong or bug just because you
> prefer current solution.
It's not wrong bacause I prefer current solution. It's because 
->curr_band is not updated when you call rt2800_config().

> >It's because ->curr_band initialize to 0 and NL80211_BAND_2GHZ
> >happen to be 0. Also problem will not trigger on single band
> >2.4GHz devices.
> 
> Can you show us how will the problem trigger on dual band devices?

When you switch from some 2.4GHz channel to 5GHz channel (or vice versa)
->curr_band will point to old band not the new one. To fix that you 
have to move curr_band assignemt before ->config() in
rt2x00lib_config() i.e:

rt2x00dev->curr_band = conf->chandef.chan->band; 
rt2x00dev->ops->lib->config(rt2x00dev, &libconf, ieee80211_flags);

However I do not see the point of replacyng rf->channel check 
to ->curr_band check. What you can do is oposite thing, replace
wrong usage of ->curr_band in very few places in rt2800_config()
subroutines to rf->channel check.

Also replacing spec->num_channels is wrong because this will
stop reporting device support 5GHz band.

Regards
Stanislaw 


Re: [PATCH] mt76x0: run vco calibration for each channel configuration

2018-09-19 Thread Stanislaw Gruszka
On Tue, Sep 18, 2018 at 10:26:09AM -0400, Sid Hayn wrote:
> mt76x0 isn't in 4.18 at all, it's being added in 4.19 isn't it?  I'm
> not sure you can call it a regression, but adding a new driver with a
> known bug that breaks an entire use case (monitor mode) seems silly
> when a small and tested fix is available.  Pretty please.

Patch conflict with pending mt76 -next patches. Apply it and rebase
all other patches on top of it, is a lot of work. I agree with
Kalle that it will be better to apply this patch on top of -next
and CC stable. Problem should be fixed in 4.19.1 or 4.19.2 .

Regards
Stanislaw


Re: mt76x0 bug report

2018-09-19 Thread Stanislaw Gruszka
On Tue, Sep 18, 2018 at 01:36:51PM -0400, Sid Hayn wrote:
> On Tue, Sep 18, 2018 at 7:56 AM Stanislaw Gruszka  wrote:
> >
> > On Mon, Sep 17, 2018 at 11:18:57PM -0400, Sid Hayn wrote:
> > > Sorry to bump the one thing that we both agreed was low priority but
> > >
> > > So was testing all of my dongles that use the driver you are working
> > > on, and running them through my connect scripts.  I moved the AP to
> > > maybe <5ft from the clients and something wierd happened.  The t1u
> > > tried to connect to one of the 2.4GHz only networks.  It failed, but
> > > it actually got enough scan data back to attempt authentication with a
> > > valid 2.4GHz only bssid.  Which means in short, that the eeprom isn't
> > > lying and your parsing of it is correct.  Something obviously makes
> > > this a 5GHz only device, as the connection failed and most of the time
> > > nothing at all is seen on 2.4GHz, but clearly it's some filter or
> > > antenna or some other mechanism which makes it 5GHz only.  So probably
> > > hardware lying to you is now even lower on your list since this safely
> > > rules out the driver parsing the eeprom incorrectly.
> >
> > First of all would be good to check if problem is not already solved,
> > latest version of the driver can be found here:
> > https://github.com/nbd168/wireless
> 
> Booting that kernel gets me instant to near instant kernel panics, so
> I am unable to test much.

This has to be fixed as well, can you provide kernel messages ?

> > Second, is there vendor driver available for this particular device?
> > Perhaps there are some tweeks needed that are not provided by generic
> > driver.
> 
> No clue, haven't even tried to look.  This hardware was all sitting on
> a shelf till it looked like a real driver was being merged into the
> kernel so um, thanks :-)

Why do you think device is 5GHz only? This is very unusual. I know
only single-band 2.4GHz or dual-band 2.4GHz & 5GHz devices.

Regards
Stanislaw 


Re: [PATCH 1/5] rt2x00: set registers based on current band

2018-09-19 Thread Stanislaw Gruszka
On Tue, Sep 18, 2018 at 04:14:33PM +0200, Tomislav Požega wrote:
> On Tue, 18 Sep 2018 14:20:16 +0200, Stanislaw Gruszka wrote:
> 
> >On Mon, Sep 17, 2018 at 06:32:51PM +0200, Tomislav Požega wrote:
> >> Use curr_band instead of rf->channel among various subroutines -
> >> mostly for 2.4GHz band but in some circumstances for 5GHz band too.
> >
> >What is the reason for that change ?
> 
> Operating band should be fetched from device capabilities, not from userspace
> variables. More changes will needed to be made to accomplish that.

Driver should provide on what channels are supported to mac80211, but
user space decide what channel to use and that imply band 2.4GHz or
5GHz. ->curr_band is just shortcut for band of current channel. Is set 
in rt2x00lib_config() after we call rt2x00dev->ops->lib->config()
[rt2800_config() for rt2800] . So patch is wrong. Either ->curr_band 
should be set before ->config call or we need to consistently use
rf->channel <= 14 for band check in any rt2800_config() function and
all it's subroutines. I prefer the second solution (i.e. rf->channel)
and now I can see few places when we use ->curr_band, what is a bug.

> >> -  if (spec->num_channels > 14) {
> >> +  if (rt2x00dev->curr_band == NL80211_BAND_5GHZ) {
> >>default_power1 = rt2800_eeprom_addr(rt2x00dev,
> >>EEPROM_TXPOWER_A1);
> >>default_power2 = rt2800_eeprom_addr(rt2x00dev,
> >
> >Above looks wrong.
> >
> >Thanks
> >Stanislaw
> 
> Worked fine when I tried run two USB cards (RT3070-RF0005, RT5390-RF5370).
> Why do you think it's wrong? Is there a dual-band card that operates on
> both bands at the same time?

It's because ->curr_band initialize to 0 and NL80211_BAND_2GHZ
happen to be 0. Also problem will not trigger on single band
2.4GHz devices.

Regards
Stanislaw


Re: [PATCH 2/5] rt2x00: rework channel config function

2018-09-18 Thread Stanislaw Gruszka
On Mon, Sep 17, 2018 at 06:32:52PM +0200, Tomislav Požega wrote:
> - switch (rt2x00dev->default_ant.tx_chain_num) {
> - case 3:
> - /* Turn on tertiary PAs */
> - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A2_EN,
> -rf->channel > 14);
> - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G2_EN,
> -rf->channel <= 14);
> - /* fall-through */
> - case 2:
> - /* Turn on secondary PAs */
> - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN,
> -rf->channel > 14);
> - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN,
> -rf->channel <= 14);
> - /* fall-through */
> - case 1:
> - /* Turn on primary PAs */
> - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN,
> -rf->channel > 14);
> - if (rt2x00_has_cap_bt_coexist(rt2x00dev))
> + if (rt2x00dev->curr_band == NL80211_BAND_5GHZ) {
> + switch (rt2x00dev->default_ant.tx_chain_num) {
> + case 3:
> + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A2_EN, 1);
> + case 2:
> + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1);
> + case 1:
> + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, 1);
> + break;

Please keep /* fall-through */ comments, this is needed 
for some automatic code checkers tools.



Re: [PATCH 1/5] rt2x00: set registers based on current band

2018-09-18 Thread Stanislaw Gruszka
On Mon, Sep 17, 2018 at 06:32:51PM +0200, Tomislav Požega wrote:
> Use curr_band instead of rf->channel among various subroutines -
> mostly for 2.4GHz band but in some circumstances for 5GHz band too.

What is the reason for that change ?

> @@ -9265,8 +9278,9 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev 
> *rt2x00dev)
>   if (WARN_ON_ONCE(!spec->channels))
>   return -ENODEV;
>  
> - spec->supported_bands = SUPPORT_BAND_2GHZ;
> - if (spec->num_channels > 14)
> + if (rt2x00dev->curr_band == NL80211_BAND_2GHZ)
> + spec->supported_bands = SUPPORT_BAND_2GHZ;
> + if (rt2x00dev->curr_band == NL80211_BAND_5GHZ)
>   spec->supported_bands |= SUPPORT_BAND_5GHZ;
>  
>   /*
> @@ -9336,7 +9350,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev 
> *rt2x00dev)
>   info[i].default_power3 = default_power3[i];
>   }
>  
> - if (spec->num_channels > 14) {
> + if (rt2x00dev->curr_band == NL80211_BAND_5GHZ) {
>   default_power1 = rt2800_eeprom_addr(rt2x00dev,
>   EEPROM_TXPOWER_A1);
>   default_power2 = rt2800_eeprom_addr(rt2x00dev,

Above looks wrong.

Thanks
Stanislaw


Re: [PATCH] mt76x0: run vco calibration for each channel configuration

2018-09-18 Thread Stanislaw Gruszka
On Tue, Sep 18, 2018 at 01:43:56PM +0200, Stanislaw Gruszka wrote:
> On Fri, Sep 07, 2018 at 11:13:12PM +0200, Lorenzo Bianconi wrote:
> > According to vendor sdk, vco calibration has to be executed
> > for each channel configuration whereas mcu calibration has to be
> > performed during channel scanning. This patch fixes the mt76x0
> > monitor mode issue since in that configuration vco calibration
> > was never executed
> > 
> > Fixes: 10de7a8b4ab9 ("mt76x0: phy files")
> > Tested-by: Sid Hayn 
> > Signed-off-by: Lorenzo Bianconi 
> 
> Acked-by: Stanislaw Gruszka 

For the record this is 4.19 material.


Re: mt76x0 bug report

2018-09-18 Thread Stanislaw Gruszka
On Mon, Sep 17, 2018 at 11:18:57PM -0400, Sid Hayn wrote:
> Sorry to bump the one thing that we both agreed was low priority but
> 
> So was testing all of my dongles that use the driver you are working
> on, and running them through my connect scripts.  I moved the AP to
> maybe <5ft from the clients and something wierd happened.  The t1u
> tried to connect to one of the 2.4GHz only networks.  It failed, but
> it actually got enough scan data back to attempt authentication with a
> valid 2.4GHz only bssid.  Which means in short, that the eeprom isn't
> lying and your parsing of it is correct.  Something obviously makes
> this a 5GHz only device, as the connection failed and most of the time
> nothing at all is seen on 2.4GHz, but clearly it's some filter or
> antenna or some other mechanism which makes it 5GHz only.  So probably
> hardware lying to you is now even lower on your list since this safely
> rules out the driver parsing the eeprom incorrectly.

First of all would be good to check if problem is not already solved,
latest version of the driver can be found here:
https://github.com/nbd168/wireless

Second, is there vendor driver available for this particular device?
Perhaps there are some tweeks needed that are not provided by generic
driver.

Thanks
Stanislaw 


Re: [PATCH] mt76x0: run vco calibration for each channel configuration

2018-09-18 Thread Stanislaw Gruszka
On Fri, Sep 07, 2018 at 11:13:12PM +0200, Lorenzo Bianconi wrote:
> According to vendor sdk, vco calibration has to be executed
> for each channel configuration whereas mcu calibration has to be
> performed during channel scanning. This patch fixes the mt76x0
> monitor mode issue since in that configuration vco calibration
> was never executed
> 
> Fixes: 10de7a8b4ab9 ("mt76x0: phy files")
> Tested-by: Sid Hayn 
> Signed-off-by: Lorenzo Bianconi 

Acked-by: Stanislaw Gruszka 



Re: [PATCH 39/42] mt76: move some irq code to common mmio module

2018-09-06 Thread Stanislaw Gruszka
On Thu, Sep 06, 2018 at 11:33:55AM +0200, Felix Fietkau wrote:
> On 2018-09-06 11:18, Stanislaw Gruszka wrote:
> > Move some irq handling code to generic mmio module.
> > 
> > Signed-off-by: Stanislaw Gruszka 
> Please drop this patch. This won't work on MT7603 and later.

Yeah, I thought MT_INT_MASK_CSR is the same 0x0204 for all chips,
but for MT7603 this is MT_HIF(0x204). I assume we can still unify 
irq_lock, irqmask fields in common structure.

Anyway would be good to have mt7603 driver unstreamed, so we could
easily see what can be shared in mt76 generic code for all chips.

Felix, do you have plans to upstream it? Want some help with that ?

Thanks
Stanislaw


Re: [PATCH 39/42] mt76: move some irq code to common mmio module

2018-09-06 Thread Stanislaw Gruszka
On Thu, Sep 06, 2018 at 11:47:53AM +0200, Lorenzo Bianconi wrote:
> >
> > On 2018-09-06 11:37, Lorenzo Bianconi wrote:
> > >>
> > >> On 2018-09-06 11:18, Stanislaw Gruszka wrote:
> > >> > Move some irq handling code to generic mmio module.
> > >> >
> > >> > Signed-off-by: Stanislaw Gruszka 
> > >> Please drop this patch. This won't work on MT7603 and later.
> > >>
> > >> - Felix
> > >
> > > I can move that code in a dedicated module with a separated patch.
> > > I have a pending patchset to fix that kind of issues for usb as well.
> > > Does it sound good?
> > I don't think it's worth having yet another dedicated module for these
> > small things. Just keep it in the common mt76x02 code, even if it
> > doesn't get used by the usb variants.
> >
> > - Felix
> 
> Ack, I agree. I guess Stanislaw can fix it sending a v2

Actually those two patches can be dropped from the set, remainging
40,41,42 patches will apply.

Kalle plese drop:
[PATCH 38/42] mt76: initial separation of mmio part
[PATCH 39/42] mt76: move some irq code to common mmio module

Thanks
Stanislaw


[PATCH] mt76: fix return value of mt76x02_wait_for_mac

2018-09-06 Thread Stanislaw Gruszka
We need to return bool value in mt76x02_wait_for_mac.

Reported-by: Dan Carpenter 
Fixes: 2735a6dd7df3 ("mt76: unify wait_for_mac")
Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x02_mac.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h 
b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h
index 1a5da35702e6..a8bb3fede8d5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.h
@@ -165,7 +165,7 @@ static inline bool mt76x02_wait_for_mac(struct mt76_dev 
*dev)
 
for (i = 0; i < 500; i++) {
if (test_bit(MT76_REMOVED, &dev->state))
-   return -EIO;
+   return false;
 
switch (dev->bus->rr(dev, MAC_CSR0)) {
case 0:
-- 
2.7.5



Re: mt76x0 bug report

2018-09-06 Thread Stanislaw Gruszka
On Wed, Sep 05, 2018 at 08:52:18PM +, Sid Hayn wrote:
> On Tue, Sep 4, 2018 at 5:11 PM Lorenzo Bianconi
>  wrote:
> >
> > >
> > > I have one mt76x2u (Alfa AWUS036ACM) and a few mt76x0.
> > >
> > > I've noticed two additional issues in my testing.
> > >
> > > First issue, is that it appears the mt76x0 devices don't work properly
> > > in monitor mode.  Sometimes they seem to monitor one channel properly,
> > > but nothing else.  The mt76x2u works great, channel control, lots of
> > > packets, etc.
> >
> > Could you elaborate a little bit please? how can you reproduce the issue?
> > just add an interface in monitor mode and run a scan?
> 
> Correct, standard stuff, use iw to create a monitor mode interface,
> use iw to remove managed mode interface, run some tool such as kismet
> or airodump-ng or even wireshark.

But what exactly are the syptomps, I don't understand what you mean by
"mt76x0 devices don't work properly in monitor mode" ?

> > I guess it depends on eeprom values. Could you please enable debug
> > messages a paste
> > syslog output?
> 
> I don't see a mediatek specific debug near the driver selection in
> menuconfig, what debug messages do you want me to enable and how?

You need to uncomment this line:

# ccflags-y := -DDEBUG

in drivers/net/wireless/mediatek/mt76/mt76x0/Makefile

Thanks
Stanislaw



[PATCH 36/42] mt76x0: use mt76_register_device for device registration

2018-09-06 Thread Stanislaw Gruszka
From: Lorenzo Bianconi 

Use mt76_register_device routine for device registration.
mt76_register_device allows to enable VHT support on 5GHz band.
Overwrite unsupported vht features with mt76x0_vht_cap_mask routine.
Remove macaddr field of mt76x0_dev data structure and
use the mt76_dev one. Moreover remove following unused routines:
- mt76_init_sband
- mt76_init_sband_2g
- mt76_init_sband_5g

Signed-off-by: Lorenzo Bianconi 
Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c |  13 +-
 drivers/net/wireless/mediatek/mt76/mt76x0/init.c   | 187 -
 drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h |   1 -
 3 files changed, 39 insertions(+), 162 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
index 0fd178d84277..2ce27de511f5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
@@ -160,18 +160,19 @@ static int
 mt76x0_set_macaddr(struct mt76x0_dev *dev, const u8 *eeprom)
 {
const void *src = eeprom + MT_EE_MAC_ADDR;
+   u8 *dst = dev->mt76.macaddr;
 
-   ether_addr_copy(dev->macaddr, src);
+   ether_addr_copy(dev->mt76.macaddr, src);
 
-   if (!is_valid_ether_addr(dev->macaddr)) {
-   eth_random_addr(dev->macaddr);
+   if (!is_valid_ether_addr(dst)) {
+   eth_random_addr(dst);
dev_info(dev->mt76.dev,
 "Invalid MAC address, using random address %pM\n",
-dev->macaddr);
+dst);
}
 
-   mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(dev->macaddr));
-   mt76_wr(dev, MT_MAC_ADDR_DW1, get_unaligned_le16(dev->macaddr + 4) |
+   mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(dst));
+   mt76_wr(dev, MT_MAC_ADDR_DW1, get_unaligned_le16(dst + 4) |
FIELD_PREP(MT_MAC_ADDR_DW1_U2ME_MASK, 0xff));
 
return 0;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
index d075b29977e3..44fcad2315a7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
@@ -23,6 +23,24 @@
 
 #include "initvals.h"
 
+static void mt76x0_vht_cap_mask(struct ieee80211_supported_band *sband)
+{
+   struct ieee80211_sta_vht_cap *vht_cap = &sband->vht_cap;
+   u16 mcs_map = 0;
+   int i;
+
+   vht_cap->cap &= ~IEEE80211_VHT_CAP_RXLDPC;
+   for (i = 0; i < 8; i++) {
+   if (!i)
+   mcs_map |= (IEEE80211_VHT_MCS_SUPPORT_0_7 << (i * 2));
+   else
+   mcs_map |=
+   (IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2));
+   }
+   vht_cap->vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
+   vht_cap->vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
+}
+
 static void
 mt76x0_set_wlan_state(struct mt76x0_dev *dev, u32 val, bool enable)
 {
@@ -488,125 +506,10 @@ struct mt76x0_dev *mt76x0_alloc_device(struct device 
*pdev)
return dev;
 }
 
-#define CHAN2G(_idx, _freq) {  \
-   .band = NL80211_BAND_2GHZ,  \
-   .center_freq = (_freq), \
-   .hw_value = (_idx), \
-   .max_power = 30,\
-}
-
-static const struct ieee80211_channel mt76_channels_2ghz[] = {
-   CHAN2G(1, 2412),
-   CHAN2G(2, 2417),
-   CHAN2G(3, 2422),
-   CHAN2G(4, 2427),
-   CHAN2G(5, 2432),
-   CHAN2G(6, 2437),
-   CHAN2G(7, 2442),
-   CHAN2G(8, 2447),
-   CHAN2G(9, 2452),
-   CHAN2G(10, 2457),
-   CHAN2G(11, 2462),
-   CHAN2G(12, 2467),
-   CHAN2G(13, 2472),
-   CHAN2G(14, 2484),
-};
-
-#define CHAN5G(_idx, _freq) {  \
-   .band = NL80211_BAND_5GHZ,  \
-   .center_freq = (_freq), \
-   .hw_value = (_idx), \
-   .max_power = 30,\
-}
-
-static const struct ieee80211_channel mt76_channels_5ghz[] = {
-   CHAN5G(36, 5180),
-   CHAN5G(40, 5200),
-   CHAN5G(44, 5220),
-   CHAN5G(46, 5230),
-   CHAN5G(48, 5240),
-   CHAN5G(52, 5260),
-   CHAN5G(56, 5280),
-   CHAN5G(60, 5300),
-   CHAN5G(64, 5320),
-
-   CHAN5G(100, 5500),
-   CHAN5G(104, 5520),
-   CHAN5G(108, 5540),
-   CHAN5G(112, 5560),
-   CHAN5G(116, 5580),
-   CHAN5G(120, 5600),
-   CHAN5G(124, 5620),
-   CHAN5G(128, 5640),
-   CHAN5G(132, 5660),
-   CHAN5G(136, 5680),
-   CHAN5G(140, 5700),
-};
-
-static int
-mt76_init_sband(struct mt76x0_dev *dev, struct ieee80211_supported_band *sband,
-   const struct ieee80211_channel *chan, int n_chan,
-   struct ieee80211_rate *rates, i

[PATCH 41/42] mt76x0: remove some usb specific code from mt76x0_register_device

2018-09-06 Thread Stanislaw Gruszka
Initial effort to make mt76x0_register_device bus neutral.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/init.c |  8 
 drivers/net/wireless/mediatek/mt76/mt76x0/usb.c  | 12 ++--
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
index 0e4a13fa42cb..4a899904d518 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
@@ -518,14 +518,6 @@ int mt76x0_register_device(struct mt76x0_dev *dev)
struct wiphy *wiphy = hw->wiphy;
int ret;
 
-   ret = mt76u_mcu_init_rx(mdev);
-   if (ret < 0)
-   return ret;
-
-   ret = mt76u_alloc_queues(mdev);
-   if (ret < 0)
-   return ret;
-
ret = mt76x0_init_hardware(dev);
if (ret)
return ret;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
index b9382092f47f..9a803fb0cd5d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
@@ -46,7 +46,7 @@ static struct usb_device_id mt76x0_device_table[] = {
{ 0, }
 };
 
-static int mt76x0_probe(struct usb_interface *usb_intf,
+static int mt76x0u_probe(struct usb_interface *usb_intf,
 const struct usb_device_id *id)
 {
struct usb_device *usb_dev = interface_to_usbdev(usb_intf);
@@ -84,6 +84,14 @@ static int mt76x0_probe(struct usb_interface *usb_intf,
if (!(mt76_rr(dev, MT_EFUSE_CTRL) & MT_EFUSE_CTRL_SEL))
dev_warn(dev->mt76.dev, "Warning: eFUSE not present\n");
 
+   ret = mt76u_mcu_init_rx(&dev->mt76);
+   if (ret < 0)
+   goto err;
+
+   ret = mt76u_alloc_queues(&dev->mt76);
+   if (ret < 0)
+   goto err;
+
ret = mt76x0_register_device(dev);
if (ret)
goto err_hw;
@@ -170,7 +178,7 @@ MODULE_LICENSE("GPL");
 static struct usb_driver mt76x0_driver = {
.name   = KBUILD_MODNAME,
.id_table   = mt76x0_device_table,
-   .probe  = mt76x0_probe,
+   .probe  = mt76x0u_probe,
.disconnect = mt76x0_disconnect,
.suspend= mt76x0_suspend,
.resume = mt76x0_resume,
-- 
2.7.5



[PATCH 42/42] mt76x0: make device allocation bus neutral

2018-09-06 Thread Stanislaw Gruszka
Remove some USB specific code form mt76x0_alloc_device.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/init.c   | 11 +++
 drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h |  3 ++-
 drivers/net/wireless/mediatek/mt76/mt76x0/pci.c|  2 +-
 drivers/net/wireless/mediatek/mt76/mt76x0/tx.c |  3 ++-
 drivers/net/wireless/mediatek/mt76/mt76x0/usb.c|  9 -
 5 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
index 4a899904d518..9c720906ea13 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
@@ -482,14 +482,9 @@ void mt76x0_cleanup(struct mt76x0_dev *dev)
 }
 EXPORT_SYMBOL_GPL(mt76x0_cleanup);
 
-struct mt76x0_dev *mt76x0_alloc_device(struct device *pdev)
+struct mt76x0_dev *
+mt76x0_alloc_device(struct device *pdev, const struct mt76_driver_ops *drv_ops)
 {
-   static const struct mt76_driver_ops drv_ops = {
-   .tx_prepare_skb = mt76x0_tx_prepare_skb,
-   .tx_complete_skb = mt76x02_tx_complete_skb,
-   .tx_status_data = mt76x02_tx_status_data,
-   .rx_skb = mt76x0_queue_rx_skb,
-   };
struct mt76x0_dev *dev;
struct mt76_dev *mdev;
 
@@ -498,7 +493,7 @@ struct mt76x0_dev *mt76x0_alloc_device(struct device *pdev)
return NULL;
 
mdev->dev = pdev;
-   mdev->drv = &drv_ops;
+   mdev->drv = drv_ops;
 
dev = container_of(mdev, struct mt76x0_dev, mt76);
mutex_init(&dev->reg_atomic_mutex);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h 
b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
index 31267a180573..87eb084bd270 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
@@ -134,7 +134,8 @@ int mt76x0_burst_write_regs(struct mt76x0_dev *dev, u32 
offset,
 const u32 *data, int n);
 
 /* Init */
-struct mt76x0_dev *mt76x0_alloc_device(struct device *dev);
+struct mt76x0_dev *
+mt76x0_alloc_device(struct device *pdev, const struct mt76_driver_ops 
*drv_ops);
 int mt76x0_init_hardware(struct mt76x0_dev *dev);
 int mt76x0_register_device(struct mt76x0_dev *dev);
 void mt76x0_cleanup(struct mt76x0_dev *dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
index 244ab64560a6..eb383f96ec9a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/pci.c
@@ -40,7 +40,7 @@ mt76x0e_probe(struct pci_dev *pdev, const struct 
pci_device_id *id)
if (ret)
return ret;
 
-   dev = mt76x0_alloc_device(&pdev->dev);
+   dev = mt76x0_alloc_device(&pdev->dev, NULL);
if (!dev)
return -ENOMEM;
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/tx.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/tx.c
index b59b16d374e1..5306fc3a90fb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/tx.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/tx.c
@@ -95,6 +95,7 @@ int mt76x0_tx_prepare_skb(struct mt76_dev *mdev, void *data,
 
return mt76x02_set_txinfo(skb, wcid, q2ep(*hwq_ptr));
 }
+EXPORT_SYMBOL_GPL(mt76x0_tx_prepare_skb);
 
 void mt76x0_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
 struct sk_buff *skb)
@@ -110,4 +111,4 @@ void mt76x0_queue_rx_skb(struct mt76_dev *mdev, enum 
mt76_rxq_id q,
 
mt76_rx(&dev->mt76, q, skb);
 }
-
+EXPORT_SYMBOL_GPL(mt76x0_queue_rx_skb);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
index 9a803fb0cd5d..89e856745fec 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
@@ -18,6 +18,7 @@
 #include "mt76x0.h"
 #include "usb.h"
 #include "trace.h"
+#include "../mt76x02_util.h"
 
 static struct usb_device_id mt76x0_device_table[] = {
{ USB_DEVICE(0x148F, 0x7610) }, /* MT7610U */
@@ -49,12 +50,18 @@ static struct usb_device_id mt76x0_device_table[] = {
 static int mt76x0u_probe(struct usb_interface *usb_intf,
 const struct usb_device_id *id)
 {
+   static const struct mt76_driver_ops drv_ops = {
+   .tx_prepare_skb = mt76x0_tx_prepare_skb,
+   .tx_complete_skb = mt76x02_tx_complete_skb,
+   .tx_status_data = mt76x02_tx_status_data,
+   .rx_skb = mt76x0_queue_rx_skb,
+   };
struct usb_device *usb_dev = interface_to_usbdev(usb_intf);
struct mt76x0_dev *dev;
u32 asic_rev, mac_rev;
int ret;
 
-   dev = mt76x0_alloc_device(&usb_intf->dev);
+   dev = mt76x0_alloc_device(&usb_intf->dev, &drv_ops);
if (!dev)
return -ENOMEM;
 
-- 
2.7.5



[PATCH 37/42] mt76x0: inital split between pci and usb

2018-09-06 Thread Stanislaw Gruszka
For now pci driver can read ASIC version from the device :-)

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/Kconfig | 23 --
 drivers/net/wireless/mediatek/mt76/Makefile|  2 +-
 drivers/net/wireless/mediatek/mt76/mt76x0/Makefile | 11 ++-
 drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c |  2 +
 drivers/net/wireless/mediatek/mt76/mt76x0/init.c   |  6 ++
 drivers/net/wireless/mediatek/mt76/mt76x0/main.c   |  7 ++
 drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h |  1 -
 drivers/net/wireless/mediatek/mt76/mt76x0/pci.c| 81 ++
 drivers/net/wireless/mediatek/mt76/mt76x0/usb.c|  6 --
 9 files changed, 121 insertions(+), 18 deletions(-)
 create mode 100644 drivers/net/wireless/mediatek/mt76/mt76x0/pci.c

diff --git a/drivers/net/wireless/mediatek/mt76/Kconfig 
b/drivers/net/wireless/mediatek/mt76/Kconfig
index 6a270e759006..e460a3a5e763 100644
--- a/drivers/net/wireless/mediatek/mt76/Kconfig
+++ b/drivers/net/wireless/mediatek/mt76/Kconfig
@@ -7,25 +7,35 @@ config MT76_USB
 
 config MT76x02_LIB
tristate
-   depends on MT76_CORE
+   select MT76_CORE
+
+config MT76x0_COMMON
+   tristate
+   select MT76x02_LIB
 
 config MT76x2_COMMON
tristate
select MT76x02_LIB
-   depends on MT76_CORE
 
 config MT76x0U
tristate "MediaTek MT76x0U (USB) support"
-   select MT76_CORE
+   select MT76x0_COMMON
+   select MT76_USB
depends on MAC80211
depends on USB
-   select MT76x02_LIB
help
  This adds support for MT7610U-based wireless USB dongles.
 
+config MT76x0E
+   tristate "MediaTek MT76x0E (PCIe) support"
+   select MT76x0_COMMON
+   depends on MAC80211
+   depends on PCI
+   help
+ This adds support for MT7610/MT7630-based wireless PCIe devices.
+
 config MT76x2E
tristate "MediaTek MT76x2E (PCIe) support"
-   select MT76_CORE
select MT76x2_COMMON
depends on MAC80211
depends on PCI
@@ -34,9 +44,8 @@ config MT76x2E
 
 config MT76x2U
tristate "MediaTek MT76x2U (USB) support"
-   select MT76_CORE
-   select MT76_USB
select MT76x2_COMMON
+   select MT76_USB
depends on MAC80211
depends on USB
help
diff --git a/drivers/net/wireless/mediatek/mt76/Makefile 
b/drivers/net/wireless/mediatek/mt76/Makefile
index a7fe5d6da857..129ac71446d6 100644
--- a/drivers/net/wireless/mediatek/mt76/Makefile
+++ b/drivers/net/wireless/mediatek/mt76/Makefile
@@ -1,6 +1,6 @@
 obj-$(CONFIG_MT76_CORE) += mt76.o
 obj-$(CONFIG_MT76_USB) += mt76-usb.o
-obj-$(CONFIG_MT76x0U) += mt76x0/
+obj-$(CONFIG_MT76x0_COMMON) += mt76x0/
 obj-$(CONFIG_MT76x02_LIB) += mt76x02-lib.o
 obj-$(CONFIG_MT76x2_COMMON) += mt76x2-common.o
 obj-$(CONFIG_MT76x2E) += mt76x2e.o
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/Makefile 
b/drivers/net/wireless/mediatek/mt76/mt76x0/Makefile
index df70690e3aff..644c867c107a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/Makefile
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/Makefile
@@ -1,7 +1,12 @@
-obj-$(CONFIG_MT76x0U)+= mt76x0.o
+obj-$(CONFIG_MT76x0U) += mt76x0u.o
+obj-$(CONFIG_MT76x0E) += mt76x0e.o
+obj-$(CONFIG_MT76x0_COMMON) += mt76x0-common.o
 
-mt76x0-objs= \
-   usb.o init.o main.o mcu.o trace.o eeprom.o phy.o \
+mt76x0-common-y := \
+   init.o main.o mcu.o trace.o eeprom.o phy.o \
mac.o debugfs.o tx.o
+mt76x0u-y := usb.o
+mt76x0e-y := pci.o
+
 # ccflags-y := -DDEBUG
 CFLAGS_trace.o := -I$(src)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
index 2ce27de511f5..79856bde1632 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
@@ -445,3 +445,5 @@ mt76x0_eeprom_init(struct mt76x0_dev *dev)
kfree(eeprom);
return ret;
 }
+
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
index 44fcad2315a7..0e4a13fa42cb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
@@ -111,6 +111,7 @@ void mt76x0_chip_onoff(struct mt76x0_dev *dev, bool enable, 
bool reset)
 
mutex_unlock(&dev->hw_atomic_mutex);
 }
+EXPORT_SYMBOL_GPL(mt76x0_chip_onoff);
 
 static void mt76x0_reset_csr_bbp(struct mt76x0_dev *dev)
 {
@@ -384,6 +385,7 @@ void mt76x0_mac_stop(struct mt76x0_dev *dev)
mt76u_stop_stat_wk(&dev->mt76);
mt76x0_mac_stop_hw(dev);
 }
+EXPORT_SYMBOL_GPL(mt76x0_mac_stop);
 
 int mt76x0_init_hardware(struct mt76x0_dev *dev)
 {
@@ -469,6 +471,7 @@ int mt76x0_init_hardware(struct mt76x0_dev *dev)
 
return 0;
 }
+EXPORT_SYMBOL_GPL(mt76x0_init_hardware);
 
 void mt76x0_cleanup(struct mt76x0_dev *dev)
 {
@@ -477,6 +480,7 @@ void mt

[PATCH 40/42] mt76x0: remove unused mt76x0_wcid

2018-09-06 Thread Stanislaw Gruszka
We do not use mt76x0_wcid any longer.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h | 9 -
 1 file changed, 9 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h 
b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
index d775d9951695..31267a180573 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
@@ -112,15 +112,6 @@ struct mt76x0_dev {
struct mac_stats stats;
 };
 
-struct mt76x0_wcid {
-   u8 idx;
-   u8 hw_key_idx;
-
-   u16 tx_rate;
-   bool tx_rate_set;
-   u8 tx_rate_nss;
-};
-
 extern const struct ieee80211_ops mt76x0_ops;
 
 static inline bool is_mt7610e(struct mt76x0_dev *dev)
-- 
2.7.5



[PATCH 39/42] mt76: move some irq code to common mmio module

2018-09-06 Thread Stanislaw Gruszka
Move some irq handling code to generic mmio module.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mmio.c| 15 +++
 drivers/net/wireless/mediatek/mt76/mmio.h| 34 
 drivers/net/wireless/mediatek/mt76/mt76.h|  3 +++
 drivers/net/wireless/mediatek/mt76/mt76x2.h  | 15 ---
 drivers/net/wireless/mediatek/mt76/mt76x2_core.c | 26 ++
 drivers/net/wireless/mediatek/mt76/mt76x2_dfs.c  |  7 ++---
 drivers/net/wireless/mediatek/mt76/mt76x2_dma.c  |  7 ++---
 drivers/net/wireless/mediatek/mt76/mt76x2_init.c |  6 ++---
 drivers/net/wireless/mediatek/mt76/mt76x2_mac.c  |  9 ---
 9 files changed, 76 insertions(+), 46 deletions(-)
 create mode 100644 drivers/net/wireless/mediatek/mt76/mmio.h

diff --git a/drivers/net/wireless/mediatek/mt76/mmio.c 
b/drivers/net/wireless/mediatek/mt76/mmio.c
index c836a2a8986a..e29d3ed3a6ce 100644
--- a/drivers/net/wireless/mediatek/mt76/mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mmio.c
@@ -51,6 +51,20 @@ static void mt76_mmio_copy(struct mt76_dev *dev, u32 offset, 
const void *data,
__iowrite32_copy(mmio->regs + offset, data, len >> 2);
 }
 
+void mt76e_set_irq_mask(struct mt76_dev *dev, u32 clear, u32 set)
+{
+   struct mt76_mmio *mmio = &dev->mmio;
+   const int MT_INT_MASK_CSR = 0x0204;
+   unsigned long flags;
+
+   spin_lock_irqsave(&mmio->irq_lock, flags);
+   mmio->irqmask &= ~clear;
+   mmio->irqmask |= set;
+   __mt76_wr(dev, MT_INT_MASK_CSR, mmio->irqmask);
+   spin_unlock_irqrestore(&mmio->irq_lock, flags);
+}
+EXPORT_SYMBOL_GPL(mt76e_set_irq_mask);
+
 void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs)
 {
static const struct mt76_bus_ops mt76_mmio_ops = {
@@ -62,6 +76,7 @@ void mt76_mmio_init(struct mt76_dev *dev, void __iomem *regs)
 
dev->bus = &mt76_mmio_ops;
dev->mmio.regs = regs;
+   spin_lock_init(&dev->mmio.irq_lock);
 }
 EXPORT_SYMBOL_GPL(mt76_mmio_init);
 
diff --git a/drivers/net/wireless/mediatek/mt76/mmio.h 
b/drivers/net/wireless/mediatek/mt76/mmio.h
new file mode 100644
index ..7f01ba31b3e1
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mmio.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 Felix Fietkau 
+ * Copyright (C) 2018 Stanislaw Gruszka 
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __MT76_MMIO_H
+#define __MT76_MMIO_H
+
+#include "mt76.h"
+
+void mt76e_set_irq_mask(struct mt76_dev *dev, u32 clear, u32 set);
+
+static inline void mt76e_irq_enable(struct mt76_dev *dev, u32 mask)
+{
+   mt76e_set_irq_mask(dev, 0, mask);
+}
+
+static inline void mt76e_irq_disable(struct mt76_dev *dev, u32 mask)
+{
+   mt76e_set_irq_mask(dev, mask, 0);
+}
+#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h 
b/drivers/net/wireless/mediatek/mt76/mt76.h
index 2987ade3cb1a..064897439a29 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -324,6 +324,9 @@ struct mt76_usb {
 };
 
 struct mt76_mmio {
+   spinlock_t irq_lock;
+   u32 irqmask;
+
void __iomem *regs;
 };
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2.h 
b/drivers/net/wireless/mediatek/mt76/mt76x2.h
index 87b805637ff8..b71e4247d42a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2.h
@@ -108,9 +108,6 @@ struct mt76x2_dev {
 
u32 aggr_stats[32];
 
-   spinlock_t irq_lock;
-   u32 irqmask;
-
struct sk_buff *beacons[8];
u8 beacon_mask;
u8 beacon_data_mask;
@@ -138,8 +135,6 @@ static inline bool is_mt7612(struct mt76x2_dev *dev)
return mt76_chip(&dev->mt76) == 0x7612;
 }
 
-void mt76x2_set_irq_mask(struct mt76x2_dev *dev, u32 clear, u32 set);
-
 static inline bool mt76x2_channel_silent(struct mt76x2_dev *dev)
 {
struct ieee80211_channel *chan = dev->mt76.chandef.chan;
@@ -148,16 +143,6 @@ static inline bool mt76x2_channel_silent(struct mt76x2_dev 
*dev)
chan->dfs_state != NL80211_DFS_AVAILABLE);
 }
 
-static inline void mt76x2_irq_enable(struct mt76x2_dev *dev, u32 mask)
-{
-   mt76x2_set_irq_mas

[PATCH 38/42] mt76: initial separation of mmio part

2018-09-06 Thread Stanislaw Gruszka
Create mt76_mmio module to contain generic mt76 PCEe/SOC code.

Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/Kconfig  |  8 ++-
 drivers/net/wireless/mediatek/mt76/Makefile |  8 +--
 drivers/net/wireless/mediatek/mt76/dma.c| 68 +++
 drivers/net/wireless/mediatek/mt76/mac80211.c   |  1 -
 drivers/net/wireless/mediatek/mt76/mmio.c   | 17 --
 drivers/net/wireless/mediatek/mt76/mmio_trace.c | 23 
 drivers/net/wireless/mediatek/mt76/mmio_trace.h | 71 +
 drivers/net/wireless/mediatek/mt76/mt76.h   | 16 --
 drivers/net/wireless/mediatek/mt76/mt76x2_dma.c |  4 +-
 drivers/net/wireless/mediatek/mt76/trace.c  | 23 
 drivers/net/wireless/mediatek/mt76/trace.h  | 71 -
 drivers/net/wireless/mediatek/mt76/tx.c | 66 ---
 12 files changed, 198 insertions(+), 178 deletions(-)
 create mode 100644 drivers/net/wireless/mediatek/mt76/mmio_trace.c
 create mode 100644 drivers/net/wireless/mediatek/mt76/mmio_trace.h
 delete mode 100644 drivers/net/wireless/mediatek/mt76/trace.c
 delete mode 100644 drivers/net/wireless/mediatek/mt76/trace.h

diff --git a/drivers/net/wireless/mediatek/mt76/Kconfig 
b/drivers/net/wireless/mediatek/mt76/Kconfig
index e460a3a5e763..0fe581ed8693 100644
--- a/drivers/net/wireless/mediatek/mt76/Kconfig
+++ b/drivers/net/wireless/mediatek/mt76/Kconfig
@@ -3,7 +3,11 @@ config MT76_CORE
 
 config MT76_USB
tristate
-   depends on MT76_CORE
+   select MT76_CORE
+
+config MT76_MMIO
+   tristate
+   select MT76_CORE
 
 config MT76x02_LIB
tristate
@@ -29,6 +33,7 @@ config MT76x0U
 config MT76x0E
tristate "MediaTek MT76x0E (PCIe) support"
select MT76x0_COMMON
+   select MT76_MMIO
depends on MAC80211
depends on PCI
help
@@ -37,6 +42,7 @@ config MT76x0E
 config MT76x2E
tristate "MediaTek MT76x2E (PCIe) support"
select MT76x2_COMMON
+   select MT76_MMIO
depends on MAC80211
depends on PCI
---help---
diff --git a/drivers/net/wireless/mediatek/mt76/Makefile 
b/drivers/net/wireless/mediatek/mt76/Makefile
index 129ac71446d6..1d366348f799 100644
--- a/drivers/net/wireless/mediatek/mt76/Makefile
+++ b/drivers/net/wireless/mediatek/mt76/Makefile
@@ -1,17 +1,17 @@
 obj-$(CONFIG_MT76_CORE) += mt76.o
 obj-$(CONFIG_MT76_USB) += mt76-usb.o
+obj-$(CONFIG_MT76_MMIO) += mt76-mmio.o
 obj-$(CONFIG_MT76x0_COMMON) += mt76x0/
 obj-$(CONFIG_MT76x02_LIB) += mt76x02-lib.o
 obj-$(CONFIG_MT76x2_COMMON) += mt76x2-common.o
 obj-$(CONFIG_MT76x2E) += mt76x2e.o
 obj-$(CONFIG_MT76x2U) += mt76x2u.o
 
-mt76-y := \
-   mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o tx.o agg-rx.o
-
+mt76-y := util.o mac80211.o debugfs.o eeprom.o tx.o agg-rx.o
+mt76-mmio-y := dma.o mmio_trace.o mmio.o
 mt76-usb-y := usb.o usb_trace.o usb_mcu.o
 
-CFLAGS_trace.o := -I$(src)
+CFLAGS_mmio_trace.o := -I$(src)
 CFLAGS_usb_trace.o := -I$(src)
 
 mt76x02-lib-y := mt76x02_util.o mt76x02_mac.o
diff --git a/drivers/net/wireless/mediatek/mt76/dma.c 
b/drivers/net/wireless/mediatek/mt76/dma.c
index c51da2205b93..138f3faa6138 100644
--- a/drivers/net/wireless/mediatek/mt76/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/dma.c
@@ -20,6 +20,72 @@
 
 #define DMA_DUMMY_TXWI ((void *) ~0)
 
+static struct mt76_txwi_cache *
+mt76_alloc_txwi(struct mt76_dev *dev)
+{
+   struct mt76_txwi_cache *t;
+   dma_addr_t addr;
+   int size;
+
+   size = (sizeof(*t) + L1_CACHE_BYTES - 1) & ~(L1_CACHE_BYTES - 1);
+   t = devm_kzalloc(dev->dev, size, GFP_ATOMIC);
+   if (!t)
+   return NULL;
+
+   addr = dma_map_single(dev->dev, &t->txwi, sizeof(t->txwi),
+ DMA_TO_DEVICE);
+   t->dma_addr = addr;
+
+   return t;
+}
+
+static struct mt76_txwi_cache *
+__mt76_get_txwi(struct mt76_dev *dev)
+{
+   struct mt76_txwi_cache *t = NULL;
+
+   spin_lock_bh(&dev->lock);
+   if (!list_empty(&dev->txwi_cache)) {
+   t = list_first_entry(&dev->txwi_cache, struct mt76_txwi_cache,
+list);
+   list_del(&t->list);
+   }
+   spin_unlock_bh(&dev->lock);
+
+   return t;
+}
+
+struct mt76_txwi_cache *
+mt76_get_txwi(struct mt76_dev *dev)
+{
+   struct mt76_txwi_cache *t = __mt76_get_txwi(dev);
+
+   if (t)
+   return t;
+
+   return mt76_alloc_txwi(dev);
+}
+
+static void
+mt76_put_txwi(struct mt76_dev *dev, struct mt76_txwi_cache *t)
+{
+   if (!t)
+   return;
+
+   spin_lock_bh(&dev->lock);
+   list_add(&t->list, &dev->txwi_cache);
+   spin_unlock_bh(&dev->lock);
+}
+
+static void mt76_tx_free(struct mt76_dev *dev)
+{
+   struct mt76_txwi_cache *t;
+
+   while (

[PATCH 01/42] mt76x2: change mt76x2_tx_complete routine signature

2018-09-06 Thread Stanislaw Gruszka
From: Lorenzo Bianconi 

Use mt76_dev instead of mt76x2_dev in mt76x2_tx_complete signature
in order to be reused in mt76x0 driver

Signed-off-by: Lorenzo Bianconi 
Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x2.h   | 2 +-
 drivers/net/wireless/mediatek/mt76/mt76x2_mac.c   | 2 +-
 drivers/net/wireless/mediatek/mt76/mt76x2_tx_common.c | 6 +++---
 drivers/net/wireless/mediatek/mt76/mt76x2u_core.c | 4 +---
 4 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2.h 
b/drivers/net/wireless/mediatek/mt76/mt76x2.h
index f275411f0e3d..9f495d4cfb6a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2.h
@@ -215,7 +215,7 @@ int mt76x2_tx_queue_mcu(struct mt76x2_dev *dev, enum 
mt76_txq_id qid,
struct sk_buff *skb, int cmd, int seq);
 void mt76x2_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
   struct sk_buff *skb);
-void mt76x2_tx_complete(struct mt76x2_dev *dev, struct sk_buff *skb);
+void mt76x2_tx_complete(struct mt76_dev *dev, struct sk_buff *skb);
 int mt76x2_tx_prepare_skb(struct mt76_dev *mdev, void *txwi,
  struct sk_buff *skb, struct mt76_queue *q,
  struct mt76_wcid *wcid, struct ieee80211_sta *sta,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_mac.c 
b/drivers/net/wireless/mediatek/mt76/mt76x2_mac.c
index 3bb02b55f146..db0cb4a2500b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_mac.c
@@ -73,7 +73,7 @@ mt76x2_mac_queue_txdone(struct mt76x2_dev *dev, struct 
sk_buff *skb,
txi->wcid = txwi->wcid;
txi->pktid = txwi->pktid;
trace_mac_txdone_add(dev, txwi->wcid, txwi->pktid);
-   mt76x2_tx_complete(dev, skb);
+   mt76x2_tx_complete(&dev->mt76, skb);
 }
 
 void mt76x2_mac_process_tx_status_fifo(struct mt76x2_dev *dev)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_tx_common.c 
b/drivers/net/wireless/mediatek/mt76/mt76x2_tx_common.c
index 056a21b006df..663229dc269d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2_tx_common.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2_tx_common.c
@@ -117,17 +117,17 @@ void mt76x2_tx_set_txpwr_auto(struct mt76x2_dev *dev, s8 
txpwr)
 }
 EXPORT_SYMBOL_GPL(mt76x2_tx_set_txpwr_auto);
 
-void mt76x2_tx_complete(struct mt76x2_dev *dev, struct sk_buff *skb)
+void mt76x2_tx_complete(struct mt76_dev *dev, struct sk_buff *skb)
 {
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
if (info->flags & IEEE80211_TX_CTL_AMPDU) {
-   ieee80211_free_txskb(mt76_hw(dev), skb);
+   ieee80211_free_txskb(dev->hw, skb);
} else {
ieee80211_tx_info_clear_status(info);
info->status.rates[0].idx = -1;
info->flags |= IEEE80211_TX_STAT_ACK;
-   ieee80211_tx_status(mt76_hw(dev), skb);
+   ieee80211_tx_status(dev->hw, skb);
}
 }
 EXPORT_SYMBOL_GPL(mt76x2_tx_complete);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2u_core.c 
b/drivers/net/wireless/mediatek/mt76/mt76x2u_core.c
index ed62d6243bb9..cdc2f2cd9141 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2u_core.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2u_core.c
@@ -102,9 +102,7 @@ int mt76x2u_tx_prepare_skb(struct mt76_dev *mdev, void 
*data,
 void mt76x2u_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q,
 struct mt76_queue_entry *e, bool flush)
 {
-   struct mt76x2_dev *dev = container_of(mdev, struct mt76x2_dev, mt76);
-
mt76x2u_remove_dma_hdr(e->skb);
-   mt76x2_tx_complete(dev, e->skb);
+   mt76x2_tx_complete(mdev, e->skb);
 }
 
-- 
2.7.5



[PATCH 25/42] mt76x0: init hw capabilities

2018-09-06 Thread Stanislaw Gruszka
From: Lorenzo Bianconi 

Enable hw capabilities supported by mt76-usb layer
- fast_xmit
- tx/rx amsdu
- MFP
- non-linear tx skbs

Signed-off-by: Lorenzo Bianconi 
Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/init.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
index 7cd939c97efe..418e1918086d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
@@ -676,6 +676,13 @@ int mt76x0_register_device(struct mt76x0_dev *dev)
ieee80211_hw_set(hw, SUPPORTS_HT_CCK_RATES);
ieee80211_hw_set(hw, AMPDU_AGGREGATION);
ieee80211_hw_set(hw, SUPPORTS_RC_TABLE);
+   ieee80211_hw_set(hw, SUPPORT_FAST_XMIT);
+   ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS);
+   ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU);
+   ieee80211_hw_set(hw, TX_AMSDU);
+   ieee80211_hw_set(hw, TX_FRAG_LIST);
+   ieee80211_hw_set(hw, MFP_CAPABLE);
+
hw->max_rates = 1;
hw->max_report_rates = 7;
hw->max_rate_tries = 1;
-- 
2.7.5



[PATCH 23/42] mt76x0: remove unused stat_work

2018-09-06 Thread Stanislaw Gruszka
From: Lorenzo Bianconi 

Remove unused definition of stat_work delayed_work definition and
related flush/cancel routines

Signed-off-by: Lorenzo Bianconi 
Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/init.c   | 2 --
 drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h | 2 --
 2 files changed, 4 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
index 75597b5a2427..1f4a0fff684b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
@@ -362,8 +362,6 @@ static void mt76x0_mac_stop_hw(struct mt76x0_dev *dev)
 void mt76x0_mac_stop(struct mt76x0_dev *dev)
 {
mt76x0_mac_stop_hw(dev);
-   flush_delayed_work(&dev->stat_work);
-   cancel_delayed_work_sync(&dev->stat_work);
 }
 
 static void mt76x0_stop_hardware(struct mt76x0_dev *dev)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h 
b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
index 0bcf54c0a06f..cd260317de27 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
@@ -84,8 +84,6 @@ struct mt76x0_dev {
struct delayed_work cal_work;
struct delayed_work mac_work;
 
-   struct delayed_work stat_work;
-
spinlock_t mac_lock;
 
const u16 *beacon_offsets;
-- 
2.7.5



[PATCH 32/42] mt76x0: move stop related routines in mt76x0_mac_stop

2018-09-06 Thread Stanislaw Gruszka
From: Lorenzo Bianconi 

Move tear-down routines in mt76x0_mac_stop function.
mt76x0_mac_stop routines will be reused in mt76x0_suspend

Signed-off-by: Lorenzo Bianconi 
Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/init.c | 3 +++
 drivers/net/wireless/mediatek/mt76/mt76x0/main.c | 4 
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
index d186f509b5a8..b1d5f647eac5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
@@ -361,6 +361,9 @@ static void mt76x0_mac_stop_hw(struct mt76x0_dev *dev)
 
 void mt76x0_mac_stop(struct mt76x0_dev *dev)
 {
+   cancel_delayed_work_sync(&dev->cal_work);
+   cancel_delayed_work_sync(&dev->mac_work);
+   mt76u_stop_stat_wk(&dev->mt76);
mt76x0_mac_stop_hw(dev);
 }
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c
index 8c8a0f676228..0d3c7accb4f8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c
@@ -48,10 +48,6 @@ static void mt76x0_stop(struct ieee80211_hw *hw)
mutex_lock(&dev->mt76.mutex);
 
clear_bit(MT76_STATE_RUNNING, &dev->mt76.state);
-
-   cancel_delayed_work_sync(&dev->cal_work);
-   cancel_delayed_work_sync(&dev->mac_work);
-   mt76u_stop_stat_wk(&dev->mt76);
mt76x0_mac_stop(dev);
 
mutex_unlock(&dev->mt76.mutex);
-- 
2.7.5



[PATCH 27/42] mt76: remove unused MT76_MORE_STATS state

2018-09-06 Thread Stanislaw Gruszka
From: Lorenzo Bianconi 

Remove no longer used hw state

Signed-off-by: Lorenzo Bianconi 
Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h 
b/drivers/net/wireless/mediatek/mt76/mt76.h
index cdd470952004..80390be041cb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -216,7 +216,6 @@ enum {
MT76_OFFCHANNEL,
MT76_REMOVED,
MT76_READING_STATS,
-   MT76_MORE_STATS,
 };
 
 struct mt76_hw_cap {
-- 
2.7.5



[PATCH 26/42] mt76x0: trim rx skb to proper length

2018-09-06 Thread Stanislaw Gruszka
We need to truncate skb to proper length. This fix below message:

wlan0: associating with AP with corrupt beacon and probe response

Fixes: 9d87d9fad47e ("mt76x0: unify tx/rx datapath with mt76x2u driver")
Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/mac.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/mac.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/mac.c
index 8fdc246964b9..f55734a922aa 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/mac.c
@@ -236,6 +236,7 @@ u32 mt76x0_mac_process_rx(struct mt76x0_dev *dev, struct 
sk_buff *skb,
 
mt76x02_remove_hdr_pad(skb, pad_len);
 
+   pskb_trim(skb, len);
status->chains = BIT(0);
rssi = mt76x0_phy_get_rssi(dev, rxwi);
status->chain_signal[0] = status->signal = rssi;
-- 
2.7.5



[PATCH 07/42] mt76x0: introduce mt76x0_tx_prepare_skb routine

2018-09-06 Thread Stanislaw Gruszka
From: Lorenzo Bianconi 

Add mt76x0_tx_prepare_skb routine as tx txwi handler.
mt76x0_tx_prepare_skb will be used by mt76-usb layer

Signed-off-by: Lorenzo Bianconi 
Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h |  5 -
 drivers/net/wireless/mediatek/mt76/mt76x0/tx.c | 15 +++
 2 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h 
b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
index 8510f120a121..8b0bef9a15e4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/mt76x0.h
@@ -250,5 +250,8 @@ void mt76x0_dma_cleanup(struct mt76x0_dev *dev);
 
 int mt76x0_dma_enqueue_tx(struct mt76x0_dev *dev, struct sk_buff *skb,
   struct mt76_wcid *wcid, int hw_q);
-
+int mt76x0_tx_prepare_skb(struct mt76_dev *mdev, void *data,
+ struct sk_buff *skb, struct mt76_queue *q,
+ struct mt76_wcid *wcid, struct ieee80211_sta *sta,
+ u32 *tx_info);
 #endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/tx.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/tx.c
index de2643d54a1e..d6dbd9b8d68b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/tx.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/tx.c
@@ -116,6 +116,21 @@ void mt76x0_tx(struct ieee80211_hw *hw, struct 
ieee80211_tx_control *control,
trace_mt76x0_tx(&dev->mt76, skb, msta, txwi);
 }
 
+int mt76x0_tx_prepare_skb(struct mt76_dev *mdev, void *data,
+ struct sk_buff *skb, struct mt76_queue *q,
+ struct mt76_wcid *wcid, struct ieee80211_sta *sta,
+ u32 *tx_info)
+{
+   struct mt76x0_dev *dev = container_of(mdev, struct mt76x0_dev, mt76);
+   int len = skb->len, *hwq_ptr = (int *)data;
+   struct mt76x02_txwi *txwi;
+
+   mt76x02_insert_hdr_pad(skb);
+   txwi = mt76x0_push_txwi(dev, skb, sta, wcid, len);
+
+   return mt76x02_set_txinfo(skb, wcid, q2ep(*hwq_ptr));
+}
+
 void mt76x0_tx_stat(struct work_struct *work)
 {
struct mt76x0_dev *dev = container_of(work, struct mt76x0_dev,
-- 
2.7.5



[PATCH 29/42] mt76: move mt76 rate definitions in mt76x02-lib module

2018-09-06 Thread Stanislaw Gruszka
From: Lorenzo Bianconi 

Move mt76x2_rate definition in mt76x02-lib module and rename it in
mt76x02_rates in order to be reused in mt76x0 driver.
Moreover remove unused mt76_rate definition

Signed-off-by: Lorenzo Bianconi 
Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/init.c   | 32 ++
 drivers/net/wireless/mediatek/mt76/mt76x02_util.c  | 29 
 drivers/net/wireless/mediatek/mt76/mt76x02_util.h  |  2 ++
 drivers/net/wireless/mediatek/mt76/mt76x2.h|  2 --
 drivers/net/wireless/mediatek/mt76/mt76x2_init.c   |  5 ++--
 .../wireless/mediatek/mt76/mt76x2_init_common.c| 29 
 drivers/net/wireless/mediatek/mt76/mt76x2u_init.c  |  4 +--
 7 files changed, 38 insertions(+), 65 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
index 5b819a224d33..ca70b62442a1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
@@ -559,34 +559,6 @@ static const struct ieee80211_channel mt76_channels_5ghz[] 
= {
CHAN5G(140, 5700),
 };
 
-#define CCK_RATE(_idx, _rate) {\
-   .bitrate = _rate,   \
-   .flags = IEEE80211_RATE_SHORT_PREAMBLE, \
-   .hw_value = (MT_PHY_TYPE_CCK << 8) | _idx,  \
-   .hw_value_short = (MT_PHY_TYPE_CCK << 8) | (8 + _idx),  \
-}
-
-#define OFDM_RATE(_idx, _rate) {   \
-   .bitrate = _rate,   \
-   .hw_value = (MT_PHY_TYPE_OFDM << 8) | _idx, \
-   .hw_value_short = (MT_PHY_TYPE_OFDM << 8) | _idx,   \
-}
-
-static struct ieee80211_rate mt76_rates[] = {
-   CCK_RATE(0, 10),
-   CCK_RATE(1, 20),
-   CCK_RATE(2, 55),
-   CCK_RATE(3, 110),
-   OFDM_RATE(0, 60),
-   OFDM_RATE(1, 90),
-   OFDM_RATE(2, 120),
-   OFDM_RATE(3, 180),
-   OFDM_RATE(4, 240),
-   OFDM_RATE(5, 360),
-   OFDM_RATE(6, 480),
-   OFDM_RATE(7, 540),
-};
-
 static int
 mt76_init_sband(struct mt76x0_dev *dev, struct ieee80211_supported_band *sband,
const struct ieee80211_channel *chan, int n_chan,
@@ -634,7 +606,7 @@ mt76_init_sband_2g(struct mt76x0_dev *dev)
 
return mt76_init_sband(dev, &dev->mt76.sband_2g.sband,
   mt76_channels_2ghz, 
ARRAY_SIZE(mt76_channels_2ghz),
-  mt76_rates, ARRAY_SIZE(mt76_rates));
+  mt76x02_rates, ARRAY_SIZE(mt76x02_rates));
 }
 
 static int
@@ -644,7 +616,7 @@ mt76_init_sband_5g(struct mt76x0_dev *dev)
 
return mt76_init_sband(dev, &dev->mt76.sband_5g.sband,
   mt76_channels_5ghz, 
ARRAY_SIZE(mt76_channels_5ghz),
-  mt76_rates + 4, ARRAY_SIZE(mt76_rates) - 4);
+  mt76x02_rates + 4, ARRAY_SIZE(mt76x02_rates) - 
4);
 }
 
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c 
b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
index 432c3661312e..f44c149aa6ef 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
@@ -20,6 +20,35 @@
 #include "mt76x02_regs.h"
 #include "mt76x02_mac.h"
 
+#define CCK_RATE(_idx, _rate) {\
+   .bitrate = _rate,   \
+   .flags = IEEE80211_RATE_SHORT_PREAMBLE, \
+   .hw_value = (MT_PHY_TYPE_CCK << 8) | _idx,  \
+   .hw_value_short = (MT_PHY_TYPE_CCK << 8) | (8 + _idx),  \
+}
+
+#define OFDM_RATE(_idx, _rate) {   \
+   .bitrate = _rate,   \
+   .hw_value = (MT_PHY_TYPE_OFDM << 8) | _idx, \
+   .hw_value_short = (MT_PHY_TYPE_OFDM << 8) | _idx,   \
+}
+
+struct ieee80211_rate mt76x02_rates[] = {
+   CCK_RATE(0, 10),
+   CCK_RATE(1, 20),
+   CCK_RATE(2, 55),
+   CCK_RATE(3, 110),
+   OFDM_RATE(0, 60),
+   OFDM_RATE(1, 90),
+   OFDM_RATE(2, 120),
+   OFDM_RATE(3, 180),
+   OFDM_RATE(4, 240),
+   OFDM_RATE(5, 360),
+   OFDM_RATE(6, 480),
+   OFDM_RATE(7, 540),
+};
+EXPORT_SYMBOL_GPL(mt76x02_rates);
+
 void mt76x02_configure_filter(struct ieee80211_hw *hw,
 unsigned int changed_flags,
 unsigned int *total_flags, u64 multicast)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.h 
b/drivers/net/wireless/mediatek/mt76/mt76x02_util.h
index 383031b9b6d8..b6ba7e6c2748 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.h
@@ -18,6 +18,8 @@
 #ifndef __MT76X02_UTIL_H
 #

[PATCH 30/42] mt76x0: alloc mcu buffers first in mt76x0_mcu_cmd_init

2018-09-06 Thread Stanislaw Gruszka
From: Lorenzo Bianconi 

swap mt76u_mcu_init_rx and mt76x0_mcu_function_select in
mt76x0_mcu_cmd_init routine in order to allocate mcu buffers
first and then send mcu commands

Signed-off-by: Lorenzo Bianconi 
Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/mcu.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/mcu.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/mcu.c
index 0a0deaf1c65d..7be2835f3b4f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/mcu.c
@@ -387,9 +387,11 @@ int mt76x0_mcu_init(struct mt76x0_dev *dev)
 
 int mt76x0_mcu_cmd_init(struct mt76x0_dev *dev)
 {
-   int ret = mt76x0_mcu_function_select(dev, Q_SELECT, 1);
+   int ret;
+
+   ret = mt76u_mcu_init_rx(&dev->mt76);
if (ret)
return ret;
 
-   return mt76u_mcu_init_rx(&dev->mt76);
+   return mt76x0_mcu_function_select(dev, Q_SELECT, 1);
 }
-- 
2.7.5



[PATCH 35/42] mt76x0: remove has_{2,5}ghz fields of mt76x0_eeprom_params

2018-09-06 Thread Stanislaw Gruszka
From: Lorenzo Bianconi 

Remove has_2ghz/has_5ghz fields of mt76x0_eeprom_params data
structure and use mt76_dev ones. This is a preliminary patch
to use shared routines for device allocation

Signed-off-by: Lorenzo Bianconi 
Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c | 11 ++-
 drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h |  3 ---
 drivers/net/wireless/mediatek/mt76/mt76x0/init.c   |  4 ++--
 3 files changed, 8 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
index 36da1e6bc21a..0fd178d84277 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
@@ -123,18 +123,19 @@ mt76x0_set_chip_cap(struct mt76x0_dev *dev, u8 *eeprom)
 
switch (FIELD_GET(MT_EE_NIC_CONF_0_BOARD_TYPE, nic_conf0)) {
case BOARD_TYPE_5GHZ:
-   dev->ee->has_5ghz = true;
+   dev->mt76.cap.has_5ghz = true;
break;
case BOARD_TYPE_2GHZ:
-   dev->ee->has_2ghz = true;
+   dev->mt76.cap.has_2ghz = true;
break;
default:
-   dev->ee->has_2ghz = true;
-   dev->ee->has_5ghz = true;
+   dev->mt76.cap.has_2ghz = true;
+   dev->mt76.cap.has_5ghz = true;
break;
}
 
-   dev_dbg(dev->mt76.dev, "Has 2GHZ %d 5GHZ %d\n", dev->ee->has_2ghz, 
dev->ee->has_5ghz);
+   dev_dbg(dev->mt76.dev, "Has 2GHZ %d 5GHZ %d\n",
+   dev->mt76.cap.has_2ghz, dev->mt76.cap.has_5ghz);
 
if (!field_valid(nic_conf1 & 0xff))
nic_conf1 &= 0xff00;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h 
b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h
index e37b573aed7b..cd0f14361405 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.h
@@ -112,9 +112,6 @@ struct mt76x0_eeprom_params {
u8 tx_pwr_per_chan[58];
 
struct reg_channel_bounds reg;
-
-   bool has_2ghz;
-   bool has_5ghz;
 };
 
 int mt76x0_eeprom_init(struct mt76x0_dev *dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
index 8f4b3197ab95..d075b29977e3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
@@ -662,13 +662,13 @@ int mt76x0_register_device(struct mt76x0_dev *dev)
wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR;
wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
 
-   if (dev->ee->has_2ghz) {
+   if (dev->mt76.cap.has_2ghz) {
ret = mt76_init_sband_2g(dev);
if (ret)
return ret;
}
 
-   if (dev->ee->has_5ghz) {
+   if (dev->mt76.cap.has_5ghz) {
ret = mt76_init_sband_5g(dev);
if (ret)
return ret;
-- 
2.7.5



[PATCH 34/42] mt76x0: do not free/alloc buffers during suspend/resume

2018-09-06 Thread Stanislaw Gruszka
From: Lorenzo Bianconi 

Do not free/alloc {tx,rx} buffers during suspend/resume phases
but use the ones previously allocated during hw probe.
Move {tx,rx}/mcu buffers allocation from mt76x0_init_hardware routine
to mt76x0_register_device

Signed-off-by: Lorenzo Bianconi 
Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/init.c | 12 +---
 drivers/net/wireless/mediatek/mt76/mt76x0/mcu.c  |  6 
 drivers/net/wireless/mediatek/mt76/mt76x0/usb.c  | 38 ++--
 3 files changed, 37 insertions(+), 19 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
index deceece52492..8f4b3197ab95 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
@@ -408,10 +408,6 @@ int mt76x0_init_hardware(struct mt76x0_dev *dev)
if (ret)
return ret;
 
-   ret = mt76u_alloc_queues(&dev->mt76);
-   if (ret < 0)
-   return ret;
-
mt76x0_init_mac_registers(dev);
 
if (!mt76_poll_msec(dev, MT_MAC_STATUS,
@@ -614,6 +610,14 @@ int mt76x0_register_device(struct mt76x0_dev *dev)
struct wiphy *wiphy = hw->wiphy;
int ret;
 
+   ret = mt76u_mcu_init_rx(mdev);
+   if (ret < 0)
+   return ret;
+
+   ret = mt76u_alloc_queues(mdev);
+   if (ret < 0)
+   return ret;
+
ret = mt76x0_init_hardware(dev);
if (ret)
return ret;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/mcu.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/mcu.c
index 7be2835f3b4f..29c0b3978af7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/mcu.c
@@ -387,11 +387,5 @@ int mt76x0_mcu_init(struct mt76x0_dev *dev)
 
 int mt76x0_mcu_cmd_init(struct mt76x0_dev *dev)
 {
-   int ret;
-
-   ret = mt76u_mcu_init_rx(&dev->mt76);
-   if (ret)
-   return ret;
-
return mt76x0_mcu_function_select(dev, Q_SELECT, 1);
 }
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
index 09b544890450..fc8884c38f7e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
@@ -124,29 +124,49 @@ static void mt76x0_disconnect(struct usb_interface 
*usb_intf)
ieee80211_free_hw(dev->mt76.hw);
 }
 
-static int mt76x0_suspend(struct usb_interface *usb_intf, pm_message_t state)
+static int __maybe_unused mt76x0_suspend(struct usb_interface *usb_intf,
+pm_message_t state)
 {
struct mt76x0_dev *dev = usb_get_intfdata(usb_intf);
+   struct mt76_usb *usb = &dev->mt76.usb;
 
-   mt76x0_cleanup(dev);
+   mt76u_stop_queues(&dev->mt76);
+   mt76x0_mac_stop(dev);
+   usb_kill_urb(usb->mcu.res.urb);
 
return 0;
 }
 
-static int mt76x0_resume(struct usb_interface *usb_intf)
+static int __maybe_unused mt76x0_resume(struct usb_interface *usb_intf)
 {
struct mt76x0_dev *dev = usb_get_intfdata(usb_intf);
+   struct mt76_usb *usb = &dev->mt76.usb;
int ret;
 
-   ret = mt76x0_init_hardware(dev);
-   if (ret) {
-   mt76x0_cleanup(dev);
-   return ret;
-   }
+   reinit_completion(&usb->mcu.cmpl);
+   ret = mt76u_submit_buf(&dev->mt76, USB_DIR_IN,
+  MT_EP_IN_CMD_RESP,
+  &usb->mcu.res, GFP_KERNEL,
+  mt76u_mcu_complete_urb,
+  &usb->mcu.cmpl);
+   if (ret < 0)
+   goto err;
 
-   set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state);
+   ret = mt76u_submit_rx_buffers(&dev->mt76);
+   if (ret < 0)
+   goto err;
+
+   tasklet_enable(&usb->rx_tasklet);
+   tasklet_enable(&usb->tx_tasklet);
+
+   ret = mt76x0_init_hardware(dev);
+   if (ret)
+   goto err;
 
return 0;
+err:
+   mt76x0_cleanup(dev);
+   return ret;
 }
 
 MODULE_DEVICE_TABLE(usb, mt76x0_device_table);
-- 
2.7.5



[PATCH 24/42] mt76x0: enable per-sta tx queueing

2018-09-06 Thread Stanislaw Gruszka
From: Lorenzo Bianconi 

Initialize wake_tx_queue function pointer in ieee80211_ops
in order to enable per-sta tx queueing. Moreover set driver
private txq size

Signed-off-by: Lorenzo Bianconi 
Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/init.c | 3 +++
 drivers/net/wireless/mediatek/mt76/mt76x0/main.c | 1 +
 2 files changed, 4 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
index 1f4a0fff684b..7cd939c97efe 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
@@ -684,6 +684,9 @@ int mt76x0_register_device(struct mt76x0_dev *dev)
hw->sta_data_size = sizeof(struct mt76x02_sta);
hw->vif_data_size = sizeof(struct mt76x02_vif);
 
+   hw->txq_data_size = sizeof(struct mt76_txq);
+   hw->max_tx_fragments = 16;
+
SET_IEEE80211_PERM_ADDR(hw, dev->macaddr);
 
wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c
index b0a1f7a7209a..8c8a0f676228 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c
@@ -180,4 +180,5 @@ const struct ieee80211_ops mt76x0_ops = {
.ampdu_action = mt76x02_ampdu_action,
.sta_rate_tbl_update = mt76x02_sta_rate_tbl_update,
.set_rts_threshold = mt76x0_set_rts_threshold,
+   .wake_tx_queue = mt76_wake_tx_queue,
 };
-- 
2.7.5



[PATCH 33/42] mt76x0: move mt76x0_init_hardware in mt76x0_register_device

2018-09-06 Thread Stanislaw Gruszka
From: Lorenzo Bianconi 

Move mt76x0_init_hardware routine in mt76x0_register_device
during hw probe. This is a preliminary patch to avoid {tx/rx}
buffer allocation during resume/suspend

Signed-off-by: Lorenzo Bianconi 
Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/init.c | 55 ++--
 drivers/net/wireless/mediatek/mt76/mt76x0/usb.c  |  8 ++--
 2 files changed, 26 insertions(+), 37 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
index b1d5f647eac5..deceece52492 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
@@ -382,27 +382,21 @@ int mt76x0_init_hardware(struct mt76x0_dev *dev)
 
mt76x0_chip_onoff(dev, true, true);
 
-   if (!mt76x02_wait_for_mac(&dev->mt76)) {
-   ret = -ETIMEDOUT;
-   goto err;
-   }
+   if (!mt76x02_wait_for_mac(&dev->mt76))
+   return -ETIMEDOUT;
 
ret = mt76x0_mcu_init(dev);
if (ret)
-   goto err;
+   return ret;
 
if (!mt76_poll_msec(dev, MT_WPDMA_GLO_CFG,
MT_WPDMA_GLO_CFG_TX_DMA_BUSY |
-   MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 100)) {
-   ret = -EIO;
-   goto err;
-   }
+   MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 100))
+   return -EIO;
 
/* Wait for ASIC ready after FW load. */
-   if (!mt76x02_wait_for_mac(&dev->mt76)) {
-   ret = -ETIMEDOUT;
-   goto err;
-   }
+   if (!mt76x02_wait_for_mac(&dev->mt76))
+   return -ETIMEDOUT;
 
mt76x0_reset_csr_bbp(dev);
mt76x0_init_usb_dma(dev);
@@ -412,33 +406,33 @@ int mt76x0_init_hardware(struct mt76x0_dev *dev)
 
ret = mt76x0_mcu_cmd_init(dev);
if (ret)
-   goto err;
+   return ret;
 
ret = mt76u_alloc_queues(&dev->mt76);
if (ret < 0)
-   goto err_mcu;
+   return ret;
 
mt76x0_init_mac_registers(dev);
 
if (!mt76_poll_msec(dev, MT_MAC_STATUS,
-   MT_MAC_STATUS_TX | MT_MAC_STATUS_RX, 0, 1000)) {
-   ret = -EIO;
-   goto err_rx;
-   }
+   MT_MAC_STATUS_TX | MT_MAC_STATUS_RX, 0, 1000))
+   return -EIO;
 
ret = mt76x0_init_bbp(dev);
if (ret)
-   goto err_rx;
+   return ret;
 
ret = mt76x0_init_wcid_mem(dev);
if (ret)
-   goto err_rx;
+   return ret;
+
ret = mt76x0_init_key_mem(dev);
if (ret)
-   goto err_rx;
+   return ret;
+
ret = mt76x0_init_wcid_attr_mem(dev);
if (ret)
-   goto err_rx;
+   return ret;
 
mt76_clear(dev, MT_BEACON_TIME_CFG, (MT_BEACON_TIME_CFG_TIMER_EN |
 MT_BEACON_TIME_CFG_SYNC_MODE |
@@ -455,18 +449,11 @@ int mt76x0_init_hardware(struct mt76x0_dev *dev)
 
ret = mt76x0_eeprom_init(dev);
if (ret)
-   goto err_rx;
+   return ret;
 
mt76x0_phy_init(dev);
-   return 0;
 
-err_rx:
-   mt76u_queues_deinit(&dev->mt76);
-err_mcu:
-   mt76u_mcu_deinit(&dev->mt76);
-err:
-   mt76x0_chip_onoff(dev, false, false);
-   return ret;
+   return 0;
 }
 
 void mt76x0_cleanup(struct mt76x0_dev *dev)
@@ -627,6 +614,10 @@ int mt76x0_register_device(struct mt76x0_dev *dev)
struct wiphy *wiphy = hw->wiphy;
int ret;
 
+   ret = mt76x0_init_hardware(dev);
+   if (ret)
+   return ret;
+
/* Reserve WCID 0 for mcast - thanks to this APs WCID will go to
 * entry no. 1 like it does in the vendor driver.
 */
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
index 219524c233ee..09b544890450 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
@@ -90,10 +90,6 @@ static int mt76x0_probe(struct usb_interface *usb_intf,
if (!(mt76_rr(dev, MT_EFUSE_CTRL) & MT_EFUSE_CTRL_SEL))
dev_warn(dev->mt76.dev, "Warning: eFUSE not present\n");
 
-   ret = mt76x0_init_hardware(dev);
-   if (ret)
-   goto err;
-
ret = mt76x0_register_device(dev);
if (ret)
goto err_hw;
@@ -143,8 +139,10 @@ static int mt76x0_resume(struct usb_interface *usb_intf)
int ret;
 
ret = mt76x0_init_hardware(dev);
-   if (ret)
+   if (ret) {
+   mt76x0_cleanup(dev);
return ret;
+   }
 
set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state);
 
-- 
2.7.5



[PATCH 31/42] mt76x0: fix memory leak during hw probe

2018-09-06 Thread Stanislaw Gruszka
From: Lorenzo Bianconi 

Fix memory leak during hw probe if mt76x0_register_device fails
since MT76_STATE_INITIALIZED has not set yet and mt76x0_cleanup
does not free tx/rx queues and mcu buffers

Signed-off-by: Lorenzo Bianconi 
Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/init.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
index ca70b62442a1..d186f509b5a8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
@@ -468,9 +468,7 @@ int mt76x0_init_hardware(struct mt76x0_dev *dev)
 
 void mt76x0_cleanup(struct mt76x0_dev *dev)
 {
-   if (!test_and_clear_bit(MT76_STATE_INITIALIZED, &dev->mt76.state))
-   return;
-
+   clear_bit(MT76_STATE_INITIALIZED, &dev->mt76.state);
mt76x0_chip_onoff(dev, false, false);
mt76u_queues_deinit(&dev->mt76);
mt76u_mcu_deinit(&dev->mt76);
-- 
2.7.5



[PATCH 28/42] mt76x0: remove mt76x0_stop_hardware routine

2018-09-06 Thread Stanislaw Gruszka
From: Lorenzo Bianconi 

Since it is actually used in a single place and it just
runs mt76x0_chip_onoff routine, remove mt76x0_stop_hardware
and use mt76x0_chip_onoff directly

Signed-off-by: Lorenzo Bianconi 
Signed-off-by: Stanislaw Gruszka 
---
 drivers/net/wireless/mediatek/mt76/mt76x0/init.c | 7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c 
b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
index 418e1918086d..5b819a224d33 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/init.c
@@ -364,11 +364,6 @@ void mt76x0_mac_stop(struct mt76x0_dev *dev)
mt76x0_mac_stop_hw(dev);
 }
 
-static void mt76x0_stop_hardware(struct mt76x0_dev *dev)
-{
-   mt76x0_chip_onoff(dev, false, false);
-}
-
 int mt76x0_init_hardware(struct mt76x0_dev *dev)
 {
static const u16 beacon_offsets[16] = {
@@ -476,7 +471,7 @@ void mt76x0_cleanup(struct mt76x0_dev *dev)
if (!test_and_clear_bit(MT76_STATE_INITIALIZED, &dev->mt76.state))
return;
 
-   mt76x0_stop_hardware(dev);
+   mt76x0_chip_onoff(dev, false, false);
mt76u_queues_deinit(&dev->mt76);
mt76u_mcu_deinit(&dev->mt76);
 }
-- 
2.7.5



<    2   3   4   5   6   7   8   9   10   11   >