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