Commit | Line | Data |
---|---|---|
12d00cad BH |
1 | /**************************************************************************** |
2 | * Driver for Solarflare Solarstorm network controllers and boards | |
3 | * Copyright 2005-2006 Fen Systems Ltd. | |
4 | * Copyright 2006-2009 Solarflare Communications Inc. | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify it | |
7 | * under the terms of the GNU General Public License version 2 as published | |
8 | * by the Free Software Foundation, incorporated herein by reference. | |
9 | */ | |
10 | ||
11 | #ifndef EFX_IO_H | |
12 | #define EFX_IO_H | |
13 | ||
14 | #include <linux/io.h> | |
15 | #include <linux/spinlock.h> | |
16 | ||
17 | /************************************************************************** | |
18 | * | |
19 | * NIC register I/O | |
20 | * | |
21 | ************************************************************************** | |
22 | * | |
23 | * Notes on locking strategy: | |
24 | * | |
25 | * Most NIC registers require 16-byte (or 8-byte, for SRAM) atomic writes | |
26 | * which necessitates locking. | |
27 | * Under normal operation few writes to NIC registers are made and these | |
28 | * registers (EVQ_RPTR_REG, RX_DESC_UPD_REG and TX_DESC_UPD_REG) are special | |
29 | * cased to allow 4-byte (hence lockless) accesses. | |
30 | * | |
31 | * It *is* safe to write to these 4-byte registers in the middle of an | |
32 | * access to an 8-byte or 16-byte register. We therefore use a | |
33 | * spinlock to protect accesses to the larger registers, but no locks | |
34 | * for the 4-byte registers. | |
35 | * | |
36 | * A write barrier is needed to ensure that DW3 is written after DW0/1/2 | |
37 | * due to the way the 16byte registers are "collected" in the BIU. | |
38 | * | |
39 | * We also lock when carrying out reads, to ensure consistency of the | |
40 | * data (made possible since the BIU reads all 128 bits into a cache). | |
41 | * Reads are very rare, so this isn't a significant performance | |
42 | * impact. (Most data transferred from NIC to host is DMAed directly | |
43 | * into host memory). | |
44 | * | |
45 | * I/O BAR access uses locks for both reads and writes (but is only provided | |
46 | * for testing purposes). | |
47 | */ | |
48 | ||
49 | #if BITS_PER_LONG == 64 | |
50 | #define EFX_USE_QWORD_IO 1 | |
51 | #endif | |
52 | ||
53 | #ifdef EFX_USE_QWORD_IO | |
54 | static inline void _efx_writeq(struct efx_nic *efx, __le64 value, | |
55 | unsigned int reg) | |
56 | { | |
57 | __raw_writeq((__force u64)value, efx->membase + reg); | |
58 | } | |
59 | static inline __le64 _efx_readq(struct efx_nic *efx, unsigned int reg) | |
60 | { | |
61 | return (__force __le64)__raw_readq(efx->membase + reg); | |
62 | } | |
63 | #endif | |
64 | ||
65 | static inline void _efx_writed(struct efx_nic *efx, __le32 value, | |
66 | unsigned int reg) | |
67 | { | |
68 | __raw_writel((__force u32)value, efx->membase + reg); | |
69 | } | |
70 | static inline __le32 _efx_readd(struct efx_nic *efx, unsigned int reg) | |
71 | { | |
72 | return (__force __le32)__raw_readl(efx->membase + reg); | |
73 | } | |
74 | ||
75 | /* Writes to a normal 16-byte Efx register, locking as appropriate. */ | |
76 | static inline void efx_writeo(struct efx_nic *efx, efx_oword_t *value, | |
77 | unsigned int reg) | |
78 | { | |
79 | unsigned long flags __attribute__ ((unused)); | |
80 | ||
62776d03 BH |
81 | netif_vdbg(efx, hw, efx->net_dev, |
82 | "writing register %x with " EFX_OWORD_FMT "\n", reg, | |
83 | EFX_OWORD_VAL(*value)); | |
12d00cad BH |
84 | |
85 | spin_lock_irqsave(&efx->biu_lock, flags); | |
86 | #ifdef EFX_USE_QWORD_IO | |
87 | _efx_writeq(efx, value->u64[0], reg + 0); | |
88 | wmb(); | |
89 | _efx_writeq(efx, value->u64[1], reg + 8); | |
90 | #else | |
91 | _efx_writed(efx, value->u32[0], reg + 0); | |
92 | _efx_writed(efx, value->u32[1], reg + 4); | |
93 | _efx_writed(efx, value->u32[2], reg + 8); | |
94 | wmb(); | |
95 | _efx_writed(efx, value->u32[3], reg + 12); | |
96 | #endif | |
97 | mmiowb(); | |
98 | spin_unlock_irqrestore(&efx->biu_lock, flags); | |
99 | } | |
100 | ||
101 | /* Write an 8-byte NIC SRAM entry through the supplied mapping, | |
102 | * locking as appropriate. */ | |
103 | static inline void efx_sram_writeq(struct efx_nic *efx, void __iomem *membase, | |
104 | efx_qword_t *value, unsigned int index) | |
105 | { | |
106 | unsigned int addr = index * sizeof(*value); | |
107 | unsigned long flags __attribute__ ((unused)); | |
108 | ||
62776d03 BH |
109 | netif_vdbg(efx, hw, efx->net_dev, |
110 | "writing SRAM address %x with " EFX_QWORD_FMT "\n", | |
111 | addr, EFX_QWORD_VAL(*value)); | |
12d00cad BH |
112 | |
113 | spin_lock_irqsave(&efx->biu_lock, flags); | |
114 | #ifdef EFX_USE_QWORD_IO | |
115 | __raw_writeq((__force u64)value->u64[0], membase + addr); | |
116 | #else | |
117 | __raw_writel((__force u32)value->u32[0], membase + addr); | |
118 | wmb(); | |
119 | __raw_writel((__force u32)value->u32[1], membase + addr + 4); | |
120 | #endif | |
121 | mmiowb(); | |
122 | spin_unlock_irqrestore(&efx->biu_lock, flags); | |
123 | } | |
124 | ||
125 | /* Write dword to NIC register that allows partial writes | |
126 | * | |
127 | * Some registers (EVQ_RPTR_REG, RX_DESC_UPD_REG and | |
128 | * TX_DESC_UPD_REG) can be written to as a single dword. This allows | |
129 | * for lockless writes. | |
130 | */ | |
131 | static inline void efx_writed(struct efx_nic *efx, efx_dword_t *value, | |
132 | unsigned int reg) | |
133 | { | |
62776d03 BH |
134 | netif_vdbg(efx, hw, efx->net_dev, |
135 | "writing partial register %x with "EFX_DWORD_FMT"\n", | |
136 | reg, EFX_DWORD_VAL(*value)); | |
12d00cad BH |
137 | |
138 | /* No lock required */ | |
139 | _efx_writed(efx, value->u32[0], reg); | |
140 | } | |
141 | ||
142 | /* Read from a NIC register | |
143 | * | |
144 | * This reads an entire 16-byte register in one go, locking as | |
145 | * appropriate. It is essential to read the first dword first, as this | |
146 | * prompts the NIC to load the current value into the shadow register. | |
147 | */ | |
148 | static inline void efx_reado(struct efx_nic *efx, efx_oword_t *value, | |
149 | unsigned int reg) | |
150 | { | |
151 | unsigned long flags __attribute__ ((unused)); | |
152 | ||
153 | spin_lock_irqsave(&efx->biu_lock, flags); | |
154 | value->u32[0] = _efx_readd(efx, reg + 0); | |
155 | rmb(); | |
156 | value->u32[1] = _efx_readd(efx, reg + 4); | |
157 | value->u32[2] = _efx_readd(efx, reg + 8); | |
158 | value->u32[3] = _efx_readd(efx, reg + 12); | |
159 | spin_unlock_irqrestore(&efx->biu_lock, flags); | |
160 | ||
62776d03 BH |
161 | netif_vdbg(efx, hw, efx->net_dev, |
162 | "read from register %x, got " EFX_OWORD_FMT "\n", reg, | |
163 | EFX_OWORD_VAL(*value)); | |
12d00cad BH |
164 | } |
165 | ||
166 | /* Read an 8-byte SRAM entry through supplied mapping, | |
167 | * locking as appropriate. */ | |
168 | static inline void efx_sram_readq(struct efx_nic *efx, void __iomem *membase, | |
169 | efx_qword_t *value, unsigned int index) | |
170 | { | |
171 | unsigned int addr = index * sizeof(*value); | |
172 | unsigned long flags __attribute__ ((unused)); | |
173 | ||
174 | spin_lock_irqsave(&efx->biu_lock, flags); | |
175 | #ifdef EFX_USE_QWORD_IO | |
176 | value->u64[0] = (__force __le64)__raw_readq(membase + addr); | |
177 | #else | |
178 | value->u32[0] = (__force __le32)__raw_readl(membase + addr); | |
179 | rmb(); | |
180 | value->u32[1] = (__force __le32)__raw_readl(membase + addr + 4); | |
181 | #endif | |
182 | spin_unlock_irqrestore(&efx->biu_lock, flags); | |
183 | ||
62776d03 BH |
184 | netif_vdbg(efx, hw, efx->net_dev, |
185 | "read from SRAM address %x, got "EFX_QWORD_FMT"\n", | |
186 | addr, EFX_QWORD_VAL(*value)); | |
12d00cad BH |
187 | } |
188 | ||
189 | /* Read dword from register that allows partial writes (sic) */ | |
190 | static inline void efx_readd(struct efx_nic *efx, efx_dword_t *value, | |
191 | unsigned int reg) | |
192 | { | |
193 | value->u32[0] = _efx_readd(efx, reg); | |
62776d03 BH |
194 | netif_vdbg(efx, hw, efx->net_dev, |
195 | "read from register %x, got "EFX_DWORD_FMT"\n", | |
196 | reg, EFX_DWORD_VAL(*value)); | |
12d00cad BH |
197 | } |
198 | ||
199 | /* Write to a register forming part of a table */ | |
200 | static inline void efx_writeo_table(struct efx_nic *efx, efx_oword_t *value, | |
201 | unsigned int reg, unsigned int index) | |
202 | { | |
203 | efx_writeo(efx, value, reg + index * sizeof(efx_oword_t)); | |
204 | } | |
205 | ||
206 | /* Read to a register forming part of a table */ | |
207 | static inline void efx_reado_table(struct efx_nic *efx, efx_oword_t *value, | |
208 | unsigned int reg, unsigned int index) | |
209 | { | |
210 | efx_reado(efx, value, reg + index * sizeof(efx_oword_t)); | |
211 | } | |
212 | ||
213 | /* Write to a dword register forming part of a table */ | |
214 | static inline void efx_writed_table(struct efx_nic *efx, efx_dword_t *value, | |
215 | unsigned int reg, unsigned int index) | |
216 | { | |
217 | efx_writed(efx, value, reg + index * sizeof(efx_oword_t)); | |
218 | } | |
219 | ||
5b98c1bf BH |
220 | /* Read from a dword register forming part of a table */ |
221 | static inline void efx_readd_table(struct efx_nic *efx, efx_dword_t *value, | |
222 | unsigned int reg, unsigned int index) | |
223 | { | |
224 | efx_readd(efx, value, reg + index * sizeof(efx_dword_t)); | |
225 | } | |
226 | ||
12d00cad BH |
227 | /* Page-mapped register block size */ |
228 | #define EFX_PAGE_BLOCK_SIZE 0x2000 | |
229 | ||
230 | /* Calculate offset to page-mapped register block */ | |
231 | #define EFX_PAGED_REG(page, reg) \ | |
232 | ((page) * EFX_PAGE_BLOCK_SIZE + (reg)) | |
233 | ||
234 | /* As for efx_writeo(), but for a page-mapped register. */ | |
235 | static inline void efx_writeo_page(struct efx_nic *efx, efx_oword_t *value, | |
236 | unsigned int reg, unsigned int page) | |
237 | { | |
238 | efx_writeo(efx, value, EFX_PAGED_REG(page, reg)); | |
239 | } | |
240 | ||
241 | /* As for efx_writed(), but for a page-mapped register. */ | |
242 | static inline void efx_writed_page(struct efx_nic *efx, efx_dword_t *value, | |
243 | unsigned int reg, unsigned int page) | |
244 | { | |
245 | efx_writed(efx, value, EFX_PAGED_REG(page, reg)); | |
246 | } | |
247 | ||
248 | /* Write dword to page-mapped register with an extra lock. | |
249 | * | |
250 | * As for efx_writed_page(), but for a register that suffers from | |
251 | * SFC bug 3181. Take out a lock so the BIU collector cannot be | |
252 | * confused. */ | |
253 | static inline void efx_writed_page_locked(struct efx_nic *efx, | |
254 | efx_dword_t *value, | |
255 | unsigned int reg, | |
256 | unsigned int page) | |
257 | { | |
258 | unsigned long flags __attribute__ ((unused)); | |
259 | ||
260 | if (page == 0) { | |
261 | spin_lock_irqsave(&efx->biu_lock, flags); | |
262 | efx_writed(efx, value, EFX_PAGED_REG(page, reg)); | |
263 | spin_unlock_irqrestore(&efx->biu_lock, flags); | |
264 | } else { | |
265 | efx_writed(efx, value, EFX_PAGED_REG(page, reg)); | |
266 | } | |
267 | } | |
268 | ||
269 | #endif /* EFX_IO_H */ |