diff mbox series

[v4,3/8] MIPS: Octeon: Add a global resource manager.

Message ID 20171129005540.28829-4-david.daney@cavium.com
State Deferred, archived
Delegated to: David Miller
Headers show
Series Cavium OCTEON-III network driver. | expand

Commit Message

David Daney Nov. 29, 2017, 12:55 a.m. UTC
From: Carlos Munoz <cmunoz@cavium.com>

Add a global resource manager to manage tagged pointers within
bootmem allocated memory. This is used by various functional
blocks in the Octeon core like the FPA, Ethernet nexus, etc.

Signed-off-by: Carlos Munoz <cmunoz@cavium.com>
Signed-off-by: Steven J. Hill <Steven.Hill@cavium.com>
Signed-off-by: David Daney <david.daney@cavium.com>
---
 arch/mips/cavium-octeon/Makefile       |   3 +-
 arch/mips/cavium-octeon/resource-mgr.c | 371 +++++++++++++++++++++++++++++++++
 arch/mips/include/asm/octeon/octeon.h  |  18 ++
 3 files changed, 391 insertions(+), 1 deletion(-)
 create mode 100644 arch/mips/cavium-octeon/resource-mgr.c

Comments

James Hogan Nov. 30, 2017, 10:53 p.m. UTC | #1
On Tue, Nov 28, 2017 at 04:55:35PM -0800, David Daney wrote:
> From: Carlos Munoz <cmunoz@cavium.com>
> 
> Add a global resource manager to manage tagged pointers within
> bootmem allocated memory. This is used by various functional
> blocks in the Octeon core like the FPA, Ethernet nexus, etc.
> 
> Signed-off-by: Carlos Munoz <cmunoz@cavium.com>
> Signed-off-by: Steven J. Hill <Steven.Hill@cavium.com>
> Signed-off-by: David Daney <david.daney@cavium.com>
> ---
>  arch/mips/cavium-octeon/Makefile       |   3 +-
>  arch/mips/cavium-octeon/resource-mgr.c | 371 +++++++++++++++++++++++++++++++++
>  arch/mips/include/asm/octeon/octeon.h  |  18 ++
>  3 files changed, 391 insertions(+), 1 deletion(-)
>  create mode 100644 arch/mips/cavium-octeon/resource-mgr.c
> 
> diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile
> index 7c02e542959a..0a299ab8719f 100644
> --- a/arch/mips/cavium-octeon/Makefile
> +++ b/arch/mips/cavium-octeon/Makefile
> @@ -9,7 +9,8 @@
>  # Copyright (C) 2005-2009 Cavium Networks
>  #
>  
> -obj-y := cpu.o setup.o octeon-platform.o octeon-irq.o csrc-octeon.o
> +obj-y := cpu.o setup.o octeon-platform.o octeon-irq.o csrc-octeon.o \
> +	 resource-mgr.o

Maybe put that on a separate line like below.

