ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / ia64 / sn / kernel / bte.c
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
7  */
8
9 #include <linux/config.h>
10 #include <asm/sn/sgi.h>
11 #include <asm/sn/nodepda.h>
12 #include <asm/sn/addrs.h>
13 #include <asm/sn/arch.h>
14 #include <asm/sn/sn_cpuid.h>
15 #include <asm/sn/pda.h>
16 #include <asm/sn/sn2/shubio.h>
17 #include <asm/nodedata.h>
18 #include <asm/delay.h>
19
20 #include <linux/bootmem.h>
21 #include <linux/string.h>
22 #include <linux/sched.h>
23
24 #include <asm/sn/bte.h>
25
26 #ifndef L1_CACHE_MASK
27 #define L1_CACHE_MASK (L1_CACHE_BYTES - 1)
28 #endif
29
30 /*
31  * The base address of for each set of bte registers.
32  */
33 static int bte_offsets[] = { IIO_IBLS0, IIO_IBLS1 };
34
35
36 /************************************************************************
37  * Block Transfer Engine copy related functions.
38  *
39  ***********************************************************************/
40
41
42 /*
43  * bte_copy(src, dest, len, mode, notification)
44  *
45  * Use the block transfer engine to move kernel memory from src to dest
46  * using the assigned mode.
47  *
48  * Paramaters:
49  *   src - physical address of the transfer source.
50  *   dest - physical address of the transfer destination.
51  *   len - number of bytes to transfer from source to dest.
52  *   mode - hardware defined.  See reference information
53  *          for IBCT0/1 in the SHUB Programmers Reference
54  *   notification - kernel virtual address of the notification cache
55  *                  line.  If NULL, the default is used and
56  *                  the bte_copy is synchronous.
57  *
58  * NOTE:  This function requires src, dest, and len to
59  * be cacheline aligned.
60  */
61 bte_result_t
62 bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification)
63 {
64         int bte_to_use;
65         u64 transfer_size;
66         struct bteinfo_s *bte;
67         bte_result_t bte_status;
68         unsigned long irq_flags;
69
70
71         BTE_PRINTK(("bte_copy(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%p)\n",
72                     src, dest, len, mode, notification));
73
74         if (len == 0) {
75                 return BTE_SUCCESS;
76         }
77
78         ASSERT(!((len & L1_CACHE_MASK) ||
79                  (src & L1_CACHE_MASK) || (dest & L1_CACHE_MASK)));
80         ASSERT(len < ((BTE_LEN_MASK + 1) << L1_CACHE_SHIFT));
81
82         do {
83                 local_irq_save(irq_flags);
84
85                 bte_to_use = 0;
86                 /* Attempt to lock one of the BTE interfaces. */
87                 while ((bte_to_use < BTES_PER_NODE) &&
88                        BTE_LOCK_IF_AVAIL(bte_to_use)) {
89                         bte_to_use++;
90                 }
91
92                 if (bte_to_use < BTES_PER_NODE) {
93                         break;
94                 }
95
96                 local_irq_restore(irq_flags);
97
98                 if (!(mode & BTE_WACQUIRE)) {
99                         return BTEFAIL_NOTAVAIL;
100                 }
101
102                 /* Wait until a bte is available. */
103                 udelay(10);
104         } while (1);
105
106         bte = pda->cpu_bte_if[bte_to_use];
107         BTE_PRINTKV(("Got a lock on bte %d\n", bte_to_use));
108
109
110         if (notification == NULL) {
111                 /* User does not want to be notified. */
112                 bte->most_rcnt_na = &bte->notify;
113         } else {
114                 bte->most_rcnt_na = notification;
115         }
116
117         /* Calculate the number of cache lines to transfer. */
118         transfer_size = ((len >> L1_CACHE_SHIFT) & BTE_LEN_MASK);
119
120         /* Initialize the notification to a known value. */
121         *bte->most_rcnt_na = -1L;
122
123         /* Set the status reg busy bit and transfer length */
124         BTE_PRINTKV(("IBLS - HUB_S(0x%p, 0x%lx)\n",
125                      BTEREG_LNSTAT_ADDR, IBLS_BUSY | transfer_size));
126         HUB_S(BTEREG_LNSTAT_ADDR, (IBLS_BUSY | transfer_size));
127
128         /* Set the source and destination registers */
129         BTE_PRINTKV(("IBSA - HUB_S(0x%p, 0x%lx)\n", BTEREG_SRC_ADDR,
130                      (TO_PHYS(src))));
131         HUB_S(BTEREG_SRC_ADDR, (TO_PHYS(src)));
132         BTE_PRINTKV(("IBDA - HUB_S(0x%p, 0x%lx)\n", BTEREG_DEST_ADDR,
133                      (TO_PHYS(dest))));
134         HUB_S(BTEREG_DEST_ADDR, (TO_PHYS(dest)));
135
136         /* Set the notification register */
137         BTE_PRINTKV(("IBNA - HUB_S(0x%p, 0x%lx)\n", BTEREG_NOTIF_ADDR,
138                      (TO_PHYS(ia64_tpa((unsigned long)bte->most_rcnt_na)))));
139         HUB_S(BTEREG_NOTIF_ADDR, (TO_PHYS(ia64_tpa((unsigned long)bte->most_rcnt_na))));
140
141
142         /* Initiate the transfer */
143         BTE_PRINTK(("IBCT - HUB_S(0x%p, 0x%lx)\n", BTEREG_CTRL_ADDR,
144                      BTE_VALID_MODE(mode)));
145         HUB_S(BTEREG_CTRL_ADDR, BTE_VALID_MODE(mode));
146
147         spin_unlock_irqrestore(&bte->spinlock, irq_flags);
148
149
150         if (notification != NULL) {
151                 return BTE_SUCCESS;
152         }
153
154         while (*bte->most_rcnt_na == -1UL) {
155         }
156
157
158         BTE_PRINTKV((" Delay Done.  IBLS = 0x%lx, most_rcnt_na = 0x%lx\n",
159                                 HUB_L(BTEREG_LNSTAT_ADDR), *bte->most_rcnt_na));
160
161         if (*bte->most_rcnt_na & IBLS_ERROR) {
162                 bte_status = *bte->most_rcnt_na & ~IBLS_ERROR;
163                 *bte->most_rcnt_na = 0L;
164         } else {
165                 bte_status = BTE_SUCCESS;
166         }
167         BTE_PRINTK(("Returning status is 0x%lx and most_rcnt_na is 0x%lx\n",
168                                 HUB_L(BTEREG_LNSTAT_ADDR), *bte->most_rcnt_na));
169
170         return bte_status;
171 }
172
173
174 /*
175  * bte_unaligned_copy(src, dest, len, mode)
176  *
177  * use the block transfer engine to move kernel
178  * memory from src to dest using the assigned mode.
179  *
180  * Paramaters:
181  *   src - physical address of the transfer source.
182  *   dest - physical address of the transfer destination.
183  *   len - number of bytes to transfer from source to dest.
184  *   mode - hardware defined.  See reference information
185  *          for IBCT0/1 in the SGI documentation.
186  *
187  * NOTE: If the source, dest, and len are all cache line aligned,
188  * then it would be _FAR_ preferrable to use bte_copy instead.
189  */
190 bte_result_t
191 bte_unaligned_copy(u64 src, u64 dest, u64 len, u64 mode)
192 {
193         int destFirstCacheOffset;
194         u64 headBteSource;
195         u64 headBteLen;
196         u64 headBcopySrcOffset;
197         u64 headBcopyDest;
198         u64 headBcopyLen;
199         u64 footBteSource;
200         u64 footBteLen;
201         u64 footBcopyDest;
202         u64 footBcopyLen;
203         bte_result_t rv;
204         char *bteBlock;
205
206         if (len == 0) {
207                 return BTE_SUCCESS;
208         }
209
210         /* temporary buffer used during unaligned transfers */
211         bteBlock = pda->cpu_bte_if[0]->scratch_buf;
212
213         headBcopySrcOffset = src & L1_CACHE_MASK;
214         destFirstCacheOffset = dest & L1_CACHE_MASK;
215
216         /*
217          * At this point, the transfer is broken into
218          * (up to) three sections.  The first section is
219          * from the start address to the first physical
220          * cache line, the second is from the first physical
221          * cache line to the last complete cache line,
222          * and the third is from the last cache line to the
223          * end of the buffer.  The first and third sections
224          * are handled by bte copying into a temporary buffer
225          * and then bcopy'ing the necessary section into the
226          * final location.  The middle section is handled with
227          * a standard bte copy.
228          *
229          * One nasty exception to the above rule is when the
230          * source and destination are not symetrically
231          * mis-aligned.  If the source offset from the first
232          * cache line is different from the destination offset,
233          * we make the first section be the entire transfer
234          * and the bcopy the entire block into place.
235          */
236         if (headBcopySrcOffset == destFirstCacheOffset) {
237
238                 /*
239                  * Both the source and destination are the same
240                  * distance from a cache line boundary so we can
241                  * use the bte to transfer the bulk of the
242                  * data.
243                  */
244                 headBteSource = src & ~L1_CACHE_MASK;
245                 headBcopyDest = dest;
246                 if (headBcopySrcOffset) {
247                         headBcopyLen =
248                             (len >
249                              (L1_CACHE_BYTES -
250                               headBcopySrcOffset) ? L1_CACHE_BYTES
251                              - headBcopySrcOffset : len);
252                         headBteLen = L1_CACHE_BYTES;
253                 } else {
254                         headBcopyLen = 0;
255                         headBteLen = 0;
256                 }
257
258                 if (len > headBcopyLen) {
259                         footBcopyLen =
260                             (len - headBcopyLen) & L1_CACHE_MASK;
261                         footBteLen = L1_CACHE_BYTES;
262
263                         footBteSource = src + len - footBcopyLen;
264                         footBcopyDest = dest + len - footBcopyLen;
265
266                         if (footBcopyDest ==
267                             (headBcopyDest + headBcopyLen)) {
268                                 /*
269                                  * We have two contigous bcopy
270                                  * blocks.  Merge them.
271                                  */
272                                 headBcopyLen += footBcopyLen;
273                                 headBteLen += footBteLen;
274                         } else if (footBcopyLen > 0) {
275                                 rv = bte_copy(footBteSource,
276                                               ia64_tpa((unsigned long)bteBlock),
277                                               footBteLen, mode, NULL);
278                                 if (rv != BTE_SUCCESS) {
279                                         return rv;
280                                 }
281
282
283                                 memcpy(__va(footBcopyDest),
284                                        (char *) bteBlock, footBcopyLen);
285                         }
286                 } else {
287                         footBcopyLen = 0;
288                         footBteLen = 0;
289                 }
290
291                 if (len > (headBcopyLen + footBcopyLen)) {
292                         /* now transfer the middle. */
293                         rv = bte_copy((src + headBcopyLen),
294                                       (dest +
295                                        headBcopyLen),
296                                       (len - headBcopyLen -
297                                        footBcopyLen), mode, NULL);
298                         if (rv != BTE_SUCCESS) {
299                                 return rv;
300                         }
301
302                 }
303         } else {
304
305
306                 /*
307                  * The transfer is not symetric, we will
308                  * allocate a buffer large enough for all the
309                  * data, bte_copy into that buffer and then
310                  * bcopy to the destination.
311                  */
312
313                 /* Add the leader from source */
314                 headBteLen = len + (src & L1_CACHE_MASK);
315                 /* Add the trailing bytes from footer. */
316                 headBteLen +=
317                     L1_CACHE_BYTES - (headBteLen & L1_CACHE_MASK);
318                 headBteSource = src & ~L1_CACHE_MASK;
319                 headBcopySrcOffset = src & L1_CACHE_MASK;
320                 headBcopyDest = dest;
321                 headBcopyLen = len;
322         }
323
324         if (headBcopyLen > 0) {
325                 rv = bte_copy(headBteSource,
326                               ia64_tpa((unsigned long)bteBlock), headBteLen, mode, NULL);
327                 if (rv != BTE_SUCCESS) {
328                         return rv;
329                 }
330
331                 memcpy(__va(headBcopyDest), ((char *) bteBlock +
332                                              headBcopySrcOffset),
333                        headBcopyLen);
334         }
335         return BTE_SUCCESS;
336 }
337
338
339 /************************************************************************
340  * Block Transfer Engine initialization functions.
341  *
342  ***********************************************************************/
343
344
345 /*
346  * bte_init_node(nodepda, cnode)
347  *
348  * Initialize the nodepda structure with BTE base addresses and
349  * spinlocks.
350  */
351 void
352 bte_init_node(nodepda_t * mynodepda, cnodeid_t cnode)
353 {
354         int i;
355
356
357         /*
358          * Indicate that all the block transfer engines on this node
359          * are available.
360          */
361
362         /*
363          * Allocate one bte_recover_t structure per node.  It holds
364          * the recovery lock for node.  All the bte interface structures
365          * will point at this one bte_recover structure to get the lock.
366          */
367         spin_lock_init(&mynodepda->bte_recovery_lock);
368         init_timer(&mynodepda->bte_recovery_timer);
369         mynodepda->bte_recovery_timer.function = bte_error_handler;
370         mynodepda->bte_recovery_timer.data = (unsigned long) mynodepda;
371
372         for (i = 0; i < BTES_PER_NODE; i++) {
373                 /* >>> Don't know why the 0x1800000L is here.  Robin */
374                 mynodepda->bte_if[i].bte_base_addr =
375                     (char *) LOCAL_MMR_ADDR(bte_offsets[i] | 0x1800000L);
376
377                 /*
378                  * Initialize the notification and spinlock
379                  * so the first transfer can occur.
380                  */
381                 mynodepda->bte_if[i].most_rcnt_na =
382                     &(mynodepda->bte_if[i].notify);
383                 mynodepda->bte_if[i].notify = 0L;
384                 spin_lock_init(&mynodepda->bte_if[i].spinlock);
385
386                 mynodepda->bte_if[i].scratch_buf =
387                     alloc_bootmem_node(NODE_DATA(cnode), BTE_MAX_XFER);
388                 mynodepda->bte_if[i].bte_cnode = cnode;
389                 mynodepda->bte_if[i].bte_error_count = 0;
390                 mynodepda->bte_if[i].bte_num = i;
391                 mynodepda->bte_if[i].cleanup_active = 0;
392                 mynodepda->bte_if[i].bh_error = 0;
393         }
394
395 }
396
397 /*
398  * bte_init_cpu()
399  *
400  * Initialize the cpupda structure with pointers to the
401  * nodepda bte blocks.
402  *
403  */
404 void
405 bte_init_cpu(void)
406 {
407         /* Called by setup.c as each cpu is being added to the nodepda */
408         if (local_node_data->active_cpu_count & 0x1) {
409                 pda->cpu_bte_if[0] = &(nodepda->bte_if[0]);
410                 pda->cpu_bte_if[1] = &(nodepda->bte_if[1]);
411         } else {
412                 pda->cpu_bte_if[0] = &(nodepda->bte_if[1]);
413                 pda->cpu_bte_if[1] = &(nodepda->bte_if[0]);
414         }
415 }