OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [pci/] [access.c] - Blame information for rev 78

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
#include <linux/pci.h>
2
#include <linux/module.h>
3
#include <linux/sched.h>
4
#include <linux/ioport.h>
5
#include <linux/wait.h>
6
 
7
#include "pci.h"
8
 
9
/*
10
 * This interrupt-safe spinlock protects all accesses to PCI
11
 * configuration space.
12
 */
13
 
14
static DEFINE_SPINLOCK(pci_lock);
15
 
16
/*
17
 *  Wrappers for all PCI configuration access functions.  They just check
18
 *  alignment, do locking and call the low-level functions pointed to
19
 *  by pci_dev->ops.
20
 */
21
 
22
#define PCI_byte_BAD 0
23
#define PCI_word_BAD (pos & 1)
24
#define PCI_dword_BAD (pos & 3)
25
 
26
#define PCI_OP_READ(size,type,len) \
27
int pci_bus_read_config_##size \
28
        (struct pci_bus *bus, unsigned int devfn, int pos, type *value) \
29
{                                                                       \
30
        int res;                                                        \
31
        unsigned long flags;                                            \
32
        u32 data = 0;                                                    \
33
        if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER;       \
34
        spin_lock_irqsave(&pci_lock, flags);                            \
35
        res = bus->ops->read(bus, devfn, pos, len, &data);              \
36
        *value = (type)data;                                            \
37
        spin_unlock_irqrestore(&pci_lock, flags);                       \
38
        return res;                                                     \
39
}
40
 
41
#define PCI_OP_WRITE(size,type,len) \
42
int pci_bus_write_config_##size \
43
        (struct pci_bus *bus, unsigned int devfn, int pos, type value)  \
44
{                                                                       \
45
        int res;                                                        \
46
        unsigned long flags;                                            \
47
        if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER;       \
48
        spin_lock_irqsave(&pci_lock, flags);                            \
49
        res = bus->ops->write(bus, devfn, pos, len, value);             \
50
        spin_unlock_irqrestore(&pci_lock, flags);                       \
51
        return res;                                                     \
52
}
53
 
54
PCI_OP_READ(byte, u8, 1)
55
PCI_OP_READ(word, u16, 2)
56
PCI_OP_READ(dword, u32, 4)
57
PCI_OP_WRITE(byte, u8, 1)
58
PCI_OP_WRITE(word, u16, 2)
59
PCI_OP_WRITE(dword, u32, 4)
60
 
61
EXPORT_SYMBOL(pci_bus_read_config_byte);
62
EXPORT_SYMBOL(pci_bus_read_config_word);
63
EXPORT_SYMBOL(pci_bus_read_config_dword);
64
EXPORT_SYMBOL(pci_bus_write_config_byte);
65
EXPORT_SYMBOL(pci_bus_write_config_word);
66
EXPORT_SYMBOL(pci_bus_write_config_dword);
67
 
68
/*
69
 * The following routines are to prevent the user from accessing PCI config
70
 * space when it's unsafe to do so.  Some devices require this during BIST and
71
 * we're required to prevent it during D-state transitions.
72
 *
73
 * We have a bit per device to indicate it's blocked and a global wait queue
74
 * for callers to sleep on until devices are unblocked.
75
 */
76
static DECLARE_WAIT_QUEUE_HEAD(pci_ucfg_wait);
77
 
78
static noinline void pci_wait_ucfg(struct pci_dev *dev)
79
{
80
        DECLARE_WAITQUEUE(wait, current);
81
 
82
        __add_wait_queue(&pci_ucfg_wait, &wait);
83
        do {
84
                set_current_state(TASK_UNINTERRUPTIBLE);
85
                spin_unlock_irq(&pci_lock);
86
                schedule();
87
                spin_lock_irq(&pci_lock);
88
        } while (dev->block_ucfg_access);
89
        __remove_wait_queue(&pci_ucfg_wait, &wait);
90
}
91
 
92
#define PCI_USER_READ_CONFIG(size,type)                                 \
93
int pci_user_read_config_##size                                         \
94
        (struct pci_dev *dev, int pos, type *val)                       \
95
{                                                                       \
96
        int ret = 0;                                                     \
97
        u32 data = -1;                                                  \
98
        if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER;       \
99
        spin_lock_irq(&pci_lock);                                       \
100
        if (unlikely(dev->block_ucfg_access)) pci_wait_ucfg(dev);       \
101
        ret = dev->bus->ops->read(dev->bus, dev->devfn,                 \
102
                                        pos, sizeof(type), &data);      \
103
        spin_unlock_irq(&pci_lock);                                     \
104
        *val = (type)data;                                              \
105
        return ret;                                                     \
106
}
107
 
108
#define PCI_USER_WRITE_CONFIG(size,type)                                \
109
int pci_user_write_config_##size                                        \
110
        (struct pci_dev *dev, int pos, type val)                        \
111
{                                                                       \
112
        int ret = -EIO;                                                 \
113
        if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER;       \
114
        spin_lock_irq(&pci_lock);                                       \
115
        if (unlikely(dev->block_ucfg_access)) pci_wait_ucfg(dev);       \
116
        ret = dev->bus->ops->write(dev->bus, dev->devfn,                \
117
                                        pos, sizeof(type), val);        \
118
        spin_unlock_irq(&pci_lock);                                     \
119
        return ret;                                                     \
120
}
121
 
122
PCI_USER_READ_CONFIG(byte, u8)
123
PCI_USER_READ_CONFIG(word, u16)
124
PCI_USER_READ_CONFIG(dword, u32)
125
PCI_USER_WRITE_CONFIG(byte, u8)
126
PCI_USER_WRITE_CONFIG(word, u16)
127
PCI_USER_WRITE_CONFIG(dword, u32)
128
 
129
/**
130
 * pci_block_user_cfg_access - Block userspace PCI config reads/writes
131
 * @dev:        pci device struct
132
 *
133
 * When user access is blocked, any reads or writes to config space will
134
 * sleep until access is unblocked again.  We don't allow nesting of
135
 * block/unblock calls.
136
 */
137
void pci_block_user_cfg_access(struct pci_dev *dev)
138
{
139
        unsigned long flags;
140
        int was_blocked;
141
 
142
        spin_lock_irqsave(&pci_lock, flags);
143
        was_blocked = dev->block_ucfg_access;
144
        dev->block_ucfg_access = 1;
145
        spin_unlock_irqrestore(&pci_lock, flags);
146
 
147
        /* If we BUG() inside the pci_lock, we're guaranteed to hose
148
         * the machine */
149
        BUG_ON(was_blocked);
150
}
151
EXPORT_SYMBOL_GPL(pci_block_user_cfg_access);
152
 
153
/**
154
 * pci_unblock_user_cfg_access - Unblock userspace PCI config reads/writes
155
 * @dev:        pci device struct
156
 *
157
 * This function allows userspace PCI config accesses to resume.
158
 */
159
void pci_unblock_user_cfg_access(struct pci_dev *dev)
160
{
161
        unsigned long flags;
162
 
163
        spin_lock_irqsave(&pci_lock, flags);
164
 
165
        /* This indicates a problem in the caller, but we don't need
166
         * to kill them, unlike a double-block above. */
167
        WARN_ON(!dev->block_ucfg_access);
168
 
169
        dev->block_ucfg_access = 0;
170
        wake_up_all(&pci_ucfg_wait);
171
        spin_unlock_irqrestore(&pci_lock, flags);
172
}
173
EXPORT_SYMBOL_GPL(pci_unblock_user_cfg_access);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.