>  obj-y += dma-octeon.o
>  obj-y += octeon-memcpy.o
>  obj-y += executive/
> diff --git a/arch/mips/cavium-octeon/resource-mgr.c b/arch/mips/cavium-octeon/resource-mgr.c
> new file mode 100644
> index 000000000000..ca25fa953402
> --- /dev/null
> +++ b/arch/mips/cavium-octeon/resource-mgr.c
> @@ -0,0 +1,371 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Resource manager for Octeon.
> + *
> + * This file is subject to the terms and conditions of the GNU General Public
> + * License.  See the file "COPYING" in the main directory of this archive
> + * for more details.
> + *
> + * Copyright (C) 2017 Cavium, Inc.
> + */
> +#include <linux/module.h>
> +
> +#include <asm/octeon/octeon.h>
> +#include <asm/octeon/cvmx-bootmem.h>
> +
> +#define RESOURCE_MGR_BLOCK_NAME		"cvmx-global-resources"
> +#define MAX_RESOURCES			128
> +#define INST_AVAILABLE			-88
> +#define OWNER				0xbadc0de
> +
> +struct global_resource_entry {
> +	struct global_resource_tag tag;
> +	u64 phys_addr;
> +	u64 size;
> +};
> +
> +struct global_resources {
> +#ifdef __LITTLE_ENDIAN_BITFIELD
> +	u32 rlock;
> +	u32 pad;
> +#else
> +	u32 pad;
> +	u32 rlock;
> +#endif
> +	u64 entry_cnt;
> +	struct global_resource_entry resource_entry[];
> +};
> +
> +static struct global_resources *res_mgr_info;
> +
> +
> +/*
> + * The resource manager interacts with software running outside of the
> + * Linux kernel, which necessitates locking to maintain data structure
> + * consistency.  These custom locking functions implement the locking
> + * protocol, and cannot be replaced by kernel locking functions that
> + * may use different in-memory structures.
> + */
> +
> +static void res_mgr_lock(void)
> +{
> +	unsigned int tmp;
> +	u64 lock = (u64)&res_mgr_info->rlock;

presumably this could be a u32 *, avoid the cast to u64, and still work
just fine below.

> +
> +	__asm__ __volatile__(
> +		".set noreorder\n"
> +		"1: ll   %[tmp], 0(%[addr])\n"
> +		"   bnez %[tmp], 1b\n"
> +		"   li   %[tmp], 1\n"

I believe the convention for .S files is for instructions in branch
delay slots to be indented an additional space for readability. Maybe
that would be worthwhile here.

> +		"   sc   %[tmp], 0(%[addr])\n"
> +		"   beqz %[tmp], 1b\n"
> +		"   nop\n"

and here also.

> +		".set reorder\n" :

nit: strictly speaking there's no need for \n on the last line.

> +		[tmp] "=&r"(tmp) :
> +		[addr] "r"(lock) :
> +		"memory");

minor style thing: its far more common to have : at the beginning of the
line rather than the end.

> +}
> +
> +static void res_mgr_unlock(void)
> +{
> +	u64 lock = (u64)&res_mgr_info->rlock;

same again

> +
> +	/* Wait until all resource operations finish before unlocking. */
> +	mb();
> +	__asm__ __volatile__(
> +		"sw $0, 0(%[addr])\n" : :
> +		[addr] "r"(lock) :
> +		"memory");
> +
> +	/* Force a write buffer flush. */
> +	mb();
> +}
> +
> +static int res_mgr_find_resource(struct global_resource_tag tag)
> +{
> +	struct global_resource_entry *res_entry;
> +	int i;
> +
> +	for (i = 0; i < res_mgr_info->entry_cnt; i++) {
> +		res_entry = &res_mgr_info->resource_entry[i];
> +		if (res_entry->tag.lo == tag.lo && res_entry->tag.hi == tag.hi)
> +			return i;
> +	}
> +	return -1;
> +}
> +
> +/**
> + * res_mgr_create_resource - Create a resource.
> + * @tag: Identifies the resource.
> + * @inst_cnt: Number of resource instances to create.
> + *
> + * Returns 0 if the source was created successfully.
> + * Returns <0 for error codes.

Only -1 seems to be returned. Is it worth returning some standard Linux
error codes instead?

> + */
> +int res_mgr_create_resource(struct global_resource_tag tag, int inst_cnt)
> +{
> +	struct global_resource_entry *res_entry;
> +	u64 size;
> +	u64 *res_addr;
> +	int res_index, i, rc = 0;
> +
> +	res_mgr_lock();
> +
> +	/* Make sure resource doesn't already exist. */
> +	res_index = res_mgr_find_resource(tag);
> +	if (res_index >= 0) {
> +		rc = -1;
> +		goto err;
> +	}
> +
> +	if (res_mgr_info->entry_cnt >= MAX_RESOURCES) {
> +		pr_err("Resource max limit reached, not created\n");
> +		rc = -1;
> +		goto err;
> +	}
> +
> +	/*
> +	 * Each instance is kept in an array of u64s. The first array element
> +	 * holds the number of allocated instances.
> +	 */
> +	size = sizeof(u64) * (inst_cnt + 1);
> +	res_addr = cvmx_bootmem_alloc_range(size, CVMX_CACHE_LINE_SIZE, 0, 0);
> +	if (!res_addr) {
> +		pr_err("Failed to allocate resource. not created\n");
> +		rc = -1;
> +		goto err;
> +	}
> +
> +	/* Initialize the newly created resource. */
> +	*res_addr = inst_cnt;
> +	for (i = 1; i < inst_cnt + 1; i++)

or "i <= inst_cnt"?

> +		*(res_addr + i) = INST_AVAILABLE;

Nit: IMO res_addr[i] is marginally more readable

> +
> +	res_index = res_mgr_info->entry_cnt;
> +	res_entry = &res_mgr_info->resource_entry[res_index];
> +	res_entry->tag.lo = tag.lo;
> +	res_entry->tag.hi = tag.hi;

or res_entry->tag = tag;?

> +	res_entry->phys_addr = virt_to_phys(res_addr);
> +	res_entry->size = size;
> +	res_mgr_info->entry_cnt++;
> +
> +err:
> +	res_mgr_unlock();
> +
> +	return rc;
> +}
> +EXPORT_SYMBOL(res_mgr_create_resource);
> +
> +/**
> + * res_mgr_alloc_range - Allocate a range of resource instances.

I don't know how strict kerndoc is on this, but I think it should be
res_mgr_alloc_range() here. Same elsewhere.

> + * @tag: Identifies the resource.
> + * @req_inst: Requested start of instance range to allocate.
> + *	      Range instances are guaranteed to be sequential
> + *	      (-1 for don't care).
> + * @req_cnt: Number of instances to allocate.
> + * @use_last_avail: Set to request the last available instance.
> + * @inst: Updated with the allocated instances.
> + *
> + * Returns 0 if the source was created successfully.
> + * Returns <0 for error codes.
> + */
> +int res_mgr_alloc_range(struct global_resource_tag tag, int req_inst,
> +			int req_cnt, bool use_last_avail, int *inst)
> +{
> +	struct global_resource_entry *res_entry;
> +	int res_index;
> +	u64 *res_addr;
> +	u64 inst_cnt;
> +	int alloc_cnt, i, rc = -1;
> +
> +	/* Start with no instances allocated. */
> +	for (i = 0; i < req_cnt; i++)
> +		inst[i] = INST_AVAILABLE;
> +
> +	res_mgr_lock();
> +
> +	/* Find the resource. */
> +	res_index = res_mgr_find_resource(tag);
> +	if (res_index < 0) {
> +		pr_err("Resource not found, can't allocate instance\n");
> +		goto err;
> +	}
> +
> +	/* Get resource data. */
> +	res_entry = &res_mgr_info->resource_entry[res_index];
> +	res_addr = phys_to_virt(res_entry->phys_addr);
> +	inst_cnt = *res_addr;
> +
> +	/* Allocate the requested instances. */
> +	if (req_inst >= 0) {
> +		/* Specific instance range requested. */
> +		if (req_inst + req_cnt >= inst_cnt) {
> +			pr_err("Requested instance out of range\n");
> +			goto err;
> +		}
> +
> +		for (i = 0; i < req_cnt; i++) {
> +			if (*(res_addr + req_inst + 1 + i) == INST_AVAILABLE)
> +				inst[i] = req_inst + i;
> +			else {

braces on all branches if on any.

> +				inst[0] = INST_AVAILABLE;
> +				break;
> +			}
> +		}
> +	} else if (use_last_avail) {
> +		/* Last available instance requested. */
> +		alloc_cnt = 0;
> +		for (i = inst_cnt; i > 0; i--) {
> +			if (*(res_addr + i) == INST_AVAILABLE) {
> +				/*
> +				 * Instance off by 1 (first element holds the
> +				 * count).
> +				 */
> +				inst[alloc_cnt] = i - 1;
> +
> +				alloc_cnt++;
> +				if (alloc_cnt == req_cnt)
> +					break;
> +			}
> +		}
> +
> +		if (i == 0)
> +			inst[0] = INST_AVAILABLE;
> +	} else {
> +		/* Next available instance requested. */
> +		alloc_cnt = 0;
> +		for (i = 1; i <= inst_cnt; i++) {
> +			if (*(res_addr + i) == INST_AVAILABLE) {
> +				/*
> +				 * Instance off by 1 (first element holds the
> +				 * count).
> +				 */
> +				inst[alloc_cnt] = i - 1;
> +
> +				alloc_cnt++;
> +				if (alloc_cnt == req_cnt)
> +					break;
> +			}
> +		}
> +
> +		if (i > inst_cnt)
> +			inst[0] = INST_AVAILABLE;
> +	}
> +
> +	if (inst[0] != INST_AVAILABLE) {
> +		for (i = 0; i < req_cnt; i++)
> +			*(res_addr + inst[i] + 1) = OWNER;
> +		rc = 0;
> +	}
> +
> +err:
> +	res_mgr_unlock();
> +
> +	return rc;
> +}
> +EXPORT_SYMBOL(res_mgr_alloc_range);
> +
> +/**
> + * res_mgr_alloc - Allocate a resource instance.
> + * @tag: Identifies the resource.
> + * @req_inst: Requested instance to allocate (-1 for don't care).
> + * @use_last_avail: Set to request the last available instance.
> + *
> + * Returns: Allocated resource instance if successful.
> + * Returns <0 for error codes.
> + */
> +int res_mgr_alloc(struct global_resource_tag tag, int req_inst, bool use_last_avail)
> +{
> +	int inst, rc;
> +
> +	rc = res_mgr_alloc_range(tag, req_inst, 1, use_last_avail, &inst);
> +	if (!rc)
> +		return inst;
> +	return rc;
> +}
> +EXPORT_SYMBOL(res_mgr_alloc);
> +
> +/**
> + * res_mgr_free_range - Free a resource instance range.
> + * @tag: Identifies the resource.
> + * @req_inst: Requested instance to free.

the parameter is called inst.

Other than these minor / style comments, it doesn't look unreasonable to
me.

Cheers
James

> + * @req_cnt: Number of instances to free.
> + */
> +void res_mgr_free_range(struct global_resource_tag tag, const int *inst, int req_cnt)
> +{
> +	struct global_resource_entry *res_entry;
> +	int res_index, i;
> +	u64 *res_addr;
> +
> +	res_mgr_lock();
> +
> +	/* Find the resource. */
> +	res_index = res_mgr_find_resource(tag);
> +	if (res_index < 0) {
> +		pr_err("Resource not found, can't free instance\n");
> +		goto err;
> +	}
> +
> +	/* Get the resource data. */
> +	res_entry = &res_mgr_info->resource_entry[res_index];
> +	res_addr = phys_to_virt(res_entry->phys_addr);
> +
> +	/* Free the resource instances. */
> +	for (i = 0; i < req_cnt; i++) {
> +		/* Instance off by 1 (first element holds the count). */
> +		*(res_addr + inst[i] + 1) = INST_AVAILABLE;
> +	}
> +
> +err:
> +	res_mgr_unlock();
> +}
> +EXPORT_SYMBOL(res_mgr_free_range);
> +
> +/**
> + * res_mgr_free - Free a resource instance.
> + * @tag: Identifies the resource.
> + * @req_inst: Requested instance to free.
> + */
> +void res_mgr_free(struct global_resource_tag tag, int inst)
> +{
> +	res_mgr_free_range(tag, &inst, 1);
> +}
> +EXPORT_SYMBOL(res_mgr_free);
> +
> +static int __init res_mgr_init(void)
> +{
> +	struct cvmx_bootmem_named_block_desc *block;
> +	int block_size;
> +	u64 addr;
> +
> +	cvmx_bootmem_lock();
> +
> +	/* Search for the resource manager data in boot memory. */
> +	block = cvmx_bootmem_phy_named_block_find(RESOURCE_MGR_BLOCK_NAME, CVMX_BOOTMEM_FLAG_NO_LOCKING);
> +	if (block) {
> +		/* Found. */
> +		res_mgr_info = phys_to_virt(block->base_addr);
> +	} else {
> +		/* Create it. */
> +		block_size = sizeof(struct global_resources) +
> +			sizeof(struct global_resource_entry) * MAX_RESOURCES;
> +		addr = cvmx_bootmem_phy_named_block_alloc(block_size, 0, 0,
> +				CVMX_CACHE_LINE_SIZE, RESOURCE_MGR_BLOCK_NAME,
> +				CVMX_BOOTMEM_FLAG_NO_LOCKING);
> +		if (!addr) {
> +			pr_err("Failed to allocate name block %s\n",
> +			       RESOURCE_MGR_BLOCK_NAME);
> +		} else {
> +			res_mgr_info = phys_to_virt(addr);
> +			memset(res_mgr_info, 0, block_size);
> +		}
> +	}
> +
> +	cvmx_bootmem_unlock();
> +
> +	return 0;
> +}
> +device_initcall(res_mgr_init);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_DESCRIPTION("Cavium, Inc. Octeon resource manager");
> diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h
> index 92a17d67c1fa..0411efdb465c 100644
> --- a/arch/mips/include/asm/octeon/octeon.h
> +++ b/arch/mips/include/asm/octeon/octeon.h
> @@ -346,6 +346,24 @@ void octeon_mult_restore3_end(void);
>  void octeon_mult_restore2(void);
>  void octeon_mult_restore2_end(void);
>  
> +/*
> + * This definition must be kept in sync with the one in
> + * cvmx-global-resources.c
> + */
> +struct global_resource_tag {
> +	uint64_t lo;
> +	uint64_t hi;
> +};
> +
> +void res_mgr_free(struct global_resource_tag tag, int inst);
> +void res_mgr_free_range(struct global_resource_tag tag, const int *inst,
> +			int req_cnt);
> +int res_mgr_alloc(struct global_resource_tag tag, int req_inst,
> +		  bool use_last_avail);
> +int res_mgr_alloc_range(struct global_resource_tag tag, int req_inst,
> +			int req_cnt, bool use_last_avail, int *inst);
> +int res_mgr_create_resource(struct global_resource_tag tag, int inst_cnt);
> +
>  /**
>   * Read a 32bit value from the Octeon NPI register space
>   *
> -- 
> 2.14.3
>
David Daney Dec. 1, 2017, 1:51 a.m. UTC | #2
On 11/30/2017 02:53 PM, James Hogan wrote:
> On Tue, Nov 28, 2017 at 04:55:35PM -0800, David Daney wrote:
>> From: Carlos Munoz <cmunoz@cavium.com>
>>
>> Add a global resource manager to manage tagged pointers within
>> bootmem allocated memory. This is used by various functional
>> blocks in the Octeon core like the FPA, Ethernet nexus, etc.
>>
>> Signed-off-by: Carlos Munoz <cmunoz@cavium.com>
>> Signed-off-by: Steven J. Hill <Steven.Hill@cavium.com>
>> Signed-off-by: David Daney <david.daney@cavium.com>
>> ---
>>   arch/mips/cavium-octeon/Makefile       |   3 +-
>>   arch/mips/cavium-octeon/resource-mgr.c | 371 +++++++++++++++++++++++++++++++++
>>   arch/mips/include/asm/octeon/octeon.h  |  18 ++
>>   3 files changed, 391 insertions(+), 1 deletion(-)
>>   create mode 100644 arch/mips/cavium-octeon/resource-mgr.c
>>
>> diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile
>> index 7c02e542959a..0a299ab8719f 100644
>> --- a/arch/mips/cavium-octeon/Makefile
>> +++ b/arch/mips/cavium-octeon/Makefile
>> @@ -9,7 +9,8 @@
>>   # Copyright (C) 2005-2009 Cavium Networks
>>   #
>>   
>> -obj-y := cpu.o setup.o octeon-platform.o octeon-irq.o csrc-octeon.o
>> +obj-y := cpu.o setup.o octeon-platform.o octeon-irq.o csrc-octeon.o \
>> +	 resource-mgr.o
> 
> Maybe put that on a separate line like below.

OK

> 
>>   obj-y += dma-octeon.o
>>   obj-y += octeon-memcpy.o
>>   obj-y += executive/
>> diff --git a/arch/mips/cavium-octeon/resource-mgr.c b/arch/mips/cavium-octeon/resource-mgr.c
>> new file mode 100644
>> index 000000000000..ca25fa953402
>> --- /dev/null
>> +++ b/arch/mips/cavium-octeon/resource-mgr.c
>> @@ -0,0 +1,371 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Resource manager for Octeon.
>> + *
>> + * This file is subject to the terms and conditions of the GNU General Public
>> + * License.  See the file "COPYING" in the main directory of this archive
>> + * for more details.
>> + *
>> + * Copyright (C) 2017 Cavium, Inc.
>> + */
>> +#include <linux/module.h>
>> +
>> +#include <asm/octeon/octeon.h>
>> +#include <asm/octeon/cvmx-bootmem.h>
>> +
>> +#define RESOURCE_MGR_BLOCK_NAME		"cvmx-global-resources"
>> +#define MAX_RESOURCES			128
>> +#define INST_AVAILABLE			-88
>> +#define OWNER				0xbadc0de
>> +
>> +struct global_resource_entry {
>> +	struct global_resource_tag tag;
>> +	u64 phys_addr;
>> +	u64 size;
>> +};
>> +
>> +struct global_resources {
>> +#ifdef __LITTLE_ENDIAN_BITFIELD
>> +	u32 rlock;
>> +	u32 pad;
>> +#else
>> +	u32 pad;
>> +	u32 rlock;
>> +#endif
>> +	u64 entry_cnt;
>> +	struct global_resource_entry resource_entry[];
>> +};
>> +
>> +static struct global_resources *res_mgr_info;
>> +
>> +
>> +/*
>> + * The resource manager interacts with software running outside of the
>> + * Linux kernel, which necessitates locking to maintain data structure
>> + * consistency.  These custom locking functions implement the locking
>> + * protocol, and cannot be replaced by kernel locking functions that
>> + * may use different in-memory structures.
>> + */
>> +
>> +static void res_mgr_lock(void)
>> +{
>> +	unsigned int tmp;
>> +	u64 lock = (u64)&res_mgr_info->rlock;
> 
> presumably this could be a u32 *, avoid the cast to u64, and still work
> just fine below.

I will rewrite to just use cmpxchg()


> 
>> +
>> +	__asm__ __volatile__(
>> +		".set noreorder\n"
>> +		"1: ll   %[tmp], 0(%[addr])\n"
>> +		"   bnez %[tmp], 1b\n"
>> +		"   li   %[tmp], 1\n"
> 
> I believe the convention for .S files is for instructions in branch
> delay slots to be indented an additional space for readability. Maybe
> that would be worthwhile here.
> 
>> +		"   sc   %[tmp], 0(%[addr])\n"
>> +		"   beqz %[tmp], 1b\n"
>> +		"   nop\n"
> 
> and here also.
> 
>> +		".set reorder\n" :
> 
> nit: strictly speaking there's no need for \n on the last line.
> 
>> +		[tmp] "=&r"(tmp) :
>> +		[addr] "r"(lock) :
>> +		"memory");
> 
> minor style thing: its far more common to have : at the beginning of the
> line rather than the end.
> 
>> +}
>> +
>> +static void res_mgr_unlock(void)
>> +{
>> +	u64 lock = (u64)&res_mgr_info->rlock;
> 
> same again
> 

Will rewrite to use WRITE_ONCE().

>> +
>> +	/* Wait until all resource operations finish before unlocking. */
>> +	mb();
>> +	__asm__ __volatile__(
>> +		"sw $0, 0(%[addr])\n" : :
>> +		[addr] "r"(lock) :
>> +		"memory");
>> +
>> +	/* Force a write buffer flush. */
>> +	mb();
>> +}
>> +
>> +static int res_mgr_find_resource(struct global_resource_tag tag)
>> +{
>> +	struct global_resource_entry *res_entry;
>> +	int i;
>> +
>> +	for (i = 0; i < res_mgr_info->entry_cnt; i++) {
>> +		res_entry = &res_mgr_info->resource_entry[i];
>> +		if (res_entry->tag.lo == tag.lo && res_entry->tag.hi == tag.hi)
>> +			return i;
>> +	}
>> +	return -1;
>> +}
>> +
>> +/**
>> + * res_mgr_create_resource - Create a resource.
>> + * @tag: Identifies the resource.
>> + * @inst_cnt: Number of resource instances to create.
>> + *
>> + * Returns 0 if the source was created successfully.
>> + * Returns <0 for error codes.
> 
> Only -1 seems to be returned. Is it worth returning some standard Linux
> error codes instead?

Yep.  I fixed this and everything below for the next version of the 
patch set.

Thanks,
David Daney
Philippe Ombredanne Dec. 1, 2017, 7:53 a.m. UTC | #3
Carlos,

On Thu, Nov 30, 2017 at 11:53 PM, James Hogan <james.hogan@mips.com> wrote:
> On Tue, Nov 28, 2017 at 04:55:35PM -0800, David Daney wrote:
>> From: Carlos Munoz <cmunoz@cavium.com>
>>
>> Add a global resource manager to manage tagged pointers within
>> bootmem allocated memory. This is used by various functional
>> blocks in the Octeon core like the FPA, Ethernet nexus, etc.
>>
>> Signed-off-by: Carlos Munoz <cmunoz@cavium.com>
>> Signed-off-by: Steven J. Hill <Steven.Hill@cavium.com>
>> Signed-off-by: David Daney <david.daney@cavium.com>
>> ---
>>  arch/mips/cavium-octeon/Makefile       |   3 +-
>>  arch/mips/cavium-octeon/resource-mgr.c | 371 +++++++++++++++++++++++++++++++++
>>  arch/mips/include/asm/octeon/octeon.h  |  18 ++
>>  3 files changed, 391 insertions(+), 1 deletion(-)
>>  create mode 100644 arch/mips/cavium-octeon/resource-mgr.c
>>
>> diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile
>> index 7c02e542959a..0a299ab8719f 100644
>> --- a/arch/mips/cavium-octeon/Makefile
>> +++ b/arch/mips/cavium-octeon/Makefile
>> @@ -9,7 +9,8 @@
>>  # Copyright (C) 2005-2009 Cavium Networks
>>  #
>>
>> -obj-y := cpu.o setup.o octeon-platform.o octeon-irq.o csrc-octeon.o
>> +obj-y := cpu.o setup.o octeon-platform.o octeon-irq.o csrc-octeon.o \
>> +      resource-mgr.o
>
> Maybe put that on a separate line like below.
>
>>  obj-y += dma-octeon.o
>>  obj-y += octeon-memcpy.o
>>  obj-y += executive/
>> diff --git a/arch/mips/cavium-octeon/resource-mgr.c b/arch/mips/cavium-octeon/resource-mgr.c
>> new file mode 100644
>> index 000000000000..ca25fa953402
>> --- /dev/null
>> +++ b/arch/mips/cavium-octeon/resource-mgr.c
>> @@ -0,0 +1,371 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Resource manager for Octeon.
>> + *
>> + * This file is subject to the terms and conditions of the GNU General Public
>> + * License.  See the file "COPYING" in the main directory of this archive
>> + * for more details.
>> + *
>> + * Copyright (C) 2017 Cavium, Inc.
>> + */

