aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/cell/spu_base.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/cell/spu_base.c')
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c44
1 files changed, 26 insertions, 18 deletions
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index 70c660121ec4..78f905bc6a42 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -219,15 +219,25 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea)
219extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap); //XXX 219extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap); //XXX
220static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr) 220static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr)
221{ 221{
222 int ret;
223
222 pr_debug("%s, %lx, %lx\n", __func__, dsisr, ea); 224 pr_debug("%s, %lx, %lx\n", __func__, dsisr, ea);
223 225
224 /* Handle kernel space hash faults immediately. 226 /*
225 User hash faults need to be deferred to process context. */ 227 * Handle kernel space hash faults immediately. User hash
226 if ((dsisr & MFC_DSISR_PTE_NOT_FOUND) 228 * faults need to be deferred to process context.
227 && REGION_ID(ea) != USER_REGION_ID 229 */
228 && hash_page(ea, _PAGE_PRESENT, 0x300) == 0) { 230 if ((dsisr & MFC_DSISR_PTE_NOT_FOUND) &&
229 spu_restart_dma(spu); 231 (REGION_ID(ea) != USER_REGION_ID)) {
230 return 0; 232
233 spin_unlock(&spu->register_lock);
234 ret = hash_page(ea, _PAGE_PRESENT, 0x300);
235 spin_lock(&spu->register_lock);
236
237 if (!ret) {
238 spu_restart_dma(spu);
239 return 0;
240 }
231 } 241 }
232 242
233 spu->class_1_dar = ea; 243 spu->class_1_dar = ea;
@@ -324,17 +334,13 @@ spu_irq_class_0(int irq, void *data)
324 stat = spu_int_stat_get(spu, 0) & mask; 334 stat = spu_int_stat_get(spu, 0) & mask;
325 335
326 spu->class_0_pending |= stat; 336 spu->class_0_pending |= stat;
327 spu->class_0_dsisr = spu_mfc_dsisr_get(spu);
328 spu->class_0_dar = spu_mfc_dar_get(spu); 337 spu->class_0_dar = spu_mfc_dar_get(spu);
329 spin_unlock(&spu->register_lock);
330
331 spu->stop_callback(spu, 0); 338 spu->stop_callback(spu, 0);
332
333 spu->class_0_pending = 0; 339 spu->class_0_pending = 0;
334 spu->class_0_dsisr = 0;
335 spu->class_0_dar = 0; 340 spu->class_0_dar = 0;
336 341
337 spu_int_stat_clear(spu, 0, stat); 342 spu_int_stat_clear(spu, 0, stat);
343 spin_unlock(&spu->register_lock);
338 344
339 return IRQ_HANDLED; 345 return IRQ_HANDLED;
340} 346}
@@ -357,13 +363,12 @@ spu_irq_class_1(int irq, void *data)
357 spu_mfc_dsisr_set(spu, 0ul); 363 spu_mfc_dsisr_set(spu, 0ul);
358 spu_int_stat_clear(spu, 1, stat); 364 spu_int_stat_clear(spu, 1, stat);
359 365
360 if (stat & CLASS1_SEGMENT_FAULT_INTR)
361 __spu_trap_data_seg(spu, dar);
362
363 spin_unlock(&spu->register_lock);
364 pr_debug("%s: %lx %lx %lx %lx\n", __func__, mask, stat, 366 pr_debug("%s: %lx %lx %lx %lx\n", __func__, mask, stat,
365 dar, dsisr); 367 dar, dsisr);
366 368
369 if (stat & CLASS1_SEGMENT_FAULT_INTR)
370 __spu_trap_data_seg(spu, dar);
371
367 if (stat & CLASS1_STORAGE_FAULT_INTR) 372 if (stat & CLASS1_STORAGE_FAULT_INTR)
368 __spu_trap_data_map(spu, dar, dsisr); 373 __spu_trap_data_map(spu, dar, dsisr);
369 374
@@ -376,6 +381,8 @@ spu_irq_class_1(int irq, void *data)
376 spu->class_1_dsisr = 0; 381 spu->class_1_dsisr = 0;
377 spu->class_1_dar = 0; 382 spu->class_1_dar = 0;
378 383
384 spin_unlock(&spu->register_lock);
385
379 return stat ? IRQ_HANDLED : IRQ_NONE; 386 return stat ? IRQ_HANDLED : IRQ_NONE;
380} 387}
381 388
@@ -394,14 +401,12 @@ spu_irq_class_2(int irq, void *data)
394 mask = spu_int_mask_get(spu, 2); 401 mask = spu_int_mask_get(spu, 2);
395 /* ignore interrupts we're not waiting for */ 402 /* ignore interrupts we're not waiting for */
396 stat &= mask; 403 stat &= mask;
397
398 /* mailbox interrupts are level triggered. mask them now before 404 /* mailbox interrupts are level triggered. mask them now before
399 * acknowledging */ 405 * acknowledging */
400 if (stat & mailbox_intrs) 406 if (stat & mailbox_intrs)
401 spu_int_mask_and(spu, 2, ~(stat & mailbox_intrs)); 407 spu_int_mask_and(spu, 2, ~(stat & mailbox_intrs));
402 /* acknowledge all interrupts before the callbacks */ 408 /* acknowledge all interrupts before the callbacks */
403 spu_int_stat_clear(spu, 2, stat); 409 spu_int_stat_clear(spu, 2, stat);
404 spin_unlock(&spu->register_lock);
405 410
406 pr_debug("class 2 interrupt %d, %lx, %lx\n", irq, stat, mask); 411 pr_debug("class 2 interrupt %d, %lx, %lx\n", irq, stat, mask);
407 412
@@ -421,6 +426,9 @@ spu_irq_class_2(int irq, void *data)
421 spu->wbox_callback(spu); 426 spu->wbox_callback(spu);
422 427
423 spu->stats.class2_intr++; 428 spu->stats.class2_intr++;
429
430 spin_unlock(&spu->register_lock);
431
424 return stat ? IRQ_HANDLED : IRQ_NONE; 432 return stat ? IRQ_HANDLED : IRQ_NONE;
425} 433}
426 434