diff options
-rw-r--r-- | arch/ppc64/kernel/ItLpQueue.c | 72 |
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 | ||
75 | static struct HvLpEvent * get_next_hvlpevent(void) | 75 | static 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 | ||
97 | static unsigned long spread_lpevents = NR_CPUS; | 100 | static 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 | ||
110 | static void hvlpevent_clear_valid(struct HvLpEvent * event) | 115 | static 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 | ||
132 | void process_hvlpevents(struct pt_regs *regs) | 142 | void 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 |