diff options
| author | David Woodhouse <David.Woodhouse@intel.com> | 2008-07-11 14:36:25 +0100 | 
|---|---|---|
| committer | David Woodhouse <David.Woodhouse@intel.com> | 2008-07-11 14:36:25 +0100 | 
| commit | a8931ef380c92d121ae74ecfb03b2d63f72eea6f (patch) | |
| tree | 980fb6b019e11e6cb1ece55b7faff184721a8053 /arch/powerpc/platforms/cell/spufs/switch.c | |
| parent | 90574d0a4d4b73308ae54a2a57a4f3f1fa98e984 (diff) | |
| parent | e5a5816f7875207cb0a0a7032e39a4686c5e10a4 (diff) | |
| download | olio-linux-3.10-a8931ef380c92d121ae74ecfb03b2d63f72eea6f.tar.xz olio-linux-3.10-a8931ef380c92d121ae74ecfb03b2d63f72eea6f.zip  | |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'arch/powerpc/platforms/cell/spufs/switch.c')
| -rw-r--r-- | arch/powerpc/platforms/cell/spufs/switch.c | 71 | 
1 files changed, 49 insertions, 22 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index d2a1249d36d..3df9a36eb2f 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -132,6 +132,14 @@ static inline void disable_interrupts(struct spu_state *csa, struct spu *spu)  	spu_int_mask_set(spu, 2, 0ul);  	eieio();  	spin_unlock_irq(&spu->register_lock); + +	/* +	 * This flag needs to be set before calling synchronize_irq so +	 * that the update will be visible to the relevant handlers +	 * via a simple load. +	 */ +	set_bit(SPU_CONTEXT_SWITCH_PENDING, &spu->flags); +	clear_bit(SPU_CONTEXT_FAULT_PENDING, &spu->flags);  	synchronize_irq(spu->irqs[0]);  	synchronize_irq(spu->irqs[1]);  	synchronize_irq(spu->irqs[2]); @@ -166,9 +174,8 @@ static inline void set_switch_pending(struct spu_state *csa, struct spu *spu)  	/* Save, Step 7:  	 * Restore, Step 5:  	 *     Set a software context switch pending flag. +	 *     Done above in Step 3 - disable_interrupts().  	 */ -	set_bit(SPU_CONTEXT_SWITCH_PENDING, &spu->flags); -	mb();  }  static inline void save_mfc_cntl(struct spu_state *csa, struct spu *spu) @@ -186,20 +193,21 @@ static inline void save_mfc_cntl(struct spu_state *csa, struct spu *spu)  				 MFC_CNTL_SUSPEND_COMPLETE);  		/* fall through */  	case MFC_CNTL_SUSPEND_COMPLETE: -		if (csa) { +		if (csa)  			csa->priv2.mfc_control_RW = -				MFC_CNTL_SUSPEND_MASK | +				in_be64(&priv2->mfc_control_RW) |  				MFC_CNTL_SUSPEND_DMA_QUEUE; -		}  		break;  	case MFC_CNTL_NORMAL_DMA_QUEUE_OPERATION:  		out_be64(&priv2->mfc_control_RW, MFC_CNTL_SUSPEND_DMA_QUEUE);  		POLL_WHILE_FALSE((in_be64(&priv2->mfc_control_RW) &  				  MFC_CNTL_SUSPEND_DMA_STATUS_MASK) ==  				 MFC_CNTL_SUSPEND_COMPLETE); -		if (csa) { -			csa->priv2.mfc_control_RW = 0; -		} +		if (csa) +			csa->priv2.mfc_control_RW = +				in_be64(&priv2->mfc_control_RW) & +				~MFC_CNTL_SUSPEND_DMA_QUEUE & +				~MFC_CNTL_SUSPEND_MASK;  		break;  	}  } @@ -249,16 +257,21 @@ static inline void save_spu_status(struct spu_state *csa, struct spu *spu)  	}  } -static inline void save_mfc_decr(struct spu_state *csa, struct spu *spu) +static inline void save_mfc_stopped_status(struct spu_state *csa, +		struct spu *spu)  {  	struct spu_priv2 __iomem *priv2 = spu->priv2; +	const u64 mask = MFC_CNTL_DECREMENTER_RUNNING | +			MFC_CNTL_DMA_QUEUES_EMPTY;  	/* Save, Step 12:  	 *     Read MFC_CNTL[Ds].  Update saved copy of  	 *     CSA.MFC_CNTL[Ds]. +	 * +	 * update: do the same with MFC_CNTL[Q].  	 */ -	csa->priv2.mfc_control_RW |= -		in_be64(&priv2->mfc_control_RW) & MFC_CNTL_DECREMENTER_RUNNING; +	csa->priv2.mfc_control_RW &= ~mask; +	csa->priv2.mfc_control_RW |= in_be64(&priv2->mfc_control_RW) & mask;  }  static inline void halt_mfc_decr(struct spu_state *csa, struct spu *spu) @@ -462,7 +475,9 @@ static inline void purge_mfc_queue(struct spu_state *csa, struct spu *spu)  	 * Restore, Step 14.  	 *     Write MFC_CNTL[Pc]=1 (purge queue).  	 */ -	out_be64(&priv2->mfc_control_RW, MFC_CNTL_PURGE_DMA_REQUEST); +	out_be64(&priv2->mfc_control_RW, +			MFC_CNTL_PURGE_DMA_REQUEST | +			MFC_CNTL_SUSPEND_MASK);  	eieio();  } @@ -725,10 +740,14 @@ static inline void set_switch_active(struct spu_state *csa, struct spu *spu)  	/* Save, Step 48:  	 * Restore, Step 23.  	 *     Change the software context switch pending flag -	 *     to context switch active. +	 *     to context switch active.  This implementation does +	 *     not uses a switch active flag.  	 * -	 *     This implementation does not uses a switch active flag. +	 * Now that we have saved the mfc in the csa, we can add in the +	 * restart command if an exception occurred.  	 */ +	if (test_bit(SPU_CONTEXT_FAULT_PENDING, &spu->flags)) +		csa->priv2.mfc_control_RW |= MFC_CNTL_RESTART_DMA_COMMAND;  	clear_bit(SPU_CONTEXT_SWITCH_PENDING, &spu->flags);  	mb();  } @@ -1690,6 +1709,13 @@ static inline void restore_mfc_sr1(struct spu_state *csa, struct spu *spu)  	eieio();  } +static inline void set_int_route(struct spu_state *csa, struct spu *spu) +{ +	struct spu_context *ctx = spu->ctx; + +	spu_cpu_affinity_set(spu, ctx->last_ran); +} +  static inline void restore_other_spu_access(struct spu_state *csa,  					    struct spu *spu)  { @@ -1721,15 +1747,15 @@ static inline void restore_mfc_cntl(struct spu_state *csa, struct spu *spu)  	 */  	out_be64(&priv2->mfc_control_RW, csa->priv2.mfc_control_RW);  	eieio(); +  	/* -	 * FIXME: this is to restart a DMA that we were processing -	 *        before the save. better remember the fault information -	 *        in the csa instead. +	 * The queue is put back into the same state that was evident prior to +	 * the context switch. The suspend flag is added to the saved state in +	 * the csa, if the operational state was suspending or suspended. In +	 * this case, the code that suspended the mfc is responsible for +	 * continuing it. Note that SPE faults do not change the operational +	 * state of the spu.  	 */ -	if ((csa->priv2.mfc_control_RW & MFC_CNTL_SUSPEND_DMA_QUEUE_MASK)) { -		out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESTART_DMA_COMMAND); -		eieio(); -	}  }  static inline void enable_user_access(struct spu_state *csa, struct spu *spu) @@ -1788,7 +1814,7 @@ static int quiece_spu(struct spu_state *prev, struct spu *spu)  	save_spu_runcntl(prev, spu);	        /* Step 9. */  	save_mfc_sr1(prev, spu);	        /* Step 10. */  	save_spu_status(prev, spu);	        /* Step 11. */ -	save_mfc_decr(prev, spu);	        /* Step 12. */ +	save_mfc_stopped_status(prev, spu);     /* Step 12. */  	halt_mfc_decr(prev, spu);	        /* Step 13. */  	save_timebase(prev, spu);		/* Step 14. */  	remove_other_spu_access(prev, spu);	/* Step 15. */ @@ -2000,6 +2026,7 @@ static void restore_csa(struct spu_state *next, struct spu *spu)  	check_ppuint_mb_stat(next, spu);	/* Step 67. */  	spu_invalidate_slbs(spu);		/* Modified Step 68. */  	restore_mfc_sr1(next, spu);	        /* Step 69. */ +	set_int_route(next, spu);		/* NEW      */  	restore_other_spu_access(next, spu);	/* Step 70. */  	restore_spu_runcntl(next, spu);	        /* Step 71. */  	restore_mfc_cntl(next, spu);	        /* Step 72. */  |