diff options
Diffstat (limited to 'arch/powerpc/platforms/cell/spufs/switch.c')
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/switch.c | 63 |
1 files changed, 53 insertions, 10 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index 0f782ca662ba..c08981ff7fc6 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c | |||
@@ -102,7 +102,7 @@ static inline int check_spu_isolate(struct spu_state *csa, struct spu *spu) | |||
102 | * saved at this time. | 102 | * saved at this time. |
103 | */ | 103 | */ |
104 | isolate_state = SPU_STATUS_ISOLATED_STATE | | 104 | isolate_state = SPU_STATUS_ISOLATED_STATE | |
105 | SPU_STATUS_ISOLATED_LOAD_STAUTUS | SPU_STATUS_ISOLATED_EXIT_STAUTUS; | 105 | SPU_STATUS_ISOLATED_LOAD_STATUS | SPU_STATUS_ISOLATED_EXIT_STATUS; |
106 | return (in_be32(&prob->spu_status_R) & isolate_state) ? 1 : 0; | 106 | return (in_be32(&prob->spu_status_R) & isolate_state) ? 1 : 0; |
107 | } | 107 | } |
108 | 108 | ||
@@ -1046,12 +1046,12 @@ static inline int suspend_spe(struct spu_state *csa, struct spu *spu) | |||
1046 | */ | 1046 | */ |
1047 | if (in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING) { | 1047 | if (in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING) { |
1048 | if (in_be32(&prob->spu_status_R) & | 1048 | if (in_be32(&prob->spu_status_R) & |
1049 | SPU_STATUS_ISOLATED_EXIT_STAUTUS) { | 1049 | SPU_STATUS_ISOLATED_EXIT_STATUS) { |
1050 | POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) & | 1050 | POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) & |
1051 | SPU_STATUS_RUNNING); | 1051 | SPU_STATUS_RUNNING); |
1052 | } | 1052 | } |
1053 | if ((in_be32(&prob->spu_status_R) & | 1053 | if ((in_be32(&prob->spu_status_R) & |
1054 | SPU_STATUS_ISOLATED_LOAD_STAUTUS) | 1054 | SPU_STATUS_ISOLATED_LOAD_STATUS) |
1055 | || (in_be32(&prob->spu_status_R) & | 1055 | || (in_be32(&prob->spu_status_R) & |
1056 | SPU_STATUS_ISOLATED_STATE)) { | 1056 | SPU_STATUS_ISOLATED_STATE)) { |
1057 | out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_STOP); | 1057 | out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_STOP); |
@@ -1085,7 +1085,7 @@ static inline void clear_spu_status(struct spu_state *csa, struct spu *spu) | |||
1085 | */ | 1085 | */ |
1086 | if (!(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING)) { | 1086 | if (!(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING)) { |
1087 | if (in_be32(&prob->spu_status_R) & | 1087 | if (in_be32(&prob->spu_status_R) & |
1088 | SPU_STATUS_ISOLATED_EXIT_STAUTUS) { | 1088 | SPU_STATUS_ISOLATED_EXIT_STATUS) { |
1089 | spu_mfc_sr1_set(spu, | 1089 | spu_mfc_sr1_set(spu, |
1090 | MFC_STATE1_MASTER_RUN_CONTROL_MASK); | 1090 | MFC_STATE1_MASTER_RUN_CONTROL_MASK); |
1091 | eieio(); | 1091 | eieio(); |
@@ -1095,7 +1095,7 @@ static inline void clear_spu_status(struct spu_state *csa, struct spu *spu) | |||
1095 | SPU_STATUS_RUNNING); | 1095 | SPU_STATUS_RUNNING); |
1096 | } | 1096 | } |
1097 | if ((in_be32(&prob->spu_status_R) & | 1097 | if ((in_be32(&prob->spu_status_R) & |
1098 | SPU_STATUS_ISOLATED_LOAD_STAUTUS) | 1098 | SPU_STATUS_ISOLATED_LOAD_STATUS) |
1099 | || (in_be32(&prob->spu_status_R) & | 1099 | || (in_be32(&prob->spu_status_R) & |
1100 | SPU_STATUS_ISOLATED_STATE)) { | 1100 | SPU_STATUS_ISOLATED_STATE)) { |
1101 | spu_mfc_sr1_set(spu, | 1101 | spu_mfc_sr1_set(spu, |
@@ -1916,6 +1916,51 @@ static void save_lscsa(struct spu_state *prev, struct spu *spu) | |||
1916 | wait_spu_stopped(prev, spu); /* Step 57. */ | 1916 | wait_spu_stopped(prev, spu); /* Step 57. */ |
1917 | } | 1917 | } |
1918 | 1918 | ||
1919 | static void force_spu_isolate_exit(struct spu *spu) | ||
1920 | { | ||
1921 | struct spu_problem __iomem *prob = spu->problem; | ||
1922 | struct spu_priv2 __iomem *priv2 = spu->priv2; | ||
1923 | |||
1924 | /* Stop SPE execution and wait for completion. */ | ||
1925 | out_be32(&prob->spu_runcntl_RW, SPU_RUNCNTL_STOP); | ||
1926 | iobarrier_rw(); | ||
1927 | POLL_WHILE_TRUE(in_be32(&prob->spu_status_R) & SPU_STATUS_RUNNING); | ||
1928 | |||
1929 | /* Restart SPE master runcntl. */ | ||
1930 | spu_mfc_sr1_set(spu, MFC_STATE1_MASTER_RUN_CONTROL_MASK); | ||
1931 | iobarrier_w(); | ||
1932 | |||
1933 | /* Initiate isolate exit request and wait for completion. */ | ||
1934 | out_be64(&priv2->spu_privcntl_RW, 4LL); | ||
1935 | iobarrier_w(); | ||
1936 | out_be32(&prob->spu_runcntl_RW, 2); | ||
1937 | iobarrier_rw(); | ||
1938 | POLL_WHILE_FALSE((in_be32(&prob->spu_status_R) | ||
1939 | & SPU_STATUS_STOPPED_BY_STOP)); | ||
1940 | |||
1941 | /* Reset load request to normal. */ | ||
1942 | out_be64(&priv2->spu_privcntl_RW, SPU_PRIVCNT_LOAD_REQUEST_NORMAL); | ||
1943 | iobarrier_w(); | ||
1944 | } | ||
1945 | |||
1946 | /** | ||
1947 | * stop_spu_isolate | ||
1948 | * Check SPU run-control state and force isolated | ||
1949 | * exit function as necessary. | ||
1950 | */ | ||
1951 | static void stop_spu_isolate(struct spu *spu) | ||
1952 | { | ||
1953 | struct spu_problem __iomem *prob = spu->problem; | ||
1954 | |||
1955 | if (in_be32(&prob->spu_status_R) & SPU_STATUS_ISOLATED_STATE) { | ||
1956 | /* The SPU is in isolated state; the only way | ||
1957 | * to get it out is to perform an isolated | ||
1958 | * exit (clean) operation. | ||
1959 | */ | ||
1960 | force_spu_isolate_exit(spu); | ||
1961 | } | ||
1962 | } | ||
1963 | |||
1919 | static void harvest(struct spu_state *prev, struct spu *spu) | 1964 | static void harvest(struct spu_state *prev, struct spu *spu) |
1920 | { | 1965 | { |
1921 | /* | 1966 | /* |
@@ -1928,6 +1973,7 @@ static void harvest(struct spu_state *prev, struct spu *spu) | |||
1928 | inhibit_user_access(prev, spu); /* Step 3. */ | 1973 | inhibit_user_access(prev, spu); /* Step 3. */ |
1929 | terminate_spu_app(prev, spu); /* Step 4. */ | 1974 | terminate_spu_app(prev, spu); /* Step 4. */ |
1930 | set_switch_pending(prev, spu); /* Step 5. */ | 1975 | set_switch_pending(prev, spu); /* Step 5. */ |
1976 | stop_spu_isolate(spu); /* NEW. */ | ||
1931 | remove_other_spu_access(prev, spu); /* Step 6. */ | 1977 | remove_other_spu_access(prev, spu); /* Step 6. */ |
1932 | suspend_mfc(prev, spu); /* Step 7. */ | 1978 | suspend_mfc(prev, spu); /* Step 7. */ |
1933 | wait_suspend_mfc_complete(prev, spu); /* Step 8. */ | 1979 | wait_suspend_mfc_complete(prev, spu); /* Step 8. */ |
@@ -2096,11 +2142,11 @@ int spu_save(struct spu_state *prev, struct spu *spu) | |||
2096 | acquire_spu_lock(spu); /* Step 1. */ | 2142 | acquire_spu_lock(spu); /* Step 1. */ |
2097 | rc = __do_spu_save(prev, spu); /* Steps 2-53. */ | 2143 | rc = __do_spu_save(prev, spu); /* Steps 2-53. */ |
2098 | release_spu_lock(spu); | 2144 | release_spu_lock(spu); |
2099 | if (rc) { | 2145 | if (rc != 0 && rc != 2 && rc != 6) { |
2100 | panic("%s failed on SPU[%d], rc=%d.\n", | 2146 | panic("%s failed on SPU[%d], rc=%d.\n", |
2101 | __func__, spu->number, rc); | 2147 | __func__, spu->number, rc); |
2102 | } | 2148 | } |
2103 | return rc; | 2149 | return 0; |
2104 | } | 2150 | } |
2105 | EXPORT_SYMBOL_GPL(spu_save); | 2151 | EXPORT_SYMBOL_GPL(spu_save); |
2106 | 2152 | ||
@@ -2165,9 +2211,6 @@ static void init_priv1(struct spu_state *csa) | |||
2165 | MFC_STATE1_PROBLEM_STATE_MASK | | 2211 | MFC_STATE1_PROBLEM_STATE_MASK | |
2166 | MFC_STATE1_RELOCATE_MASK | MFC_STATE1_BUS_TLBIE_MASK; | 2212 | MFC_STATE1_RELOCATE_MASK | MFC_STATE1_BUS_TLBIE_MASK; |
2167 | 2213 | ||
2168 | /* Set storage description. */ | ||
2169 | csa->priv1.mfc_sdr_RW = mfspr(SPRN_SDR1); | ||
2170 | |||
2171 | /* Enable OS-specific set of interrupts. */ | 2214 | /* Enable OS-specific set of interrupts. */ |
2172 | csa->priv1.int_mask_class0_RW = CLASS0_ENABLE_DMA_ALIGNMENT_INTR | | 2215 | csa->priv1.int_mask_class0_RW = CLASS0_ENABLE_DMA_ALIGNMENT_INTR | |
2173 | CLASS0_ENABLE_INVALID_DMA_COMMAND_INTR | | 2216 | CLASS0_ENABLE_INVALID_DMA_COMMAND_INTR | |