Since you nicely included an SPDX id, you would not need the
boilerplate anymore. e.g. these can go alright?

>> + * This file is subject to the terms and conditions of the GNU General Public
>> + * License.  See the file "COPYING" in the main directory of this archive
>> + * for more details.
David Daney Dec. 1, 2017, 5:42 p.m. UTC | #4
On 11/30/2017 11:53 PM, Philippe Ombredanne wrote:
> Carlos,
> 
> On Thu, Nov 30, 2017 at 11:53 PM, James Hogan <james.hogan@mips.com> wrote:
>> On Tue, Nov 28, 2017 at 04:55:35PM -0800, David Daney wrote:
>>> From: Carlos Munoz <cmunoz@cavium.com>
>>>
>>> Add a global resource manager to manage tagged pointers within
>>> bootmem allocated memory. This is used by various functional
>>> blocks in the Octeon core like the FPA, Ethernet nexus, etc.
>>>
>>> Signed-off-by: Carlos Munoz <cmunoz@cavium.com>
>>> Signed-off-by: Steven J. Hill <Steven.Hill@cavium.com>
>>> Signed-off-by: David Daney <david.daney@cavium.com>
>>> ---
>>>   arch/mips/cavium-octeon/Makefile       |   3 +-
>>>   arch/mips/cavium-octeon/resource-mgr.c | 371 +++++++++++++++++++++++++++++++++
>>>   arch/mips/include/asm/octeon/octeon.h  |  18 ++
>>>   3 files changed, 391 insertions(+), 1 deletion(-)
>>>   create mode 100644 arch/mips/cavium-octeon/resource-mgr.c
>>>
>>> diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile
>>> index 7c02e542959a..0a299ab8719f 100644
>>> --- a/arch/mips/cavium-octeon/Makefile
>>> +++ b/arch/mips/cavium-octeon/Makefile
>>> @@ -9,7 +9,8 @@
>>>   # Copyright (C) 2005-2009 Cavium Networks
>>>   #
>>>
>>> -obj-y := cpu.o setup.o octeon-platform.o octeon-irq.o csrc-octeon.o
>>> +obj-y := cpu.o setup.o octeon-platform.o octeon-irq.o csrc-octeon.o \
>>> +      resource-mgr.o
>>
>> Maybe put that on a separate line like below.
>>
>>>   obj-y += dma-octeon.o
>>>   obj-y += octeon-memcpy.o
>>>   obj-y += executive/
>>> diff --git a/arch/mips/cavium-octeon/resource-mgr.c b/arch/mips/cavium-octeon/resource-mgr.c
>>> new file mode 100644
>>> index 000000000000..ca25fa953402
>>> --- /dev/null
>>> +++ b/arch/mips/cavium-octeon/resource-mgr.c
>>> @@ -0,0 +1,371 @@
>>> +// SPDX-License-Identifier: GPL-2.0
>>> +/*
>>> + * Resource manager for Octeon.
>>> + *
>>> + * This file is subject to the terms and conditions of the GNU General Public
>>> + * License.  See the file "COPYING" in the main directory of this archive
>>> + * for more details.
>>> + *
>>> + * Copyright (C) 2017 Cavium, Inc.
>>> + */
> 
> Since you nicely included an SPDX id, you would not need the
> boilerplate anymore. e.g. these can go alright?

