diff --git a/mt7603.h b/mt7603.h index 46fb44b7..3abca533 100644 --- a/mt7603.h +++ b/mt7603.h @@ -25,6 +25,12 @@ enum { MT7603_REV_E2 = 0x10 }; +enum mt7603_bw { + MT_BW_20, + MT_BW_40, + MT_BW_80, +}; + enum mt7603_txq_id { MT_TXQ_VO = IEEE80211_AC_VO, MT_TXQ_VI = IEEE80211_AC_VI, @@ -50,6 +56,7 @@ struct mt7603_mcu { struct mt7603_dev { struct mt76_dev mt76; + struct mutex mutex; struct cfg80211_chan_def chandef; u32 irqmask; @@ -57,6 +64,9 @@ struct mt7603_dev { u32 rxfilter; + u8 rx_chains; + u8 tx_chains; + struct mt7603_mcu mcu; struct mt76_queue q_rx; struct mt76_queue q_tx[__MT_TXQ_MAX]; @@ -92,4 +102,6 @@ static inline void mt7603_irq_disable(struct mt7603_dev *dev, u32 mask) mt7603_set_irq_mask(dev, mask, 0); } +int mt7603_mcu_set_channel(struct mt7603_dev *dev); + #endif diff --git a/mt7603_init.c b/mt7603_init.c index 9f891325..03d35c55 100644 --- a/mt7603_init.c +++ b/mt7603_init.c @@ -150,6 +150,11 @@ int mt7603_register_device(struct mt7603_dev *dev) struct wiphy *wiphy = hw->wiphy; int ret; + mutex_init(&dev->mutex); + + dev->rx_chains = 3; + dev->tx_chains = 3; + ret = mt7603_init_hardware(dev); if (ret) return ret; diff --git a/mt7603_main.c b/mt7603_main.c index 7c7c44f6..19fd93a1 100644 --- a/mt7603_main.c +++ b/mt7603_main.c @@ -16,7 +16,7 @@ static int mt7603_start(struct ieee80211_hw *hw) { - return -EINVAL; + return 0; } static void @@ -38,7 +38,19 @@ mt7603_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) static int mt7603_config(struct ieee80211_hw *hw, u32 changed) { - return -EINVAL; + struct mt7603_dev *dev = hw->priv; + int ret = 0; + + mutex_lock(&dev->mutex); + + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + dev->chandef = hw->conf.chandef; + ret = mt7603_mcu_set_channel(dev); + } + + mutex_unlock(&dev->mutex); + + return ret; } static void diff --git a/mt7603_mcu.c b/mt7603_mcu.c index edf8343f..d5285171 100644 --- a/mt7603_mcu.c +++ b/mt7603_mcu.c @@ -298,3 +298,28 @@ int mt7603_mcu_init(struct mt7603_dev *dev) mutex_init(&dev->mcu.mutex); return mt7603_load_firmware(dev); } + +int mt7603_mcu_set_channel(struct mt7603_dev *dev) +{ + struct { + u8 control_chan; + u8 center_chan; + u8 bw; + u8 tx_streams; + u8 rx_streams; + u8 _res0[7]; + u8 txpower[21]; + u8 _res1[3]; + } req = { + .control_chan = dev->chandef.chan->hw_value, + .center_chan = dev->chandef.chan->hw_value, + .bw = MT_BW_20, + .tx_streams = dev->tx_chains, + .rx_streams = dev->rx_chains, + }; + struct sk_buff *skb; + + memset(req.txpower, 0xff, sizeof(req.txpower)); + skb = mt7603_mcu_msg_alloc(dev, &req, sizeof(req)); + return mt7603_mcu_msg_send(dev, skb, MCU_EXT_CMD_CHANNEL_SWITCH, MCU_Q_SET); +}