Re: [PATCH 15/24] C6X: cache control

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Monday 08 August 2011, Mark Salter wrote:
> +/*
> + *  Copyright (C) 2011 Texas Instruments Incorporated
> + *  Author: Mark Salter <msalter@xxxxxxxxxx>
> + *
> + *  This program is free software; you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License version 2 as
> + *  published by the Free Software Foundation.
> + */
> +#include <linux/io.h>
> +
> +#include <asm/cache.h>
> +#include <asm/machdep.h>
> +#include <asm/soc.h>
> +
> +#define IMCR_BASE	  0x01840000

Please don't hardcode MMIO regions like this. You should have the base address in
the device tree and use of_iomap() like you do in some other cases.
If you need this really early, you might need to 

> +static void cache_block_operation_wait(unsigned int wc_reg)
> +{
> +	/* Wait for completion */
> +	while (imcr_get(wc_reg))
> +		;
> +}

When you have blocking loops like this one, better use cpu_relax() in the
loop body. I realize that that is currently a nop, but it's better style
to use it anyway.

> +/*
> + * Generic function to perform a block cache operation as
> + * invalidate or writeback/invalidate
> + */
> +static void cache_block_operation(unsigned int *start,
> +				  unsigned int *end,
> +				  unsigned int bar_reg,
> +				  unsigned int wc_reg)
> +{
> +	unsigned long flags;
> +	unsigned int wcnt =
> +		(L2_CACHE_ALIGN_CNT((unsigned int) end)
> +		 - L2_CACHE_ALIGN_LOW((unsigned int) start)) >> 2;
> +	unsigned int wc = 0;
> +
> +	for (; wcnt; wcnt -= wc, start += wc) {
> +loop:
> +		local_irq_save(flags);
> +
> +		/*
> +		 * If another cache operation is occuring
> +		 */
> +		if (unlikely(imcr_get(wc_reg))) {
> +			local_irq_restore(flags);
> +
> +			/* Wait for previous operation completion */
> +			cache_block_operation_wait(wc_reg);
> +
> +			/* Try again */
> +			goto loop;
> +		}
> +
> +		imcr_set(bar_reg, L2_CACHE_ALIGN_LOW((unsigned int) start));
> +
> +		if (wcnt > 0xffff)
> +			wc = 0xffff;
> +		else
> +			wc = wcnt;
> +
> +		/* Set word count value in the WC register */
> +		imcr_set(wc_reg, wc & 0xffff);
> +
> +		local_irq_restore(flags);
> +
> +		/* Wait for completion */
> +		cache_block_operation_wait(wc_reg);
> +	}
> +}

Doesn't this need a proper spinlock instead of a local_irq_save?
You should try to write code with SMP in mind, even if the current usage
is UP only. The resulting object code is the same on UP.

> + *  L1P global-invalidate all
> + */
> +void L1P_cache_global_invalidate(void)
> +{
> +	unsigned int set = 1;
> +	imcr_set(IMCR_L1PINV, set);
> +	while (imcr_get(IMCR_L1PINV) & 1)
> +		;
> +}
> +
> +/*
> + *  L1D global-invalidate all
> + *
> + * Warning: this operation causes all updated data in L1D to
> + * be discarded rather than written back to the lower levels of
> + * memory
> + */
> +void L1D_cache_global_invalidate(void)
> +{
> +	unsigned int set = 1;
> +	imcr_set(IMCR_L1DINV, set);
> +	while (imcr_get(IMCR_L1DINV) & 1)
> +		;
> +}
> +
> +void L1D_cache_global_writeback(void)
> +{
> +	unsigned int set = 1;
> +	imcr_set(IMCR_L1DWB, set);
> +	while (imcr_get(IMCR_L1DWB) & 1)
> +		;
> +}
> +
> +void L1D_cache_global_writeback_invalidate(void)
> +{
> +	unsigned int set = 1;
> +	imcr_set(IMCR_L1DWBINV, set);
> +	while (imcr_get(IMCR_L1DWBINV) & 1)
> +		;
> +}

cpu_relax() again.

	Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-arch" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel]     [Kernel Newbies]     [x86 Platform Driver]     [Netdev]     [Linux Wireless]     [Netfilter]     [Bugtraq]     [Linux Filesystems]     [Yosemite Discussion]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Device Mapper]

  Powered by Linux