diff options
author | Felix Fietkau <nbd@nbd.name> | 2021-01-19 17:41:04 +0100 |
---|---|---|
committer | Felix Fietkau <nbd@nbd.name> | 2021-01-27 17:33:43 +0100 |
commit | 9093cfff72e3e55b703ed38fa1af87c204d89cf1 (patch) | |
tree | 1f40436ea3a9bcdc999f2e7cc3e037bc77895615 /drivers/net/wireless/mediatek/mt76/mt7915/pci.c | |
parent | 94b6df08da9c4e0f96d3fbd2ec79c40d8cdac4ae (diff) |
mt76: mt7915: add support for using a secondary PCIe link for gen1
For performance reasons, mt7915 supports using 2 PCIE gen1 links on
platforms that don't support gen2.
Add support for using this to move traffic for a second DBDC band onto
a dedicated link
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt7915/pci.c')
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7915/pci.c | 173 |
1 files changed, 167 insertions, 6 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c index 99f11588601d..13880cc9c9e8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c @@ -12,11 +12,72 @@ #include "mac.h" #include "../trace.h" +static LIST_HEAD(hif_list); +static DEFINE_SPINLOCK(hif_lock); +static u32 hif_idx; + static const struct pci_device_id mt7915_pci_device_table[] = { - { PCI_DEVICE(0x14c3, 0x7915) }, + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7915) }, { }, }; +static const struct pci_device_id mt7915_hif_device_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7916) }, + { }, +}; + +void mt7915_dual_hif_set_irq_mask(struct mt7915_dev *dev, bool write_reg, + u32 clear, u32 set) +{ + struct mt76_dev *mdev = &dev->mt76; + unsigned long flags; + + spin_lock_irqsave(&mdev->mmio.irq_lock, flags); + + mdev->mmio.irqmask &= ~clear; + mdev->mmio.irqmask |= set; + + if (write_reg) { + mt76_wr(dev, MT_INT_MASK_CSR, mdev->mmio.irqmask); + mt76_wr(dev, MT_INT1_MASK_CSR, mdev->mmio.irqmask); + } + + spin_unlock_irqrestore(&mdev->mmio.irq_lock, flags); +} + +static struct mt7915_hif * +mt7915_pci_get_hif2(struct mt7915_dev *dev) +{ + struct mt7915_hif *hif; + u32 val; + + spin_lock_bh(&hif_lock); + + list_for_each_entry(hif, &hif_list, list) { + val = readl(hif->regs + MT_PCIE_RECOG_ID); + val &= MT_PCIE_RECOG_ID_MASK; + if (val != dev->hif_idx) + continue; + + get_device(hif->dev); + goto out; + } + hif = NULL; + +out: + spin_unlock_bh(&hif_lock); + + return hif; +} + +static void mt7915_put_hif2(struct mt7915_hif *hif) +{ + if (!hif) + return; + + put_device(hif->dev); +} + static void mt7915_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) { @@ -36,12 +97,20 @@ mt7915_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q) static irqreturn_t mt7915_irq_handler(int irq, void *dev_instance) { struct mt7915_dev *dev = dev_instance; - u32 intr, mask; + u32 intr, intr1, mask; intr = mt76_rr(dev, MT_INT_SOURCE_CSR); intr &= dev->mt76.mmio.irqmask; mt76_wr(dev, MT_INT_SOURCE_CSR, intr); + if (dev->hif2) { + intr1 = mt76_rr(dev, MT_INT1_SOURCE_CSR); + intr1 &= dev->mt76.mmio.irqmask; + mt76_wr(dev, MT_INT1_SOURCE_CSR, intr1); + + intr |= intr1; + } + if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state)) return IRQ_NONE; @@ -107,6 +176,53 @@ mt7915_alloc_device(struct pci_dev *pdev, struct mt7915_dev *dev) return 0; } +static void mt7915_pci_init_hif2(struct mt7915_dev *dev) +{ + struct mt7915_hif *hif; + + dev->hif_idx = ++hif_idx; + if (!pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7916, NULL)) + return; + + mt76_wr(dev, MT_PCIE_RECOG_ID, dev->hif_idx | MT_PCIE_RECOG_ID_SEM); + + hif = mt7915_pci_get_hif2(dev); + if (!hif) + return; + + dev->hif2 = hif; + + mt76_wr(dev, MT_INT1_MASK_CSR, 0); + + if (devm_request_irq(dev->mt76.dev, hif->irq, mt7915_irq_handler, + IRQF_SHARED, KBUILD_MODNAME "-hif", dev)) { + mt7915_put_hif2(hif); + hif = NULL; + } + + /* master switch of PCIe tnterrupt enable */ + mt7915_l1_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff); +} + +static int mt7915_pci_hif2_probe(struct pci_dev *pdev) +{ + struct mt7915_hif *hif; + + hif = devm_kzalloc(&pdev->dev, sizeof(*hif), GFP_KERNEL); + if (!hif) + return -ENOMEM; + + hif->dev = &pdev->dev; + hif->regs = pcim_iomap_table(pdev)[0]; + hif->irq = pdev->irq; + spin_lock_bh(&hif_lock); + list_add(&hif->list, &hif_list); + spin_unlock_bh(&hif_lock); + pci_set_drvdata(pdev, hif); + + return 0; +} + static int mt7915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -145,6 +261,9 @@ static int mt7915_pci_probe(struct pci_dev *pdev, if (ret) return ret; + if (id->device == 0x7916) + return mt7915_pci_hif2_probe(pdev); + mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7915_ops, &drv_ops); if (!mdev) @@ -170,6 +289,8 @@ static int mt7915_pci_probe(struct pci_dev *pdev, if (ret) goto error; + mt7915_pci_init_hif2(dev); + ret = mt7915_register_device(dev); if (ret) goto error; @@ -181,24 +302,64 @@ error: return ret; } +static void mt7915_hif_remove(struct pci_dev *pdev) +{ + struct mt7915_hif *hif = pci_get_drvdata(pdev); + + list_del(&hif->list); +} + static void mt7915_pci_remove(struct pci_dev *pdev) { - struct mt76_dev *mdev = pci_get_drvdata(pdev); - struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76); + struct mt76_dev *mdev; + struct mt7915_dev *dev; + mdev = pci_get_drvdata(pdev); + dev = container_of(mdev, struct mt7915_dev, mt76); + mt7915_put_hif2(dev->hif2); mt7915_unregister_device(dev); } -struct pci_driver mt7915_pci_driver = { +static struct pci_driver mt7915_hif_driver = { + .name = KBUILD_MODNAME "_hif", + .id_table = mt7915_hif_device_table, + .probe = mt7915_pci_probe, + .remove = mt7915_hif_remove, +}; + +static struct pci_driver mt7915_pci_driver = { .name = KBUILD_MODNAME, .id_table = mt7915_pci_device_table, .probe = mt7915_pci_probe, .remove = mt7915_pci_remove, }; -module_pci_driver(mt7915_pci_driver); +static int __init mt7915_init(void) +{ + int ret; + + ret = pci_register_driver(&mt7915_hif_driver); + if (ret) + return ret; + + ret = pci_register_driver(&mt7915_pci_driver); + if (ret) + pci_unregister_driver(&mt7915_hif_driver); + + return ret; +} + +static void __exit mt7915_exit(void) +{ + pci_unregister_driver(&mt7915_pci_driver); + pci_unregister_driver(&mt7915_hif_driver); +} + +module_init(mt7915_init); +module_exit(mt7915_exit); MODULE_DEVICE_TABLE(pci, mt7915_pci_device_table); +MODULE_DEVICE_TABLE(pci, mt7915_hif_device_table); MODULE_FIRMWARE(MT7915_FIRMWARE_WA); MODULE_FIRMWARE(MT7915_FIRMWARE_WM); MODULE_FIRMWARE(MT7915_ROM_PATCH); |