They may not be strictly speaking necessary, but I don't think they hurt 
anything.  Unless there is a requirement to strip out the license text, 
we would stick with it as is.

> 
>>> + * This file is subject to the terms and conditions of the GNU General Public
>>> + * License.  See the file "COPYING" in the main directory of this archive
>>> + * for more details.
>
Philippe Ombredanne Dec. 1, 2017, 7:49 p.m. UTC | #5
David, Greg,

On Fri, Dec 1, 2017 at 6:42 PM, David Daney <ddaney@caviumnetworks.com> wrote:
> On 11/30/2017 11:53 PM, Philippe Ombredanne wrote:
[...]
>>>> --- /dev/null
>>>> +++ b/arch/mips/cavium-octeon/resource-mgr.c
>>>> @@ -0,0 +1,371 @@
>>>> +// SPDX-License-Identifier: GPL-2.0
>>>> +/*
>>>> + * Resource manager for Octeon.
>>>> + *
>>>> + * This file is subject to the terms and conditions of the GNU General
>>>> Public
>>>> + * License.  See the file "COPYING" in the main directory of this
>>>> archive
>>>> + * for more details.
>>>> + *
>>>> + * Copyright (C) 2017 Cavium, Inc.
>>>> + */
>>
>>
>> Since you nicely included an SPDX id, you would not need the
>> boilerplate anymore. e.g. these can go alright?
>
>
> They may not be strictly speaking necessary, but I don't think they hurt
> anything.  Unless there is a requirement to strip out the license text, we
> would stick with it as is.

