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

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

sgi-xp: add usage of GRU driver by xpc_remote_memcpy()



Add UV support to xpc_remote_memcpy(), which involves interfacing to the
GRU driver.

Signed-off-by: default avatarDean Nelson <dcn@sgi.com>
Cc: Jack Steiner <steiner@sgi.com>
Cc: "Luck, Tony" <tony.luck@intel.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 261f3b49
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -207,7 +207,9 @@ enum xp_retval {
	xpUnsupported,		/* 56: unsupported functionality or resource */
	xpNeedMoreInfo,		/* 57: more info is needed by SAL */

	xpUnknownReason		/* 58: unknown reason - must be last in enum */
	xpGruCopyError,		/* 58: gru_copy_gru() returned error */

	xpUnknownReason		/* 59: unknown reason - must be last in enum */
};

/*
@@ -349,7 +351,9 @@ extern short xp_max_npartitions;
extern short xp_partition_id;
extern u8 xp_region_size;

extern enum xp_retval (*xp_remote_memcpy) (void *, const void *, size_t);
extern unsigned long (*xp_pa) (void *);
extern enum xp_retval (*xp_remote_memcpy) (unsigned long, const unsigned long,
		       size_t);
extern int (*xp_cpu_to_nasid) (int);

extern u64 xp_nofault_PIOR_target;
+5 −1
Original line number Diff line number Diff line
@@ -41,7 +41,11 @@ EXPORT_SYMBOL_GPL(xp_partition_id);
u8 xp_region_size;
EXPORT_SYMBOL_GPL(xp_region_size);

enum xp_retval (*xp_remote_memcpy) (void *dst, const void *src, size_t len);
unsigned long (*xp_pa) (void *addr);
EXPORT_SYMBOL_GPL(xp_pa);

enum xp_retval (*xp_remote_memcpy) (unsigned long dst_gpa,
				    const unsigned long src_gpa, size_t len);
EXPORT_SYMBOL_GPL(xp_remote_memcpy);

int (*xp_cpu_to_nasid) (int cpuid);
+24 −26
Original line number Diff line number Diff line
@@ -63,7 +63,7 @@ xp_register_nofault_code_sn2(void)
	return xpSuccess;
}

void
static void
xp_unregister_nofault_code_sn2(void)
{
	u64 func_addr = *(u64 *)xp_nofault_PIOR;
@@ -74,45 +74,42 @@ xp_unregister_nofault_code_sn2(void)
				       err_func_addr, 1, 0);
}

/*
 * Convert a virtual memory address to a physical memory address.
 */
static unsigned long
xp_pa_sn2(void *addr)
{
	return __pa(addr);
}

/*
 * Wrapper for bte_copy().
 *
 *	vdst - virtual address of the destination of the transfer.
 *	psrc - physical address of the source of the transfer.
 *	dst_pa - physical address of the destination of the transfer.
 *	src_pa - physical address of the source of the transfer.
 *	len - number of bytes to transfer from source to destination.
 *
 * Note: xp_remote_memcpy_sn2() should never be called while holding a spinlock.
 */
static enum xp_retval
xp_remote_memcpy_sn2(void *vdst, const void *psrc, size_t len)
xp_remote_memcpy_sn2(unsigned long dst_pa, const unsigned long src_pa,
		     size_t len)
{
	bte_result_t ret;
	u64 pdst = ia64_tpa(vdst);
	/* ??? What are the rules governing the src and dst addresses passed in?
	 * ??? Currently we're assuming that dst is a virtual address and src
	 * ??? is a physical address, is this appropriate? Can we allow them to
	 * ??? be whatever and we make the change here without damaging the
	 * ??? addresses?
	 */

	/*
	 * Ensure that the physically mapped memory is contiguous.
	 *
	 * We do this by ensuring that the memory is from region 7 only.
	 * If the need should arise to use memory from one of the other
	 * regions, then modify the BUG_ON() statement to ensure that the
	 * memory from that region is always physically contiguous.
	 */
	BUG_ON(REGION_NUMBER(vdst) != RGN_KERNEL);

	ret = bte_copy((u64)psrc, pdst, len, (BTE_NOTIFY | BTE_WACQUIRE), NULL);
	ret = bte_copy(src_pa, dst_pa, len, (BTE_NOTIFY | BTE_WACQUIRE), NULL);
	if (ret == BTE_SUCCESS)
		return xpSuccess;

	if (is_shub2())
		dev_err(xp, "bte_copy() on shub2 failed, error=0x%x\n", ret);
	else
		dev_err(xp, "bte_copy() failed, error=%d\n", ret);
	if (is_shub2()) {
		dev_err(xp, "bte_copy() on shub2 failed, error=0x%x dst_pa="
			"0x%016lx src_pa=0x%016lx len=%ld\\n", ret, dst_pa,
			src_pa, len);
	} else {
		dev_err(xp, "bte_copy() failed, error=%d dst_pa=0x%016lx "
			"src_pa=0x%016lx len=%ld\\n", ret, dst_pa, src_pa, len);
	}

	return xpBteCopyError;
}
@@ -132,6 +129,7 @@ xp_init_sn2(void)
	xp_partition_id = sn_partition_id;
	xp_region_size = sn_region_size;

	xp_pa = xp_pa_sn2;
	xp_remote_memcpy = xp_remote_memcpy_sn2;
	xp_cpu_to_nasid = xp_cpu_to_nasid_sn2;

