mt76_worker_disable(&dev->tx_worker);
netif_napi_del(&dev->tx_napi);
- for (i = 0; i < ARRAY_SIZE(dev->phy.q_tx); i++) {
- mt76_dma_tx_cleanup(dev, dev->phy.q_tx[i], true);
- if (dev->phy2)
- mt76_dma_tx_cleanup(dev, dev->phy2->q_tx[i], true);
+ for (i = 0; i < ARRAY_SIZE(dev->phys); i++) {
+ struct mt76_phy *phy = dev->phys[i];
+ int j;
+
+ if (!phy)
+ continue;
+
+ for (j = 0; j < ARRAY_SIZE(phy->q_tx); j++)
+ mt76_dma_tx_cleanup(dev, phy->q_tx[j], true);
}
for (i = 0; i < ARRAY_SIZE(dev->q_mcu); i++)
struct mt76_phy *
mt76_alloc_phy(struct mt76_dev *dev, unsigned int size,
- const struct ieee80211_ops *ops)
+ const struct ieee80211_ops *ops, u8 band_idx)
{
struct ieee80211_hw *hw;
unsigned int phy_size;
phy->dev = dev;
phy->hw = hw;
phy->priv = hw->priv + phy_size;
+ phy->band_idx = band_idx;
hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
hw->wiphy->interface_modes =
if (ret)
return ret;
- phy->dev->phy2 = phy;
+ phy->dev->phys[phy->band_idx] = phy;
return 0;
}
mt76_tx_status_check(dev, true);
ieee80211_unregister_hw(phy->hw);
- dev->phy2 = NULL;
+ dev->phys[phy->band_idx] = NULL;
}
EXPORT_SYMBOL_GPL(mt76_unregister_phy);
phy = &dev->phy;
phy->dev = dev;
phy->hw = hw;
+ phy->band_idx = MT_BAND0;
+ dev->phys[phy->band_idx] = phy;
spin_lock_init(&dev->rx_lock);
spin_lock_init(&dev->lock);
__MT_RXQ_MAX
};
+enum mt76_band_id {
+ MT_BAND0,
+ MT_BAND1,
+ MT_BAND2,
+ __MT_MAX_BAND
+};
+
enum mt76_cipher_type {
MT_CIPHER_NONE,
MT_CIPHER_WEP40,
void *priv;
unsigned long state;
+ u8 band_idx;
struct mt76_queue *q_tx[__MT_TXQ_MAX];
struct mt76_dev {
struct mt76_phy phy; /* must be first */
-
- struct mt76_phy *phy2;
+ struct mt76_phy *phys[__MT_MAX_BAND];
struct ieee80211_hw *hw;
{
if (wcid <= MT76_N_WCIDS &&
mt76_wcid_mask_test(dev->wcid_phy_mask, wcid))
- return dev->phy2->hw;
+ return dev->phys[MT_BAND1]->hw;
return dev->phy.hw;
}
void mt76_unregister_phy(struct mt76_phy *phy);
struct mt76_phy *mt76_alloc_phy(struct mt76_dev *dev, unsigned int size,
- const struct ieee80211_ops *ops);
+ const struct ieee80211_ops *ops,
+ u8 band_idx);
int mt76_register_phy(struct mt76_phy *phy, bool vht,
struct ieee80211_rate *rates, int n_rates);
static inline struct mt76_phy *
mt76_dev_phy(struct mt76_dev *dev, u8 phy_idx)
{
- if (phy_idx && dev->phy2)
- return dev->phy2;
+ if ((phy_idx == MT_BAND1 && dev->phys[phy_idx]) ||
+ (phy_idx == MT_BAND2 && dev->phys[phy_idx]))
+ return dev->phys[phy_idx];
return &dev->phy;
}
struct ieee80211_hw **hw)
{
#ifdef CONFIG_NL80211_TESTMODE
- if (skb == dev->phy.test.tx_skb)
- *hw = dev->phy.hw;
- else if (dev->phy2 && skb == dev->phy2->test.tx_skb)
- *hw = dev->phy2->hw;
- else
- return false;
- return true;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(dev->phys); i++) {
+ struct mt76_phy *phy = dev->phys[i];
+
+ if (phy && skb == phy->test.tx_skb) {
+ *hw = dev->phys[i]->hw;
+ return true;
+ }
+ }
+ return false;
#else
return false;
#endif
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hw *hw = dev->phy.hw;
- if ((info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY) && dev->phy2)
- hw = dev->phy2->hw;
+ if ((info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY) && dev->phys[MT_BAND1])
+ hw = dev->phys[MT_BAND1]->hw;
info->hw_queue &= ~MT_TX_HW_QUEUE_EXT_PHY;
return 0;
mt7615_cap_dbdc_enable(dev);
- mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7615_ops);
+ mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7615_ops, MT_BAND1);
if (!mphy)
return -ENOMEM;
void mt7615_unregister_ext_phy(struct mt7615_dev *dev)
{
struct mt7615_phy *phy = mt7615_ext_phy(dev);
- struct mt76_phy *mphy = dev->mt76.phy2;
+ struct mt76_phy *mphy = dev->mt76.phys[MT_BAND1];
if (!phy)
return;
void mt7615_mac_reset_counters(struct mt7615_dev *dev)
{
+ struct mt76_phy *mphy_ext = dev->mt76.phys[MT_BAND1];
int i;
for (i = 0; i < 4; i++) {
memset(dev->mt76.aggr_stats, 0, sizeof(dev->mt76.aggr_stats));
dev->mt76.phy.survey_time = ktime_get_boottime();
- if (dev->mt76.phy2)
- dev->mt76.phy2->survey_time = ktime_get_boottime();
+ if (mphy_ext)
+ mphy_ext->survey_time = ktime_get_boottime();
/* reset airtime counters */
mt76_rr(dev, MT_MIB_SDR9(0));
struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
struct mt76_phy *mphy = &dev->mt76.phy;
struct mt7615_phy *phy = &dev->phy;
- struct mt7615_phy *phy2 = dev->mt76.phy2 ? dev->mt76.phy2->priv : NULL;
struct ieee80211_supported_band *sband;
struct ieee80211_hdr *hdr;
+ struct mt7615_phy *phy2;
__le32 *rxd = (__le32 *)skb->data;
u32 rxd0 = le32_to_cpu(rxd[0]);
u32 rxd1 = le32_to_cpu(rxd[1]);
memset(status, 0, sizeof(*status));
chfreq = FIELD_GET(MT_RXD1_NORMAL_CH_FREQ, rxd1);
+
+ phy2 = dev->mt76.phys[MT_BAND1] ? dev->mt76.phys[MT_BAND1]->priv : NULL;
if (!phy2)
phy_idx = 0;
else if (phy2->chfreq == phy->chfreq)
}
if (phy_idx == 1 && phy2) {
- mphy = dev->mt76.phy2;
+ mphy = dev->mt76.phys[MT_BAND1];
phy = phy2;
status->phy_idx = phy_idx;
}
tx_count = msta->rate_count;
}
- if (ext_phy && dev->mt76.phy2)
- mphy = dev->mt76.phy2;
+ if (ext_phy && dev->mt76.phys[MT_BAND1])
+ mphy = dev->mt76.phys[MT_BAND1];
fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2;
fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4;
if (sta->rate_probe) {
struct mt7615_phy *phy = &dev->phy;
- if (sta->wcid.ext_phy && dev->mt76.phy2)
- phy = dev->mt76.phy2->priv;
+ if (sta->wcid.ext_phy && dev->mt76.phys[MT_BAND1])
+ phy = dev->mt76.phys[MT_BAND1]->priv;
mt7615_mac_set_rates(phy, sta, NULL, sta->rates);
}
fallthrough;
case MT_PHY_TYPE_OFDM:
mphy = &dev->mphy;
- if (sta->wcid.ext_phy && dev->mt76.phy2)
- mphy = dev->mt76.phy2;
+ if (sta->wcid.ext_phy && dev->mt76.phys[MT_BAND1])
+ mphy = dev->mt76.phys[MT_BAND1];
if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
sband = &mphy->sband_5g.sband;
if (wcidx >= MT7615_WTBL_STA || !sta)
goto out;
- if (wcid->ext_phy && dev->mt76.phy2)
- mphy = dev->mt76.phy2;
+ if (wcid->ext_phy && dev->mt76.phys[MT_BAND1])
+ mphy = dev->mt76.phys[MT_BAND1];
if (mt7615_fill_txs(dev, msta, &info, txs_data))
ieee80211_tx_status_noskb(mphy->hw, sta, &info);
static void mt7615_update_survey(struct mt7615_dev *dev)
{
struct mt76_dev *mdev = &dev->mt76;
+ struct mt76_phy *mphy_ext = mdev->phys[MT_BAND1];
ktime_t cur_time;
/* MT7615 can only update both phys simultaneously
*/
mt7615_phy_update_channel(&mdev->phy, 0);
- if (mdev->phy2)
- mt7615_phy_update_channel(mdev->phy2, 1);
+ if (mphy_ext)
+ mt7615_phy_update_channel(mphy_ext, 1);
cur_time = ktime_get_boottime();
mt76_update_survey_active_time(&mdev->phy, cur_time);
- if (mdev->phy2)
- mt76_update_survey_active_time(mdev->phy2, cur_time);
+ if (mphy_ext)
+ mt76_update_survey_active_time(mphy_ext, cur_time);
/* reset obss airtime */
mt76_set(dev, MT_WF_RMAC_MIB_TIME0, MT_WF_RMAC_MIB_RXTIME_CLR);
return;
if (ext_phy && ext_phy->omac_mask & BIT_ULL(c->omac_idx))
- mphy = dev->mt76.phy2;
+ mphy = dev->mt76.phys[MT_BAND1];
ieee80211_iterate_active_interfaces_atomic(mphy->hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
!r->constant_prf_detected && !r->staggered_prf_detected)
return;
- if (r->band_idx && dev->mt76.phy2)
- mphy = dev->mt76.phy2;
+ if (r->band_idx && dev->mt76.phys[MT_BAND1])
+ mphy = dev->mt76.phys[MT_BAND1];
if (mt76_phy_dfs_state(mphy) < MT_DFS_STATE_CAC)
return;
struct mt7615_phy *phy;
struct mt76_phy *mphy;
- if (*seq_num & BIT(7) && dev->mt76.phy2)
- mphy = dev->mt76.phy2;
+ if (*seq_num & BIT(7) && dev->mt76.phys[MT_BAND1])
+ mphy = dev->mt76.phys[MT_BAND1];
else
mphy = &dev->mt76.phy;
skb_pull(skb, sizeof(struct mt7615_mcu_rxd));
event = (struct mt7615_roc_tlv *)skb->data;
- if (event->dbdc_band && dev->mt76.phy2)
- mphy = dev->mt76.phy2;
+ if (event->dbdc_band && dev->mt76.phys[MT_BAND1])
+ mphy = dev->mt76.phys[MT_BAND1];
else
mphy = &dev->mt76.phy;
skb_pull(skb, sizeof(struct mt7615_mcu_rxd));
event = (struct mt76_connac_beacon_loss_event *)skb->data;
- if (band_idx && dev->mt76.phy2)
- mphy = dev->mt76.phy2;
+ if (band_idx && dev->mt76.phys[MT_BAND1])
+ mphy = dev->mt76.phys[MT_BAND1];
else
mphy = &dev->mt76.phy;
skb_pull(skb, sizeof(struct mt7615_mcu_rxd));
event = (struct mt76_connac_mcu_bss_event *)skb->data;
- if (band_idx && dev->mt76.phy2)
- mphy = dev->mt76.phy2;
+ if (band_idx && dev->mt76.phys[MT_BAND1])
+ mphy = dev->mt76.phys[MT_BAND1];
else
mphy = &dev->mt76.phy;
.bw = mt7615_mcu_chan_bw(chandef),
.band = chandef->center_freq1 > 4000,
- .dbdc_en = !!dev->mt76.phy2,
+ .dbdc_en = !!dev->mt76.phys[MT_BAND1],
};
u16 center_freq = chandef->center_freq1;
int freq_idx;
.bw = mt7615_mcu_chan_bw(chandef),
.band = chandef->center_freq1 > 4000,
- .dbdc_en = !!dev->mt76.phy2,
+ .dbdc_en = !!dev->mt76.phys[MT_BAND1],
};
u16 center_freq = chandef->center_freq1;
int freq_idx;
static inline struct mt7615_phy *
mt7615_ext_phy(struct mt7615_dev *dev)
{
- struct mt76_phy *phy = dev->mt76.phy2;
+ struct mt76_phy *phy = dev->mt76.phys[MT_BAND1];
if (!phy)
return NULL;
if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && msta) {
struct mt7615_phy *phy = &dev->phy;
- if ((info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY) && mdev->phy2)
- phy = mdev->phy2->priv;
+ if ((info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY) && mdev->phys[MT_BAND1])
+ phy = mdev->phys[MT_BAND1]->priv;
spin_lock_bh(&dev->mt76.lock);
mt7615_mac_set_rates(phy, msta, &info->control.rates[0],
static void
mt7615_update_beacons(struct mt7615_dev *dev)
{
+ struct mt76_phy *mphy_ext = dev->mt76.phys[MT_BAND1];
+
ieee80211_iterate_active_interfaces(dev->mt76.hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7615_update_vif_beacon, dev->mt76.hw);
- if (!dev->mt76.phy2)
+ if (!mphy_ext)
return;
- ieee80211_iterate_active_interfaces(dev->mt76.phy2->hw,
+ ieee80211_iterate_active_interfaces(mphy_ext->hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
- mt7615_update_vif_beacon, dev->mt76.phy2->hw);
+ mt7615_update_vif_beacon, mphy_ext->hw);
}
void mt7615_mac_reset_work(struct work_struct *work)
int i;
dev = container_of(work, struct mt7615_dev, reset_work);
- ext_phy = dev->mt76.phy2;
+ ext_phy = dev->mt76.phys[MT_BAND1];
phy2 = ext_phy ? ext_phy->priv : NULL;
if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_PDMA))
band_idx = mvif->band_idx;
}
- if (ext_phy && dev->phy2)
- mphy = dev->phy2;
+ if (ext_phy && dev->phys[MT_BAND1])
+ mphy = dev->phys[MT_BAND1];
if (inband_disc) {
p_fmt = MT_TX_TYPE_FW;
fallthrough;
case MT_PHY_TYPE_OFDM:
mphy = &dev->phy;
- if (wcid->ext_phy && dev->phy2)
- mphy = dev->phy2;
+ if (wcid->ext_phy && dev->phys[MT_BAND1])
+ mphy = dev->phys[MT_BAND1];
if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
sband = &mphy->sband_5g.sband;
if (!dev->dbdc_support)
return NULL;
- mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7915_ops);
+ mphy = mt76_alloc_phy(&dev->mt76, sizeof(*phy), &mt7915_ops, MT_BAND1);
if (!mphy)
return ERR_PTR(-ENOMEM);
static void mt7915_unregister_ext_phy(struct mt7915_dev *dev)
{
struct mt7915_phy *phy = mt7915_ext_phy(dev);
- struct mt76_phy *mphy = dev->mt76.phy2;
+ struct mt76_phy *mphy = dev->mt76.phys[MT_BAND1];
if (!phy)
return;
memset(status, 0, sizeof(*status));
if ((rxd1 & MT_RXD1_NORMAL_BAND_IDX) && !phy->band_idx) {
- mphy = dev->mt76.phy2;
+ mphy = dev->mt76.phys[MT_BAND1];
if (!mphy)
return -EINVAL;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct mt76_phy *mphy = &dev->phy;
- if ((info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY) && dev->phy2)
- mphy = dev->phy2;
+ if ((info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY) && dev->phys[MT_BAND1])
+ mphy = dev->phys[MT_BAND1];
mt76_connac2_mac_write_txwi(dev, txwi, skb, wcid, key, pid, qid, changed);
mt7915_mac_tx_free_prepare(struct mt7915_dev *dev)
{
struct mt76_dev *mdev = &dev->mt76;
- struct mt76_phy *mphy_ext = mdev->phy2;
+ struct mt76_phy *mphy_ext = mdev->phys[MT_BAND1];
/* clean DMA queues and unmap buffers first */
mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false);
static void
mt7915_update_beacons(struct mt7915_dev *dev)
{
+ struct mt76_phy *mphy_ext = dev->mt76.phys[MT_BAND1];
+
ieee80211_iterate_active_interfaces(dev->mt76.hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7915_update_vif_beacon, dev->mt76.hw);
- if (!dev->mt76.phy2)
+ if (!mphy_ext)
return;
- ieee80211_iterate_active_interfaces(dev->mt76.phy2->hw,
+ ieee80211_iterate_active_interfaces(mphy_ext->hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
- mt7915_update_vif_beacon, dev->mt76.phy2->hw);
+ mt7915_update_vif_beacon, mphy_ext->hw);
}
static void
mt7915_dma_reset(struct mt7915_dev *dev)
{
- struct mt76_phy *mphy_ext = dev->mt76.phy2;
+ struct mt76_phy *mphy_ext = dev->mt76.phys[MT_BAND1];
u32 hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
int i;
int i;
dev = container_of(work, struct mt7915_dev, reset_work);
- ext_phy = dev->mt76.phy2;
+ ext_phy = dev->mt76.phys[MT_BAND1];
phy2 = ext_phy ? ext_phy->priv : NULL;
if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_DMA))
c = (struct mt7915_mcu_csa_notify *)skb->data;
- if ((c->band_idx && !dev->phy.band_idx) && dev->mt76.phy2)
- mphy = dev->mt76.phy2;
+ if ((c->band_idx && !dev->phy.band_idx) && dev->mt76.phys[MT_BAND1])
+ mphy = dev->mt76.phys[MT_BAND1];
ieee80211_iterate_active_interfaces_atomic(mphy->hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
if (t->ctrl.ctrl_id != THERMAL_PROTECT_ENABLE)
return;
- if ((t->ctrl.band_idx && !dev->phy.band_idx) && dev->mt76.phy2)
- mphy = dev->mt76.phy2;
+ if ((t->ctrl.band_idx && !dev->phy.band_idx) && dev->mt76.phys[MT_BAND1])
+ mphy = dev->mt76.phys[MT_BAND1];
phy = (struct mt7915_phy *)mphy->priv;
phy->throttle_state = t->ctrl.duty.duty_cycle;
r = (struct mt7915_mcu_rdd_report *)skb->data;
- if ((r->band_idx && !dev->phy.band_idx) && dev->mt76.phy2)
- mphy = dev->mt76.phy2;
+ if ((r->band_idx && !dev->phy.band_idx) && dev->mt76.phys[MT_BAND1])
+ mphy = dev->mt76.phys[MT_BAND1];
if (r->band_idx == MT_RX_SEL2)
cfg80211_background_radar_event(mphy->hw->wiphy,
b = (struct mt7915_mcu_bcc_notify *)skb->data;
- if ((b->band_idx && !dev->phy.band_idx) && dev->mt76.phy2)
- mphy = dev->mt76.phy2;
+ if ((b->band_idx && !dev->phy.band_idx) && dev->mt76.phys[MT_BAND1])
+ mphy = dev->mt76.phys[MT_BAND1];
ieee80211_iterate_active_interfaces_atomic(mphy->hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
static inline struct mt7915_phy *
mt7915_ext_phy(struct mt7915_dev *dev)
{
- struct mt76_phy *phy = dev->mt76.phy2;
+ struct mt76_phy *phy = dev->mt76.phys[MT_BAND1];
if (!phy)
return NULL;
void mt76_tx_worker_run(struct mt76_dev *dev)
{
- mt76_txq_schedule_all(&dev->phy);
- if (dev->phy2)
- mt76_txq_schedule_all(dev->phy2);
+ struct mt76_phy *phy;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(dev->phys); i++) {
+ phy = dev->phys[i];
+ if (!phy)
+ continue;
+
+ mt76_txq_schedule_all(phy);
+ }
#ifdef CONFIG_NL80211_TESTMODE
- if (dev->phy.test.tx_pending)
- mt76_testmode_tx_pending(&dev->phy);
- if (dev->phy2 && dev->phy2->test.tx_pending)
- mt76_testmode_tx_pending(dev->phy2);
+ for (i = 0; i < ARRAY_SIZE(dev->phys); i++) {
+ phy = dev->phys[i];
+ if (!phy || !phy->test.tx_pending)
+ continue;
+
+ mt76_testmode_tx_pending(phy);
+ }
#endif
}
EXPORT_SYMBOL_GPL(mt76_tx_worker_run);
void __mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked)
{
- struct mt76_phy *phy = &dev->phy, *phy2 = dev->phy2;
- struct mt76_queue *q, *q2 = NULL;
+ struct mt76_phy *phy = &dev->phy;
+ struct mt76_queue *q = phy->q_tx[0];
- q = phy->q_tx[0];
if (blocked == q->blocked)
return;
q->blocked = blocked;
- if (phy2) {
- q2 = phy2->q_tx[0];
- q2->blocked = blocked;
+
+ phy = dev->phys[MT_BAND1];
+ if (phy) {
+ q = phy->q_tx[0];
+ q->blocked = blocked;
+ }
+ phy = dev->phys[MT_BAND2];
+ if (phy) {
+ q = phy->q_tx[0];
+ q->blocked = blocked;
}
if (!blocked)