I think the requirement is there and that would be much better for
everyone: keeping both is redundant and does not bring any value, does
it? Instead it kinda removes the benefits of having the SPDX id in the
first place IMHO.

Furthermore, as there have been already ~12K+ files cleaned up and
still over 60K files to go, it would really nice if new files could
adopt the new style: this way we will not have to revisit and repatch
them in the future.
David Daney Dec. 1, 2017, 8:01 p.m. UTC | #6
On 12/01/2017 11:49 AM, Philippe Ombredanne wrote:
> David, Greg,
> 
> On Fri, Dec 1, 2017 at 6:42 PM, David Daney <ddaney@caviumnetworks.com> wrote:
>> On 11/30/2017 11:53 PM, Philippe Ombredanne wrote:
> [...]
>>>>> --- /dev/null
>>>>> +++ b/arch/mips/cavium-octeon/resource-mgr.c
>>>>> @@ -0,0 +1,371 @@
>>>>> +// SPDX-License-Identifier: GPL-2.0
>>>>> +/*
>>>>> + * Resource manager for Octeon.
>>>>> + *
>>>>> + * This file is subject to the terms and conditions of the GNU General
>>>>> Public
>>>>> + * License.  See the file "COPYING" in the main directory of this
>>>>> archive
>>>>> + * for more details.
>>>>> + *
>>>>> + * Copyright (C) 2017 Cavium, Inc.
>>>>> + */
>>>
>>>
>>> Since you nicely included an SPDX id, you would not need the
>>> boilerplate anymore. e.g. these can go alright?
>>
>>
>> They may not be strictly speaking necessary, but I don't think they hurt
>> anything.  Unless there is a requirement to strip out the license text, we
>> would stick with it as is.
> 
> I think the requirement is there and that would be much better for
> everyone: keeping both is redundant and does not bring any value, does
> it? Instead it kinda removes the benefits of having the SPDX id in the
> first place IMHO.
> 
> Furthermore, as there have been already ~12K+ files cleaned up and
> still over 60K files to go, it would really nice if new files could
> adopt the new style: this way we will not have to revisit and repatch
> them in the future.
> 

I am happy to follow any style Greg would suggest.  There doesn't seem 
to be much documentation about how this should be done yet.

David Daney
Philippe Ombredanne Dec. 1, 2017, 8:41 p.m. UTC | #7
David,

On Fri, Dec 1, 2017 at 9:01 PM, David Daney <ddaney@caviumnetworks.com> wrote:
> On 12/01/2017 11:49 AM, Philippe Ombredanne wrote:
>>
>> David, Greg,
>>
>> On Fri, Dec 1, 2017 at 6:42 PM, David Daney <ddaney@caviumnetworks.com>
>> wrote:
>>>
>>> On 11/30/2017 11:53 PM, Philippe Ombredanne wrote:
>>
>> [...]
>>>>>>
>>>>>> --- /dev/null
>>>>>> +++ b/arch/mips/cavium-octeon/resource-mgr.c
>>>>>> @@ -0,0 +1,371 @@
>>>>>> +// SPDX-License-Identifier: GPL-2.0
>>>>>> +/*
>>>>>> + * Resource manager for Octeon.
>>>>>> + *
>>>>>> + * This file is subject to the terms and conditions of the GNU
>>>>>> General
>>>>>> Public
>>>>>> + * License.  See the file "COPYING" in the main directory of this
>>>>>> archive
>>>>>> + * for more details.
>>>>>> + *
>>>>>> + * Copyright (C) 2017 Cavium, Inc.
>>>>>> + */
>>>>
>>>>
>>>>
>>>> Since you nicely included an SPDX id, you would not need the
>>>> boilerplate anymore. e.g. these can go alright?
>>>
>>>
>>>
>>> They may not be strictly speaking necessary, but I don't think they hurt
>>> anything.  Unless there is a requirement to strip out the license text,
>>> we
>>> would stick with it as is.
>>
>>
>> I think the requirement is there and that would be much better for
>> everyone: keeping both is redundant and does not bring any value, does
>> it? Instead it kinda removes the benefits of having the SPDX id in the
>> first place IMHO.
>>
>> Furthermore, as there have been already ~12K+ files cleaned up and
>> still over 60K files to go, it would really nice if new files could
>> adopt the new style: this way we will not have to revisit and repatch
>> them in the future.
>>
>
> I am happy to follow any style Greg would suggest.  There doesn't seem to be
> much documentation about how this should be done yet.

