mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	MIPS: c-r4k: Avoid small flush_icache_range SMP calls
Avoid SMP calls for flushing small icache ranges. On non-CM platforms, and CM platforms too after we make r4k_on_each_cpu() take the cache op type into account, it will be called on multiple CPUs due to the possibility that local_r4k_flush_icache_range_ipi() could do non-globalized indexed cache ops. This rougly copies the range size check out into r4k_flush_icache_range(), which can disallow indexed cache ops and allow r4k_on_each_cpu() to skip the SMP call. Signed-off-by: James Hogan <james.hogan@imgtec.com> Cc: Paul Burton <paul.burton@imgtec.com> Cc: Leonid Yegoshin <leonid.yegoshin@imgtec.com> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/13805/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
		
							parent
							
								
									27b93d9c1d
								
							
						
					
					
						commit
						f70ddc07b6
					
				
					 1 changed files with 21 additions and 0 deletions
				
			
		| 
						 | 
					@ -784,12 +784,33 @@ static inline void local_r4k_flush_icache_range_ipi(void *args)
 | 
				
			||||||
static void r4k_flush_icache_range(unsigned long start, unsigned long end)
 | 
					static void r4k_flush_icache_range(unsigned long start, unsigned long end)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct flush_icache_range_args args;
 | 
						struct flush_icache_range_args args;
 | 
				
			||||||
 | 
						unsigned long size, cache_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	args.start = start;
 | 
						args.start = start;
 | 
				
			||||||
	args.end = end;
 | 
						args.end = end;
 | 
				
			||||||
	args.type = R4K_HIT | R4K_INDEX;
 | 
						args.type = R4K_HIT | R4K_INDEX;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Indexed cache ops require an SMP call.
 | 
				
			||||||
 | 
						 * Consider if that can or should be avoided.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						preempt_disable();
 | 
				
			||||||
 | 
						if (r4k_op_needs_ipi(R4K_INDEX) && !r4k_op_needs_ipi(R4K_HIT)) {
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * If address-based cache ops don't require an SMP call, then
 | 
				
			||||||
 | 
							 * use them exclusively for small flushes.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							size = start - end;
 | 
				
			||||||
 | 
							cache_size = icache_size;
 | 
				
			||||||
 | 
							if (!cpu_has_ic_fills_f_dc) {
 | 
				
			||||||
 | 
								size *= 2;
 | 
				
			||||||
 | 
								cache_size += dcache_size;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (size <= cache_size)
 | 
				
			||||||
 | 
								args.type &= ~R4K_INDEX;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	r4k_on_each_cpu(args.type, local_r4k_flush_icache_range_ipi, &args);
 | 
						r4k_on_each_cpu(args.type, local_r4k_flush_icache_range_ipi, &args);
 | 
				
			||||||
 | 
						preempt_enable();
 | 
				
			||||||
	instruction_hazard();
 | 
						instruction_hazard();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue