Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bc63d387 authored by Dean Nelson's avatar Dean Nelson Committed by Linus Torvalds
Browse files

sgi-xp: support runtime selection of xp_max_npartitions



Support runtime selection of the max number of partitions based on the
hardware being run on.

Signed-off-by: default avatarDean Nelson <dcn@sgi.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 78ce1bbe
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -3,7 +3,8 @@
#

obj-$(CONFIG_SGI_XP)		+= xp.o
xp-y				:= xp_main.o xp_nofault.o
xp-y				:= xp_main.o xp_uv.o
xp-$(CONFIG_IA64)		+= xp_sn2.o xp_nofault.o

obj-$(CONFIG_SGI_XP)		+= xpc.o
xpc-y				:= xpc_main.o xpc_channel.o xpc_partition.o
+35 −18
Original line number Diff line number Diff line
@@ -18,6 +18,9 @@
#include <linux/mutex.h>
#include <asm/sn/types.h>
#include <asm/sn/bte.h>
#ifdef CONFIG_IA64
#include <asm/sn/arch.h>
#endif

/* >>> Add this #define to some linux header file some day. */
#define BYTES_PER_WORD	sizeof(void *)
@@ -45,17 +48,18 @@
#endif

/*
 * Define the maximum number of logically defined partitions the system
 * can support. It is constrained by the maximum number of hardware
 * partitionable regions. The term 'region' in this context refers to the
 * minimum number of nodes that can comprise an access protection grouping.
 * The access protection is in regards to memory, IPI and IOI.
 * Define the maximum number of partitions the system can possibly support.
 * It is based on the maximum number of hardware partitionable regions. The
 * term 'region' in this context refers to the minimum number of nodes that
 * can comprise an access protection grouping. The access protection is in
 * regards to memory, IPI and IOI.
 *
 * The maximum number of hardware partitionable regions is equal to the
 * maximum number of nodes in the entire system divided by the minimum number
 * of nodes that comprise an access protection grouping.
 */
#define XP_MAX_PARTITIONS	64
#define XP_MAX_NPARTITIONS_SN2	64
#define XP_MAX_NPARTITIONS_UV	256

/*
 * Define the number of u64s required to represent all the C-brick nasids
@@ -112,24 +116,28 @@ xp_bte_copy(u64 src, u64 vdst, u64 len, u64 mode, void *notification)
 * other partition that is currently up. Over these channels, kernel-level
 * `users' can communicate with their counterparts on the other partitions.
 *
 * The maxinum number of channels is limited to eight. For performance reasons,
 * the internal cross partition structures require sixteen bytes per channel,
 * and eight allows all of this interface-shared info to fit in one cache line.
>>> The following described limitation of a max of eight channels possible
>>> pertains only to ia64-sn2. THIS ISN'T TRUE SINCE I'M PLANNING TO JUST
>>> TIE INTO THE EXISTING MECHANISM ONCE THE CHANNEL MESSAGES ARE RECEIVED.
>>> THE 128-BYTE CACHELINE PERFORMANCE ISSUE IS TIED TO IA64-SN2.
 *
 * XPC_NCHANNELS reflects the total number of channels currently defined.
 * If the need for additional channels arises, one can simply increase
 * XPC_NCHANNELS accordingly. If the day should come where that number
 * exceeds the MAXIMUM number of channels allowed (eight), then one will need
 * to make changes to the XPC code to allow for this.
 * XPC_MAX_NCHANNELS accordingly. If the day should come where that number
 * exceeds the absolute MAXIMUM number of channels possible (eight), then one
 * will need to make changes to the XPC code to accommodate for this.
 *
 * The absolute maximum number of channels possible is currently limited to
 * eight for performance reasons. The internal cross partition structures
 * require sixteen bytes per channel, and eight allows all of this
 * interface-shared info to fit in one 128-byte cacheline.
 */
#define XPC_MEM_CHANNEL		0	/* memory channel number */
#define	XPC_NET_CHANNEL		1	/* network channel number */

#define	XPC_NCHANNELS		2	/* #of defined channels */
#define XPC_MAX_NCHANNELS	8	/* max #of channels allowed */
#define XPC_MAX_NCHANNELS	2	/* max #of channels allowed */

#if XPC_NCHANNELS > XPC_MAX_NCHANNELS
#error	XPC_NCHANNELS exceeds MAXIMUM allowed.
#if XPC_MAX_NCHANNELS > 8
#error	XPC_MAX_NCHANNELS exceeds absolute MAXIMUM possible.
#endif

