diff options
Diffstat (limited to 'arch/powerpc/xmon/xmon.c')
-rw-r--r-- | arch/powerpc/xmon/xmon.c | 356 |
1 files changed, 324 insertions, 32 deletions
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index f56ffef4defa..a34ed49e0356 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c | |||
@@ -37,13 +37,18 @@ | |||
37 | #include <asm/sstep.h> | 37 | #include <asm/sstep.h> |
38 | #include <asm/bug.h> | 38 | #include <asm/bug.h> |
39 | #include <asm/irq_regs.h> | 39 | #include <asm/irq_regs.h> |
40 | #include <asm/spu.h> | ||
41 | #include <asm/spu_priv1.h> | ||
42 | #include <asm/firmware.h> | ||
40 | 43 | ||
41 | #ifdef CONFIG_PPC64 | 44 | #ifdef CONFIG_PPC64 |
42 | #include <asm/hvcall.h> | 45 | #include <asm/hvcall.h> |
43 | #include <asm/paca.h> | 46 | #include <asm/paca.h> |
47 | #include <asm/iseries/it_lp_reg_save.h> | ||
44 | #endif | 48 | #endif |
45 | 49 | ||
46 | #include "nonstdio.h" | 50 | #include "nonstdio.h" |
51 | #include "dis-asm.h" | ||
47 | 52 | ||
48 | #define scanhex xmon_scanhex | 53 | #define scanhex xmon_scanhex |
49 | #define skipbl xmon_skipbl | 54 | #define skipbl xmon_skipbl |
@@ -107,7 +112,6 @@ static int bsesc(void); | |||
107 | static void dump(void); | 112 | static void dump(void); |
108 | static void prdump(unsigned long, long); | 113 | static void prdump(unsigned long, long); |
109 | static int ppc_inst_dump(unsigned long, long, int); | 114 | static int ppc_inst_dump(unsigned long, long, int); |
110 | void print_address(unsigned long); | ||
111 | static void backtrace(struct pt_regs *); | 115 | static void backtrace(struct pt_regs *); |
112 | static void excprint(struct pt_regs *); | 116 | static void excprint(struct pt_regs *); |
113 | static void prregs(struct pt_regs *); | 117 | static void prregs(struct pt_regs *); |
@@ -147,9 +151,9 @@ static void xmon_print_symbol(unsigned long address, const char *mid, | |||
147 | const char *after); | 151 | const char *after); |
148 | static const char *getvecname(unsigned long vec); | 152 | static const char *getvecname(unsigned long vec); |
149 | 153 | ||
150 | int xmon_no_auto_backtrace; | 154 | static int do_spu_cmd(void); |
151 | 155 | ||
152 | extern int print_insn_powerpc(unsigned long, unsigned long, int); | 156 | int xmon_no_auto_backtrace; |
153 | 157 | ||
154 | extern void xmon_enter(void); | 158 | extern void xmon_enter(void); |
155 | extern void xmon_leave(void); | 159 | extern void xmon_leave(void); |
@@ -209,8 +213,15 @@ Commands:\n\ | |||
209 | mi show information about memory allocation\n\ | 213 | mi show information about memory allocation\n\ |
210 | p call a procedure\n\ | 214 | p call a procedure\n\ |
211 | r print registers\n\ | 215 | r print registers\n\ |
212 | s single step\n\ | 216 | s single step\n" |
213 | S print special registers\n\ | 217 | #ifdef CONFIG_SPU_BASE |
218 | " ss stop execution on all spus\n\ | ||
219 | sr restore execution on stopped spus\n\ | ||
220 | sf # dump spu fields for spu # (in hex)\n\ | ||
221 | sd # dump spu local store for spu # (in hex)\ | ||
222 | sdi # disassemble spu local store for spu # (in hex)\n" | ||
223 | #endif | ||
224 | " S print special registers\n\ | ||
214 | t print backtrace\n\ | 225 | t print backtrace\n\ |
215 | x exit monitor and recover\n\ | 226 | x exit monitor and recover\n\ |
216 | X exit monitor and dont recover\n" | 227 | X exit monitor and dont recover\n" |
@@ -518,6 +529,7 @@ int xmon(struct pt_regs *excp) | |||
518 | xmon_save_regs(®s); | 529 | xmon_save_regs(®s); |
519 | excp = ®s; | 530 | excp = ®s; |
520 | } | 531 | } |
532 | |||
521 | return xmon_core(excp, 0); | 533 | return xmon_core(excp, 0); |
522 | } | 534 | } |
523 | EXPORT_SYMBOL(xmon); | 535 | EXPORT_SYMBOL(xmon); |
@@ -809,6 +821,8 @@ cmds(struct pt_regs *excp) | |||
809 | cacheflush(); | 821 | cacheflush(); |
810 | break; | 822 | break; |
811 | case 's': | 823 | case 's': |
824 | if (do_spu_cmd() == 0) | ||
825 | break; | ||
812 | if (do_step(excp)) | 826 | if (do_step(excp)) |
813 | return cmd; | 827 | return cmd; |
814 | break; | 828 | break; |
@@ -1555,11 +1569,6 @@ void super_regs(void) | |||
1555 | { | 1569 | { |
1556 | int cmd; | 1570 | int cmd; |
1557 | unsigned long val; | 1571 | unsigned long val; |
1558 | #ifdef CONFIG_PPC_ISERIES | ||
1559 | struct paca_struct *ptrPaca = NULL; | ||
1560 | struct lppaca *ptrLpPaca = NULL; | ||
1561 | struct ItLpRegSave *ptrLpRegSave = NULL; | ||
1562 | #endif | ||
1563 | 1572 | ||
1564 | cmd = skipbl(); | 1573 | cmd = skipbl(); |
1565 | if (cmd == '\n') { | 1574 | if (cmd == '\n') { |
@@ -1576,26 +1585,32 @@ void super_regs(void) | |||
1576 | printf("sp = "REG" sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3)); | 1585 | printf("sp = "REG" sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3)); |
1577 | printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR)); | 1586 | printf("toc = "REG" dar = "REG"\n", toc, mfspr(SPRN_DAR)); |
1578 | #ifdef CONFIG_PPC_ISERIES | 1587 | #ifdef CONFIG_PPC_ISERIES |
1579 | // Dump out relevant Paca data areas. | 1588 | if (firmware_has_feature(FW_FEATURE_ISERIES)) { |
1580 | printf("Paca: \n"); | 1589 | struct paca_struct *ptrPaca; |
1581 | ptrPaca = get_paca(); | 1590 | struct lppaca *ptrLpPaca; |
1582 | 1591 | struct ItLpRegSave *ptrLpRegSave; | |
1583 | printf(" Local Processor Control Area (LpPaca): \n"); | 1592 | |
1584 | ptrLpPaca = ptrPaca->lppaca_ptr; | 1593 | /* Dump out relevant Paca data areas. */ |
1585 | printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n", | 1594 | printf("Paca: \n"); |
1586 | ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1); | 1595 | ptrPaca = get_paca(); |
1587 | printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n", | 1596 | |
1588 | ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4); | 1597 | printf(" Local Processor Control Area (LpPaca): \n"); |
1589 | printf(" Saved Gpr5=%.16lx \n", ptrLpPaca->saved_gpr5); | 1598 | ptrLpPaca = ptrPaca->lppaca_ptr; |
1590 | 1599 | printf(" Saved Srr0=%.16lx Saved Srr1=%.16lx \n", | |
1591 | printf(" Local Processor Register Save Area (LpRegSave): \n"); | 1600 | ptrLpPaca->saved_srr0, ptrLpPaca->saved_srr1); |
1592 | ptrLpRegSave = ptrPaca->reg_save_ptr; | 1601 | printf(" Saved Gpr3=%.16lx Saved Gpr4=%.16lx \n", |
1593 | printf(" Saved Sprg0=%.16lx Saved Sprg1=%.16lx \n", | 1602 | ptrLpPaca->saved_gpr3, ptrLpPaca->saved_gpr4); |
1594 | ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0); | 1603 | printf(" Saved Gpr5=%.16lx \n", ptrLpPaca->saved_gpr5); |
1595 | printf(" Saved Sprg2=%.16lx Saved Sprg3=%.16lx \n", | 1604 | |
1596 | ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3); | 1605 | printf(" Local Processor Register Save Area (LpRegSave): \n"); |
1597 | printf(" Saved Msr =%.16lx Saved Nia =%.16lx \n", | 1606 | ptrLpRegSave = ptrPaca->reg_save_ptr; |
1598 | ptrLpRegSave->xMSR, ptrLpRegSave->xNIA); | 1607 | printf(" Saved Sprg0=%.16lx Saved Sprg1=%.16lx \n", |
1608 | ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0); | ||
1609 | printf(" Saved Sprg2=%.16lx Saved Sprg3=%.16lx \n", | ||
1610 | ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3); | ||
1611 | printf(" Saved Msr =%.16lx Saved Nia =%.16lx \n", | ||
1612 | ptrLpRegSave->xMSR, ptrLpRegSave->xNIA); | ||
1613 | } | ||
1599 | #endif | 1614 | #endif |
1600 | 1615 | ||
1601 | return; | 1616 | return; |
@@ -2053,8 +2068,11 @@ prdump(unsigned long adrs, long ndump) | |||
2053 | } | 2068 | } |
2054 | } | 2069 | } |
2055 | 2070 | ||
2071 | typedef int (*instruction_dump_func)(unsigned long inst, unsigned long addr); | ||
2072 | |||
2056 | int | 2073 | int |
2057 | ppc_inst_dump(unsigned long adr, long count, int praddr) | 2074 | generic_inst_dump(unsigned long adr, long count, int praddr, |
2075 | instruction_dump_func dump_func) | ||
2058 | { | 2076 | { |
2059 | int nr, dotted; | 2077 | int nr, dotted; |
2060 | unsigned long first_adr; | 2078 | unsigned long first_adr; |
@@ -2084,12 +2102,18 @@ ppc_inst_dump(unsigned long adr, long count, int praddr) | |||
2084 | if (praddr) | 2102 | if (praddr) |
2085 | printf(REG" %.8x", adr, inst); | 2103 | printf(REG" %.8x", adr, inst); |
2086 | printf("\t"); | 2104 | printf("\t"); |
2087 | print_insn_powerpc(inst, adr, 0); /* always returns 4 */ | 2105 | dump_func(inst, adr); |
2088 | printf("\n"); | 2106 | printf("\n"); |
2089 | } | 2107 | } |
2090 | return adr - first_adr; | 2108 | return adr - first_adr; |
2091 | } | 2109 | } |
2092 | 2110 | ||
2111 | int | ||
2112 | ppc_inst_dump(unsigned long adr, long count, int praddr) | ||
2113 | { | ||
2114 | return generic_inst_dump(adr, count, praddr, print_insn_powerpc); | ||
2115 | } | ||
2116 | |||
2093 | void | 2117 | void |
2094 | print_address(unsigned long addr) | 2118 | print_address(unsigned long addr) |
2095 | { | 2119 | { |
@@ -2557,6 +2581,10 @@ void dump_segments(void) | |||
2557 | 2581 | ||
2558 | void xmon_init(int enable) | 2582 | void xmon_init(int enable) |
2559 | { | 2583 | { |
2584 | #ifdef CONFIG_PPC_ISERIES | ||
2585 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | ||
2586 | return; | ||
2587 | #endif | ||
2560 | if (enable) { | 2588 | if (enable) { |
2561 | __debugger = xmon; | 2589 | __debugger = xmon; |
2562 | __debugger_ipi = xmon_ipi; | 2590 | __debugger_ipi = xmon_ipi; |
@@ -2594,6 +2622,10 @@ static struct sysrq_key_op sysrq_xmon_op = | |||
2594 | 2622 | ||
2595 | static int __init setup_xmon_sysrq(void) | 2623 | static int __init setup_xmon_sysrq(void) |
2596 | { | 2624 | { |
2625 | #ifdef CONFIG_PPC_ISERIES | ||
2626 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | ||
2627 | return 0; | ||
2628 | #endif | ||
2597 | register_sysrq_key('x', &sysrq_xmon_op); | 2629 | register_sysrq_key('x', &sysrq_xmon_op); |
2598 | return 0; | 2630 | return 0; |
2599 | } | 2631 | } |
@@ -2630,3 +2662,263 @@ void __init xmon_setup(void) | |||
2630 | if (xmon_early) | 2662 | if (xmon_early) |
2631 | debugger(NULL); | 2663 | debugger(NULL); |
2632 | } | 2664 | } |
2665 | |||
2666 | #ifdef CONFIG_SPU_BASE | ||
2667 | |||
2668 | struct spu_info { | ||
2669 | struct spu *spu; | ||
2670 | u64 saved_mfc_sr1_RW; | ||
2671 | u32 saved_spu_runcntl_RW; | ||
2672 | unsigned long dump_addr; | ||
2673 | u8 stopped_ok; | ||
2674 | }; | ||
2675 | |||
2676 | #define XMON_NUM_SPUS 16 /* Enough for current hardware */ | ||
2677 | |||
2678 | static struct spu_info spu_info[XMON_NUM_SPUS]; | ||
2679 | |||
2680 | void xmon_register_spus(struct list_head *list) | ||
2681 | { | ||
2682 | struct spu *spu; | ||
2683 | |||
2684 | list_for_each_entry(spu, list, full_list) { | ||
2685 | if (spu->number >= XMON_NUM_SPUS) { | ||
2686 | WARN_ON(1); | ||
2687 | continue; | ||
2688 | } | ||
2689 | |||
2690 | spu_info[spu->number].spu = spu; | ||
2691 | spu_info[spu->number].stopped_ok = 0; | ||
2692 | spu_info[spu->number].dump_addr = (unsigned long) | ||
2693 | spu_info[spu->number].spu->local_store; | ||
2694 | } | ||
2695 | } | ||
2696 | |||
2697 | static void stop_spus(void) | ||
2698 | { | ||
2699 | struct spu *spu; | ||
2700 | int i; | ||
2701 | u64 tmp; | ||
2702 | |||
2703 | for (i = 0; i < XMON_NUM_SPUS; i++) { | ||
2704 | if (!spu_info[i].spu) | ||
2705 | continue; | ||
2706 | |||
2707 | if (setjmp(bus_error_jmp) == 0) { | ||
2708 | catch_memory_errors = 1; | ||
2709 | sync(); | ||
2710 | |||
2711 | spu = spu_info[i].spu; | ||
2712 | |||
2713 | spu_info[i].saved_spu_runcntl_RW = | ||
2714 | in_be32(&spu->problem->spu_runcntl_RW); | ||
2715 | |||
2716 | tmp = spu_mfc_sr1_get(spu); | ||
2717 | spu_info[i].saved_mfc_sr1_RW = tmp; | ||
2718 | |||
2719 | tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK; | ||
2720 | spu_mfc_sr1_set(spu, tmp); | ||
2721 | |||
2722 | sync(); | ||
2723 | __delay(200); | ||
2724 | |||
2725 | spu_info[i].stopped_ok = 1; | ||
2726 | |||
2727 | printf("Stopped spu %.2d (was %s)\n", i, | ||
2728 | spu_info[i].saved_spu_runcntl_RW ? | ||
2729 | "running" : "stopped"); | ||
2730 | } else { | ||
2731 | catch_memory_errors = 0; | ||
2732 | printf("*** Error stopping spu %.2d\n", i); | ||
2733 | } | ||
2734 | catch_memory_errors = 0; | ||
2735 | } | ||
2736 | } | ||
2737 | |||
2738 | static void restart_spus(void) | ||
2739 | { | ||
2740 | struct spu *spu; | ||
2741 | int i; | ||
2742 | |||
2743 | for (i = 0; i < XMON_NUM_SPUS; i++) { | ||
2744 | if (!spu_info[i].spu) | ||
2745 | continue; | ||
2746 | |||
2747 | if (!spu_info[i].stopped_ok) { | ||
2748 | printf("*** Error, spu %d was not successfully stopped" | ||
2749 | ", not restarting\n", i); | ||
2750 | continue; | ||
2751 | } | ||
2752 | |||
2753 | if (setjmp(bus_error_jmp) == 0) { | ||
2754 | catch_memory_errors = 1; | ||
2755 | sync(); | ||
2756 | |||
2757 | spu = spu_info[i].spu; | ||
2758 | spu_mfc_sr1_set(spu, spu_info[i].saved_mfc_sr1_RW); | ||
2759 | out_be32(&spu->problem->spu_runcntl_RW, | ||
2760 | spu_info[i].saved_spu_runcntl_RW); | ||
2761 | |||
2762 | sync(); | ||
2763 | __delay(200); | ||
2764 | |||
2765 | printf("Restarted spu %.2d\n", i); | ||
2766 | } else { | ||
2767 | catch_memory_errors = 0; | ||
2768 | printf("*** Error restarting spu %.2d\n", i); | ||
2769 | } | ||
2770 | catch_memory_errors = 0; | ||
2771 | } | ||
2772 | } | ||
2773 | |||
2774 | #define DUMP_WIDTH 23 | ||
2775 | #define DUMP_VALUE(format, field, value) \ | ||
2776 | do { \ | ||
2777 | if (setjmp(bus_error_jmp) == 0) { \ | ||
2778 | catch_memory_errors = 1; \ | ||
2779 | sync(); \ | ||
2780 | printf(" %-*s = "format"\n", DUMP_WIDTH, \ | ||
2781 | #field, value); \ | ||
2782 | sync(); \ | ||
2783 | __delay(200); \ | ||
2784 | } else { \ | ||
2785 | catch_memory_errors = 0; \ | ||
2786 | printf(" %-*s = *** Error reading field.\n", \ | ||
2787 | DUMP_WIDTH, #field); \ | ||
2788 | } \ | ||
2789 | catch_memory_errors = 0; \ | ||
2790 | } while (0) | ||
2791 | |||
2792 | #define DUMP_FIELD(obj, format, field) \ | ||
2793 | DUMP_VALUE(format, field, obj->field) | ||
2794 | |||
2795 | static void dump_spu_fields(struct spu *spu) | ||
2796 | { | ||
2797 | printf("Dumping spu fields at address %p:\n", spu); | ||
2798 | |||
2799 | DUMP_FIELD(spu, "0x%x", number); | ||
2800 | DUMP_FIELD(spu, "%s", name); | ||
2801 | DUMP_FIELD(spu, "0x%lx", local_store_phys); | ||
2802 | DUMP_FIELD(spu, "0x%p", local_store); | ||
2803 | DUMP_FIELD(spu, "0x%lx", ls_size); | ||
2804 | DUMP_FIELD(spu, "0x%x", node); | ||
2805 | DUMP_FIELD(spu, "0x%lx", flags); | ||
2806 | DUMP_FIELD(spu, "0x%lx", dar); | ||
2807 | DUMP_FIELD(spu, "0x%lx", dsisr); | ||
2808 | DUMP_FIELD(spu, "%d", class_0_pending); | ||
2809 | DUMP_FIELD(spu, "0x%lx", irqs[0]); | ||
2810 | DUMP_FIELD(spu, "0x%lx", irqs[1]); | ||
2811 | DUMP_FIELD(spu, "0x%lx", irqs[2]); | ||
2812 | DUMP_FIELD(spu, "0x%x", slb_replace); | ||
2813 | DUMP_FIELD(spu, "%d", pid); | ||
2814 | DUMP_FIELD(spu, "%d", prio); | ||
2815 | DUMP_FIELD(spu, "0x%p", mm); | ||
2816 | DUMP_FIELD(spu, "0x%p", ctx); | ||
2817 | DUMP_FIELD(spu, "0x%p", rq); | ||
2818 | DUMP_FIELD(spu, "0x%p", timestamp); | ||
2819 | DUMP_FIELD(spu, "0x%lx", problem_phys); | ||
2820 | DUMP_FIELD(spu, "0x%p", problem); | ||
2821 | DUMP_VALUE("0x%x", problem->spu_runcntl_RW, | ||
2822 | in_be32(&spu->problem->spu_runcntl_RW)); | ||
2823 | DUMP_VALUE("0x%x", problem->spu_status_R, | ||
2824 | in_be32(&spu->problem->spu_status_R)); | ||
2825 | DUMP_VALUE("0x%x", problem->spu_npc_RW, | ||
2826 | in_be32(&spu->problem->spu_npc_RW)); | ||
2827 | DUMP_FIELD(spu, "0x%p", priv2); | ||
2828 | DUMP_FIELD(spu, "0x%p", pdata); | ||
2829 | } | ||
2830 | |||
2831 | int | ||
2832 | spu_inst_dump(unsigned long adr, long count, int praddr) | ||
2833 | { | ||
2834 | return generic_inst_dump(adr, count, praddr, print_insn_spu); | ||
2835 | } | ||
2836 | |||
2837 | static void dump_spu_ls(unsigned long num, int subcmd) | ||
2838 | { | ||
2839 | unsigned long offset, addr, ls_addr; | ||
2840 | |||
2841 | if (setjmp(bus_error_jmp) == 0) { | ||
2842 | catch_memory_errors = 1; | ||
2843 | sync(); | ||
2844 | ls_addr = (unsigned long)spu_info[num].spu->local_store; | ||
2845 | sync(); | ||
2846 | __delay(200); | ||
2847 | } else { | ||
2848 | catch_memory_errors = 0; | ||
2849 | printf("*** Error: accessing spu info for spu %d\n", num); | ||
2850 | return; | ||
2851 | } | ||
2852 | catch_memory_errors = 0; | ||
2853 | |||
2854 | if (scanhex(&offset)) | ||
2855 | addr = ls_addr + offset; | ||
2856 | else | ||
2857 | addr = spu_info[num].dump_addr; | ||
2858 | |||
2859 | if (addr >= ls_addr + LS_SIZE) { | ||
2860 | printf("*** Error: address outside of local store\n"); | ||
2861 | return; | ||
2862 | } | ||
2863 | |||
2864 | switch (subcmd) { | ||
2865 | case 'i': | ||
2866 | addr += spu_inst_dump(addr, 16, 1); | ||
2867 | last_cmd = "sdi\n"; | ||
2868 | break; | ||
2869 | default: | ||
2870 | prdump(addr, 64); | ||
2871 | addr += 64; | ||
2872 | last_cmd = "sd\n"; | ||
2873 | break; | ||
2874 | } | ||
2875 | |||
2876 | spu_info[num].dump_addr = addr; | ||
2877 | } | ||
2878 | |||
2879 | static int do_spu_cmd(void) | ||
2880 | { | ||
2881 | static unsigned long num = 0; | ||
2882 | int cmd, subcmd = 0; | ||
2883 | |||
2884 | cmd = inchar(); | ||
2885 | switch (cmd) { | ||
2886 | case 's': | ||
2887 | stop_spus(); | ||
2888 | break; | ||
2889 | case 'r': | ||
2890 | restart_spus(); | ||
2891 | break; | ||
2892 | case 'd': | ||
2893 | subcmd = inchar(); | ||
2894 | if (isxdigit(subcmd) || subcmd == '\n') | ||
2895 | termch = subcmd; | ||
2896 | case 'f': | ||
2897 | scanhex(&num); | ||
2898 | if (num >= XMON_NUM_SPUS || !spu_info[num].spu) { | ||
2899 | printf("*** Error: invalid spu number\n"); | ||
2900 | return 0; | ||
2901 | } | ||
2902 | |||
2903 | switch (cmd) { | ||
2904 | case 'f': | ||
2905 | dump_spu_fields(spu_info[num].spu); | ||
2906 | break; | ||
2907 | default: | ||
2908 | dump_spu_ls(num, subcmd); | ||
2909 | break; | ||
2910 | } | ||
2911 | |||
2912 | break; | ||
2913 | default: | ||
2914 | return -1; | ||
2915 | } | ||
2916 | |||
2917 | return 0; | ||
2918 | } | ||
2919 | #else /* ! CONFIG_SPU_BASE */ | ||
2920 | static int do_spu_cmd(void) | ||
2921 | { | ||
2922 | return -1; | ||
2923 | } | ||
2924 | #endif | ||