1 /*
2  * HvCall.c
3  * Copyright (C) 2001  Mike Corrigan IBM Corporation
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  */
10 
11 #include <linux/stddef.h>
12 #include <linux/kernel.h>
13 #include <linux/mm.h>
14 #include <linux/slab.h>
15 #include <asm/system.h>
16 #include <asm/page.h>
17 #include <asm/iSeries/HvCall.h>
18 #ifndef  _HVCALLSC_H
19 #include <asm/iSeries/HvCallSc.h>
20 #endif
21 #include <asm/iSeries/LparData.h>
22 
23 #ifndef  _HVTYPES_H
24 #include <asm/iSeries/HvTypes.h>
25 #endif
26 
27 
28 /*=====================================================================
29  * Note that this call takes at MOST one page worth of data
30  */
HvCall_readLogBuffer(HvLpIndex lpIndex,void * buffer,u64 bufLen)31 int HvCall_readLogBuffer(HvLpIndex lpIndex, void *buffer, u64 bufLen)
32 {
33 	struct HvLpBufferList *bufList;
34 	u64 bytesLeft = bufLen;
35 	u64 leftThisPage;
36 	u64 curPtr = virt_to_absolute( (unsigned long) buffer );
37 	u64 retVal;
38 	int npages;
39 	int i;
40 
41 	npages = 0;
42 	while (bytesLeft) {
43 		npages++;
44 		leftThisPage = ((curPtr & PAGE_MASK) + PAGE_SIZE) - curPtr;
45 
46 		if (leftThisPage > bytesLeft)
47 			bytesLeft = 0;
48 		else
49 			bytesLeft -= leftThisPage;
50 
51 		curPtr = (curPtr & PAGE_MASK) + PAGE_SIZE;
52 	}
53 
54 	if (npages == 0)
55 		return 0;
56 
57 	bufList = (struct HvLpBufferList *)
58 		kmalloc(npages * sizeof(struct HvLpBufferList), GFP_ATOMIC);
59 	bytesLeft = bufLen;
60 	curPtr = virt_to_absolute( (unsigned long) buffer );
61 	for(i=0; i<npages; i++) {
62 		bufList[i].addr = curPtr;
63 
64 		leftThisPage = ((curPtr & PAGE_MASK) + PAGE_SIZE) - curPtr;
65 
66 		if (leftThisPage > bytesLeft) {
67 			bufList[i].len = bytesLeft;
68 			bytesLeft = 0;
69 		} else {
70 			bufList[i].len = leftThisPage;
71 			bytesLeft -= leftThisPage;
72 		}
73 
74 		curPtr = (curPtr & PAGE_MASK) + PAGE_SIZE;
75 	}
76 
77 
78 	retVal = HvCall3(HvCallBaseReadLogBuffer, lpIndex,
79 			 virt_to_absolute((unsigned long)bufList), bufLen);
80 
81 	kfree(bufList);
82 
83 	return (int)retVal;
84 }
85 
86 /*=====================================================================
87  */
HvCall_writeLogBuffer(const void * buffer,u64 bufLen)88 void HvCall_writeLogBuffer(const void *buffer, u64 bufLen)
89 {
90 	struct HvLpBufferList bufList;
91 	u64 bytesLeft = bufLen;
92 	u64 leftThisPage;
93 	u64 curPtr = virt_to_absolute((unsigned long) buffer);
94 
95 	while (bytesLeft) {
96 		bufList.addr = curPtr;
97 
98 		leftThisPage = ((curPtr & PAGE_MASK) + PAGE_SIZE) - curPtr;
99 
100 		if (leftThisPage > bytesLeft) {
101 			bufList.len = bytesLeft;
102 			bytesLeft = 0;
103 		} else {
104 			bufList.len = leftThisPage;
105 			bytesLeft -= leftThisPage;
106 		}
107 
108 
109 		HvCall2(HvCallBaseWriteLogBuffer,
110 			virt_to_absolute((unsigned long) &bufList),
111 			bufList.len);
112 
113 		curPtr = (curPtr & PAGE_MASK) + PAGE_SIZE;
114 	}
115 }
116