Thomas (tglx) has already submitted a first series of doc patches a
few weeks ago. And AFAIK he might be working on posting the updates
soon, whenever his real time clock yields a few cycles away from real
time coding work ;)

See also these discussions with Linus [1][2][3], Thomas[4] and Greg[5]
on this and mostly related topics

[1] https://lkml.org/lkml/2017/11/2/715
[2] https://lkml.org/lkml/2017/11/25/125
[3] https://lkml.org/lkml/2017/11/25/133
[4] https://lkml.org/lkml/2017/11/2/805
[5] https://lkml.org/lkml/2017/10/19/165
David Daney Dec. 1, 2017, 8:56 p.m. UTC | #8
On 12/01/2017 12:41 PM, Philippe Ombredanne wrote:
> David,
> 
> On Fri, Dec 1, 2017 at 9:01 PM, David Daney <ddaney@caviumnetworks.com> wrote:
>> On 12/01/2017 11:49 AM, Philippe Ombredanne wrote:
>>>
>>> David, Greg,
>>>
>>> On Fri, Dec 1, 2017 at 6:42 PM, David Daney <ddaney@caviumnetworks.com>
>>> wrote:
>>>>
>>>> On 11/30/2017 11:53 PM, Philippe Ombredanne wrote:
>>>
>>> [...]
>>>>>>>
>>>>>>> --- /dev/null
>>>>>>> +++ b/arch/mips/cavium-octeon/resource-mgr.c
>>>>>>> @@ -0,0 +1,371 @@
>>>>>>> +// SPDX-License-Identifier: GPL-2.0
>>>>>>> +/*
>>>>>>> + * Resource manager for Octeon.
>>>>>>> + *
>>>>>>> + * This file is subject to the terms and conditions of the GNU
>>>>>>> General
>>>>>>> Public
>>>>>>> + * License.  See the file "COPYING" in the main directory of this
>>>>>>> archive
>>>>>>> + * for more details.
>>>>>>> + *
>>>>>>> + * Copyright (C) 2017 Cavium, Inc.
>>>>>>> + */
>>>>>
>>>>>
>>>>>
>>>>> Since you nicely included an SPDX id, you would not need the
>>>>> boilerplate anymore. e.g. these can go alright?
>>>>
>>>>
>>>>
>>>> They may not be strictly speaking necessary, but I don't think they hurt
>>>> anything.  Unless there is a requirement to strip out the license text,
>>>> we
>>>> would stick with it as is.
>>>
>>>
>>> I think the requirement is there and that would be much better for
>>> everyone: keeping both is redundant and does not bring any value, does
>>> it? Instead it kinda removes the benefits of having the SPDX id in the
>>> first place IMHO.
>>>
>>> Furthermore, as there have been already ~12K+ files cleaned up and
>>> still over 60K files to go, it would really nice if new files could
>>> adopt the new style: this way we will not have to revisit and repatch
>>> them in the future.
>>>
>>
>> I am happy to follow any style Greg would suggest.  There doesn't seem to be
>> much documentation about how this should be done yet.
> 
> Thomas (tglx) has already submitted a first series of doc patches a
> few weeks ago. And AFAIK he might be working on posting the updates
> soon, whenever his real time clock yields a few cycles away from real
> time coding work ;)
> 
> See also these discussions with Linus [1][2][3], Thomas[4] and Greg[5]
> on this and mostly related topics
> 
> [1] https://lkml.org/lkml/2017/11/2/715
> [2] https://lkml.org/lkml/2017/11/25/125
> [3] https://lkml.org/lkml/2017/11/25/133
> [4] https://lkml.org/lkml/2017/11/2/805
> [5] https://lkml.org/lkml/2017/10/19/165
> 

OK, you convinced me.

Thanks,
David
Philippe Ombredanne Dec. 1, 2017, 11:33 p.m. UTC | #9
On Fri, Dec 1, 2017 at 9:56 PM, David Daney <ddaney@caviumnetworks.com> wrote:
> On 12/01/2017 12:41 PM, Philippe Ombredanne wrote:
>>
>> David,
>>
>> On Fri, Dec 1, 2017 at 9:01 PM, David Daney <ddaney@caviumnetworks.com>
>> wrote:
>>>
>>> On 12/01/2017 11:49 AM, Philippe Ombredanne wrote:
>>>>
>>>>
>>>> David, Greg,
>>>>
>>>> On Fri, Dec 1, 2017 at 6:42 PM, David Daney <ddaney@caviumnetworks.com>
>>>> wrote:
>>>>>
>>>>>
>>>>> On 11/30/2017 11:53 PM, Philippe Ombredanne wrote:
>>>>
>>>>
>>>> [...]
>>>>>>>>
>>>>>>>>
>>>>>>>> --- /dev/null
>>>>>>>> +++ b/arch/mips/cavium-octeon/resource-mgr.c
>>>>>>>> @@ -0,0 +1,371 @@
>>>>>>>> +// SPDX-License-Identifier: GPL-2.0
>>>>>>>> +/*
>>>>>>>> + * Resource manager for Octeon.
>>>>>>>> + *
>>>>>>>> + * This file is subject to the terms and conditions of the GNU
>>>>>>>> General
>>>>>>>> Public
>>>>>>>> + * License.  See the file "COPYING" in the main directory of this
>>>>>>>> archive
>>>>>>>> + * for more details.
>>>>>>>> + *
>>>>>>>> + * Copyright (C) 2017 Cavium, Inc.
>>>>>>>> + */
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> Since you nicely included an SPDX id, you would not need the
>>>>>> boilerplate anymore. e.g. these can go alright?
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> They may not be strictly speaking necessary, but I don't think they
>>>>> hurt
>>>>> anything.  Unless there is a requirement to strip out the license text,
>>>>> we
>>>>> would stick with it as is.
>>>>
>>>>
>>>>
>>>> I think the requirement is there and that would be much better for
>>>> everyone: keeping both is redundant and does not bring any value, does
>>>> it? Instead it kinda removes the benefits of having the SPDX id in the
>>>> first place IMHO.
>>>>
>>>> Furthermore, as there have been already ~12K+ files cleaned up and
>>>> still over 60K files to go, it would really nice if new files could
>>>> adopt the new style: this way we will not have to revisit and repatch
>>>> them in the future.
>>>>
>>>
>>> I am happy to follow any style Greg would suggest.  There doesn't seem to
>>> be
>>> much documentation about how this should be done yet.
>>
>>
>> Thomas (tglx) has already submitted a first series of doc patches a
>> few weeks ago. And AFAIK he might be working on posting the updates
>> soon, whenever his real time clock yields a few cycles away from real
>> time coding work ;)
>>
>> See also these discussions with Linus [1][2][3], Thomas[4] and Greg[5]
>> on this and mostly related topics
>>
>> [1] https://lkml.org/lkml/2017/11/2/715
>> [2] https://lkml.org/lkml/2017/11/25/125
>> [3] https://lkml.org/lkml/2017/11/25/133
>> [4] https://lkml.org/lkml/2017/11/2/805
>> [5] https://lkml.org/lkml/2017/10/19/165
>>
>
> OK, you convinced me.
>
> Thanks,
> David
>

