access.c 4.9 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3
#include <linux/pci.h>
#include <linux/module.h>
#include <linux/ioport.h>
4
#include <linux/wait.h>
L
Linus Torvalds 已提交
5

6 7
#include "pci.h"

L
Linus Torvalds 已提交
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
/*
 * This interrupt-safe spinlock protects all accesses to PCI
 * configuration space.
 */

static DEFINE_SPINLOCK(pci_lock);

/*
 *  Wrappers for all PCI configuration access functions.  They just check
 *  alignment, do locking and call the low-level functions pointed to
 *  by pci_dev->ops.
 */

#define PCI_byte_BAD 0
#define PCI_word_BAD (pos & 1)
#define PCI_dword_BAD (pos & 3)

#define PCI_OP_READ(size,type,len) \
int pci_bus_read_config_##size \
	(struct pci_bus *bus, unsigned int devfn, int pos, type *value)	\
{									\
	int res;							\
	unsigned long flags;						\
	u32 data = 0;							\
	if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER;	\
	spin_lock_irqsave(&pci_lock, flags);				\
	res = bus->ops->read(bus, devfn, pos, len, &data);		\
	*value = (type)data;						\
	spin_unlock_irqrestore(&pci_lock, flags);			\
	return res;							\
}

#define PCI_OP_WRITE(size,type,len) \
int pci_bus_write_config_##size \
	(struct pci_bus *bus, unsigned int devfn, int pos, type value)	\
{									\
	int res;							\
	unsigned long flags;						\
	if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER;	\
	spin_lock_irqsave(&pci_lock, flags);				\
	res = bus->ops->write(bus, devfn, pos, len, value);		\
	spin_unlock_irqrestore(&pci_lock, flags);			\
	return res;							\
}

PCI_OP_READ(byte, u8, 1)
PCI_OP_READ(word, u16, 2)
PCI_OP_READ(dword, u32, 4)
PCI_OP_WRITE(byte, u8, 1)
PCI_OP_WRITE(word, u16, 2)
PCI_OP_WRITE(dword, u32, 4)

EXPORT_SYMBOL(pci_bus_read_config_byte);
EXPORT_SYMBOL(pci_bus_read_config_word);
EXPORT_SYMBOL(pci_bus_read_config_dword);
EXPORT_SYMBOL(pci_bus_write_config_byte);
EXPORT_SYMBOL(pci_bus_write_config_word);
EXPORT_SYMBOL(pci_bus_write_config_dword);
66

67 68 69 70 71 72 73 74 75
/*
 * The following routines are to prevent the user from accessing PCI config
 * space when it's unsafe to do so.  Some devices require this during BIST and
 * we're required to prevent it during D-state transitions.
 *
 * We have a bit per device to indicate it's blocked and a global wait queue
 * for callers to sleep on until devices are unblocked.
 */
static DECLARE_WAIT_QUEUE_HEAD(pci_ucfg_wait);
76

77 78 79 80 81 82 83 84 85 86 87 88
static noinline void pci_wait_ucfg(struct pci_dev *dev)
{
	DECLARE_WAITQUEUE(wait, current);

	__add_wait_queue(&pci_ucfg_wait, &wait);
	do {
		set_current_state(TASK_UNINTERRUPTIBLE);
		spin_unlock_irq(&pci_lock);
		schedule();
		spin_lock_irq(&pci_lock);
	} while (dev->block_ucfg_access);
	__remove_wait_queue(&pci_ucfg_wait, &wait);
89 90 91 92 93 94 95 96 97
}

#define PCI_USER_READ_CONFIG(size,type)					\
int pci_user_read_config_##size						\
	(struct pci_dev *dev, int pos, type *val)			\
{									\
	int ret = 0;							\
	u32 data = -1;							\
	if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER;	\
98 99 100
	spin_lock_irq(&pci_lock);					\
	if (unlikely(dev->block_ucfg_access)) pci_wait_ucfg(dev);	\
	ret = dev->bus->ops->read(dev->bus, dev->devfn,			\
101
					pos, sizeof(type), &data);	\
102
	spin_unlock_irq(&pci_lock);					\
103 104 105 106 107 108 109 110 111 112
	*val = (type)data;						\
	return ret;							\
}

#define PCI_USER_WRITE_CONFIG(size,type)				\
int pci_user_write_config_##size					\
	(struct pci_dev *dev, int pos, type val)			\
{									\
	int ret = -EIO;							\
	if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER;	\
113 114 115
	spin_lock_irq(&pci_lock);					\
	if (unlikely(dev->block_ucfg_access)) pci_wait_ucfg(dev);	\
	ret = dev->bus->ops->write(dev->bus, dev->devfn,		\
116
					pos, sizeof(type), val);	\
117
	spin_unlock_irq(&pci_lock);					\
118 119 120 121 122 123 124 125 126 127 128 129 130 131
	return ret;							\
}

PCI_USER_READ_CONFIG(byte, u8)
PCI_USER_READ_CONFIG(word, u16)
PCI_USER_READ_CONFIG(dword, u32)
PCI_USER_WRITE_CONFIG(byte, u8)
PCI_USER_WRITE_CONFIG(word, u16)
PCI_USER_WRITE_CONFIG(dword, u32)

/**
 * pci_block_user_cfg_access - Block userspace PCI config reads/writes
 * @dev:	pci device struct
 *
132 133 134 135
 * When user access is blocked, any reads or writes to config space will
 * sleep until access is unblocked again.  We don't allow nesting of
 * block/unblock calls.
 */
136 137 138
void pci_block_user_cfg_access(struct pci_dev *dev)
{
	unsigned long flags;
139
	int was_blocked;
140 141

	spin_lock_irqsave(&pci_lock, flags);
142
	was_blocked = dev->block_ucfg_access;
143 144
	dev->block_ucfg_access = 1;
	spin_unlock_irqrestore(&pci_lock, flags);
145 146 147 148

	/* If we BUG() inside the pci_lock, we're guaranteed to hose
	 * the machine */
	BUG_ON(was_blocked);
149 150 151 152 153 154 155 156
}
EXPORT_SYMBOL_GPL(pci_block_user_cfg_access);

/**
 * pci_unblock_user_cfg_access - Unblock userspace PCI config reads/writes
 * @dev:	pci device struct
 *
 * This function allows userspace PCI config accesses to resume.
157
 */
158 159 160 161 162
void pci_unblock_user_cfg_access(struct pci_dev *dev)
{
	unsigned long flags;

	spin_lock_irqsave(&pci_lock, flags);
163 164 165 166 167

	/* This indicates a problem in the caller, but we don't need
	 * to kill them, unlike a double-block above. */
	WARN_ON(!dev->block_ucfg_access);

168
	dev->block_ucfg_access = 0;
169
	wake_up_all(&pci_ucfg_wait);
170 171 172
	spin_unlock_irqrestore(&pci_lock, flags);
}
EXPORT_SYMBOL_GPL(pci_unblock_user_cfg_access);