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

cardbus.c (2867B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * cardbus.c -- 16-bit PCMCIA core support
      4 *
      5 * The initial developer of the original code is David A. Hinds
      6 * <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
      7 * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
      8 *
      9 * (C) 1999		David A. Hinds
     10 */
     11
     12/*
     13 * Cardbus handling has been re-written to be more of a PCI bridge thing,
     14 * and the PCI code basically does all the resource handling.
     15 *
     16 *		Linus, Jan 2000
     17 */
     18
     19
     20#include <linux/kernel.h>
     21#include <linux/module.h>
     22#include <linux/pci.h>
     23
     24#include <pcmcia/ss.h>
     25#include <pcmcia/cistpl.h>
     26
     27#include "cs_internal.h"
     28
     29static void cardbus_config_irq_and_cls(struct pci_bus *bus, int irq)
     30{
     31	struct pci_dev *dev;
     32
     33	list_for_each_entry(dev, &bus->devices, bus_list) {
     34		u8 irq_pin;
     35
     36		/*
     37		 * Since there is only one interrupt available to
     38		 * CardBus devices, all devices downstream of this
     39		 * device must be using this IRQ.
     40		 */
     41		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq_pin);
     42		if (irq_pin) {
     43			dev->irq = irq;
     44			pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
     45		}
     46
     47		/*
     48		 * Some controllers transfer very slowly with 0 CLS.
     49		 * Configure it.  This may fail as CLS configuration
     50		 * is mandatory only for MWI.
     51		 */
     52		pci_set_cacheline_size(dev);
     53
     54		if (dev->subordinate)
     55			cardbus_config_irq_and_cls(dev->subordinate, irq);
     56	}
     57}
     58
     59/**
     60 * cb_alloc() - add CardBus device
     61 * @s:		the pcmcia_socket where the CardBus device is located
     62 *
     63 * cb_alloc() allocates the kernel data structures for a Cardbus device
     64 * and handles the lowest level PCI device setup issues.
     65 */
     66int __ref cb_alloc(struct pcmcia_socket *s)
     67{
     68	struct pci_bus *bus = s->cb_dev->subordinate;
     69	struct pci_dev *dev;
     70	unsigned int max, pass;
     71
     72	pci_lock_rescan_remove();
     73
     74	s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0));
     75	pci_fixup_cardbus(bus);
     76
     77	max = bus->busn_res.start;
     78	for (pass = 0; pass < 2; pass++)
     79		for_each_pci_bridge(dev, bus)
     80			max = pci_scan_bridge(bus, dev, max, pass);
     81
     82	/*
     83	 * Size all resources below the CardBus controller.
     84	 */
     85	pci_bus_size_bridges(bus);
     86	pci_bus_assign_resources(bus);
     87	cardbus_config_irq_and_cls(bus, s->pci_irq);
     88
     89	/* socket specific tune function */
     90	if (s->tune_bridge)
     91		s->tune_bridge(s, bus);
     92
     93	pci_bus_add_devices(bus);
     94
     95	pci_unlock_rescan_remove();
     96	return 0;
     97}
     98
     99/**
    100 * cb_free() - remove CardBus device
    101 * @s:		the pcmcia_socket where the CardBus device was located
    102 *
    103 * cb_free() handles the lowest level PCI device cleanup.
    104 */
    105void cb_free(struct pcmcia_socket *s)
    106{
    107	struct pci_dev *bridge, *dev, *tmp;
    108	struct pci_bus *bus;
    109
    110	bridge = s->cb_dev;
    111	if (!bridge)
    112		return;
    113
    114	bus = bridge->subordinate;
    115	if (!bus)
    116		return;
    117
    118	pci_lock_rescan_remove();
    119
    120	list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list)
    121		pci_stop_and_remove_bus_device(dev);
    122
    123	pci_unlock_rescan_remove();
    124}