+24 −3
Original line number Diff line number Diff line
@@ -13,13 +13,33 @@
 *
 */

#include <linux/device.h>
#include <asm/uv/uv_hub.h>
#include "../sgi-gru/grukservices.h"
#include "xp.h"

/*
 * Convert a virtual memory address to a physical memory address.
 */
static unsigned long
xp_pa_uv(void *addr)
{
	return uv_gpa(addr);
}

static enum xp_retval
xp_remote_memcpy_uv(void *vdst, const void *psrc, size_t len)
xp_remote_memcpy_uv(unsigned long dst_gpa, const unsigned long src_gpa,
		    size_t len)
{
	/* !!! this function needs fleshing out */
	return xpUnsupported;
	int ret;

	ret = gru_copy_gpa(dst_gpa, src_gpa, len);
	if (ret == 0)
		return xpSuccess;

	dev_err(xp, "gru_copy_gpa() failed, dst_gpa=0x%016lx src_gpa=0x%016lx "
		"len=%ld\n", dst_gpa, src_gpa, len);
	return xpGruCopyError;
}

enum xp_retval
@@ -29,6 +49,7 @@ xp_init_uv(void)

	xp_max_npartitions = XP_MAX_NPARTITIONS_UV;

	xp_pa = xp_pa_uv;
	xp_remote_memcpy = xp_remote_memcpy_uv;

	return xpSuccess;
