cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pci.c (6701B)


      1// SPDX-License-Identifier: ISC
      2/* Copyright (C) 2020 MediaTek Inc.
      3 *
      4 * Author: Ryder Lee <ryder.lee@mediatek.com>
      5 */
      6
      7#include <linux/kernel.h>
      8#include <linux/module.h>
      9#include <linux/pci.h>
     10
     11#include "mt7915.h"
     12#include "mac.h"
     13#include "../trace.h"
     14
     15static bool wed_enable = false;
     16module_param(wed_enable, bool, 0644);
     17
     18static LIST_HEAD(hif_list);
     19static DEFINE_SPINLOCK(hif_lock);
     20static u32 hif_idx;
     21
     22static const struct pci_device_id mt7915_pci_device_table[] = {
     23	{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7915) },
     24	{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7906) },
     25	{ },
     26};
     27
     28static const struct pci_device_id mt7915_hif_device_table[] = {
     29	{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7916) },
     30	{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x790a) },
     31	{ },
     32};
     33
     34static struct mt7915_hif *mt7915_pci_get_hif2(u32 idx)
     35{
     36	struct mt7915_hif *hif;
     37	u32 val;
     38
     39	spin_lock_bh(&hif_lock);
     40
     41	list_for_each_entry(hif, &hif_list, list) {
     42		val = readl(hif->regs + MT_PCIE_RECOG_ID);
     43		val &= MT_PCIE_RECOG_ID_MASK;
     44		if (val != idx)
     45			continue;
     46
     47		get_device(hif->dev);
     48		goto out;
     49	}
     50	hif = NULL;
     51
     52out:
     53	spin_unlock_bh(&hif_lock);
     54
     55	return hif;
     56}
     57
     58static void mt7915_put_hif2(struct mt7915_hif *hif)
     59{
     60	if (!hif)
     61		return;
     62
     63	put_device(hif->dev);
     64}
     65
     66static struct mt7915_hif *mt7915_pci_init_hif2(struct pci_dev *pdev)
     67{
     68	hif_idx++;
     69	if (!pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x7916, NULL) &&
     70	    !pci_get_device(PCI_VENDOR_ID_MEDIATEK, 0x790a, NULL))
     71		return NULL;
     72
     73	writel(hif_idx | MT_PCIE_RECOG_ID_SEM,
     74	       pcim_iomap_table(pdev)[0] + MT_PCIE_RECOG_ID);
     75
     76	return mt7915_pci_get_hif2(hif_idx);
     77}
     78
     79static int mt7915_pci_hif2_probe(struct pci_dev *pdev)
     80{
     81	struct mt7915_hif *hif;
     82
     83	hif = devm_kzalloc(&pdev->dev, sizeof(*hif), GFP_KERNEL);
     84	if (!hif)
     85		return -ENOMEM;
     86
     87	hif->dev = &pdev->dev;
     88	hif->regs = pcim_iomap_table(pdev)[0];
     89	hif->irq = pdev->irq;
     90	spin_lock_bh(&hif_lock);
     91	list_add(&hif->list, &hif_list);
     92	spin_unlock_bh(&hif_lock);
     93	pci_set_drvdata(pdev, hif);
     94
     95	return 0;
     96}
     97
     98#ifdef CONFIG_NET_MEDIATEK_SOC_WED
     99static int mt7915_wed_offload_enable(struct mtk_wed_device *wed)
    100{
    101	struct mt7915_dev *dev;
    102	int ret;
    103
    104	dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
    105
    106	spin_lock_bh(&dev->mt76.token_lock);
    107	dev->mt76.token_size = wed->wlan.token_start;
    108	spin_unlock_bh(&dev->mt76.token_lock);
    109
    110	ret = wait_event_timeout(dev->mt76.tx_wait,
    111				 !dev->mt76.wed_token_count, HZ);
    112	if (!ret)
    113		return -EAGAIN;
    114
    115	return 0;
    116}
    117
    118static void mt7915_wed_offload_disable(struct mtk_wed_device *wed)
    119{
    120	struct mt7915_dev *dev;
    121
    122	dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed);
    123
    124	spin_lock_bh(&dev->mt76.token_lock);
    125	dev->mt76.token_size = MT7915_TOKEN_SIZE;
    126	spin_unlock_bh(&dev->mt76.token_lock);
    127}
    128#endif
    129
    130static int
    131mt7915_pci_wed_init(struct mt7915_dev *dev, struct pci_dev *pdev, int *irq)
    132{
    133#ifdef CONFIG_NET_MEDIATEK_SOC_WED
    134	struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
    135	int ret;
    136
    137	if (!wed_enable)
    138		return 0;
    139
    140	wed->wlan.pci_dev = pdev;
    141	wed->wlan.wpdma_phys = pci_resource_start(pdev, 0) +
    142			       MT_WFDMA_EXT_CSR_BASE;
    143	wed->wlan.nbuf = 4096;
    144	wed->wlan.token_start = MT7915_TOKEN_SIZE - wed->wlan.nbuf;
    145	wed->wlan.init_buf = mt7915_wed_init_buf;
    146	wed->wlan.offload_enable = mt7915_wed_offload_enable;
    147	wed->wlan.offload_disable = mt7915_wed_offload_disable;
    148
    149	if (mtk_wed_device_attach(wed) != 0)
    150		return 0;
    151
    152	*irq = wed->irq;
    153	dev->mt76.dma_dev = wed->dev;
    154
    155	ret = dma_set_mask(wed->dev, DMA_BIT_MASK(32));
    156	if (ret)
    157		return ret;
    158
    159	return 1;
    160#else
    161	return 0;
    162#endif
    163}
    164
    165static int mt7915_pci_probe(struct pci_dev *pdev,
    166			    const struct pci_device_id *id)
    167{
    168	struct mt7915_hif *hif2 = NULL;
    169	struct mt7915_dev *dev;
    170	struct mt76_dev *mdev;
    171	int irq;
    172	int ret;
    173
    174	ret = pcim_enable_device(pdev);
    175	if (ret)
    176		return ret;
    177
    178	ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));
    179	if (ret)
    180		return ret;
    181
    182	pci_set_master(pdev);
    183
    184	ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
    185	if (ret)
    186		return ret;
    187
    188	mt76_pci_disable_aspm(pdev);
    189
    190	if (id->device == 0x7916 || id->device == 0x790a)
    191		return mt7915_pci_hif2_probe(pdev);
    192
    193	dev = mt7915_mmio_probe(&pdev->dev, pcim_iomap_table(pdev)[0],
    194				id->device);
    195	if (IS_ERR(dev))
    196		return PTR_ERR(dev);
    197
    198	mdev = &dev->mt76;
    199	mt7915_wfsys_reset(dev);
    200	hif2 = mt7915_pci_init_hif2(pdev);
    201
    202	ret = mt7915_pci_wed_init(dev, pdev, &irq);
    203	if (ret < 0)
    204		goto free_wed_or_irq_vector;
    205
    206	if (!ret) {
    207		hif2 = mt7915_pci_init_hif2(pdev);
    208
    209		ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
    210		if (ret < 0)
    211			goto free_device;
    212
    213		irq = pdev->irq;
    214	}
    215
    216	ret = devm_request_irq(mdev->dev, irq, mt7915_irq_handler,
    217			       IRQF_SHARED, KBUILD_MODNAME, dev);
    218	if (ret)
    219		goto free_wed_or_irq_vector;
    220
    221	/* master switch of PCIe tnterrupt enable */
    222	mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
    223
    224	if (hif2) {
    225		dev->hif2 = hif2;
    226
    227		mt76_wr(dev, MT_INT1_MASK_CSR, 0);
    228		/* master switch of PCIe tnterrupt enable */
    229		if (is_mt7915(mdev))
    230			mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff);
    231		else
    232			mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE_MT7916, 0xff);
    233
    234		ret = devm_request_irq(mdev->dev, dev->hif2->irq,
    235				       mt7915_irq_handler, IRQF_SHARED,
    236				       KBUILD_MODNAME "-hif", dev);
    237		if (ret)
    238			goto free_hif2;
    239	}
    240
    241	ret = mt7915_register_device(dev);
    242	if (ret)
    243		goto free_hif2_irq;
    244
    245	return 0;
    246
    247free_hif2_irq:
    248	if (dev->hif2)
    249		devm_free_irq(mdev->dev, dev->hif2->irq, dev);
    250free_hif2:
    251	if (dev->hif2)
    252		put_device(dev->hif2->dev);
    253	devm_free_irq(mdev->dev, irq, dev);
    254free_wed_or_irq_vector:
    255	if (mtk_wed_device_active(&mdev->mmio.wed))
    256		mtk_wed_device_detach(&mdev->mmio.wed);
    257	else
    258		pci_free_irq_vectors(pdev);
    259free_device:
    260	mt76_free_device(&dev->mt76);
    261
    262	return ret;
    263}
    264
    265static void mt7915_hif_remove(struct pci_dev *pdev)
    266{
    267	struct mt7915_hif *hif = pci_get_drvdata(pdev);
    268
    269	list_del(&hif->list);
    270}
    271
    272static void mt7915_pci_remove(struct pci_dev *pdev)
    273{
    274	struct mt76_dev *mdev;
    275	struct mt7915_dev *dev;
    276
    277	mdev = pci_get_drvdata(pdev);
    278	dev = container_of(mdev, struct mt7915_dev, mt76);
    279	mt7915_put_hif2(dev->hif2);
    280	mt7915_unregister_device(dev);
    281}
    282
    283struct pci_driver mt7915_hif_driver = {
    284	.name		= KBUILD_MODNAME "_hif",
    285	.id_table	= mt7915_hif_device_table,
    286	.probe		= mt7915_pci_probe,
    287	.remove		= mt7915_hif_remove,
    288};
    289
    290struct pci_driver mt7915_pci_driver = {
    291	.name		= KBUILD_MODNAME,
    292	.id_table	= mt7915_pci_device_table,
    293	.probe		= mt7915_pci_probe,
    294	.remove		= mt7915_pci_remove,
    295};
    296
    297MODULE_DEVICE_TABLE(pci, mt7915_pci_device_table);
    298MODULE_DEVICE_TABLE(pci, mt7915_hif_device_table);
    299MODULE_FIRMWARE(MT7915_FIRMWARE_WA);
    300MODULE_FIRMWARE(MT7915_FIRMWARE_WM);
    301MODULE_FIRMWARE(MT7915_ROM_PATCH);
    302MODULE_FIRMWARE(MT7916_FIRMWARE_WA);
    303MODULE_FIRMWARE(MT7916_FIRMWARE_WM);
    304MODULE_FIRMWARE(MT7916_ROM_PATCH);