No! Thank you to you: For doing real work on the kernel that makes my
servers and laptops run, while I am nitpicking you on comments.
diff mbox series

Patch

diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile
index 7c02e542959a..0a299ab8719f 100644
--- a/arch/mips/cavium-octeon/Makefile
+++ b/arch/mips/cavium-octeon/Makefile
@@ -9,7 +9,8 @@ 
 # Copyright (C) 2005-2009 Cavium Networks
 #
 
-obj-y := cpu.o setup.o octeon-platform.o octeon-irq.o csrc-octeon.o
+obj-y := cpu.o setup.o octeon-platform.o octeon-irq.o csrc-octeon.o \
+	 resource-mgr.o
 obj-y += dma-octeon.o
 obj-y += octeon-memcpy.o
 obj-y += executive/
diff --git a/arch/mips/cavium-octeon/resource-mgr.c b/arch/mips/cavium-octeon/resource-mgr.c
new file mode 100644
index 000000000000..ca25fa953402
--- /dev/null
+++ b/arch/mips/cavium-octeon/resource-mgr.c
@@ -0,0 +1,371 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Resource manager for Octeon.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2017 Cavium, Inc.
+ */
+#include <linux/module.h>
+
+#include <asm/octeon/octeon.h>
+#include <asm/octeon/cvmx-bootmem.h>
+
+#define RESOURCE_MGR_BLOCK_NAME		"cvmx-global-resources"
+#define MAX_RESOURCES			128
+#define INST_AVAILABLE			-88
+#define OWNER				0xbadc0de
+
+struct global_resource_entry {
+	struct global_resource_tag tag;
+	u64 phys_addr;
+	u64 size;
+};
+
+struct global_resources {
+#ifdef __LITTLE_ENDIAN_BITFIELD
+	u32 rlock;
+	u32 pad;
+#else
+	u32 pad;
+	u32 rlock;
+#endif
+	u64 entry_cnt;
+	struct global_resource_entry resource_entry[];
+};
+
+static struct global_resources *res_mgr_info;
+
+
+/*
+ * The resource manager interacts with software running outside of the
+ * Linux kernel, which necessitates locking to maintain data structure
+ * consistency.  These custom locking functions implement the locking
+ * protocol, and cannot be replaced by kernel locking functions that
+ * may use different in-memory structures.
+ */
+
+static void res_mgr_lock(void)
+{
+	unsigned int tmp;
+	u64 lock = (u64)&res_mgr_info->rlock;
+
+	__asm__ __volatile__(
+		".set noreorder\n"
+		"1: ll   %[tmp], 0(%[addr])\n"
+		"   bnez %[tmp], 1b\n"
+		"   li   %[tmp], 1\n"
+		"   sc   %[tmp], 0(%[addr])\n"
+		"   beqz %[tmp], 1b\n"
+		"   nop\n"
+		".set reorder\n" :
+		[tmp] "=&r"(tmp) :
+		[addr] "r"(lock) :
+		"memory");
+}
+
+static void res_mgr_unlock(void)
+{
+	u64 lock = (u64)&res_mgr_info->rlock;
+
+	/* Wait until all resource operations finish before unlocking. */
+	mb();
+	__asm__ __volatile__(
+		"sw $0, 0(%[addr])\n" : :
+		[addr] "r"(lock) :
+		"memory");
+
+	/* Force a write buffer flush. */
+	mb();
+}
+
+static int res_mgr_find_resource(struct global_resource_tag tag)
+{
+	struct global_resource_entry *res_entry;
+	int i;
+
+	for (i = 0; i < res_mgr_info->entry_cnt; i++) {
+		res_entry = &res_mgr_info->resource_entry[i];
+		if (res_entry->tag.lo == tag.lo && res_entry->tag.hi == tag.hi)
+			return i;
+	}
+	return -1;
+}
+
+/**
+ * res_mgr_create_resource - Create a resource.
+ * @tag: Identifies the resource.
+ * @inst_cnt: Number of resource instances to create.
+ *
+ * Returns 0 if the source was created successfully.
+ * Returns <0 for error codes.
+ */
+int res_mgr_create_resource(struct global_resource_tag tag, int inst_cnt)
+{
+	struct global_resource_entry *res_entry;
+	u64 size;
+	u64 *res_addr;
+	int res_index, i, rc = 0;
+
+	res_mgr_lock();
+
+	/* Make sure resource doesn't already exist. */
+	res_index = res_mgr_find_resource(tag);
+	if (res_index >= 0) {
+		rc = -1;
+		goto err;
+	}
+
+	if (res_mgr_info->entry_cnt >= MAX_RESOURCES) {
+		pr_err("Resource max limit reached, not created\n");
+		rc = -1;
+		goto err;
+	}
+
+	/*
+	 * Each instance is kept in an array of u64s. The first array element
+	 * holds the number of allocated instances.
+	 */
+	size = sizeof(u64) * (inst_cnt + 1);
+	res_addr = cvmx_bootmem_alloc_range(size, CVMX_CACHE_LINE_SIZE, 0, 0);
+	if (!res_addr) {
+		pr_err("Failed to allocate resource. not created\n");
+		rc = -1;
+		goto err;
+	}
+
+	/* Initialize the newly created resource. */
+	*res_addr = inst_cnt;
+	for (i = 1; i < inst_cnt + 1; i++)
+		*(res_addr + i) = INST_AVAILABLE;
+
+	res_index = res_mgr_info->entry_cnt;
+	res_entry = &res_mgr_info->resource_entry[res_index];
+	res_entry->tag.lo = tag.lo;
+	res_entry->tag.hi = tag.hi;
+	res_entry->phys_addr = virt_to_phys(res_addr);
+	res_entry->size = size;
+	res_mgr_info->entry_cnt++;
+
+err:
+	res_mgr_unlock();
+
+	return rc;
+}
+EXPORT_SYMBOL(res_mgr_create_resource);
+
+/**
+ * res_mgr_alloc_range - Allocate a range of resource instances.
+ * @tag: Identifies the resource.
+ * @req_inst: Requested start of instance range to allocate.
+ *	      Range instances are guaranteed to be sequential
+ *	      (-1 for don't care).
+ * @req_cnt: Number of instances to allocate.
+ * @use_last_avail: Set to request the last available instance.
+ * @inst: Updated with the allocated instances.
+ *
+ * Returns 0 if the source was created successfully.
+ * Returns <0 for error codes.
+ */
+int res_mgr_alloc_range(struct global_resource_tag tag, int req_inst,
+			int req_cnt, bool use_last_avail, int *inst)
+{
+	struct global_resource_entry *res_entry;
+	int res_index;
+	u64 *res_addr;
+	u64 inst_cnt;
+	int alloc_cnt, i, rc = -1;
+
+	/* Start with no instances allocated. */
+	for (i = 0; i < req_cnt; i++)
+		inst[i] = INST_AVAILABLE;
+
+	res_mgr_lock();
+
+	/* Find the resource. */
+	res_index = res_mgr_find_resource(tag);
+	if (res_index < 0) {
+		pr_err("Resource not found, can't allocate instance\n");
+		goto err;
+	}
+
+	/* Get resource data. */
+	res_entry = &res_mgr_info->resource_entry[res_index];
+	res_addr = phys_to_virt(res_entry->phys_addr);
+	inst_cnt = *res_addr;
+
+	/* Allocate the requested instances. */
+	if (req_inst >= 0) {
+		/* Specific instance range requested. */
+		if (req_inst + req_cnt >= inst_cnt) {
+			pr_err("Requested instance out of range\n");
+			goto err;
+		}
+
+		for (i = 0; i < req_cnt; i++) {
+			if (*(res_addr + req_inst + 1 + i) == INST_AVAILABLE)
+				inst[i] = req_inst + i;
+			else {
+				inst[0] = INST_AVAILABLE;
+				break;
+			}
+		}
+	} else if (use_last_avail) {
+		/* Last available instance requested. */
+		alloc_cnt = 0;
+		for (i = inst_cnt; i > 0; i--) {
+			if (*(res_addr + i) == INST_AVAILABLE) {
+				/*
+				 * Instance off by 1 (first element holds the
+				 * count).
+				 */
+				inst[alloc_cnt] = i - 1;
+
+				alloc_cnt++;
+				if (alloc_cnt == req_cnt)
+					break;
+			}
+		}
+
+		if (i == 0)
+			inst[0] = INST_AVAILABLE;
+	} else {
+		/* Next available instance requested. */
+		alloc_cnt = 0;
+		for (i = 1; i <= inst_cnt; i++) {
+			if (*(res_addr + i) == INST_AVAILABLE) {
+				/*
+				 * Instance off by 1 (first element holds the
+				 * count).
+				 */
+				inst[alloc_cnt] = i - 1;
+
+				alloc_cnt++;
+				if (alloc_cnt == req_cnt)
+					break;
+			}
+		}
+
+		if (i > inst_cnt)
+			inst[0] = INST_AVAILABLE;
+	}
+
+	if (inst[0] != INST_AVAILABLE) {
+		for (i = 0; i < req_cnt; i++)
+			*(res_addr + inst[i] + 1) = OWNER;
+		rc = 0;
+	}
+
+err:
+	res_mgr_unlock();
+
+	return rc;
+}
+EXPORT_SYMBOL(res_mgr_alloc_range);
+
+/**
+ * res_mgr_alloc - Allocate a resource instance.
+ * @tag: Identifies the resource.
+ * @req_inst: Requested instance to allocate (-1 for don't care).
+ * @use_last_avail: Set to request the last available instance.
+ *
+ * Returns: Allocated resource instance if successful.
+ * Returns <0 for error codes.
+ */
+int res_mgr_alloc(struct global_resource_tag tag, int req_inst, bool use_last_avail)
+{
+	int inst, rc;
+
+	rc = res_mgr_alloc_range(tag, req_inst, 1, use_last_avail, &inst);
+	if (!rc)
+		return inst;
+	return rc;
+}
+EXPORT_SYMBOL(res_mgr_alloc);
+
+/**
+ * res_mgr_free_range - Free a resource instance range.
+ * @tag: Identifies the resource.
+ * @req_inst: Requested instance to free.
+ * @req_cnt: Number of instances to free.
+ */
+void res_mgr_free_range(struct global_resource_tag tag, const int *inst, int req_cnt)
+{
+	struct global_resource_entry *res_entry;
+	int res_index, i;
+	u64 *res_addr;
+
+	res_mgr_lock();
+
+	/* Find the resource. */
+	res_index = res_mgr_find_resource(tag);
+	if (res_index < 0) {
+		pr_err("Resource not found, can't free instance\n");
+		goto err;
+	}
+
+	/* Get the resource data. */
+	res_entry = &res_mgr_info->resource_entry[res_index];
+	res_addr = phys_to_virt(res_entry->phys_addr);
+
+	/* Free the resource instances. */
+	for (i = 0; i < req_cnt; i++) {
+		/* Instance off by 1 (first element holds the count). */
+		*(res_addr + inst[i] + 1) = INST_AVAILABLE;
+	}
+
+err:
+	res_mgr_unlock();
+}
+EXPORT_SYMBOL(res_mgr_free_range);
+
+/**
+ * res_mgr_free - Free a resource instance.
+ * @tag: Identifies the resource.
+ * @req_inst: Requested instance to free.
+ */
+void res_mgr_free(struct global_resource_tag tag, int inst)
+{
+	res_mgr_free_range(tag, &inst, 1);
+}
+EXPORT_SYMBOL(res_mgr_free);
+
+static int __init res_mgr_init(void)
+{
+	struct cvmx_bootmem_named_block_desc *block;
+	int block_size;
+	u64 addr;
+
+	cvmx_bootmem_lock();
+
+	/* Search for the resource manager data in boot memory. */
+	block = cvmx_bootmem_phy_named_block_find(RESOURCE_MGR_BLOCK_NAME, CVMX_BOOTMEM_FLAG_NO_LOCKING);
+	if (block) {
+		/* Found. */
+		res_mgr_info = phys_to_virt(block->base_addr);
+	} else {
+		/* Create it. */
+		block_size = sizeof(struct global_resources) +
+			sizeof(struct global_resource_entry) * MAX_RESOURCES;
+		addr = cvmx_bootmem_phy_named_block_alloc(block_size, 0, 0,
+				CVMX_CACHE_LINE_SIZE, RESOURCE_MGR_BLOCK_NAME,
+				CVMX_BOOTMEM_FLAG_NO_LOCKING);
+		if (!addr) {
+			pr_err("Failed to allocate name block %s\n",
+			       RESOURCE_MGR_BLOCK_NAME);
+		} else {
+			res_mgr_info = phys_to_virt(addr);
+			memset(res_mgr_info, 0, block_size);
+		}
+	}
+
+	cvmx_bootmem_unlock();
+
+	return 0;
+}
+device_initcall(res_mgr_init);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Cavium, Inc. Octeon resource manager");
diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h
index 92a17d67c1fa..0411efdb465c 100644
--- a/arch/mips/include/asm/octeon/octeon.h
+++ b/arch/mips/include/asm/octeon/octeon.h
@@ -346,6 +346,24 @@  void octeon_mult_restore3_end(void);
 void octeon_mult_restore2(void);
 void octeon_mult_restore2_end(void);
 
+/*
+ * This definition must be kept in sync with the one in
+ * cvmx-global-resources.c
+ */
+struct global_resource_tag {
+	uint64_t lo;
+	uint64_t hi;
+};
+
+void res_mgr_free(struct global_resource_tag tag, int inst);
+void res_mgr_free_range(struct global_resource_tag tag, const int *inst,
+			int req_cnt);
+int res_mgr_alloc(struct global_resource_tag tag, int req_inst,
+		  bool use_last_avail);
+int res_mgr_alloc_range(struct global_resource_tag tag, int req_inst,
+			int req_cnt, bool use_last_avail, int *inst);
+int res_mgr_create_resource(struct global_resource_tag tag, int inst_cnt);
+
 /**
  * Read a 32bit value from the Octeon NPI register space
  *