+23 −21
Original line number Diff line number Diff line
@@ -91,8 +91,8 @@ struct xpc_rsvd_page {
	u8 version;
	u8 pad1[3];		/* align to next u64 in 1st 64-byte cacheline */
	union {
		u64 vars_pa;	/* physical address of struct xpc_vars */
		u64 activate_mq_gpa;	/* global phys address of activate_mq */
		unsigned long vars_pa;	/* phys address of struct xpc_vars */
		unsigned long activate_mq_gpa; /* gru phy addr of activate_mq */
	} sn;
	unsigned long ts_jiffies; /* timestamp when rsvd pg was setup by XPC */
	u64 pad2[10];		/* align to last u64 in 2nd 64-byte cacheline */
@@ -122,8 +122,8 @@ struct xpc_vars_sn2 {
	u64 heartbeat_offline;	/* if 0, heartbeat should be changing */
	int activate_IRQ_nasid;
	int activate_IRQ_phys_cpuid;
	u64 vars_part_pa;
	u64 amos_page_pa;	/* paddr of page of amos from MSPEC driver */
	unsigned long vars_part_pa;
	unsigned long amos_page_pa;/* paddr of page of amos from MSPEC driver */
	struct amo *amos_page;	/* vaddr of page of amos from MSPEC driver */
};

@@ -142,10 +142,10 @@ struct xpc_vars_sn2 {
struct xpc_vars_part_sn2 {
	u64 magic;

	u64 openclose_args_pa;	/* physical address of open and close args */
	u64 GPs_pa;		/* physical address of Get/Put values */
	unsigned long openclose_args_pa; /* phys addr of open and close args */
	unsigned long GPs_pa;	/* physical address of Get/Put values */

	u64 chctl_amo_pa;	/* physical address of chctl flags' amo */
	unsigned long chctl_amo_pa; /* physical address of chctl flags' amo */

	int notify_IRQ_nasid;	/* nasid of where to send notify IRQs */
	int notify_IRQ_phys_cpuid;	/* CPUID of where to send notify IRQs */
@@ -213,7 +213,7 @@ struct xpc_openclose_args {
	u16 msg_size;		/* sizeof each message entry */
	u16 remote_nentries;	/* #of message entries in remote msg queue */
	u16 local_nentries;	/* #of message entries in local msg queue */
	u64 local_msgqueue_pa;	/* physical address of local message queue */
	unsigned long local_msgqueue_pa; /* phys addr of local message queue */
};

#define XPC_OPENCLOSE_ARGS_SIZE \
@@ -366,7 +366,7 @@ struct xpc_channel {
	void *remote_msgqueue_base;	/* base address of kmalloc'd space */
	struct xpc_msg *remote_msgqueue; /* cached copy of remote partition's */
					 /* local message queue */
	u64 remote_msgqueue_pa;	/* phys addr of remote partition's */
	unsigned long remote_msgqueue_pa; /* phys addr of remote partition's */
					  /* local message queue */

	atomic_t references;	/* #of external references to queues */
@@ -491,12 +491,12 @@ xpc_any_msg_chctl_flags_set(union xpc_channel_ctl_flags *chctl)
 */

struct xpc_partition_sn2 {
	u64 remote_amos_page_pa;	/* phys addr of partition's amos page */
	unsigned long remote_amos_page_pa; /* paddr of partition's amos page */
	int activate_IRQ_nasid;	/* active partition's act/deact nasid */
	int activate_IRQ_phys_cpuid;	/* active part's act/deact phys cpuid */

	u64 remote_vars_pa;	/* phys addr of partition's vars */
	u64 remote_vars_part_pa;	/* phys addr of partition's vars part */
	unsigned long remote_vars_pa;	/* phys addr of partition's vars */
	unsigned long remote_vars_part_pa; /* paddr of partition's vars part */
	u8 remote_vars_version;	/* version# of partition's vars */

	void *local_GPs_base;	/* base address of kmalloc'd space */
@@ -504,10 +504,10 @@ struct xpc_partition_sn2 {
	void *remote_GPs_base;	/* base address of kmalloc'd space */
	struct xpc_gp_sn2 *remote_GPs;	/* copy of remote partition's local */
					/* Get/Put values */
	u64 remote_GPs_pa;	/* phys address of remote partition's local */
	unsigned long remote_GPs_pa; /* phys addr of remote partition's local */
				     /* Get/Put values */

	u64 remote_openclose_args_pa;	/* phys addr of remote's args */
	unsigned long remote_openclose_args_pa;	/* phys addr of remote's args */

	int notify_IRQ_nasid;	/* nasid of where to send notify IRQs */
	int notify_IRQ_phys_cpuid;	/* CPUID of where to send notify IRQs */
@@ -529,7 +529,7 @@ struct xpc_partition {

	u8 remote_rp_version;	/* version# of partition's rsvd pg */
	unsigned long remote_rp_ts_jiffies; /* timestamp when rsvd pg setup */
	u64 remote_rp_pa;	/* phys addr of partition's rsvd pg */
	unsigned long remote_rp_pa;	/* phys addr of partition's rsvd pg */
	u64 last_heartbeat;	/* HB at last read */
	u32 activate_IRQ_rcvd;	/* IRQs since activation */
	spinlock_t act_lock;	/* protect updating of act_state */
@@ -623,7 +623,8 @@ extern void xpc_activate_partition(struct xpc_partition *);
extern void xpc_activate_kthreads(struct xpc_channel *, int);
extern void xpc_create_kthreads(struct xpc_channel *, int, int);
extern void xpc_disconnect_wait(int);
extern enum xp_retval (*xpc_get_partition_rsvd_page_pa) (u64, u64 *, u64 *,
extern enum xp_retval (*xpc_get_partition_rsvd_page_pa) (void *, u64 *,
							 unsigned long *,
							 size_t *);
extern enum xp_retval (*xpc_rsvd_page_init) (struct xpc_rsvd_page *);
extern void (*xpc_heartbeat_init) (void);
@@ -640,8 +641,8 @@ extern void (*xpc_notify_senders_of_disconnect) (struct xpc_channel *);
extern void (*xpc_process_msg_chctl_flags) (struct xpc_partition *, int);
extern int (*xpc_n_of_deliverable_msgs) (struct xpc_channel *);
extern struct xpc_msg *(*xpc_get_deliverable_msg) (struct xpc_channel *);
extern void (*xpc_request_partition_activation) (struct xpc_rsvd_page *, u64,
						 int);
extern void (*xpc_request_partition_activation) (struct xpc_rsvd_page *,
						 unsigned long, int);
extern void (*xpc_request_partition_reactivation) (struct xpc_partition *);
extern void (*xpc_request_partition_deactivation) (struct xpc_partition *);
extern void (*xpc_cancel_partition_deactivation_request) (
@@ -690,7 +691,8 @@ extern enum xp_retval xpc_mark_partition_active(struct xpc_partition *);
extern void xpc_mark_partition_inactive(struct xpc_partition *);
extern void xpc_discovery(void);
extern enum xp_retval xpc_get_remote_rp(int, unsigned long *,
					struct xpc_rsvd_page *, u64 *);
					struct xpc_rsvd_page *,
					unsigned long *);
extern void xpc_deactivate_partition(const int, struct xpc_partition *,
				     enum xp_retval);
extern enum xp_retval xpc_initiate_partid_to_nasids(short, void *);
Loading