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

hostap_pci.c (10707B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2#define PRISM2_PCI
      3
      4/* Host AP driver's support for Intersil Prism2.5 PCI cards is based on
      5 * driver patches from Reyk Floeter <reyk@vantronix.net> and
      6 * Andy Warner <andyw@pobox.com> */
      7
      8#include <linux/module.h>
      9#include <linux/if.h>
     10#include <linux/skbuff.h>
     11#include <linux/netdevice.h>
     12#include <linux/slab.h>
     13#include <linux/workqueue.h>
     14#include <linux/wireless.h>
     15#include <net/iw_handler.h>
     16
     17#include <linux/ioport.h>
     18#include <linux/pci.h>
     19#include <asm/io.h>
     20
     21#include "hostap_wlan.h"
     22
     23
     24static char *dev_info = "hostap_pci";
     25
     26
     27MODULE_AUTHOR("Jouni Malinen");
     28MODULE_DESCRIPTION("Support for Intersil Prism2.5-based 802.11 wireless LAN "
     29		   "PCI cards.");
     30MODULE_LICENSE("GPL");
     31
     32
     33/* struct local_info::hw_priv */
     34struct hostap_pci_priv {
     35	void __iomem *mem_start;
     36};
     37
     38
     39/* FIX: do we need mb/wmb/rmb with memory operations? */
     40
     41
     42static const struct pci_device_id prism2_pci_id_table[] = {
     43	/* Intersil Prism3 ISL3872 11Mb/s WLAN Controller */
     44	{ 0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID },
     45	/* Intersil Prism2.5 ISL3874 11Mb/s WLAN Controller */
     46	{ 0x1260, 0x3873, PCI_ANY_ID, PCI_ANY_ID },
     47	/* Samsung MagicLAN SWL-2210P */
     48	{ 0x167d, 0xa000, PCI_ANY_ID, PCI_ANY_ID },
     49	{ 0 }
     50};
     51
     52
     53#ifdef PRISM2_IO_DEBUG
     54
     55static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v)
     56{
     57	struct hostap_interface *iface;
     58	struct hostap_pci_priv *hw_priv;
     59	local_info_t *local;
     60	unsigned long flags;
     61
     62	iface = netdev_priv(dev);
     63	local = iface->local;
     64	hw_priv = local->hw_priv;
     65
     66	spin_lock_irqsave(&local->lock, flags);
     67	prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTB, a, v);
     68	writeb(v, hw_priv->mem_start + a);
     69	spin_unlock_irqrestore(&local->lock, flags);
     70}
     71
     72static inline u8 hfa384x_inb_debug(struct net_device *dev, int a)
     73{
     74	struct hostap_interface *iface;
     75	struct hostap_pci_priv *hw_priv;
     76	local_info_t *local;
     77	unsigned long flags;
     78	u8 v;
     79
     80	iface = netdev_priv(dev);
     81	local = iface->local;
     82	hw_priv = local->hw_priv;
     83
     84	spin_lock_irqsave(&local->lock, flags);
     85	v = readb(hw_priv->mem_start + a);
     86	prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INB, a, v);
     87	spin_unlock_irqrestore(&local->lock, flags);
     88	return v;
     89}
     90
     91static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v)
     92{
     93	struct hostap_interface *iface;
     94	struct hostap_pci_priv *hw_priv;
     95	local_info_t *local;
     96	unsigned long flags;
     97
     98	iface = netdev_priv(dev);
     99	local = iface->local;
    100	hw_priv = local->hw_priv;
    101
    102	spin_lock_irqsave(&local->lock, flags);
    103	prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTW, a, v);
    104	writew(v, hw_priv->mem_start + a);
    105	spin_unlock_irqrestore(&local->lock, flags);
    106}
    107
    108static inline u16 hfa384x_inw_debug(struct net_device *dev, int a)
    109{
    110	struct hostap_interface *iface;
    111	struct hostap_pci_priv *hw_priv;
    112	local_info_t *local;
    113	unsigned long flags;
    114	u16 v;
    115
    116	iface = netdev_priv(dev);
    117	local = iface->local;
    118	hw_priv = local->hw_priv;
    119
    120	spin_lock_irqsave(&local->lock, flags);
    121	v = readw(hw_priv->mem_start + a);
    122	prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INW, a, v);
    123	spin_unlock_irqrestore(&local->lock, flags);
    124	return v;
    125}
    126
    127#define HFA384X_OUTB(v,a) hfa384x_outb_debug(dev, (a), (v))
    128#define HFA384X_INB(a) hfa384x_inb_debug(dev, (a))
    129#define HFA384X_OUTW(v,a) hfa384x_outw_debug(dev, (a), (v))
    130#define HFA384X_INW(a) hfa384x_inw_debug(dev, (a))
    131#define HFA384X_OUTW_DATA(v,a) hfa384x_outw_debug(dev, (a), le16_to_cpu((v)))
    132#define HFA384X_INW_DATA(a) cpu_to_le16(hfa384x_inw_debug(dev, (a)))
    133
    134#else /* PRISM2_IO_DEBUG */
    135
    136static inline void hfa384x_outb(struct net_device *dev, int a, u8 v)
    137{
    138	struct hostap_interface *iface;
    139	struct hostap_pci_priv *hw_priv;
    140	iface = netdev_priv(dev);
    141	hw_priv = iface->local->hw_priv;
    142	writeb(v, hw_priv->mem_start + a);
    143}
    144
    145static inline u8 hfa384x_inb(struct net_device *dev, int a)
    146{
    147	struct hostap_interface *iface;
    148	struct hostap_pci_priv *hw_priv;
    149	iface = netdev_priv(dev);
    150	hw_priv = iface->local->hw_priv;
    151	return readb(hw_priv->mem_start + a);
    152}
    153
    154static inline void hfa384x_outw(struct net_device *dev, int a, u16 v)
    155{
    156	struct hostap_interface *iface;
    157	struct hostap_pci_priv *hw_priv;
    158	iface = netdev_priv(dev);
    159	hw_priv = iface->local->hw_priv;
    160	writew(v, hw_priv->mem_start + a);
    161}
    162
    163static inline u16 hfa384x_inw(struct net_device *dev, int a)
    164{
    165	struct hostap_interface *iface;
    166	struct hostap_pci_priv *hw_priv;
    167	iface = netdev_priv(dev);
    168	hw_priv = iface->local->hw_priv;
    169	return readw(hw_priv->mem_start + a);
    170}
    171
    172#define HFA384X_OUTB(v,a) hfa384x_outb(dev, (a), (v))
    173#define HFA384X_INB(a) hfa384x_inb(dev, (a))
    174#define HFA384X_OUTW(v,a) hfa384x_outw(dev, (a), (v))
    175#define HFA384X_INW(a) hfa384x_inw(dev, (a))
    176#define HFA384X_OUTW_DATA(v,a) hfa384x_outw(dev, (a), le16_to_cpu((v)))
    177#define HFA384X_INW_DATA(a) cpu_to_le16(hfa384x_inw(dev, (a)))
    178
    179#endif /* PRISM2_IO_DEBUG */
    180
    181
    182static int hfa384x_from_bap(struct net_device *dev, u16 bap, void *buf,
    183			    int len)
    184{
    185	u16 d_off;
    186	__le16 *pos;
    187
    188	d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF;
    189	pos = (__le16 *) buf;
    190
    191	for ( ; len > 1; len -= 2)
    192		*pos++ = HFA384X_INW_DATA(d_off);
    193
    194	if (len & 1)
    195		*((char *) pos) = HFA384X_INB(d_off);
    196
    197	return 0;
    198}
    199
    200
    201static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len)
    202{
    203	u16 d_off;
    204	__le16 *pos;
    205
    206	d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF;
    207	pos = (__le16 *) buf;
    208
    209	for ( ; len > 1; len -= 2)
    210		HFA384X_OUTW_DATA(*pos++, d_off);
    211
    212	if (len & 1)
    213		HFA384X_OUTB(*((char *) pos), d_off);
    214
    215	return 0;
    216}
    217
    218
    219/* FIX: This might change at some point.. */
    220#include "hostap_hw.c"
    221
    222static void prism2_pci_cor_sreset(local_info_t *local)
    223{
    224	struct net_device *dev = local->dev;
    225	u16 reg;
    226
    227	reg = HFA384X_INB(HFA384X_PCICOR_OFF);
    228	printk(KERN_DEBUG "%s: Original COR value: 0x%0x\n", dev->name, reg);
    229
    230	/* linux-wlan-ng uses extremely long hold and settle times for
    231	 * COR sreset. A comment in the driver code mentions that the long
    232	 * delays appear to be necessary. However, at least IBM 22P6901 seems
    233	 * to work fine with shorter delays.
    234	 *
    235	 * Longer delays can be configured by uncommenting following line: */
    236/* #define PRISM2_PCI_USE_LONG_DELAYS */
    237
    238#ifdef PRISM2_PCI_USE_LONG_DELAYS
    239	int i;
    240
    241	HFA384X_OUTW(reg | 0x0080, HFA384X_PCICOR_OFF);
    242	mdelay(250);
    243
    244	HFA384X_OUTW(reg & ~0x0080, HFA384X_PCICOR_OFF);
    245	mdelay(500);
    246
    247	/* Wait for f/w to complete initialization (CMD:BUSY == 0) */
    248	i = 2000000 / 10;
    249	while ((HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY) && --i)
    250		udelay(10);
    251
    252#else /* PRISM2_PCI_USE_LONG_DELAYS */
    253
    254	HFA384X_OUTW(reg | 0x0080, HFA384X_PCICOR_OFF);
    255	mdelay(2);
    256	HFA384X_OUTW(reg & ~0x0080, HFA384X_PCICOR_OFF);
    257	mdelay(2);
    258
    259#endif /* PRISM2_PCI_USE_LONG_DELAYS */
    260
    261	if (HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY) {
    262		printk(KERN_DEBUG "%s: COR sreset timeout\n", dev->name);
    263	}
    264}
    265
    266
    267static void prism2_pci_genesis_reset(local_info_t *local, int hcr)
    268{
    269	struct net_device *dev = local->dev;
    270
    271	HFA384X_OUTW(0x00C5, HFA384X_PCICOR_OFF);
    272	mdelay(10);
    273	HFA384X_OUTW(hcr, HFA384X_PCIHCR_OFF);
    274	mdelay(10);
    275	HFA384X_OUTW(0x0045, HFA384X_PCICOR_OFF);
    276	mdelay(10);
    277}
    278
    279
    280static struct prism2_helper_functions prism2_pci_funcs =
    281{
    282	.card_present	= NULL,
    283	.cor_sreset	= prism2_pci_cor_sreset,
    284	.genesis_reset	= prism2_pci_genesis_reset,
    285	.hw_type	= HOSTAP_HW_PCI,
    286};
    287
    288
    289static int prism2_pci_probe(struct pci_dev *pdev,
    290			    const struct pci_device_id *id)
    291{
    292	unsigned long phymem;
    293	void __iomem *mem = NULL;
    294	local_info_t *local = NULL;
    295	struct net_device *dev = NULL;
    296	static int cards_found /* = 0 */;
    297	int irq_registered = 0;
    298	struct hostap_interface *iface;
    299	struct hostap_pci_priv *hw_priv;
    300
    301	hw_priv = kzalloc(sizeof(*hw_priv), GFP_KERNEL);
    302	if (hw_priv == NULL)
    303		return -ENOMEM;
    304
    305	if (pci_enable_device(pdev))
    306		goto err_out_free;
    307
    308	phymem = pci_resource_start(pdev, 0);
    309
    310	if (!request_mem_region(phymem, pci_resource_len(pdev, 0), "Prism2")) {
    311		printk(KERN_ERR "prism2: Cannot reserve PCI memory region\n");
    312		goto err_out_disable;
    313	}
    314
    315	mem = pci_ioremap_bar(pdev, 0);
    316	if (mem == NULL) {
    317		printk(KERN_ERR "prism2: Cannot remap PCI memory region\n") ;
    318		goto fail;
    319	}
    320
    321	dev = prism2_init_local_data(&prism2_pci_funcs, cards_found,
    322				     &pdev->dev);
    323	if (dev == NULL)
    324		goto fail;
    325	iface = netdev_priv(dev);
    326	local = iface->local;
    327	local->hw_priv = hw_priv;
    328	cards_found++;
    329
    330        dev->irq = pdev->irq;
    331        hw_priv->mem_start = mem;
    332	dev->base_addr = (unsigned long) mem;
    333
    334	prism2_pci_cor_sreset(local);
    335
    336	pci_set_drvdata(pdev, dev);
    337
    338	if (request_irq(dev->irq, prism2_interrupt, IRQF_SHARED, dev->name,
    339			dev)) {
    340		printk(KERN_WARNING "%s: request_irq failed\n", dev->name);
    341		goto fail;
    342	} else
    343		irq_registered = 1;
    344
    345	if (!local->pri_only && prism2_hw_config(dev, 1)) {
    346		printk(KERN_DEBUG "%s: hardware initialization failed\n",
    347		       dev_info);
    348		goto fail;
    349	}
    350
    351	printk(KERN_INFO "%s: Intersil Prism2.5 PCI: "
    352	       "mem=0x%lx, irq=%d\n", dev->name, phymem, dev->irq);
    353
    354	return hostap_hw_ready(dev);
    355
    356 fail:
    357	if (irq_registered && dev)
    358		free_irq(dev->irq, dev);
    359
    360	if (mem)
    361		iounmap(mem);
    362
    363	release_mem_region(phymem, pci_resource_len(pdev, 0));
    364
    365 err_out_disable:
    366	pci_disable_device(pdev);
    367	prism2_free_local_data(dev);
    368
    369 err_out_free:
    370	kfree(hw_priv);
    371
    372	return -ENODEV;
    373}
    374
    375
    376static void prism2_pci_remove(struct pci_dev *pdev)
    377{
    378	struct net_device *dev;
    379	struct hostap_interface *iface;
    380	void __iomem *mem_start;
    381	struct hostap_pci_priv *hw_priv;
    382
    383	dev = pci_get_drvdata(pdev);
    384	iface = netdev_priv(dev);
    385	hw_priv = iface->local->hw_priv;
    386
    387	/* Reset the hardware, and ensure interrupts are disabled. */
    388	prism2_pci_cor_sreset(iface->local);
    389	hfa384x_disable_interrupts(dev);
    390
    391	if (dev->irq)
    392		free_irq(dev->irq, dev);
    393
    394	mem_start = hw_priv->mem_start;
    395	prism2_free_local_data(dev);
    396	kfree(hw_priv);
    397
    398	iounmap(mem_start);
    399
    400	release_mem_region(pci_resource_start(pdev, 0),
    401			   pci_resource_len(pdev, 0));
    402	pci_disable_device(pdev);
    403}
    404
    405static int __maybe_unused prism2_pci_suspend(struct device *dev_d)
    406{
    407	struct net_device *dev = dev_get_drvdata(dev_d);
    408
    409	if (netif_running(dev)) {
    410		netif_stop_queue(dev);
    411		netif_device_detach(dev);
    412	}
    413	prism2_suspend(dev);
    414
    415	return 0;
    416}
    417
    418static int __maybe_unused prism2_pci_resume(struct device *dev_d)
    419{
    420	struct net_device *dev = dev_get_drvdata(dev_d);
    421
    422	prism2_hw_config(dev, 0);
    423	if (netif_running(dev)) {
    424		netif_device_attach(dev);
    425		netif_start_queue(dev);
    426	}
    427
    428	return 0;
    429}
    430
    431MODULE_DEVICE_TABLE(pci, prism2_pci_id_table);
    432
    433static SIMPLE_DEV_PM_OPS(prism2_pci_pm_ops,
    434			 prism2_pci_suspend,
    435			 prism2_pci_resume);
    436
    437static struct pci_driver prism2_pci_driver = {
    438	.name		= "hostap_pci",
    439	.id_table	= prism2_pci_id_table,
    440	.probe		= prism2_pci_probe,
    441	.remove		= prism2_pci_remove,
    442	.driver.pm	= &prism2_pci_pm_ops,
    443};
    444
    445module_pci_driver(prism2_pci_driver);