[PATCH] ppc64: Fix compile warnings in arch/ppc64/kernel/lparcfg.c
[linux-2.6] / arch / ppc64 / kernel / mf.c
1 /*
2   * mf.c
3   * Copyright (C) 2001 Troy D. Armstrong  IBM Corporation
4   * Copyright (C) 2004-2005 Stephen Rothwell  IBM Corporation
5   *
6   * This modules exists as an interface between a Linux secondary partition
7   * running on an iSeries and the primary partition's Virtual Service
8   * Processor (VSP) object.  The VSP has final authority over powering on/off
9   * all partitions in the iSeries.  It also provides miscellaneous low-level
10   * machine facility type operations.
11   *
12   *
13   * This program is free software; you can redistribute it and/or modify
14   * it under the terms of the GNU General Public License as published by
15   * the Free Software Foundation; either version 2 of the License, or
16   * (at your option) any later version.
17   *
18   * This program is distributed in the hope that it will be useful,
19   * but WITHOUT ANY WARRANTY; without even the implied warranty of
20   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21   * GNU General Public License for more details.
22   *
23   * You should have received a copy of the GNU General Public License
24   * along with this program; if not, write to the Free Software
25   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
26   */
27
28 #include <linux/types.h>
29 #include <linux/errno.h>
30 #include <linux/kernel.h>
31 #include <linux/init.h>
32 #include <linux/completion.h>
33 #include <linux/delay.h>
34 #include <linux/dma-mapping.h>
35 #include <linux/bcd.h>
36
37 #include <asm/time.h>
38 #include <asm/uaccess.h>
39 #include <asm/paca.h>
40 #include <asm/iSeries/vio.h>
41 #include <asm/iSeries/mf.h>
42 #include <asm/iSeries/HvLpConfig.h>
43 #include <asm/iSeries/ItLpQueue.h>
44
45 /*
46  * This is the structure layout for the Machine Facilites LPAR event
47  * flows.
48  */
49 struct vsp_cmd_data {
50         u64 token;
51         u16 cmd;
52         HvLpIndex lp_index;
53         u8 result_code;
54         u32 reserved;
55         union {
56                 u64 state;      /* GetStateOut */
57                 u64 ipl_type;   /* GetIplTypeOut, Function02SelectIplTypeIn */
58                 u64 ipl_mode;   /* GetIplModeOut, Function02SelectIplModeIn */
59                 u64 page[4];    /* GetSrcHistoryIn */
60                 u64 flag;       /* GetAutoIplWhenPrimaryIplsOut,
61                                    SetAutoIplWhenPrimaryIplsIn,
62                                    WhiteButtonPowerOffIn,
63                                    Function08FastPowerOffIn,
64                                    IsSpcnRackPowerIncompleteOut */
65                 struct {
66                         u64 token;
67                         u64 address_type;
68                         u64 side;
69                         u32 length;
70                         u32 offset;
71                 } kern;         /* SetKernelImageIn, GetKernelImageIn,
72                                    SetKernelCmdLineIn, GetKernelCmdLineIn */
73                 u32 length_out; /* GetKernelImageOut, GetKernelCmdLineOut */
74                 u8 reserved[80];
75         } sub_data;
76 };
77
78 struct vsp_rsp_data {
79         struct completion com;
80         struct vsp_cmd_data *response;
81 };
82
83 struct alloc_data {
84         u16 size;
85         u16 type;
86         u32 count;
87         u16 reserved1;
88         u8 reserved2;
89         HvLpIndex target_lp;
90 };
91
92 struct ce_msg_data;
93
94 typedef void (*ce_msg_comp_hdlr)(void *token, struct ce_msg_data *vsp_cmd_rsp);
95
96 struct ce_msg_comp_data {
97         ce_msg_comp_hdlr handler;
98         void *token;
99 };
100
101 struct ce_msg_data {
102         u8 ce_msg[12];
103         char reserved[4];
104         struct ce_msg_comp_data *completion;
105 };
106
107 struct io_mf_lp_event {
108         struct HvLpEvent hp_lp_event;
109         u16 subtype_result_code;
110         u16 reserved1;
111         u32 reserved2;
112         union {
113                 struct alloc_data alloc;
114                 struct ce_msg_data ce_msg;
115                 struct vsp_cmd_data vsp_cmd;
116         } data;
117 };
118
119 #define subtype_data(a, b, c, d)        \
120                 (((a) << 24) + ((b) << 16) + ((c) << 8) + (d))
121
122 /*
123  * All outgoing event traffic is kept on a FIFO queue.  The first
124  * pointer points to the one that is outstanding, and all new
125  * requests get stuck on the end.  Also, we keep a certain number of
126  * preallocated pending events so that we can operate very early in
127  * the boot up sequence (before kmalloc is ready).
128  */
129 struct pending_event {
130         struct pending_event *next;
131         struct io_mf_lp_event event;
132         MFCompleteHandler hdlr;
133         char dma_data[72];
134         unsigned dma_data_length;
135         unsigned remote_address;
136 };
137 static spinlock_t pending_event_spinlock;
138 static struct pending_event *pending_event_head;
139 static struct pending_event *pending_event_tail;
140 static struct pending_event *pending_event_avail;
141 static struct pending_event pending_event_prealloc[16];
142
143 /*
144  * Put a pending event onto the available queue, so it can get reused.
145  * Attention! You must have the pending_event_spinlock before calling!
146  */
147 static void free_pending_event(struct pending_event *ev)
148 {
149         if (ev != NULL) {
150                 ev->next = pending_event_avail;
151                 pending_event_avail = ev;
152         }
153 }
154
155 /*
156  * Enqueue the outbound event onto the stack.  If the queue was
157  * empty to begin with, we must also issue it via the Hypervisor
158  * interface.  There is a section of code below that will touch
159  * the first stack pointer without the protection of the pending_event_spinlock.
160  * This is OK, because we know that nobody else will be modifying
161  * the first pointer when we do this.
162  */
163 static int signal_event(struct pending_event *ev)
164 {
165         int rc = 0;
166         unsigned long flags;
167         int go = 1;
168         struct pending_event *ev1;
169         HvLpEvent_Rc hv_rc;
170
171         /* enqueue the event */
172         if (ev != NULL) {
173                 ev->next = NULL;
174                 spin_lock_irqsave(&pending_event_spinlock, flags);
175                 if (pending_event_head == NULL)
176                         pending_event_head = ev;
177                 else {
178                         go = 0;
179                         pending_event_tail->next = ev;
180                 }
181                 pending_event_tail = ev;
182                 spin_unlock_irqrestore(&pending_event_spinlock, flags);
183         }
184
185         /* send the event */
186         while (go) {
187                 go = 0;
188
189                 /* any DMA data to send beforehand? */
190                 if (pending_event_head->dma_data_length > 0)
191                         HvCallEvent_dmaToSp(pending_event_head->dma_data,
192                                         pending_event_head->remote_address,
193                                         pending_event_head->dma_data_length,
194                                         HvLpDma_Direction_LocalToRemote);
195
196                 hv_rc = HvCallEvent_signalLpEvent(
197                                 &pending_event_head->event.hp_lp_event);
198                 if (hv_rc != HvLpEvent_Rc_Good) {
199                         printk(KERN_ERR "mf.c: HvCallEvent_signalLpEvent() "
200                                         "failed with %d\n", (int)hv_rc);
201
202                         spin_lock_irqsave(&pending_event_spinlock, flags);
203                         ev1 = pending_event_head;
204                         pending_event_head = pending_event_head->next;
205                         if (pending_event_head != NULL)
206                                 go = 1;
207                         spin_unlock_irqrestore(&pending_event_spinlock, flags);
208
209                         if (ev1 == ev)
210                                 rc = -EIO;
211                         else if (ev1->hdlr != NULL)
212                                 (*ev1->hdlr)((void *)ev1->event.hp_lp_event.xCorrelationToken, -EIO);
213
214                         spin_lock_irqsave(&pending_event_spinlock, flags);
215                         free_pending_event(ev1);
216                         spin_unlock_irqrestore(&pending_event_spinlock, flags);
217                 }
218         }
219
220         return rc;
221 }
222
223 /*
224  * Allocate a new pending_event structure, and initialize it.
225  */
226 static struct pending_event *new_pending_event(void)
227 {
228         struct pending_event *ev = NULL;
229         HvLpIndex primary_lp = HvLpConfig_getPrimaryLpIndex();
230         unsigned long flags;
231         struct HvLpEvent *hev;
232
233         spin_lock_irqsave(&pending_event_spinlock, flags);
234         if (pending_event_avail != NULL) {
235                 ev = pending_event_avail;
236                 pending_event_avail = pending_event_avail->next;
237         }
238         spin_unlock_irqrestore(&pending_event_spinlock, flags);
239         if (ev == NULL) {
240                 ev = kmalloc(sizeof(struct pending_event), GFP_ATOMIC);
241                 if (ev == NULL) {
242                         printk(KERN_ERR "mf.c: unable to kmalloc %ld bytes\n",
243                                         sizeof(struct pending_event));
244                         return NULL;
245                 }
246         }
247         memset(ev, 0, sizeof(struct pending_event));
248         hev = &ev->event.hp_lp_event;
249         hev->xFlags.xValid = 1;
250         hev->xFlags.xAckType = HvLpEvent_AckType_ImmediateAck;
251         hev->xFlags.xAckInd = HvLpEvent_AckInd_DoAck;
252         hev->xFlags.xFunction = HvLpEvent_Function_Int;
253         hev->xType = HvLpEvent_Type_MachineFac;
254         hev->xSourceLp = HvLpConfig_getLpIndex();
255         hev->xTargetLp = primary_lp;
256         hev->xSizeMinus1 = sizeof(ev->event) - 1;
257         hev->xRc = HvLpEvent_Rc_Good;
258         hev->xSourceInstanceId = HvCallEvent_getSourceLpInstanceId(primary_lp,
259                         HvLpEvent_Type_MachineFac);
260         hev->xTargetInstanceId = HvCallEvent_getTargetLpInstanceId(primary_lp,
261                         HvLpEvent_Type_MachineFac);
262
263         return ev;
264 }
265
266 static int signal_vsp_instruction(struct vsp_cmd_data *vsp_cmd)
267 {
268         struct pending_event *ev = new_pending_event();
269         int rc;
270         struct vsp_rsp_data response;
271
272         if (ev == NULL)
273                 return -ENOMEM;
274
275         init_completion(&response.com);
276         response.response = vsp_cmd;
277         ev->event.hp_lp_event.xSubtype = 6;
278         ev->event.hp_lp_event.x.xSubtypeData =
279                 subtype_data('M', 'F',  'V',  'I');
280         ev->event.data.vsp_cmd.token = (u64)&response;
281         ev->event.data.vsp_cmd.cmd = vsp_cmd->cmd;
282         ev->event.data.vsp_cmd.lp_index = HvLpConfig_getLpIndex();
283         ev->event.data.vsp_cmd.result_code = 0xFF;
284         ev->event.data.vsp_cmd.reserved = 0;
285         memcpy(&(ev->event.data.vsp_cmd.sub_data),
286                         &(vsp_cmd->sub_data), sizeof(vsp_cmd->sub_data));
287         mb();
288
289         rc = signal_event(ev);
290         if (rc == 0)
291                 wait_for_completion(&response.com);
292         return rc;
293 }
294
295
296 /*
297  * Send a 12-byte CE message to the primary partition VSP object
298  */
299 static int signal_ce_msg(char *ce_msg, struct ce_msg_comp_data *completion)
300 {
301         struct pending_event *ev = new_pending_event();
302
303         if (ev == NULL)
304                 return -ENOMEM;
305
306         ev->event.hp_lp_event.xSubtype = 0;
307         ev->event.hp_lp_event.x.xSubtypeData =
308                 subtype_data('M',  'F',  'C',  'E');
309         memcpy(ev->event.data.ce_msg.ce_msg, ce_msg, 12);
310         ev->event.data.ce_msg.completion = completion;
311         return signal_event(ev);
312 }
313
314 /*
315  * Send a 12-byte CE message (with no data) to the primary partition VSP object
316  */
317 static int signal_ce_msg_simple(u8 ce_op, struct ce_msg_comp_data *completion)
318 {
319         u8 ce_msg[12];
320
321         memset(ce_msg, 0, sizeof(ce_msg));
322         ce_msg[3] = ce_op;
323         return signal_ce_msg(ce_msg, completion);
324 }
325
326 /*
327  * Send a 12-byte CE message and DMA data to the primary partition VSP object
328  */
329 static int dma_and_signal_ce_msg(char *ce_msg,
330                 struct ce_msg_comp_data *completion, void *dma_data,
331                 unsigned dma_data_length, unsigned remote_address)
332 {
333         struct pending_event *ev = new_pending_event();
334
335         if (ev == NULL)
336                 return -ENOMEM;
337
338         ev->event.hp_lp_event.xSubtype = 0;
339         ev->event.hp_lp_event.x.xSubtypeData =
340                 subtype_data('M', 'F', 'C', 'E');
341         memcpy(ev->event.data.ce_msg.ce_msg, ce_msg, 12);
342         ev->event.data.ce_msg.completion = completion;
343         memcpy(ev->dma_data, dma_data, dma_data_length);
344         ev->dma_data_length = dma_data_length;
345         ev->remote_address = remote_address;
346         return signal_event(ev);
347 }
348
349 /*
350  * Initiate a nice (hopefully) shutdown of Linux.  We simply are
351  * going to try and send the init process a SIGINT signal.  If
352  * this fails (why?), we'll simply force it off in a not-so-nice
353  * manner.
354  */
355 static int shutdown(void)
356 {
357         int rc = kill_proc(1, SIGINT, 1);
358
359         if (rc) {
360                 printk(KERN_ALERT "mf.c: SIGINT to init failed (%d), "
361                                 "hard shutdown commencing\n", rc);
362                 mf_power_off();
363         } else
364                 printk(KERN_INFO "mf.c: init has been successfully notified "
365                                 "to proceed with shutdown\n");
366         return rc;
367 }
368
369 /*
370  * The primary partition VSP object is sending us a new
371  * event flow.  Handle it...
372  */
373 static void handle_int(struct io_mf_lp_event *event)
374 {
375         struct ce_msg_data *ce_msg_data;
376         struct ce_msg_data *pce_msg_data;
377         unsigned long flags;
378         struct pending_event *pev;
379
380         /* ack the interrupt */
381         event->hp_lp_event.xRc = HvLpEvent_Rc_Good;
382         HvCallEvent_ackLpEvent(&event->hp_lp_event);
383
384         /* process interrupt */
385         switch (event->hp_lp_event.xSubtype) {
386         case 0: /* CE message */
387                 ce_msg_data = &event->data.ce_msg;
388                 switch (ce_msg_data->ce_msg[3]) {
389                 case 0x5B:      /* power control notification */
390                         if ((ce_msg_data->ce_msg[5] & 0x20) != 0) {
391                                 printk(KERN_INFO "mf.c: Commencing partition shutdown\n");
392                                 if (shutdown() == 0)
393                                         signal_ce_msg_simple(0xDB, NULL);
394                         }
395                         break;
396                 case 0xC0:      /* get time */
397                         spin_lock_irqsave(&pending_event_spinlock, flags);
398                         pev = pending_event_head;
399                         if (pev != NULL)
400                                 pending_event_head = pending_event_head->next;
401                         spin_unlock_irqrestore(&pending_event_spinlock, flags);
402                         if (pev == NULL)
403                                 break;
404                         pce_msg_data = &pev->event.data.ce_msg;
405                         if (pce_msg_data->ce_msg[3] != 0x40)
406                                 break;
407                         if (pce_msg_data->completion != NULL) {
408                                 ce_msg_comp_hdlr handler =
409                                         pce_msg_data->completion->handler;
410                                 void *token = pce_msg_data->completion->token;
411
412                                 if (handler != NULL)
413                                         (*handler)(token, ce_msg_data);
414                         }
415                         spin_lock_irqsave(&pending_event_spinlock, flags);
416                         free_pending_event(pev);
417                         spin_unlock_irqrestore(&pending_event_spinlock, flags);
418                         /* send next waiting event */
419                         if (pending_event_head != NULL)
420                                 signal_event(NULL);
421                         break;
422                 }
423                 break;
424         case 1: /* IT sys shutdown */
425                 printk(KERN_INFO "mf.c: Commencing system shutdown\n");
426                 shutdown();
427                 break;
428         }
429 }
430
431 /*
432  * The primary partition VSP object is acknowledging the receipt
433  * of a flow we sent to them.  If there are other flows queued
434  * up, we must send another one now...
435  */
436 static void handle_ack(struct io_mf_lp_event *event)
437 {
438         unsigned long flags;
439         struct pending_event *two = NULL;
440         unsigned long free_it = 0;
441         struct ce_msg_data *ce_msg_data;
442         struct ce_msg_data *pce_msg_data;
443         struct vsp_rsp_data *rsp;
444
445         /* handle current event */
446         if (pending_event_head == NULL) {
447                 printk(KERN_ERR "mf.c: stack empty for receiving ack\n");
448                 return;
449         }
450
451         switch (event->hp_lp_event.xSubtype) {
452         case 0:     /* CE msg */
453                 ce_msg_data = &event->data.ce_msg;
454                 if (ce_msg_data->ce_msg[3] != 0x40) {
455                         free_it = 1;
456                         break;
457                 }
458                 if (ce_msg_data->ce_msg[2] == 0)
459                         break;
460                 free_it = 1;
461                 pce_msg_data = &pending_event_head->event.data.ce_msg;
462                 if (pce_msg_data->completion != NULL) {
463                         ce_msg_comp_hdlr handler =
464                                 pce_msg_data->completion->handler;
465                         void *token = pce_msg_data->completion->token;
466
467                         if (handler != NULL)
468                                 (*handler)(token, ce_msg_data);
469                 }
470                 break;
471         case 4: /* allocate */
472         case 5: /* deallocate */
473                 if (pending_event_head->hdlr != NULL)
474                         (*pending_event_head->hdlr)((void *)event->hp_lp_event.xCorrelationToken, event->data.alloc.count);
475                 free_it = 1;
476                 break;
477         case 6:
478                 free_it = 1;
479                 rsp = (struct vsp_rsp_data *)event->data.vsp_cmd.token;
480                 if (rsp == NULL) {
481                         printk(KERN_ERR "mf.c: no rsp\n");
482                         break;
483                 }
484                 if (rsp->response != NULL)
485                         memcpy(rsp->response, &event->data.vsp_cmd,
486                                         sizeof(event->data.vsp_cmd));
487                 complete(&rsp->com);
488                 break;
489         }
490
491         /* remove from queue */
492         spin_lock_irqsave(&pending_event_spinlock, flags);
493         if ((pending_event_head != NULL) && (free_it == 1)) {
494                 struct pending_event *oldHead = pending_event_head;
495
496                 pending_event_head = pending_event_head->next;
497                 two = pending_event_head;
498                 free_pending_event(oldHead);
499         }
500         spin_unlock_irqrestore(&pending_event_spinlock, flags);
501
502         /* send next waiting event */
503         if (two != NULL)
504                 signal_event(NULL);
505 }
506
507 /*
508  * This is the generic event handler we are registering with
509  * the Hypervisor.  Ensure the flows are for us, and then
510  * parse it enough to know if it is an interrupt or an
511  * acknowledge.
512  */
513 static void hv_handler(struct HvLpEvent *event, struct pt_regs *regs)
514 {
515         if ((event != NULL) && (event->xType == HvLpEvent_Type_MachineFac)) {
516                 switch(event->xFlags.xFunction) {
517                 case HvLpEvent_Function_Ack:
518                         handle_ack((struct io_mf_lp_event *)event);
519                         break;
520                 case HvLpEvent_Function_Int:
521                         handle_int((struct io_mf_lp_event *)event);
522                         break;
523                 default:
524                         printk(KERN_ERR "mf.c: non ack/int event received\n");
525                         break;
526                 }
527         } else
528                 printk(KERN_ERR "mf.c: alien event received\n");
529 }
530
531 /*
532  * Global kernel interface to allocate and seed events into the
533  * Hypervisor.
534  */
535 void mf_allocate_lp_events(HvLpIndex target_lp, HvLpEvent_Type type,
536                 unsigned size, unsigned count, MFCompleteHandler hdlr,
537                 void *user_token)
538 {
539         struct pending_event *ev = new_pending_event();
540         int rc;
541
542         if (ev == NULL) {
543                 rc = -ENOMEM;
544         } else {
545                 ev->event.hp_lp_event.xSubtype = 4;
546                 ev->event.hp_lp_event.xCorrelationToken = (u64)user_token;
547                 ev->event.hp_lp_event.x.xSubtypeData =
548                         subtype_data('M', 'F', 'M', 'A');
549                 ev->event.data.alloc.target_lp = target_lp;
550                 ev->event.data.alloc.type = type;
551                 ev->event.data.alloc.size = size;
552                 ev->event.data.alloc.count = count;
553                 ev->hdlr = hdlr;
554                 rc = signal_event(ev);
555         }
556         if ((rc != 0) && (hdlr != NULL))
557                 (*hdlr)(user_token, rc);
558 }
559 EXPORT_SYMBOL(mf_allocate_lp_events);
560
561 /*
562  * Global kernel interface to unseed and deallocate events already in
563  * Hypervisor.
564  */
565 void mf_deallocate_lp_events(HvLpIndex target_lp, HvLpEvent_Type type,
566                 unsigned count, MFCompleteHandler hdlr, void *user_token)
567 {
568         struct pending_event *ev = new_pending_event();
569         int rc;
570
571         if (ev == NULL)
572                 rc = -ENOMEM;
573         else {
574                 ev->event.hp_lp_event.xSubtype = 5;
575                 ev->event.hp_lp_event.xCorrelationToken = (u64)user_token;
576                 ev->event.hp_lp_event.x.xSubtypeData =
577                         subtype_data('M', 'F', 'M', 'D');
578                 ev->event.data.alloc.target_lp = target_lp;
579                 ev->event.data.alloc.type = type;
580                 ev->event.data.alloc.count = count;
581                 ev->hdlr = hdlr;
582                 rc = signal_event(ev);
583         }
584         if ((rc != 0) && (hdlr != NULL))
585                 (*hdlr)(user_token, rc);
586 }
587 EXPORT_SYMBOL(mf_deallocate_lp_events);
588
589 /*
590  * Global kernel interface to tell the VSP object in the primary
591  * partition to power this partition off.
592  */
593 void mf_power_off(void)
594 {
595         printk(KERN_INFO "mf.c: Down it goes...\n");
596         signal_ce_msg_simple(0x4d, NULL);
597         for (;;)
598                 ;
599 }
600
601 /*
602  * Global kernel interface to tell the VSP object in the primary
603  * partition to reboot this partition.
604  */
605 void mf_reboot(void)
606 {
607         printk(KERN_INFO "mf.c: Preparing to bounce...\n");
608         signal_ce_msg_simple(0x4e, NULL);
609         for (;;)
610                 ;
611 }
612
613 /*
614  * Display a single word SRC onto the VSP control panel.
615  */
616 void mf_display_src(u32 word)
617 {
618         u8 ce[12];
619
620         memset(ce, 0, sizeof(ce));
621         ce[3] = 0x4a;
622         ce[7] = 0x01;
623         ce[8] = word >> 24;
624         ce[9] = word >> 16;
625         ce[10] = word >> 8;
626         ce[11] = word;
627         signal_ce_msg(ce, NULL);
628 }
629
630 /*
631  * Display a single word SRC of the form "PROGXXXX" on the VSP control panel.
632  */
633 void mf_display_progress(u16 value)
634 {
635         u8 ce[12];
636         u8 src[72];
637
638         memcpy(ce, "\x00\x00\x04\x4A\x00\x00\x00\x48\x00\x00\x00\x00", 12);
639         memcpy(src, "\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00"
640                 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
641                 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
642                 "\x00\x00\x00\x00PROGxxxx                        ",
643                 72);
644         src[6] = value >> 8;
645         src[7] = value & 255;
646         src[44] = "0123456789ABCDEF"[(value >> 12) & 15];
647         src[45] = "0123456789ABCDEF"[(value >> 8) & 15];
648         src[46] = "0123456789ABCDEF"[(value >> 4) & 15];
649         src[47] = "0123456789ABCDEF"[value & 15];
650         dma_and_signal_ce_msg(ce, NULL, src, sizeof(src), 9 * 64 * 1024);
651 }
652
653 /*
654  * Clear the VSP control panel.  Used to "erase" an SRC that was
655  * previously displayed.
656  */
657 void mf_clear_src(void)
658 {
659         signal_ce_msg_simple(0x4b, NULL);
660 }
661
662 /*
663  * Initialization code here.
664  */
665 void mf_init(void)
666 {
667         int i;
668
669         /* initialize */
670         spin_lock_init(&pending_event_spinlock);
671         for (i = 0;
672              i < sizeof(pending_event_prealloc) / sizeof(*pending_event_prealloc);
673              ++i)
674                 free_pending_event(&pending_event_prealloc[i]);
675         HvLpEvent_registerHandler(HvLpEvent_Type_MachineFac, &hv_handler);
676
677         /* virtual continue ack */
678         signal_ce_msg_simple(0x57, NULL);
679
680         /* initialization complete */
681         printk(KERN_NOTICE "mf.c: iSeries Linux LPAR Machine Facilities "
682                         "initialized\n");
683 }
684
685 struct rtc_time_data {
686         struct completion com;
687         struct ce_msg_data ce_msg;
688         int rc;
689 };
690
691 static void get_rtc_time_complete(void *token, struct ce_msg_data *ce_msg)
692 {
693         struct rtc_time_data *rtc = token;
694
695         memcpy(&rtc->ce_msg, ce_msg, sizeof(rtc->ce_msg));
696         rtc->rc = 0;
697         complete(&rtc->com);
698 }
699
700 static int rtc_set_tm(int rc, u8 *ce_msg, struct rtc_time *tm)
701 {
702         tm->tm_wday = 0;
703         tm->tm_yday = 0;
704         tm->tm_isdst = 0;
705         if (rc) {
706                 tm->tm_sec = 0;
707                 tm->tm_min = 0;
708                 tm->tm_hour = 0;
709                 tm->tm_mday = 15;
710                 tm->tm_mon = 5;
711                 tm->tm_year = 52;
712                 return rc;
713         }
714
715         if ((ce_msg[2] == 0xa9) ||
716             (ce_msg[2] == 0xaf)) {
717                 /* TOD clock is not set */
718                 tm->tm_sec = 1;
719                 tm->tm_min = 1;
720                 tm->tm_hour = 1;
721                 tm->tm_mday = 10;
722                 tm->tm_mon = 8;
723                 tm->tm_year = 71;
724                 mf_set_rtc(tm);
725         }
726         {
727                 u8 year = ce_msg[5];
728                 u8 sec = ce_msg[6];
729                 u8 min = ce_msg[7];
730                 u8 hour = ce_msg[8];
731                 u8 day = ce_msg[10];
732                 u8 mon = ce_msg[11];
733
734                 BCD_TO_BIN(sec);
735                 BCD_TO_BIN(min);
736                 BCD_TO_BIN(hour);
737                 BCD_TO_BIN(day);
738                 BCD_TO_BIN(mon);
739                 BCD_TO_BIN(year);
740
741                 if (year <= 69)
742                         year += 100;
743
744                 tm->tm_sec = sec;
745                 tm->tm_min = min;
746                 tm->tm_hour = hour;
747                 tm->tm_mday = day;
748                 tm->tm_mon = mon;
749                 tm->tm_year = year;
750         }
751
752         return 0;
753 }
754
755 int mf_get_rtc(struct rtc_time *tm)
756 {
757         struct ce_msg_comp_data ce_complete;
758         struct rtc_time_data rtc_data;
759         int rc;
760
761         memset(&ce_complete, 0, sizeof(ce_complete));
762         memset(&rtc_data, 0, sizeof(rtc_data));
763         init_completion(&rtc_data.com);
764         ce_complete.handler = &get_rtc_time_complete;
765         ce_complete.token = &rtc_data;
766         rc = signal_ce_msg_simple(0x40, &ce_complete);
767         if (rc)
768                 return rc;
769         wait_for_completion(&rtc_data.com);
770         return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm);
771 }
772
773 struct boot_rtc_time_data {
774         int busy;
775         struct ce_msg_data ce_msg;
776         int rc;
777 };
778
779 static void get_boot_rtc_time_complete(void *token, struct ce_msg_data *ce_msg)
780 {
781         struct boot_rtc_time_data *rtc = token;
782
783         memcpy(&rtc->ce_msg, ce_msg, sizeof(rtc->ce_msg));
784         rtc->rc = 0;
785         rtc->busy = 0;
786 }
787
788 int mf_get_boot_rtc(struct rtc_time *tm)
789 {
790         struct ce_msg_comp_data ce_complete;
791         struct boot_rtc_time_data rtc_data;
792         int rc;
793
794         memset(&ce_complete, 0, sizeof(ce_complete));
795         memset(&rtc_data, 0, sizeof(rtc_data));
796         rtc_data.busy = 1;
797         ce_complete.handler = &get_boot_rtc_time_complete;
798         ce_complete.token = &rtc_data;
799         rc = signal_ce_msg_simple(0x40, &ce_complete);
800         if (rc)
801                 return rc;
802         /* We need to poll here as we are not yet taking interrupts */
803         while (rtc_data.busy) {
804                 extern unsigned long lpevent_count;
805                 struct ItLpQueue *lpq = get_paca()->lpqueue_ptr;
806                 if (lpq && ItLpQueue_isLpIntPending(lpq))
807                         lpevent_count += ItLpQueue_process(lpq, NULL);
808         }
809         return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm);
810 }
811
812 int mf_set_rtc(struct rtc_time *tm)
813 {
814         char ce_time[12];
815         u8 day, mon, hour, min, sec, y1, y2;
816         unsigned year;
817
818         year = 1900 + tm->tm_year;
819         y1 = year / 100;
820         y2 = year % 100;
821
822         sec = tm->tm_sec;
823         min = tm->tm_min;
824         hour = tm->tm_hour;
825         day = tm->tm_mday;
826         mon = tm->tm_mon + 1;
827
828         BIN_TO_BCD(sec);
829         BIN_TO_BCD(min);
830         BIN_TO_BCD(hour);
831         BIN_TO_BCD(mon);
832         BIN_TO_BCD(day);
833         BIN_TO_BCD(y1);
834         BIN_TO_BCD(y2);
835
836         memset(ce_time, 0, sizeof(ce_time));
837         ce_time[3] = 0x41;
838         ce_time[4] = y1;
839         ce_time[5] = y2;
840         ce_time[6] = sec;
841         ce_time[7] = min;
842         ce_time[8] = hour;
843         ce_time[10] = day;
844         ce_time[11] = mon;
845
846         return signal_ce_msg(ce_time, NULL);
847 }
848
849 #ifdef CONFIG_PROC_FS
850
851 static int proc_mf_dump_cmdline(char *page, char **start, off_t off,
852                 int count, int *eof, void *data)
853 {
854         int len;
855         char *p;
856         struct vsp_cmd_data vsp_cmd;
857         int rc;
858         dma_addr_t dma_addr;
859
860         /* The HV appears to return no more than 256 bytes of command line */
861         if (off >= 256)
862                 return 0;
863         if ((off + count) > 256)
864                 count = 256 - off;
865
866         dma_addr = dma_map_single(iSeries_vio_dev, page, off + count,
867                         DMA_FROM_DEVICE);
868         if (dma_mapping_error(dma_addr))
869                 return -ENOMEM;
870         memset(page, 0, off + count);
871         memset(&vsp_cmd, 0, sizeof(vsp_cmd));
872         vsp_cmd.cmd = 33;
873         vsp_cmd.sub_data.kern.token = dma_addr;
874         vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex;
875         vsp_cmd.sub_data.kern.side = (u64)data;
876         vsp_cmd.sub_data.kern.length = off + count;
877         mb();
878         rc = signal_vsp_instruction(&vsp_cmd);
879         dma_unmap_single(iSeries_vio_dev, dma_addr, off + count,
880                         DMA_FROM_DEVICE);
881         if (rc)
882                 return rc;
883         if (vsp_cmd.result_code != 0)
884                 return -ENOMEM;
885         p = page;
886         len = 0;
887         while (len < (off + count)) {
888                 if ((*p == '\0') || (*p == '\n')) {
889                         if (*p == '\0')
890                                 *p = '\n';
891                         p++;
892                         len++;
893                         *eof = 1;
894                         break;
895                 }
896                 p++;
897                 len++;
898         }
899
900         if (len < off) {
901                 *eof = 1;
902                 len = 0;
903         }
904         return len;
905 }
906
907 #if 0
908 static int mf_getVmlinuxChunk(char *buffer, int *size, int offset, u64 side)
909 {
910         struct vsp_cmd_data vsp_cmd;
911         int rc;
912         int len = *size;
913         dma_addr_t dma_addr;
914
915         dma_addr = dma_map_single(iSeries_vio_dev, buffer, len,
916                         DMA_FROM_DEVICE);
917         memset(buffer, 0, len);
918         memset(&vsp_cmd, 0, sizeof(vsp_cmd));
919         vsp_cmd.cmd = 32;
920         vsp_cmd.sub_data.kern.token = dma_addr;
921         vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex;
922         vsp_cmd.sub_data.kern.side = side;
923         vsp_cmd.sub_data.kern.offset = offset;
924         vsp_cmd.sub_data.kern.length = len;
925         mb();
926         rc = signal_vsp_instruction(&vsp_cmd);
927         if (rc == 0) {
928                 if (vsp_cmd.result_code == 0)
929                         *size = vsp_cmd.sub_data.length_out;
930                 else
931                         rc = -ENOMEM;
932         }
933
934         dma_unmap_single(iSeries_vio_dev, dma_addr, len, DMA_FROM_DEVICE);
935
936         return rc;
937 }
938
939 static int proc_mf_dump_vmlinux(char *page, char **start, off_t off,
940                 int count, int *eof, void *data)
941 {
942         int sizeToGet = count;
943
944         if (!capable(CAP_SYS_ADMIN))
945                 return -EACCES;
946
947         if (mf_getVmlinuxChunk(page, &sizeToGet, off, (u64)data) == 0) {
948                 if (sizeToGet != 0) {
949                         *start = page + off;
950                         return sizeToGet;
951                 }
952                 *eof = 1;
953                 return 0;
954         }
955         *eof = 1;
956         return 0;
957 }
958 #endif
959
960 static int proc_mf_dump_side(char *page, char **start, off_t off,
961                 int count, int *eof, void *data)
962 {
963         int len;
964         char mf_current_side = ' ';
965         struct vsp_cmd_data vsp_cmd;
966
967         memset(&vsp_cmd, 0, sizeof(vsp_cmd));
968         vsp_cmd.cmd = 2;
969         vsp_cmd.sub_data.ipl_type = 0;
970         mb();
971
972         if (signal_vsp_instruction(&vsp_cmd) == 0) {
973                 if (vsp_cmd.result_code == 0) {
974                         switch (vsp_cmd.sub_data.ipl_type) {
975                         case 0: mf_current_side = 'A';
976                                 break;
977                         case 1: mf_current_side = 'B';
978                                 break;
979                         case 2: mf_current_side = 'C';
980                                 break;
981                         default:        mf_current_side = 'D';
982                                 break;
983                         }
984                 }
985         }
986
987         len = sprintf(page, "%c\n", mf_current_side);
988
989         if (len <= (off + count))
990                 *eof = 1;
991         *start = page + off;
992         len -= off;
993         if (len > count)
994                 len = count;
995         if (len < 0)
996                 len = 0;
997         return len;
998 }
999
1000 static int proc_mf_change_side(struct file *file, const char __user *buffer,
1001                 unsigned long count, void *data)
1002 {
1003         char side;
1004         u64 newSide;
1005         struct vsp_cmd_data vsp_cmd;
1006
1007         if (!capable(CAP_SYS_ADMIN))
1008                 return -EACCES;
1009
1010         if (count == 0)
1011                 return 0;
1012
1013         if (get_user(side, buffer))
1014                 return -EFAULT;
1015
1016         switch (side) {
1017         case 'A':       newSide = 0;
1018                         break;
1019         case 'B':       newSide = 1;
1020                         break;
1021         case 'C':       newSide = 2;
1022                         break;
1023         case 'D':       newSide = 3;
1024                         break;
1025         default:
1026                 printk(KERN_ERR "mf_proc.c: proc_mf_change_side: invalid side\n");
1027                 return -EINVAL;
1028         }
1029
1030         memset(&vsp_cmd, 0, sizeof(vsp_cmd));
1031         vsp_cmd.sub_data.ipl_type = newSide;
1032         vsp_cmd.cmd = 10;
1033
1034         (void)signal_vsp_instruction(&vsp_cmd);
1035
1036         return count;
1037 }
1038
1039 #if 0
1040 static void mf_getSrcHistory(char *buffer, int size)
1041 {
1042         struct IplTypeReturnStuff return_stuff;
1043         struct pending_event *ev = new_pending_event();
1044         int rc = 0;
1045         char *pages[4];
1046
1047         pages[0] = kmalloc(4096, GFP_ATOMIC);
1048         pages[1] = kmalloc(4096, GFP_ATOMIC);
1049         pages[2] = kmalloc(4096, GFP_ATOMIC);
1050         pages[3] = kmalloc(4096, GFP_ATOMIC);
1051         if ((ev == NULL) || (pages[0] == NULL) || (pages[1] == NULL)
1052                          || (pages[2] == NULL) || (pages[3] == NULL))
1053                 return -ENOMEM;
1054
1055         return_stuff.xType = 0;
1056         return_stuff.xRc = 0;
1057         return_stuff.xDone = 0;
1058         ev->event.hp_lp_event.xSubtype = 6;
1059         ev->event.hp_lp_event.x.xSubtypeData =
1060                 subtype_data('M', 'F', 'V', 'I');
1061         ev->event.data.vsp_cmd.xEvent = &return_stuff;
1062         ev->event.data.vsp_cmd.cmd = 4;
1063         ev->event.data.vsp_cmd.lp_index = HvLpConfig_getLpIndex();
1064         ev->event.data.vsp_cmd.result_code = 0xFF;
1065         ev->event.data.vsp_cmd.reserved = 0;
1066         ev->event.data.vsp_cmd.sub_data.page[0] = ISERIES_HV_ADDR(pages[0]);
1067         ev->event.data.vsp_cmd.sub_data.page[1] = ISERIES_HV_ADDR(pages[1]);
1068         ev->event.data.vsp_cmd.sub_data.page[2] = ISERIES_HV_ADDR(pages[2]);
1069         ev->event.data.vsp_cmd.sub_data.page[3] = ISERIES_HV_ADDR(pages[3]);
1070         mb();
1071         if (signal_event(ev) != 0)
1072                 return;
1073
1074         while (return_stuff.xDone != 1)
1075                 udelay(10);
1076         if (return_stuff.xRc == 0)
1077                 memcpy(buffer, pages[0], size);
1078         kfree(pages[0]);
1079         kfree(pages[1]);
1080         kfree(pages[2]);
1081         kfree(pages[3]);
1082 }
1083 #endif
1084
1085 static int proc_mf_dump_src(char *page, char **start, off_t off,
1086                 int count, int *eof, void *data)
1087 {
1088 #if 0
1089         int len;
1090
1091         mf_getSrcHistory(page, count);
1092         len = count;
1093         len -= off;
1094         if (len < count) {
1095                 *eof = 1;
1096                 if (len <= 0)
1097                         return 0;
1098         } else
1099                 len = count;
1100         *start = page + off;
1101         return len;
1102 #else
1103         return 0;
1104 #endif
1105 }
1106
1107 static int proc_mf_change_src(struct file *file, const char __user *buffer,
1108                 unsigned long count, void *data)
1109 {
1110         char stkbuf[10];
1111
1112         if (!capable(CAP_SYS_ADMIN))
1113                 return -EACCES;
1114
1115         if ((count < 4) && (count != 1)) {
1116                 printk(KERN_ERR "mf_proc: invalid src\n");
1117                 return -EINVAL;
1118         }
1119
1120         if (count > (sizeof(stkbuf) - 1))
1121                 count = sizeof(stkbuf) - 1;
1122         if (copy_from_user(stkbuf, buffer, count))
1123                 return -EFAULT;
1124
1125         if ((count == 1) && (*stkbuf == '\0'))
1126                 mf_clear_src();
1127         else
1128                 mf_display_src(*(u32 *)stkbuf);
1129
1130         return count;
1131 }
1132
1133 static int proc_mf_change_cmdline(struct file *file, const char __user *buffer,
1134                 unsigned long count, void *data)
1135 {
1136         struct vsp_cmd_data vsp_cmd;
1137         dma_addr_t dma_addr;
1138         char *page;
1139         int ret = -EACCES;
1140
1141         if (!capable(CAP_SYS_ADMIN))
1142                 goto out;
1143
1144         dma_addr = 0;
1145         page = dma_alloc_coherent(iSeries_vio_dev, count, &dma_addr,
1146                         GFP_ATOMIC);
1147         ret = -ENOMEM;
1148         if (page == NULL)
1149                 goto out;
1150
1151         ret = -EFAULT;
1152         if (copy_from_user(page, buffer, count))
1153                 goto out_free;
1154
1155         memset(&vsp_cmd, 0, sizeof(vsp_cmd));
1156         vsp_cmd.cmd = 31;
1157         vsp_cmd.sub_data.kern.token = dma_addr;
1158         vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex;
1159         vsp_cmd.sub_data.kern.side = (u64)data;
1160         vsp_cmd.sub_data.kern.length = count;
1161         mb();
1162         (void)signal_vsp_instruction(&vsp_cmd);
1163         ret = count;
1164
1165 out_free:
1166         dma_free_coherent(iSeries_vio_dev, count, page, dma_addr);
1167 out:
1168         return ret;
1169 }
1170
1171 static ssize_t proc_mf_change_vmlinux(struct file *file,
1172                                       const char __user *buf,
1173                                       size_t count, loff_t *ppos)
1174 {
1175         struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
1176         ssize_t rc;
1177         dma_addr_t dma_addr;
1178         char *page;
1179         struct vsp_cmd_data vsp_cmd;
1180
1181         rc = -EACCES;
1182         if (!capable(CAP_SYS_ADMIN))
1183                 goto out;
1184
1185         dma_addr = 0;
1186         page = dma_alloc_coherent(iSeries_vio_dev, count, &dma_addr,
1187                         GFP_ATOMIC);
1188         rc = -ENOMEM;
1189         if (page == NULL) {
1190                 printk(KERN_ERR "mf.c: couldn't allocate memory to set vmlinux chunk\n");
1191                 goto out;
1192         }
1193         rc = -EFAULT;
1194         if (copy_from_user(page, buf, count))
1195                 goto out_free;
1196
1197         memset(&vsp_cmd, 0, sizeof(vsp_cmd));
1198         vsp_cmd.cmd = 30;
1199         vsp_cmd.sub_data.kern.token = dma_addr;
1200         vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex;
1201         vsp_cmd.sub_data.kern.side = (u64)dp->data;
1202         vsp_cmd.sub_data.kern.offset = *ppos;
1203         vsp_cmd.sub_data.kern.length = count;
1204         mb();
1205         rc = signal_vsp_instruction(&vsp_cmd);
1206         if (rc)
1207                 goto out_free;
1208         rc = -ENOMEM;
1209         if (vsp_cmd.result_code != 0)
1210                 goto out_free;
1211
1212         *ppos += count;
1213         rc = count;
1214 out_free:
1215         dma_free_coherent(iSeries_vio_dev, count, page, dma_addr);
1216 out:
1217         return rc;
1218 }
1219
1220 static struct file_operations proc_vmlinux_operations = {
1221         .write          = proc_mf_change_vmlinux,
1222 };
1223
1224 static int __init mf_proc_init(void)
1225 {
1226         struct proc_dir_entry *mf_proc_root;
1227         struct proc_dir_entry *ent;
1228         struct proc_dir_entry *mf;
1229         char name[2];
1230         int i;
1231
1232         mf_proc_root = proc_mkdir("iSeries/mf", NULL);
1233         if (!mf_proc_root)
1234                 return 1;
1235
1236         name[1] = '\0';
1237         for (i = 0; i < 4; i++) {
1238                 name[0] = 'A' + i;
1239                 mf = proc_mkdir(name, mf_proc_root);
1240                 if (!mf)
1241                         return 1;
1242
1243                 ent = create_proc_entry("cmdline", S_IFREG|S_IRUSR|S_IWUSR, mf);
1244                 if (!ent)
1245                         return 1;
1246                 ent->nlink = 1;
1247                 ent->data = (void *)(long)i;
1248                 ent->read_proc = proc_mf_dump_cmdline;
1249                 ent->write_proc = proc_mf_change_cmdline;
1250
1251                 if (i == 3)     /* no vmlinux entry for 'D' */
1252                         continue;
1253
1254                 ent = create_proc_entry("vmlinux", S_IFREG|S_IWUSR, mf);
1255                 if (!ent)
1256                         return 1;
1257                 ent->nlink = 1;
1258                 ent->data = (void *)(long)i;
1259                 ent->proc_fops = &proc_vmlinux_operations;
1260         }
1261
1262         ent = create_proc_entry("side", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root);
1263         if (!ent)
1264                 return 1;
1265         ent->nlink = 1;
1266         ent->data = (void *)0;
1267         ent->read_proc = proc_mf_dump_side;
1268         ent->write_proc = proc_mf_change_side;
1269
1270         ent = create_proc_entry("src", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root);
1271         if (!ent)
1272                 return 1;
1273         ent->nlink = 1;
1274         ent->data = (void *)0;
1275         ent->read_proc = proc_mf_dump_src;
1276         ent->write_proc = proc_mf_change_src;
1277
1278         return 0;
1279 }
1280
1281 __initcall(mf_proc_init);
1282
1283 #endif /* CONFIG_PROC_FS */