aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/ppc64/kernel/ItLpQueue.c72
1 files changed, 41 insertions, 31 deletions
diff --git a/arch/ppc64/kernel/ItLpQueue.c b/arch/ppc64/kernel/ItLpQueue.c
index 61a9dbdd295a..a4f32cbf5297 100644
--- a/arch/ppc64/kernel/ItLpQueue.c
+++ b/arch/ppc64/kernel/ItLpQueue.c
@@ -74,24 +74,27 @@ unsigned long ItLpQueueInProcess = 0;
74 74
75static struct HvLpEvent * get_next_hvlpevent(void) 75static struct HvLpEvent * get_next_hvlpevent(void)
76{ 76{
77 struct HvLpEvent * nextLpEvent = 77 struct HvLpEvent * event;
78 (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr; 78 event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr;
79 if (nextLpEvent->xFlags.xValid) { 79
80 if (event->xFlags.xValid) {
80 /* rmb() needed only for weakly consistent machines (regatta) */ 81 /* rmb() needed only for weakly consistent machines (regatta) */
81 rmb(); 82 rmb();
82 /* Set pointer to next potential event */ 83 /* Set pointer to next potential event */
83 hvlpevent_queue.xSlicCurEventPtr += ((nextLpEvent->xSizeMinus1 + 84 hvlpevent_queue.xSlicCurEventPtr += ((event->xSizeMinus1 +
84 LpEventAlign) / 85 LpEventAlign) / LpEventAlign) * LpEventAlign;
85 LpEventAlign) * 86
86 LpEventAlign;
87 /* Wrap to beginning if no room at end */ 87 /* Wrap to beginning if no room at end */
88 if (hvlpevent_queue.xSlicCurEventPtr > hvlpevent_queue.xSlicLastValidEventPtr) 88 if (hvlpevent_queue.xSlicCurEventPtr >
89 hvlpevent_queue.xSlicCurEventPtr = hvlpevent_queue.xSlicEventStackPtr; 89 hvlpevent_queue.xSlicLastValidEventPtr) {
90 hvlpevent_queue.xSlicCurEventPtr =
91 hvlpevent_queue.xSlicEventStackPtr;
92 }
93 } else {
94 event = NULL;
90 } 95 }
91 else
92 nextLpEvent = NULL;
93 96
94 return nextLpEvent; 97 return event;
95} 98}
96 99
97static unsigned long spread_lpevents = NR_CPUS; 100static unsigned long spread_lpevents = NR_CPUS;
@@ -104,34 +107,41 @@ int hvlpevent_is_pending(void)
104 return 0; 107 return 0;
105 108
106 next_event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr; 109 next_event = (struct HvLpEvent *)hvlpevent_queue.xSlicCurEventPtr;
107 return next_event->xFlags.xValid | hvlpevent_queue.xPlicOverflowIntPending; 110
111 return next_event->xFlags.xValid |
112 hvlpevent_queue.xPlicOverflowIntPending;
108} 113}
109 114
110static void hvlpevent_clear_valid(struct HvLpEvent * event) 115static void hvlpevent_clear_valid(struct HvLpEvent * event)
111{ 116{
112 /* Clear the valid bit of the event 117 /* Tell the Hypervisor that we're done with this event.
113 * Also clear bits within this event that might 118 * Also clear bits within this event that might look like valid bits.
114 * look like valid bits (on 64-byte boundaries) 119 * ie. on 64-byte boundaries.
115 */ 120 */
121 struct HvLpEvent *tmp;
116 unsigned extra = ((event->xSizeMinus1 + LpEventAlign) / 122 unsigned extra = ((event->xSizeMinus1 + LpEventAlign) /
117 LpEventAlign) - 1; 123 LpEventAlign) - 1;
124
118 switch (extra) { 125 switch (extra) {
119 case 3: 126 case 3:
120 ((struct HvLpEvent*)((char*)event+3*LpEventAlign))->xFlags.xValid=0; 127 tmp = (struct HvLpEvent*)((char*)event + 3 * LpEventAlign);
128 tmp->xFlags.xValid = 0;
121 case 2: 129 case 2:
122 ((struct HvLpEvent*)((char*)event+2*LpEventAlign))->xFlags.xValid=0; 130 tmp = (struct HvLpEvent*)((char*)event + 2 * LpEventAlign);
131 tmp->xFlags.xValid = 0;
123 case 1: 132 case 1:
124 ((struct HvLpEvent*)((char*)event+1*LpEventAlign))->xFlags.xValid=0; 133 tmp = (struct HvLpEvent*)((char*)event + 1 * LpEventAlign);
125 case 0: 134 tmp->xFlags.xValid = 0;
126 ;
127 } 135 }
136
128 mb(); 137 mb();
138
129 event->xFlags.xValid = 0; 139 event->xFlags.xValid = 0;
130} 140}
131 141
132void process_hvlpevents(struct pt_regs *regs) 142void process_hvlpevents(struct pt_regs *regs)
133{ 143{
134 struct HvLpEvent * nextLpEvent; 144 struct HvLpEvent * event;
135 145
136 /* If we have recursed, just return */ 146 /* If we have recursed, just return */
137 if ( !set_inUse() ) 147 if ( !set_inUse() )
@@ -143,8 +153,8 @@ void process_hvlpevents(struct pt_regs *regs)
143 BUG(); 153 BUG();
144 154
145 for (;;) { 155 for (;;) {
146 nextLpEvent = get_next_hvlpevent(); 156 event = get_next_hvlpevent();
147 if (nextLpEvent) { 157 if (event) {
148 /* Call appropriate handler here, passing 158 /* Call appropriate handler here, passing
149 * a pointer to the LpEvent. The handler 159 * a pointer to the LpEvent. The handler
150 * must make a copy of the LpEvent if it 160 * must make a copy of the LpEvent if it
@@ -158,15 +168,15 @@ void process_hvlpevents(struct pt_regs *regs)
158 * registered for, so no type check is necessary 168 * registered for, so no type check is necessary
159 * here! 169 * here!
160 */ 170 */
161 if (nextLpEvent->xType < HvLpEvent_Type_NumTypes) 171 if (event->xType < HvLpEvent_Type_NumTypes)
162 __get_cpu_var(hvlpevent_counts)[nextLpEvent->xType]++; 172 __get_cpu_var(hvlpevent_counts)[event->xType]++;
163 if (nextLpEvent->xType < HvLpEvent_Type_NumTypes && 173 if (event->xType < HvLpEvent_Type_NumTypes &&
164 lpEventHandler[nextLpEvent->xType]) 174 lpEventHandler[event->xType])
165 lpEventHandler[nextLpEvent->xType](nextLpEvent, regs); 175 lpEventHandler[event->xType](event, regs);
166 else 176 else
167 printk(KERN_INFO "Unexpected Lp Event type=%d\n", nextLpEvent->xType ); 177 printk(KERN_INFO "Unexpected Lp Event type=%d\n", event->xType );
168 178
169 hvlpevent_clear_valid(nextLpEvent); 179 hvlpevent_clear_valid(event);
170 } else if (hvlpevent_queue.xPlicOverflowIntPending) 180 } else if (hvlpevent_queue.xPlicOverflowIntPending)
171 /* 181 /*
172 * No more valid events. If overflow events are 182 * No more valid events. If overflow events are