/*
@@ -254,7 +262,8 @@ enum xp_retval {
	xpBteCopyError,		/* 52: bte_copy() returned error */
	xpSalError,		/* 53: sn SAL error */

	xpUnknownReason		/* 54: unknown reason - must be last in enum */
	xpUnsupported,		/* 54: unsupported functionality or resource */
	xpUnknownReason		/* 55: unknown reason - must be last in enum */
};

/*
@@ -397,8 +406,16 @@ xpc_partid_to_nasids(short partid, void *nasids)
	return xpc_interface.partid_to_nasids(partid, nasids);
}

extern short xp_max_npartitions;

extern u64 xp_nofault_PIOR_target;
extern int xp_nofault_PIOR(void *);
extern int xp_error_PIOR(void);

extern struct device *xp;
extern enum xp_retval xp_init_sn2(void);
extern enum xp_retval xp_init_uv(void);
extern void xp_exit_sn2(void);
extern void xp_exit_uv(void);

#endif /* _DRIVERS_MISC_SGIXP_XP_H */
+34 −50
Original line number Diff line number Diff line
@@ -15,28 +15,32 @@
 */

#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <asm/sn/intr.h>
#include <asm/sn/sn_sal.h>
#include <linux/device.h>
#include "xp.h"

/*
 * The export of xp_nofault_PIOR needs to happen here since it is defined
 * in drivers/misc/sgi-xp/xp_nofault.S. The target of the nofault read is
 * defined here.
 */
EXPORT_SYMBOL_GPL(xp_nofault_PIOR);
/* define the XP debug device structures to be used with dev_dbg() et al */

u64 xp_nofault_PIOR_target;
EXPORT_SYMBOL_GPL(xp_nofault_PIOR_target);
struct device_driver xp_dbg_name = {
	.name = "xp"
};

struct device xp_dbg_subname = {
	.bus_id = {0},		/* set to "" */
	.driver = &xp_dbg_name
};

struct device *xp = &xp_dbg_subname;

/* max #of partitions possible */
short xp_max_npartitions;
EXPORT_SYMBOL_GPL(xp_max_npartitions);

/*
 * xpc_registrations[] keeps track of xpc_connect()'s done by the kernel-level
 * users of XPC.
 */
struct xpc_registration xpc_registrations[XPC_NCHANNELS];
struct xpc_registration xpc_registrations[XPC_MAX_NCHANNELS];
EXPORT_SYMBOL_GPL(xpc_registrations);

/*
@@ -135,7 +139,7 @@ xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size,
{
	struct xpc_registration *registration;

	DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
	DBUG_ON(ch_number < 0 || ch_number >= XPC_MAX_NCHANNELS);
	DBUG_ON(payload_size == 0 || nentries == 0);
	DBUG_ON(func == NULL);
	DBUG_ON(assigned_limit == 0 || idle_limit > assigned_limit);
@@ -185,7 +189,7 @@ xpc_disconnect(int ch_number)
{
	struct xpc_registration *registration;

	DBUG_ON(ch_number < 0 || ch_number >= XPC_NCHANNELS);
	DBUG_ON(ch_number < 0 || ch_number >= XPC_MAX_NCHANNELS);

	registration = &xpc_registrations[ch_number];

@@ -221,39 +225,21 @@ EXPORT_SYMBOL_GPL(xpc_disconnect);
int __init
xp_init(void)
{
	int ret, ch_number;
	u64 func_addr = *(u64 *)xp_nofault_PIOR;
	u64 err_func_addr = *(u64 *)xp_error_PIOR;

	if (!ia64_platform_is("sn2"))
		return -ENODEV;
	enum xp_retval ret;
	int ch_number;

	/*
	 * Register a nofault code region which performs a cross-partition
	 * PIO read. If the PIO read times out, the MCA handler will consume
	 * the error and return to a kernel-provided instruction to indicate
	 * an error. This PIO read exists because it is guaranteed to timeout
	 * if the destination is down (AMO operations do not timeout on at
	 * least some CPUs on Shubs <= v1.2, which unfortunately we have to
	 * work around).
	 */
	ret = sn_register_nofault_code(func_addr, err_func_addr, err_func_addr,
				       1, 1);
	if (ret != 0) {
		printk(KERN_ERR "XP: can't register nofault code, error=%d\n",
		       ret);
	}
	/*
	 * Setup the nofault PIO read target. (There is no special reason why
	 * SH_IPI_ACCESS was selected.)
	 */
	if (is_shub2())
		xp_nofault_PIOR_target = SH2_IPI_ACCESS0;
	if (is_shub())
		ret = xp_init_sn2();
	else if (is_uv())
		ret = xp_init_uv();
	else
		xp_nofault_PIOR_target = SH1_IPI_ACCESS;
		ret = xpUnsupported;

	if (ret != xpSuccess)
		return -ENODEV;

	/* initialize the connection registration mutex */
	for (ch_number = 0; ch_number < XPC_NCHANNELS; ch_number++)
	for (ch_number = 0; ch_number < XPC_MAX_NCHANNELS; ch_number++)
		mutex_init(&xpc_registrations[ch_number].mutex);

	return 0;
