1 /*
2 *
3 * This file is subject to the terms and conditions of the GNU General Public
4 * License. See the file "COPYING" in the main directory of this archive
5 * for more details.
6 *
7 * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved.
8 */
9
10 #include <linux/types.h>
11 #include <linux/slab.h>
12 #include <linux/module.h>
13 #include <asm/sn/sgi.h>
14 #include <asm/sn/sn_cpuid.h>
15 #include <asm/sn/addrs.h>
16 #include <asm/sn/arch.h>
17 #include <asm/sn/iograph.h>
18 #include <asm/sn/invent.h>
19 #include <asm/sn/hcl.h>
20 #include <asm/sn/labelcl.h>
21 #include <asm/sn/xtalk/xwidget.h>
22 #include <asm/sn/pci/bridge.h>
23 #include <asm/sn/pci/pciio.h>
24 #include <asm/sn/pci/pcibr.h>
25 #include <asm/sn/pci/pcibr_private.h>
26 #include <asm/sn/pci/pci_defs.h>
27 #include <asm/sn/prio.h>
28 #include <asm/sn/xtalk/xbow.h>
29 #include <asm/sn/ioc3.h>
30 #include <asm/sn/io.h>
31 #include <asm/sn/sn_private.h>
32
33 #ifndef LOCAL
34 #define LOCAL static
35 #endif
36
37 /*
38 * functions
39 */
40 int pcibr_init_ext_ate_ram(bridge_t *);
41 int pcibr_ate_alloc(pcibr_soft_t, int);
42 void pcibr_ate_free(pcibr_soft_t, int, int);
43 bridge_ate_t pcibr_flags_to_ate(unsigned);
44 bridge_ate_p pcibr_ate_addr(pcibr_soft_t, int);
45 unsigned ate_freeze(pcibr_dmamap_t pcibr_dmamap,
46 #if PCIBR_FREEZE_TIME
47 unsigned *freeze_time_ptr,
48 #endif
49 unsigned *cmd_regs);
50 void ate_write(pcibr_soft_t pcibr_soft, bridge_ate_p ate_ptr, int ate_count, bridge_ate_t ate);
51 void ate_thaw(pcibr_dmamap_t pcibr_dmamap,
52 int ate_index,
53 #if PCIBR_FREEZE_TIME
54 bridge_ate_t ate,
55 int ate_total,
56 unsigned freeze_time_start,
57 #endif
58 unsigned *cmd_regs,
59 unsigned s);
60
61
62 /* Convert from ssram_bits in control register to number of SSRAM entries */
63 #define ATE_NUM_ENTRIES(n) _ate_info[n]
64
65 /* Possible choices for number of ATE entries in Bridge's SSRAM */
66 LOCAL int _ate_info[] =
67 {
68 0, /* 0 entries */
69 8 * 1024, /* 8K entries */
70 16 * 1024, /* 16K entries */
71 64 * 1024 /* 64K entries */
72 };
73
74 #define ATE_NUM_SIZES (sizeof(_ate_info) / sizeof(int))
75 #define ATE_PROBE_VALUE 0x0123456789abcdefULL
76
77 /*
78 * Determine the size of this bridge's external mapping SSRAM, and set
79 * the control register appropriately to reflect this size, and initialize
80 * the external SSRAM.
81 */
82 int
pcibr_init_ext_ate_ram(bridge_t * bridge)83 pcibr_init_ext_ate_ram(bridge_t *bridge)
84 {
85 int largest_working_size = 0;
86 int num_entries, entry;
87 int i, j;
88 bridgereg_t old_enable, new_enable;
89
90 /* Probe SSRAM to determine its size. */
91 old_enable = bridge->b_int_enable;
92 new_enable = old_enable & ~BRIDGE_IMR_PCI_MST_TIMEOUT;
93 bridge->b_int_enable = new_enable;
94
95 for (i = 1; i < ATE_NUM_SIZES; i++) {
96 /* Try writing a value */
97 bridge->b_ext_ate_ram[ATE_NUM_ENTRIES(i) - 1] = ATE_PROBE_VALUE;
98
99 /* Guard against wrap */
100 for (j = 1; j < i; j++)
101 bridge->b_ext_ate_ram[ATE_NUM_ENTRIES(j) - 1] = 0;
102
103 /* See if value was written */
104 if (bridge->b_ext_ate_ram[ATE_NUM_ENTRIES(i) - 1] == ATE_PROBE_VALUE)
105 largest_working_size = i;
106 }
107 bridge->b_int_enable = old_enable;
108 bridge->b_wid_tflush; /* wait until Bridge PIO complete */
109
110 /*
111 * ensure that we write and read without any interruption.
112 * The read following the write is required for the Bridge war
113 */
114
115 bridge->b_wid_control = (bridge->b_wid_control
116 & ~BRIDGE_CTRL_SSRAM_SIZE_MASK)
117 | BRIDGE_CTRL_SSRAM_SIZE(largest_working_size);
118 bridge->b_wid_control; /* inval addr bug war */
119
120 num_entries = ATE_NUM_ENTRIES(largest_working_size);
121
122 if (pcibr_debug_mask & PCIBR_DEBUG_ATE) {
123 if (num_entries) {
124 PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATE, NULL,
125 "bridge at 0x%x: clearing %d external ATEs\n",
126 bridge, num_entries));
127 } else {
128 PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATE, NULL,
129 "bridge at 0x%x: no external ATE RAM found\n",
130 bridge));
131 }
132 }
133
134 /* Initialize external mapping entries */
135 for (entry = 0; entry < num_entries; entry++)
136 bridge->b_ext_ate_ram[entry] = 0;
137
138 return (num_entries);
139 }
140
141 /*
142 * Allocate "count" contiguous Bridge Address Translation Entries
143 * on the specified bridge to be used for PCI to XTALK mappings.
144 * Indices in rm map range from 1..num_entries. Indicies returned
145 * to caller range from 0..num_entries-1.
146 *
147 * Return the start index on success, -1 on failure.
148 */
149 int
pcibr_ate_alloc(pcibr_soft_t pcibr_soft,int count)150 pcibr_ate_alloc(pcibr_soft_t pcibr_soft, int count)
151 {
152 int status = 0;
153 struct resource *new_res;
154 struct resource **allocated_res;
155
156 new_res = (struct resource *) kmalloc( sizeof(struct resource), GFP_ATOMIC);
157 memset(new_res, 0, sizeof(*new_res));
158 status = allocate_resource( &pcibr_soft->bs_int_ate_resource, new_res,
159 count, pcibr_soft->bs_int_ate_resource.start,
160 pcibr_soft->bs_int_ate_resource.end, 1,
161 NULL, NULL);
162
163 if ( status && (pcibr_soft->bs_ext_ate_resource.end != 0) ) {
164 status = allocate_resource( &pcibr_soft->bs_ext_ate_resource, new_res,
165 count, pcibr_soft->bs_ext_ate_resource.start,
166 pcibr_soft->bs_ext_ate_resource.end, 1,
167 NULL, NULL);
168 if (status) {
169 new_res->start = -1;
170 }
171 }
172
173 if (status) {
174 /* Failed to allocate */
175 kfree(new_res);
176 return -1;
177 }
178
179 /* Save the resource for freeing */
180 allocated_res = (struct resource **)(((unsigned long)pcibr_soft->bs_allocated_ate_res) + new_res->start * sizeof( unsigned long));
181 *allocated_res = new_res;
182
183 return new_res->start;
184 }
185
186 void
pcibr_ate_free(pcibr_soft_t pcibr_soft,int index,int count)187 pcibr_ate_free(pcibr_soft_t pcibr_soft, int index, int count)
188 /* Who says there's no such thing as a free meal? :-) */
189 {
190
191 struct resource **allocated_res;
192 int status = 0;
193
194 allocated_res = (struct resource **)(((unsigned long)pcibr_soft->bs_allocated_ate_res) + index * sizeof(unsigned long));
195
196 status = release_resource(*allocated_res);
197 if (status)
198 BUG(); /* Ouch .. */
199 kfree(*allocated_res);
200
201 }
202
203 /*
204 * Convert PCI-generic software flags and Bridge-specific software flags
205 * into Bridge-specific Address Translation Entry attribute bits.
206 */
207 bridge_ate_t
pcibr_flags_to_ate(unsigned flags)208 pcibr_flags_to_ate(unsigned flags)
209 {
210 bridge_ate_t attributes;
211
212 /* default if nothing specified:
213 * NOBARRIER
214 * NOPREFETCH
215 * NOPRECISE
216 * COHERENT
217 * Plus the valid bit
218 */
219 attributes = ATE_CO | ATE_V;
220
221 /* Generic macro flags
222 */
223 if (flags & PCIIO_DMA_DATA) { /* standard data channel */
224 attributes &= ~ATE_BAR; /* no barrier */
225 attributes |= ATE_PREF; /* prefetch on */
226 }
227 if (flags & PCIIO_DMA_CMD) { /* standard command channel */
228 attributes |= ATE_BAR; /* barrier bit on */
229 attributes &= ~ATE_PREF; /* disable prefetch */
230 }
231 /* Generic detail flags
232 */
233 if (flags & PCIIO_PREFETCH)
234 attributes |= ATE_PREF;
235 if (flags & PCIIO_NOPREFETCH)
236 attributes &= ~ATE_PREF;
237
238 /* Provider-specific flags
239 */
240 if (flags & PCIBR_BARRIER)
241 attributes |= ATE_BAR;
242 if (flags & PCIBR_NOBARRIER)
243 attributes &= ~ATE_BAR;
244
245 if (flags & PCIBR_PREFETCH)
246 attributes |= ATE_PREF;
247 if (flags & PCIBR_NOPREFETCH)
248 attributes &= ~ATE_PREF;
249
250 if (flags & PCIBR_PRECISE)
251 attributes |= ATE_PREC;
252 if (flags & PCIBR_NOPRECISE)
253 attributes &= ~ATE_PREC;
254
255 return (attributes);
256 }
257
258 /*
259 * Setup an Address Translation Entry as specified. Use either the Bridge
260 * internal maps or the external map RAM, as appropriate.
261 */
262 bridge_ate_p
pcibr_ate_addr(pcibr_soft_t pcibr_soft,int ate_index)263 pcibr_ate_addr(pcibr_soft_t pcibr_soft,
264 int ate_index)
265 {
266 bridge_t *bridge = pcibr_soft->bs_base;
267
268 return (ate_index < pcibr_soft->bs_int_ate_size)
269 ? &(bridge->b_int_ate_ram[ate_index].wr)
270 : &(bridge->b_ext_ate_ram[ate_index]);
271 }
272
273 /* We are starting to get more complexity
274 * surrounding writing ATEs, so pull
275 * the writing code into this new function.
276 */
277
278 #if PCIBR_FREEZE_TIME
279 #define ATE_FREEZE() s = ate_freeze(pcibr_dmamap, &freeze_time, cmd_regs)
280 #else
281 #define ATE_FREEZE() s = ate_freeze(pcibr_dmamap, cmd_regs)
282 #endif
283
284 unsigned
ate_freeze(pcibr_dmamap_t pcibr_dmamap,unsigned * freeze_time_ptr,unsigned * cmd_regs)285 ate_freeze(pcibr_dmamap_t pcibr_dmamap,
286 #if PCIBR_FREEZE_TIME
287 unsigned *freeze_time_ptr,
288 #endif
289 unsigned *cmd_regs)
290 {
291 pcibr_soft_t pcibr_soft = pcibr_dmamap->bd_soft;
292 #ifdef LATER
293 int dma_slot = pcibr_dmamap->bd_slot;
294 #endif
295 int ext_ates = pcibr_dmamap->bd_flags & PCIBR_DMAMAP_SSRAM;
296 int slot;
297
298 unsigned long s;
299 unsigned cmd_reg;
300 volatile unsigned *cmd_lwa;
301 unsigned cmd_lwd;
302
303 if (!ext_ates)
304 return 0;
305
306 /* Bridge Hardware Bug WAR #484930:
307 * Bridge can't handle updating External ATEs
308 * while DMA is occurring that uses External ATEs,
309 * even if the particular ATEs involved are disjoint.
310 */
311
312 /* need to prevent anyone else from
313 * unfreezing the grant while we
314 * are working; also need to prevent
315 * this thread from being interrupted
316 * to keep PCI grant freeze time
317 * at an absolute minimum.
318 */
319 s = pcibr_lock(pcibr_soft);
320
321 #ifdef LATER
322 /* just in case pcibr_dmamap_done was not called */
323 if (pcibr_dmamap->bd_flags & PCIBR_DMAMAP_BUSY) {
324 pcibr_dmamap->bd_flags &= ~PCIBR_DMAMAP_BUSY;
325 if (pcibr_dmamap->bd_flags & PCIBR_DMAMAP_SSRAM)
326 atomic_dec(&(pcibr_soft->bs_slot[dma_slot]. bss_ext_ates_active));
327 xtalk_dmamap_done(pcibr_dmamap->bd_xtalk);
328 }
329 #endif /* LATER */
330 #if PCIBR_FREEZE_TIME
331 *freeze_time_ptr = get_timestamp();
332 #endif
333
334 cmd_lwa = 0;
335 for (slot = pcibr_soft->bs_min_slot;
336 slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot)
337 if (atomic_read(&pcibr_soft->bs_slot[slot].bss_ext_ates_active)) {
338 cmd_reg = pcibr_soft->
339 bs_slot[slot].
340 bss_cmd_shadow;
341 if (cmd_reg & PCI_CMD_BUS_MASTER) {
342 cmd_lwa = pcibr_soft->
343 bs_slot[slot].
344 bss_cmd_pointer;
345 cmd_lwd = cmd_reg ^ PCI_CMD_BUS_MASTER;
346 cmd_lwa[0] = cmd_lwd;
347 }
348 cmd_regs[slot] = cmd_reg;
349 } else
350 cmd_regs[slot] = 0;
351
352 if (cmd_lwa) {
353 bridge_t *bridge = pcibr_soft->bs_base;
354
355 /* Read the last master bit that has been cleared. This PIO read
356 * on the PCI bus is to ensure the completion of any DMAs that
357 * are due to bus requests issued by PCI devices before the
358 * clearing of master bits.
359 */
360 cmd_lwa[0];
361
362 /* Flush all the write buffers in the bridge */
363 for (slot = pcibr_soft->bs_min_slot;
364 slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) {
365 if (atomic_read(&pcibr_soft->bs_slot[slot].bss_ext_ates_active)) {
366 /* Flush the write buffer associated with this
367 * PCI device which might be using dma map RAM.
368 */
369 bridge->b_wr_req_buf[slot].reg;
370 }
371 }
372 }
373 return s;
374 }
375
376 void
ate_write(pcibr_soft_t pcibr_soft,bridge_ate_p ate_ptr,int ate_count,bridge_ate_t ate)377 ate_write(pcibr_soft_t pcibr_soft,
378 bridge_ate_p ate_ptr,
379 int ate_count,
380 bridge_ate_t ate)
381 {
382 while (ate_count-- > 0) {
383 *ate_ptr++ = ate;
384 ate += IOPGSIZE;
385 }
386 }
387
388 #if PCIBR_FREEZE_TIME
389 #define ATE_THAW() ate_thaw(pcibr_dmamap, ate_index, ate, ate_total, freeze_time, cmd_regs, s)
390 #else
391 #define ATE_THAW() ate_thaw(pcibr_dmamap, ate_index, cmd_regs, s)
392 #endif
393
394 void
ate_thaw(pcibr_dmamap_t pcibr_dmamap,int ate_index,bridge_ate_t ate,int ate_total,unsigned freeze_time_start,unsigned * cmd_regs,unsigned s)395 ate_thaw(pcibr_dmamap_t pcibr_dmamap,
396 int ate_index,
397 #if PCIBR_FREEZE_TIME
398 bridge_ate_t ate,
399 int ate_total,
400 unsigned freeze_time_start,
401 #endif
402 unsigned *cmd_regs,
403 unsigned s)
404 {
405 pcibr_soft_t pcibr_soft = pcibr_dmamap->bd_soft;
406 int dma_slot = pcibr_dmamap->bd_slot;
407 int slot;
408 bridge_t *bridge = pcibr_soft->bs_base;
409 int ext_ates = pcibr_dmamap->bd_flags & PCIBR_DMAMAP_SSRAM;
410
411 unsigned cmd_reg;
412
413 #if PCIBR_FREEZE_TIME
414 unsigned freeze_time;
415 static unsigned max_freeze_time = 0;
416 static unsigned max_ate_total;
417 #endif
418
419 if (!ext_ates)
420 return;
421
422 /* restore cmd regs */
423 for (slot = pcibr_soft->bs_min_slot;
424 slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) {
425 if ((cmd_reg = cmd_regs[slot]) & PCI_CMD_BUS_MASTER) {
426 pcibr_slot_config_set(bridge, slot, PCI_CFG_COMMAND/4, cmd_reg);
427 }
428 }
429 pcibr_dmamap->bd_flags |= PCIBR_DMAMAP_BUSY;
430 atomic_inc(&(pcibr_soft->bs_slot[dma_slot]. bss_ext_ates_active));
431
432 #if PCIBR_FREEZE_TIME
433 freeze_time = get_timestamp() - freeze_time_start;
434
435 if ((max_freeze_time < freeze_time) ||
436 (max_ate_total < ate_total)) {
437 if (max_freeze_time < freeze_time)
438 max_freeze_time = freeze_time;
439 if (max_ate_total < ate_total)
440 max_ate_total = ate_total;
441 pcibr_unlock(pcibr_soft, s);
442 printk( "%s: pci freeze time %d usec for %d ATEs\n"
443 "\tfirst ate: %R\n",
444 pcibr_soft->bs_name,
445 freeze_time * 1000 / 1250,
446 ate_total,
447 ate, ate_bits);
448 } else
449 #endif
450 pcibr_unlock(pcibr_soft, s);
451 }
452