diff options
Diffstat (limited to 'drivers/pci/msi.h')
-rw-r--r-- | drivers/pci/msi.h | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h new file mode 100644 index 000000000000..bef21ae3cbd0 --- /dev/null +++ b/drivers/pci/msi.h | |||
@@ -0,0 +1,159 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003-2004 Intel | ||
3 | * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com) | ||
4 | */ | ||
5 | |||
6 | #ifndef MSI_H | ||
7 | #define MSI_H | ||
8 | |||
9 | #include <asm/msi.h> | ||
10 | |||
11 | /* | ||
12 | * Assume the maximum number of hot plug slots supported by the system is about | ||
13 | * ten. The worstcase is that each of these slots is hot-added with a device, | ||
14 | * which has two MSI/MSI-X capable functions. To avoid any MSI-X driver, which | ||
15 | * attempts to request all available vectors, NR_HP_RESERVED_VECTORS is defined | ||
16 | * as below to ensure at least one message is assigned to each detected MSI/ | ||
17 | * MSI-X device function. | ||
18 | */ | ||
19 | #define NR_HP_RESERVED_VECTORS 20 | ||
20 | |||
21 | extern int vector_irq[NR_VECTORS]; | ||
22 | extern cpumask_t pending_irq_balance_cpumask[NR_IRQS]; | ||
23 | extern void (*interrupt[NR_IRQS])(void); | ||
24 | extern int pci_vector_resources(int last, int nr_released); | ||
25 | |||
26 | #ifdef CONFIG_SMP | ||
27 | #define set_msi_irq_affinity set_msi_affinity | ||
28 | #else | ||
29 | #define set_msi_irq_affinity NULL | ||
30 | #endif | ||
31 | |||
32 | #ifndef CONFIG_IRQBALANCE | ||
33 | static inline void move_msi(int vector) {} | ||
34 | #endif | ||
35 | |||
36 | /* | ||
37 | * MSI-X Address Register | ||
38 | */ | ||
39 | #define PCI_MSIX_FLAGS_QSIZE 0x7FF | ||
40 | #define PCI_MSIX_FLAGS_ENABLE (1 << 15) | ||
41 | #define PCI_MSIX_FLAGS_BIRMASK (7 << 0) | ||
42 | #define PCI_MSIX_FLAGS_BITMASK (1 << 0) | ||
43 | |||
44 | #define PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET 0 | ||
45 | #define PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET 4 | ||
46 | #define PCI_MSIX_ENTRY_DATA_OFFSET 8 | ||
47 | #define PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET 12 | ||
48 | #define PCI_MSIX_ENTRY_SIZE 16 | ||
49 | |||
50 | #define msi_control_reg(base) (base + PCI_MSI_FLAGS) | ||
51 | #define msi_lower_address_reg(base) (base + PCI_MSI_ADDRESS_LO) | ||
52 | #define msi_upper_address_reg(base) (base + PCI_MSI_ADDRESS_HI) | ||
53 | #define msi_data_reg(base, is64bit) \ | ||
54 | ( (is64bit == 1) ? base+PCI_MSI_DATA_64 : base+PCI_MSI_DATA_32 ) | ||
55 | #define msi_mask_bits_reg(base, is64bit) \ | ||
56 | ( (is64bit == 1) ? base+PCI_MSI_MASK_BIT : base+PCI_MSI_MASK_BIT-4) | ||
57 | #define msi_disable(control) control &= ~PCI_MSI_FLAGS_ENABLE | ||
58 | #define multi_msi_capable(control) \ | ||
59 | (1 << ((control & PCI_MSI_FLAGS_QMASK) >> 1)) | ||
60 | #define multi_msi_enable(control, num) \ | ||
61 | control |= (((num >> 1) << 4) & PCI_MSI_FLAGS_QSIZE); | ||
62 | #define is_64bit_address(control) (control & PCI_MSI_FLAGS_64BIT) | ||
63 | #define is_mask_bit_support(control) (control & PCI_MSI_FLAGS_MASKBIT) | ||
64 | #define msi_enable(control, num) multi_msi_enable(control, num); \ | ||
65 | control |= PCI_MSI_FLAGS_ENABLE | ||
66 | |||
67 | #define msix_control_reg msi_control_reg | ||
68 | #define msix_table_offset_reg(base) (base + 0x04) | ||
69 | #define msix_pba_offset_reg(base) (base + 0x08) | ||
70 | #define msix_enable(control) control |= PCI_MSIX_FLAGS_ENABLE | ||
71 | #define msix_disable(control) control &= ~PCI_MSIX_FLAGS_ENABLE | ||
72 | #define msix_table_size(control) ((control & PCI_MSIX_FLAGS_QSIZE)+1) | ||
73 | #define multi_msix_capable msix_table_size | ||
74 | #define msix_unmask(address) (address & ~PCI_MSIX_FLAGS_BITMASK) | ||
75 | #define msix_mask(address) (address | PCI_MSIX_FLAGS_BITMASK) | ||
76 | #define msix_is_pending(address) (address & PCI_MSIX_FLAGS_PENDMASK) | ||
77 | |||
78 | /* | ||
79 | * MSI Defined Data Structures | ||
80 | */ | ||
81 | #define MSI_ADDRESS_HEADER 0xfee | ||
82 | #define MSI_ADDRESS_HEADER_SHIFT 12 | ||
83 | #define MSI_ADDRESS_HEADER_MASK 0xfff000 | ||
84 | #define MSI_ADDRESS_DEST_ID_MASK 0xfff0000f | ||
85 | #define MSI_TARGET_CPU_MASK 0xff | ||
86 | #define MSI_DELIVERY_MODE 0 | ||
87 | #define MSI_LEVEL_MODE 1 /* Edge always assert */ | ||
88 | #define MSI_TRIGGER_MODE 0 /* MSI is edge sensitive */ | ||
89 | #define MSI_PHYSICAL_MODE 0 | ||
90 | #define MSI_LOGICAL_MODE 1 | ||
91 | #define MSI_REDIRECTION_HINT_MODE 0 | ||
92 | |||
93 | struct msg_data { | ||
94 | #if defined(__LITTLE_ENDIAN_BITFIELD) | ||
95 | __u32 vector : 8; | ||
96 | __u32 delivery_mode : 3; /* 000b: FIXED | 001b: lowest prior */ | ||
97 | __u32 reserved_1 : 3; | ||
98 | __u32 level : 1; /* 0: deassert | 1: assert */ | ||
99 | __u32 trigger : 1; /* 0: edge | 1: level */ | ||
100 | __u32 reserved_2 : 16; | ||
101 | #elif defined(__BIG_ENDIAN_BITFIELD) | ||
102 | __u32 reserved_2 : 16; | ||
103 | __u32 trigger : 1; /* 0: edge | 1: level */ | ||
104 | __u32 level : 1; /* 0: deassert | 1: assert */ | ||
105 | __u32 reserved_1 : 3; | ||
106 | __u32 delivery_mode : 3; /* 000b: FIXED | 001b: lowest prior */ | ||
107 | __u32 vector : 8; | ||
108 | #else | ||
109 | #error "Bitfield endianness not defined! Check your byteorder.h" | ||
110 | #endif | ||
111 | } __attribute__ ((packed)); | ||
112 | |||
113 | struct msg_address { | ||
114 | union { | ||
115 | struct { | ||
116 | #if defined(__LITTLE_ENDIAN_BITFIELD) | ||
117 | __u32 reserved_1 : 2; | ||
118 | __u32 dest_mode : 1; /*0:physic | 1:logic */ | ||
119 | __u32 redirection_hint: 1; /*0: dedicated CPU | ||
120 | 1: lowest priority */ | ||
121 | __u32 reserved_2 : 4; | ||
122 | __u32 dest_id : 24; /* Destination ID */ | ||
123 | #elif defined(__BIG_ENDIAN_BITFIELD) | ||
124 | __u32 dest_id : 24; /* Destination ID */ | ||
125 | __u32 reserved_2 : 4; | ||
126 | __u32 redirection_hint: 1; /*0: dedicated CPU | ||
127 | 1: lowest priority */ | ||
128 | __u32 dest_mode : 1; /*0:physic | 1:logic */ | ||
129 | __u32 reserved_1 : 2; | ||
130 | #else | ||
131 | #error "Bitfield endianness not defined! Check your byteorder.h" | ||
132 | #endif | ||
133 | }u; | ||
134 | __u32 value; | ||
135 | }lo_address; | ||
136 | __u32 hi_address; | ||
137 | } __attribute__ ((packed)); | ||
138 | |||
139 | struct msi_desc { | ||
140 | struct { | ||
141 | __u8 type : 5; /* {0: unused, 5h:MSI, 11h:MSI-X} */ | ||
142 | __u8 maskbit : 1; /* mask-pending bit supported ? */ | ||
143 | __u8 state : 1; /* {0: free, 1: busy} */ | ||
144 | __u8 reserved: 1; /* reserved */ | ||
145 | __u8 entry_nr; /* specific enabled entry */ | ||
146 | __u8 default_vector; /* default pre-assigned vector */ | ||
147 | __u8 current_cpu; /* current destination cpu */ | ||
148 | }msi_attrib; | ||
149 | |||
150 | struct { | ||
151 | __u16 head; | ||
152 | __u16 tail; | ||
153 | }link; | ||
154 | |||
155 | void __iomem *mask_base; | ||
156 | struct pci_dev *dev; | ||
157 | }; | ||
158 | |||
159 | #endif /* MSI_H */ | ||