@@ -264,12 +250,10 @@ module_init(xp_init);
void __exit
xp_exit(void)
{
	u64 func_addr = *(u64 *)xp_nofault_PIOR;
	u64 err_func_addr = *(u64 *)xp_error_PIOR;

	/* unregister the PIO read nofault code region */
	(void)sn_register_nofault_code(func_addr, err_func_addr,
				       err_func_addr, 1, 0);
	if (is_shub())
		xp_exit_sn2();
	else if (is_uv())
		xp_exit_uv();
}

module_exit(xp_exit);
+92 −0
Original line number Diff line number Diff line
/*
 * 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) 2008 Silicon Graphics, Inc.  All Rights Reserved.
 */

/*
 * Cross Partition (XP) sn2-based functions.
 *
 *      Architecture specific implementation of common functions.
 */

#include <linux/device.h>
#include <asm/sn/sn_sal.h>
#include "xp.h"

/*
 * The export of xp_nofault_PIOR needs to happen here since it is defined
 * in drivers/misc/sgi-xp/xp_nofault.S. The target of the nofault read is
 * defined here.
 */
EXPORT_SYMBOL_GPL(xp_nofault_PIOR);

u64 xp_nofault_PIOR_target;
EXPORT_SYMBOL_GPL(xp_nofault_PIOR_target);

/*
 * Register a nofault code region which performs a cross-partition PIO read.
 * If the PIO read times out, the MCA handler will consume the error and
 * return to a kernel-provided instruction to indicate an error. This PIO read
 * exists because it is guaranteed to timeout if the destination is down
 * (AMO operations do not timeout on at least some CPUs on Shubs <= v1.2,
 * which unfortunately we have to work around).
 */
static enum xp_retval
xp_register_nofault_code_sn2(void)
{
	int ret;
	u64 func_addr;
	u64 err_func_addr;

	func_addr = *(u64 *)xp_nofault_PIOR;
	err_func_addr = *(u64 *)xp_error_PIOR;
	ret = sn_register_nofault_code(func_addr, err_func_addr, err_func_addr,
				       1, 1);
	if (ret != 0) {
		dev_err(xp, "can't register nofault code, error=%d\n", ret);
		return xpSalError;
	}
	/*
	 * Setup the nofault PIO read target. (There is no special reason why
	 * SH_IPI_ACCESS was selected.)
	 */
	if (is_shub1())
		xp_nofault_PIOR_target = SH1_IPI_ACCESS;
	else if (is_shub2())
		xp_nofault_PIOR_target = SH2_IPI_ACCESS0;

	return xpSuccess;
}

void
xp_unregister_nofault_code_sn2(void)
{
	u64 func_addr = *(u64 *)xp_nofault_PIOR;
	u64 err_func_addr = *(u64 *)xp_error_PIOR;

	/* unregister the PIO read nofault code region */
	(void)sn_register_nofault_code(func_addr, err_func_addr,
				       err_func_addr, 1, 0);
}

enum xp_retval
xp_init_sn2(void)
{
	BUG_ON(!is_shub());

	xp_max_npartitions = XP_MAX_NPARTITIONS_SN2;

	return xp_register_nofault_code_sn2();
}

void
xp_exit_sn2(void)
{
	BUG_ON(!is_shub());

	xp_unregister_nofault_code_sn2();
}
+30 −0
Original line number Diff line number Diff line
/*
 * 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) 2008 Silicon Graphics, Inc.  All Rights Reserved.
 */

/*
 * Cross Partition (XP) uv-based functions.
 *
 *      Architecture specific implementation of common functions.
 *
 */

#include "xp.h"

enum xp_retval
xp_init_uv(void)
{
	BUG_ON(!is_uv());

	xp_max_npartitions = XP_MAX_NPARTITIONS_UV;
}

void
xp_exit_uv(void)
{
	BUG_ON(!is_uv());
}
Loading