drivers/net/wireless/mediatek/mt76/mt7996/init.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/mediatek/mt76/mt7996/init.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/mediatek/mt76/mt7996/init.c
Extension
.c
Size
52315 bytes
Lines
1818
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

mt7996_band_valid(dev, MT_BAND2)) {
		ret = mt7996_mcu_set_txbf(dev, BF_MOD_EN_CTRL);
		if (ret)
			return ret;
	}

	/* trigger sounding packets */
	ret = mt7996_mcu_set_txbf(dev, BF_SOUNDING_ON);
	if (ret)
		return ret;

	/* enable eBF */
	return mt7996_mcu_set_txbf(dev, BF_HW_EN_UPDATE);
}

static int mt7996_register_phy(struct mt7996_dev *dev, enum mt76_band_id band)
{
	struct mt7996_phy *phy;
	struct mt76_phy *mphy;
	u32 mac_ofs, hif1_ofs = 0;
	int ret;
	struct mtk_wed_device *wed = &dev->mt76.mmio.wed;

	if (!mt7996_band_valid(dev, band))
		return 0;

	if (dev->hif2 &&
	    ((is_mt7992(&dev->mt76) && band == MT_BAND1) ||
	     (is_mt7996(&dev->mt76) && band == MT_BAND2 &&
	      !mt76_npu_device_active(&dev->mt76)))) {
		hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
		wed = &dev->mt76.mmio.wed_hif2;
	}

	mphy = mt76_alloc_radio_phy(&dev->mt76, sizeof(*phy), band);
	if (!mphy)
		return -ENOMEM;

	phy = mphy->priv;
	phy->dev = dev;
	phy->mt76 = mphy;
	mphy->dev->phys[band] = mphy;

	INIT_DELAYED_WORK(&mphy->mac_work, mt7996_mac_work);

	ret = mt7996_eeprom_parse_hw_cap(dev, phy);
	if (ret)
		goto error;

	mac_ofs = band == MT_BAND2 ? MT_EE_MAC_ADDR3 : MT_EE_MAC_ADDR2;
	memcpy(mphy->macaddr, dev->mt76.eeprom.data + mac_ofs, ETH_ALEN);
	/* Make the extra PHY MAC address local without overlapping with
	 * the usual MAC address allocation scheme on multiple virtual interfaces
	 */
	if (!is_valid_ether_addr(mphy->macaddr)) {
		memcpy(mphy->macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
		       ETH_ALEN);
		mphy->macaddr[0] |= 2;
		mphy->macaddr[0] ^= BIT(7);
		if (band == MT_BAND2)
			mphy->macaddr[0] ^= BIT(6);
	}
	ret = mt76_eeprom_override(mphy);
	if (ret)
		goto error;

	/* init wiphy according to mphy and phy */
	mt7996_init_wiphy_band(mphy->hw, phy);

	if (is_mt7996(&dev->mt76) &&
	    ((band == MT_BAND1 && !dev->hif2) ||
	     (band == MT_BAND2 && mt76_npu_device_active(&dev->mt76)))) {
		int i;

		for (i = 0; i <= MT_TXQ_PSD; i++)
			mphy->q_tx[i] = dev->mt76.phys[band - 1]->q_tx[0];
	} else {
		int size = is_mt7996(&dev->mt76) &&
			   mt76_npu_device_active(&dev->mt76)
			   ? MT7996_NPU_TX_RING_SIZE / 2 : MT7996_TX_RING_SIZE;

		ret = mt7996_init_tx_queues(mphy->priv, MT_TXQ_ID(band), size,
					    MT_TXQ_RING_BASE(band) + hif1_ofs,
					    wed);
		if (ret)
			goto error;
	}

	ret = mt76_register_phy(mphy, true, mt76_rates,
				ARRAY_SIZE(mt76_rates));

Annotation

Implementation Notes