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