sgi-xp: add usage of GRU driver by xpc_remote_memcpy()
[pandora-kernel.git] / drivers / misc / sgi-xp / xpc_partition.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) 2004-2008 Silicon Graphics, Inc.  All Rights Reserved.
7  */
8
9 /*
10  * Cross Partition Communication (XPC) partition support.
11  *
12  *      This is the part of XPC that detects the presence/absence of
13  *      other partitions. It provides a heartbeat and monitors the
14  *      heartbeats of other partitions.
15  *
16  */
17
18 #include <linux/device.h>
19 #include <linux/hardirq.h>
20 #include "xpc.h"
21
22 /* XPC is exiting flag */
23 int xpc_exiting;
24
25 /* this partition's reserved page pointers */
26 struct xpc_rsvd_page *xpc_rsvd_page;
27 static unsigned long *xpc_part_nasids;
28 unsigned long *xpc_mach_nasids;
29
30 static int xpc_nasid_mask_nbytes;       /* #of bytes in nasid mask */
31 int xpc_nasid_mask_nlongs;      /* #of longs in nasid mask */
32
33 struct xpc_partition *xpc_partitions;
34
35 /*
36  * Guarantee that the kmalloc'd memory is cacheline aligned.
37  */
38 void *
39 xpc_kmalloc_cacheline_aligned(size_t size, gfp_t flags, void **base)
40 {
41         /* see if kmalloc will give us cachline aligned memory by default */
42         *base = kmalloc(size, flags);
43         if (*base == NULL)
44                 return NULL;
45
46         if ((u64)*base == L1_CACHE_ALIGN((u64)*base))
47                 return *base;
48
49         kfree(*base);
50
51         /* nope, we'll have to do it ourselves */
52         *base = kmalloc(size + L1_CACHE_BYTES, flags);
53         if (*base == NULL)
54                 return NULL;
55
56         return (void *)L1_CACHE_ALIGN((u64)*base);
57 }
58
59 /*
60  * Given a nasid, get the physical address of the  partition's reserved page
61  * for that nasid. This function returns 0 on any error.
62  */
63 static unsigned long
64 xpc_get_rsvd_page_pa(int nasid)
65 {
66         enum xp_retval ret;
67         u64 cookie = 0;
68         unsigned long rp_pa = nasid;    /* seed with nasid */
69         size_t len = 0;
70         size_t buf_len = 0;
71         void *buf = buf;
72         void *buf_base = NULL;
73
74         while (1) {
75
76                 ret = xpc_get_partition_rsvd_page_pa(buf, &cookie, &rp_pa,
77                                                      &len);
78
79                 dev_dbg(xpc_part, "SAL returned with ret=%d, cookie=0x%016lx, "
80                         "address=0x%016lx, len=0x%016lx\n", ret,
81                         (unsigned long)cookie, rp_pa, len);
82
83                 if (ret != xpNeedMoreInfo)
84                         break;
85
86                 /* !!! L1_CACHE_ALIGN() is only a sn2-bte_copy requirement */
87                 if (L1_CACHE_ALIGN(len) > buf_len) {
88                         kfree(buf_base);
89                         buf_len = L1_CACHE_ALIGN(len);
90                         buf = xpc_kmalloc_cacheline_aligned(buf_len, GFP_KERNEL,
91                                                             &buf_base);
92                         if (buf_base == NULL) {
93                                 dev_err(xpc_part, "unable to kmalloc "
94                                         "len=0x%016lx\n", buf_len);
95                                 ret = xpNoMemory;
96                                 break;
97                         }
98                 }
99
100                 ret = xp_remote_memcpy(xp_pa(buf), rp_pa, buf_len);
101                 if (ret != xpSuccess) {
102                         dev_dbg(xpc_part, "xp_remote_memcpy failed %d\n", ret);
103                         break;
104                 }
105         }
106
107         kfree(buf_base);
108
109         if (ret != xpSuccess)
110                 rp_pa = 0;
111
112         dev_dbg(xpc_part, "reserved page at phys address 0x%016lx\n", rp_pa);
113         return rp_pa;
114 }
115
116 /*
117  * Fill the partition reserved page with the information needed by
118  * other partitions to discover we are alive and establish initial
119  * communications.
120  */
121 struct xpc_rsvd_page *
122 xpc_setup_rsvd_page(void)
123 {
124         struct xpc_rsvd_page *rp;
125         unsigned long rp_pa;
126         unsigned long new_ts_jiffies;
127
128         /* get the local reserved page's address */
129
130         preempt_disable();
131         rp_pa = xpc_get_rsvd_page_pa(xp_cpu_to_nasid(smp_processor_id()));
132         preempt_enable();
133         if (rp_pa == 0) {
134                 dev_err(xpc_part, "SAL failed to locate the reserved page\n");
135                 return NULL;
136         }
137         rp = (struct xpc_rsvd_page *)__va(rp_pa);
138
139         if (rp->SAL_version < 3) {
140                 /* SAL_versions < 3 had a SAL_partid defined as a u8 */
141                 rp->SAL_partid &= 0xff;
142         }
143         BUG_ON(rp->SAL_partid != xp_partition_id);
144
145         if (rp->SAL_partid < 0 || rp->SAL_partid >= xp_max_npartitions) {
146                 dev_err(xpc_part, "the reserved page's partid of %d is outside "
147                         "supported range (< 0 || >= %d)\n", rp->SAL_partid,
148                         xp_max_npartitions);
149                 return NULL;
150         }
151
152         rp->version = XPC_RP_VERSION;
153         rp->max_npartitions = xp_max_npartitions;
154
155         /* establish the actual sizes of the nasid masks */
156         if (rp->SAL_version == 1) {
157                 /* SAL_version 1 didn't set the nasids_size field */
158                 rp->SAL_nasids_size = 128;
159         }
160         xpc_nasid_mask_nbytes = rp->SAL_nasids_size;
161         xpc_nasid_mask_nlongs = BITS_TO_LONGS(rp->SAL_nasids_size *
162                                               BITS_PER_BYTE);
163
164         /* setup the pointers to the various items in the reserved page */
165         xpc_part_nasids = XPC_RP_PART_NASIDS(rp);
166         xpc_mach_nasids = XPC_RP_MACH_NASIDS(rp);
167
168         if (xpc_rsvd_page_init(rp) != xpSuccess)
169                 return NULL;
170
171         /*
172          * Set timestamp of when reserved page was setup by XPC.
173          * This signifies to the remote partition that our reserved
174          * page is initialized.
175          */
176         new_ts_jiffies = jiffies;
177         if (new_ts_jiffies == 0 || new_ts_jiffies == rp->ts_jiffies)
178                 new_ts_jiffies++;
179         rp->ts_jiffies = new_ts_jiffies;
180
181         return rp;
182 }
183
184 /*
185  * Get a copy of a portion of the remote partition's rsvd page.
186  *
187  * remote_rp points to a buffer that is cacheline aligned for BTE copies and
188  * is large enough to contain a copy of their reserved page header and
189  * part_nasids mask.
190  */
191 enum xp_retval
192 xpc_get_remote_rp(int nasid, unsigned long *discovered_nasids,
193                   struct xpc_rsvd_page *remote_rp, unsigned long *remote_rp_pa)
194 {
195         int l;
196         enum xp_retval ret;
197
198         /* get the reserved page's physical address */
199
200         *remote_rp_pa = xpc_get_rsvd_page_pa(nasid);
201         if (*remote_rp_pa == 0)
202                 return xpNoRsvdPageAddr;
203
204         /* pull over the reserved page header and part_nasids mask */
205         ret = xp_remote_memcpy(xp_pa(remote_rp), *remote_rp_pa,
206                                XPC_RP_HEADER_SIZE + xpc_nasid_mask_nbytes);
207         if (ret != xpSuccess)
208                 return ret;
209
210         if (discovered_nasids != NULL) {
211                 unsigned long *remote_part_nasids =
212                     XPC_RP_PART_NASIDS(remote_rp);
213
214                 for (l = 0; l < xpc_nasid_mask_nlongs; l++)
215                         discovered_nasids[l] |= remote_part_nasids[l];
216         }
217
218         /* zero timestamp indicates the reserved page has not been setup */
219         if (remote_rp->ts_jiffies == 0)
220                 return xpRsvdPageNotSet;
221
222         if (XPC_VERSION_MAJOR(remote_rp->version) !=
223             XPC_VERSION_MAJOR(XPC_RP_VERSION)) {
224                 return xpBadVersion;
225         }
226
227         /* check that both remote and local partids are valid for each side */
228         if (remote_rp->SAL_partid < 0 ||
229             remote_rp->SAL_partid >= xp_max_npartitions ||
230             remote_rp->max_npartitions <= xp_partition_id) {
231                 return xpInvalidPartid;
232         }
233
234         if (remote_rp->SAL_partid == xp_partition_id)
235                 return xpLocalPartid;
236
237         return xpSuccess;
238 }
239
240 /*
241  * See if the other side has responded to a partition deactivate request
242  * from us. Though we requested the remote partition to deactivate with regard
243  * to us, we really only need to wait for the other side to disengage from us.
244  */
245 int
246 xpc_partition_disengaged(struct xpc_partition *part)
247 {
248         short partid = XPC_PARTID(part);
249         int disengaged;
250
251         disengaged = !xpc_partition_engaged(partid);
252         if (part->disengage_timeout) {
253                 if (!disengaged) {
254                         if (time_is_after_jiffies(part->disengage_timeout)) {
255                                 /* timelimit hasn't been reached yet */
256                                 return 0;
257                         }
258
259                         /*
260                          * Other side hasn't responded to our deactivate
261                          * request in a timely fashion, so assume it's dead.
262                          */
263
264                         dev_info(xpc_part, "deactivate request to remote "
265                                  "partition %d timed out\n", partid);
266                         xpc_disengage_timedout = 1;
267                         xpc_assume_partition_disengaged(partid);
268                         disengaged = 1;
269                 }
270                 part->disengage_timeout = 0;
271
272                 /* cancel the timer function, provided it's not us */
273                 if (!in_interrupt())
274                         del_singleshot_timer_sync(&part->disengage_timer);
275
276                 DBUG_ON(part->act_state != XPC_P_DEACTIVATING &&
277                         part->act_state != XPC_P_INACTIVE);
278                 if (part->act_state != XPC_P_INACTIVE)
279                         xpc_wakeup_channel_mgr(part);
280
281                 xpc_cancel_partition_deactivation_request(part);
282         }
283         return disengaged;
284 }
285
286 /*
287  * Mark specified partition as active.
288  */
289 enum xp_retval
290 xpc_mark_partition_active(struct xpc_partition *part)
291 {
292         unsigned long irq_flags;
293         enum xp_retval ret;
294
295         dev_dbg(xpc_part, "setting partition %d to ACTIVE\n", XPC_PARTID(part));
296
297         spin_lock_irqsave(&part->act_lock, irq_flags);
298         if (part->act_state == XPC_P_ACTIVATING) {
299                 part->act_state = XPC_P_ACTIVE;
300                 ret = xpSuccess;
301         } else {
302                 DBUG_ON(part->reason == xpSuccess);
303                 ret = part->reason;
304         }
305         spin_unlock_irqrestore(&part->act_lock, irq_flags);
306
307         return ret;
308 }
309
310 /*
311  * Start the process of deactivating the specified partition.
312  */
313 void
314 xpc_deactivate_partition(const int line, struct xpc_partition *part,
315                          enum xp_retval reason)
316 {
317         unsigned long irq_flags;
318
319         spin_lock_irqsave(&part->act_lock, irq_flags);
320
321         if (part->act_state == XPC_P_INACTIVE) {
322                 XPC_SET_REASON(part, reason, line);
323                 spin_unlock_irqrestore(&part->act_lock, irq_flags);
324                 if (reason == xpReactivating) {
325                         /* we interrupt ourselves to reactivate partition */
326                         xpc_request_partition_reactivation(part);
327                 }
328                 return;
329         }
330         if (part->act_state == XPC_P_DEACTIVATING) {
331                 if ((part->reason == xpUnloading && reason != xpUnloading) ||
332                     reason == xpReactivating) {
333                         XPC_SET_REASON(part, reason, line);
334                 }
335                 spin_unlock_irqrestore(&part->act_lock, irq_flags);
336                 return;
337         }
338
339         part->act_state = XPC_P_DEACTIVATING;
340         XPC_SET_REASON(part, reason, line);
341
342         spin_unlock_irqrestore(&part->act_lock, irq_flags);
343
344         /* ask remote partition to deactivate with regard to us */
345         xpc_request_partition_deactivation(part);
346
347         /* set a timelimit on the disengage phase of the deactivation request */
348         part->disengage_timeout = jiffies + (xpc_disengage_timelimit * HZ);
349         part->disengage_timer.expires = part->disengage_timeout;
350         add_timer(&part->disengage_timer);
351
352         dev_dbg(xpc_part, "bringing partition %d down, reason = %d\n",
353                 XPC_PARTID(part), reason);
354
355         xpc_partition_going_down(part, reason);
356 }
357
358 /*
359  * Mark specified partition as inactive.
360  */
361 void
362 xpc_mark_partition_inactive(struct xpc_partition *part)
363 {
364         unsigned long irq_flags;
365
366         dev_dbg(xpc_part, "setting partition %d to INACTIVE\n",
367                 XPC_PARTID(part));
368
369         spin_lock_irqsave(&part->act_lock, irq_flags);
370         part->act_state = XPC_P_INACTIVE;
371         spin_unlock_irqrestore(&part->act_lock, irq_flags);
372         part->remote_rp_pa = 0;
373 }
374
375 /*
376  * SAL has provided a partition and machine mask.  The partition mask
377  * contains a bit for each even nasid in our partition.  The machine
378  * mask contains a bit for each even nasid in the entire machine.
379  *
380  * Using those two bit arrays, we can determine which nasids are
381  * known in the machine.  Each should also have a reserved page
382  * initialized if they are available for partitioning.
383  */
384 void
385 xpc_discovery(void)
386 {
387         void *remote_rp_base;
388         struct xpc_rsvd_page *remote_rp;
389         unsigned long remote_rp_pa;
390         int region;
391         int region_size;
392         int max_regions;
393         int nasid;
394         struct xpc_rsvd_page *rp;
395         unsigned long *discovered_nasids;
396         enum xp_retval ret;
397
398         remote_rp = xpc_kmalloc_cacheline_aligned(XPC_RP_HEADER_SIZE +
399                                                   xpc_nasid_mask_nbytes,
400                                                   GFP_KERNEL, &remote_rp_base);
401         if (remote_rp == NULL)
402                 return;
403
404         discovered_nasids = kzalloc(sizeof(long) * xpc_nasid_mask_nlongs,
405                                     GFP_KERNEL);
406         if (discovered_nasids == NULL) {
407                 kfree(remote_rp_base);
408                 return;
409         }
410
411         rp = (struct xpc_rsvd_page *)xpc_rsvd_page;
412
413         /*
414          * The term 'region' in this context refers to the minimum number of
415          * nodes that can comprise an access protection grouping. The access
416          * protection is in regards to memory, IOI and IPI.
417          */
418         max_regions = 64;
419         region_size = xp_region_size;
420
421         switch (region_size) {
422         case 128:
423                 max_regions *= 2;
424         case 64:
425                 max_regions *= 2;
426         case 32:
427                 max_regions *= 2;
428                 region_size = 16;
429                 DBUG_ON(!is_shub2());
430         }
431
432         for (region = 0; region < max_regions; region++) {
433
434                 if (xpc_exiting)
435                         break;
436
437                 dev_dbg(xpc_part, "searching region %d\n", region);
438
439                 for (nasid = (region * region_size * 2);
440                      nasid < ((region + 1) * region_size * 2); nasid += 2) {
441
442                         if (xpc_exiting)
443                                 break;
444
445                         dev_dbg(xpc_part, "checking nasid %d\n", nasid);
446
447                         if (test_bit(nasid / 2, xpc_part_nasids)) {
448                                 dev_dbg(xpc_part, "PROM indicates Nasid %d is "
449                                         "part of the local partition; skipping "
450                                         "region\n", nasid);
451                                 break;
452                         }
453
454                         if (!(test_bit(nasid / 2, xpc_mach_nasids))) {
455                                 dev_dbg(xpc_part, "PROM indicates Nasid %d was "
456                                         "not on Numa-Link network at reset\n",
457                                         nasid);
458                                 continue;
459                         }
460
461                         if (test_bit(nasid / 2, discovered_nasids)) {
462                                 dev_dbg(xpc_part, "Nasid %d is part of a "
463                                         "partition which was previously "
464                                         "discovered\n", nasid);
465                                 continue;
466                         }
467
468                         /* pull over the rsvd page header & part_nasids mask */
469
470                         ret = xpc_get_remote_rp(nasid, discovered_nasids,
471                                                 remote_rp, &remote_rp_pa);
472                         if (ret != xpSuccess) {
473                                 dev_dbg(xpc_part, "unable to get reserved page "
474                                         "from nasid %d, reason=%d\n", nasid,
475                                         ret);
476
477                                 if (ret == xpLocalPartid)
478                                         break;
479
480                                 continue;
481                         }
482
483                         xpc_request_partition_activation(remote_rp,
484                                                          remote_rp_pa, nasid);
485                 }
486         }
487
488         kfree(discovered_nasids);
489         kfree(remote_rp_base);
490 }
491
492 /*
493  * Given a partid, get the nasids owned by that partition from the
494  * remote partition's reserved page.
495  */
496 enum xp_retval
497 xpc_initiate_partid_to_nasids(short partid, void *nasid_mask)
498 {
499         struct xpc_partition *part;
500         unsigned long part_nasid_pa;
501
502         part = &xpc_partitions[partid];
503         if (part->remote_rp_pa == 0)
504                 return xpPartitionDown;
505
506         memset(nasid_mask, 0, xpc_nasid_mask_nbytes);
507
508         part_nasid_pa = (unsigned long)XPC_RP_PART_NASIDS(part->remote_rp_pa);
509
510         return xp_remote_memcpy(xp_pa(nasid_mask), part_nasid_pa,
511                                 xpc_nasid_mask_nbytes);
512 }