summaryrefslogtreecommitdiffstats
path: root/drivers/misc/sgi-xp/xpc_sn2.c
diff options
context:
space:
mode:
authorDean Nelson <dcn@sgi.com>2008-07-29 22:34:18 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-30 09:41:50 -0700
commit5b8669dfd110a62a74eea525a009342f73987ea0 (patch)
tree04572d8508f450131298b6ec072e97aa9fdba539 /drivers/misc/sgi-xp/xpc_sn2.c
parent83469b5525b4a35be40b17cb41d64118d84d9f80 (diff)
downloadblackbird-op-linux-5b8669dfd110a62a74eea525a009342f73987ea0.tar.gz
blackbird-op-linux-5b8669dfd110a62a74eea525a009342f73987ea0.zip
sgi-xp: setup the activate GRU message queue
Setup the activate GRU message queue that is used for partition activation and channel connection on UV systems. Signed-off-by: Dean Nelson <dcn@sgi.com> Cc: Jack Steiner <steiner@sgi.com> Cc: "Luck, Tony" <tony.luck@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/misc/sgi-xp/xpc_sn2.c')
-rw-r--r--drivers/misc/sgi-xp/xpc_sn2.c387
1 files changed, 154 insertions, 233 deletions
diff --git a/drivers/misc/sgi-xp/xpc_sn2.c b/drivers/misc/sgi-xp/xpc_sn2.c
index d1ccadc0857d..8b4b0653d9e9 100644
--- a/drivers/misc/sgi-xp/xpc_sn2.c
+++ b/drivers/misc/sgi-xp/xpc_sn2.c
@@ -53,12 +53,19 @@
* Buffer used to store a local copy of portions of a remote partition's
* reserved page (either its header and part_nasids mask, or its vars).
*/
-static char *xpc_remote_copy_buffer_sn2;
static void *xpc_remote_copy_buffer_base_sn2;
+static char *xpc_remote_copy_buffer_sn2;
static struct xpc_vars_sn2 *xpc_vars_sn2;
static struct xpc_vars_part_sn2 *xpc_vars_part_sn2;
+static int
+xpc_setup_partitions_sn_sn2(void)
+{
+ /* nothing needs to be done */
+ return 0;
+}
+
/* SH_IPI_ACCESS shub register value on startup */
static u64 xpc_sh1_IPI_access_sn2;
static u64 xpc_sh2_IPI_access0_sn2;
@@ -198,7 +205,12 @@ xpc_init_IRQ_amo_sn2(int index)
static irqreturn_t
xpc_handle_activate_IRQ_sn2(int irq, void *dev_id)
{
- atomic_inc(&xpc_activate_IRQ_rcvd);
+ unsigned long irq_flags;
+
+ spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
+ xpc_activate_IRQ_rcvd++;
+ spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
+
wake_up_interruptible(&xpc_activate_IRQ_wq);
return IRQ_HANDLED;
}
@@ -222,6 +234,7 @@ xpc_send_activate_IRQ_sn2(unsigned long amos_page_pa, int from_nasid,
static void
xpc_send_local_activate_IRQ_sn2(int from_nasid)
{
+ unsigned long irq_flags;
struct amo *amos = (struct amo *)__va(xpc_vars_sn2->amos_page_pa +
(XPC_ACTIVATE_IRQ_AMOS_SN2 *
sizeof(struct amo)));
@@ -230,7 +243,10 @@ xpc_send_local_activate_IRQ_sn2(int from_nasid)
FETCHOP_STORE_OP(TO_AMO((u64)&amos[BIT_WORD(from_nasid / 2)].variable),
FETCHOP_OR, BIT_MASK(from_nasid / 2));
- atomic_inc(&xpc_activate_IRQ_rcvd);
+ spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
+ xpc_activate_IRQ_rcvd++;
+ spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
+
wake_up_interruptible(&xpc_activate_IRQ_wq);
}
@@ -375,7 +391,7 @@ static void
xpc_send_chctl_closerequest_sn2(struct xpc_channel *ch,
unsigned long *irq_flags)
{
- struct xpc_openclose_args *args = ch->local_openclose_args;
+ struct xpc_openclose_args *args = ch->sn.sn2.local_openclose_args;
args->reason = ch->reason;
XPC_SEND_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_CLOSEREQUEST, irq_flags);
@@ -390,7 +406,7 @@ xpc_send_chctl_closereply_sn2(struct xpc_channel *ch, unsigned long *irq_flags)
static void
xpc_send_chctl_openrequest_sn2(struct xpc_channel *ch, unsigned long *irq_flags)
{
- struct xpc_openclose_args *args = ch->local_openclose_args;
+ struct xpc_openclose_args *args = ch->sn.sn2.local_openclose_args;
args->msg_size = ch->msg_size;
args->local_nentries = ch->local_nentries;
@@ -400,11 +416,11 @@ xpc_send_chctl_openrequest_sn2(struct xpc_channel *ch, unsigned long *irq_flags)
static void
xpc_send_chctl_openreply_sn2(struct xpc_channel *ch, unsigned long *irq_flags)
{
- struct xpc_openclose_args *args = ch->local_openclose_args;
+ struct xpc_openclose_args *args = ch->sn.sn2.local_openclose_args;
args->remote_nentries = ch->remote_nentries;
args->local_nentries = ch->local_nentries;
- args->local_msgqueue_pa = xp_pa(ch->local_msgqueue);
+ args->local_msgqueue_pa = xp_pa(ch->sn.sn2.local_msgqueue);
XPC_SEND_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_OPENREPLY, irq_flags);
}
@@ -420,6 +436,13 @@ xpc_send_chctl_local_msgrequest_sn2(struct xpc_channel *ch)
XPC_SEND_LOCAL_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_MSGREQUEST);
}
+static void
+xpc_save_remote_msgqueue_pa_sn2(struct xpc_channel *ch,
+ unsigned long msgqueue_pa)
+{
+ ch->sn.sn2.remote_msgqueue_pa = msgqueue_pa;
+}
+
/*
* This next set of functions are used to keep track of when a partition is
* potentially engaged in accessing memory belonging to another partition.
@@ -489,6 +512,17 @@ xpc_indicate_partition_disengaged_sn2(struct xpc_partition *part)
part_sn2->activate_IRQ_phys_cpuid);
}
+static void
+xpc_assume_partition_disengaged_sn2(short partid)
+{
+ struct amo *amo = xpc_vars_sn2->amos_page +
+ XPC_ENGAGED_PARTITIONS_AMO_SN2;
+
+ /* clear bit(s) based on partid mask in our partition's amo */
+ FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
+ ~BIT(partid));
+}
+
static int
xpc_partition_engaged_sn2(short partid)
{
@@ -510,17 +544,6 @@ xpc_any_partition_engaged_sn2(void)
return FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_LOAD) != 0;
}
-static void
-xpc_assume_partition_disengaged_sn2(short partid)
-{
- struct amo *amo = xpc_vars_sn2->amos_page +
- XPC_ENGAGED_PARTITIONS_AMO_SN2;
-
- /* clear bit(s) based on partid mask in our partition's amo */
- FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
- ~BIT(partid));
-}
-
/* original protection values for each node */
static u64 xpc_prot_vec_sn2[MAX_NUMNODES];
@@ -595,8 +618,8 @@ xpc_get_partition_rsvd_page_pa_sn2(void *buf, u64 *cookie, unsigned long *rp_pa,
}
-static enum xp_retval
-xpc_rsvd_page_init_sn2(struct xpc_rsvd_page *rp)
+static int
+xpc_setup_rsvd_page_sn_sn2(struct xpc_rsvd_page *rp)
{
struct amo *amos_page;
int i;
@@ -627,7 +650,7 @@ xpc_rsvd_page_init_sn2(struct xpc_rsvd_page *rp)
amos_page = (struct amo *)TO_AMO(uncached_alloc_page(0, 1));
if (amos_page == NULL) {
dev_err(xpc_part, "can't allocate page of amos\n");
- return xpNoMemory;
+ return -ENOMEM;
}
/*
@@ -639,7 +662,7 @@ xpc_rsvd_page_init_sn2(struct xpc_rsvd_page *rp)
dev_err(xpc_part, "can't allow amo operations\n");
uncached_free_page(__IA64_UNCACHED_OFFSET |
TO_PHYS((u64)amos_page), 1);
- return ret;
+ return -EPERM;
}
}
@@ -665,7 +688,7 @@ xpc_rsvd_page_init_sn2(struct xpc_rsvd_page *rp)
(void)xpc_init_IRQ_amo_sn2(XPC_ENGAGED_PARTITIONS_AMO_SN2);
(void)xpc_init_IRQ_amo_sn2(XPC_DEACTIVATE_REQUEST_AMO_SN2);
- return xpSuccess;
+ return 0;
}
static void
@@ -1082,10 +1105,19 @@ xpc_identify_activate_IRQ_sender_sn2(void)
}
static void
-xpc_process_activate_IRQ_rcvd_sn2(int n_IRQs_expected)
+xpc_process_activate_IRQ_rcvd_sn2(void)
{
+ unsigned long irq_flags;
+ int n_IRQs_expected;
int n_IRQs_detected;
+ DBUG_ON(xpc_activate_IRQ_rcvd == 0);
+
+ spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
+ n_IRQs_expected = xpc_activate_IRQ_rcvd;
+ xpc_activate_IRQ_rcvd = 0;
+ spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
+
n_IRQs_detected = xpc_identify_activate_IRQ_sender_sn2();
if (n_IRQs_detected < n_IRQs_expected) {
/* retry once to help avoid missing amo */
@@ -1094,116 +1126,63 @@ xpc_process_activate_IRQ_rcvd_sn2(int n_IRQs_expected)
}
/*
- * Guarantee that the kzalloc'd memory is cacheline aligned.
- */
-static void *
-xpc_kzalloc_cacheline_aligned_sn2(size_t size, gfp_t flags, void **base)
-{
- /* see if kzalloc will give us cachline aligned memory by default */
- *base = kzalloc(size, flags);
- if (*base == NULL)
- return NULL;
-
- if ((u64)*base == L1_CACHE_ALIGN((u64)*base))
- return *base;
-
- kfree(*base);
-
- /* nope, we'll have to do it ourselves */
- *base = kzalloc(size + L1_CACHE_BYTES, flags);
- if (*base == NULL)
- return NULL;
-
- return (void *)L1_CACHE_ALIGN((u64)*base);
-}
-
-/*
- * Setup the infrastructure necessary to support XPartition Communication
- * between the specified remote partition and the local one.
+ * Setup the channel structures that are sn2 specific.
*/
static enum xp_retval
-xpc_setup_infrastructure_sn2(struct xpc_partition *part)
+xpc_setup_ch_structures_sn_sn2(struct xpc_partition *part)
{
struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
+ struct xpc_channel_sn2 *ch_sn2;
enum xp_retval retval;
int ret;
int cpuid;
int ch_number;
- struct xpc_channel *ch;
struct timer_list *timer;
short partid = XPC_PARTID(part);
- /*
- * Allocate all of the channel structures as a contiguous chunk of
- * memory.
- */
- DBUG_ON(part->channels != NULL);
- part->channels = kzalloc(sizeof(struct xpc_channel) * XPC_MAX_NCHANNELS,
- GFP_KERNEL);
- if (part->channels == NULL) {
- dev_err(xpc_chan, "can't get memory for channels\n");
- return xpNoMemory;
- }
-
/* allocate all the required GET/PUT values */
part_sn2->local_GPs =
- xpc_kzalloc_cacheline_aligned_sn2(XPC_GP_SIZE, GFP_KERNEL,
- &part_sn2->local_GPs_base);
+ xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE, GFP_KERNEL,
+ &part_sn2->local_GPs_base);
if (part_sn2->local_GPs == NULL) {
dev_err(xpc_chan, "can't get memory for local get/put "
"values\n");
- retval = xpNoMemory;
- goto out_1;
+ return xpNoMemory;
}
part_sn2->remote_GPs =
- xpc_kzalloc_cacheline_aligned_sn2(XPC_GP_SIZE, GFP_KERNEL,
- &part_sn2->remote_GPs_base);
+ xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE, GFP_KERNEL,
+ &part_sn2->remote_GPs_base);
if (part_sn2->remote_GPs == NULL) {
dev_err(xpc_chan, "can't get memory for remote get/put "
"values\n");
retval = xpNoMemory;
- goto out_2;
+ goto out_1;
}
part_sn2->remote_GPs_pa = 0;
/* allocate all the required open and close args */
- part->local_openclose_args =
- xpc_kzalloc_cacheline_aligned_sn2(XPC_OPENCLOSE_ARGS_SIZE,
- GFP_KERNEL,
- &part->local_openclose_args_base);
- if (part->local_openclose_args == NULL) {
+ part_sn2->local_openclose_args =
+ xpc_kzalloc_cacheline_aligned(XPC_OPENCLOSE_ARGS_SIZE,
+ GFP_KERNEL, &part_sn2->
+ local_openclose_args_base);
+ if (part_sn2->local_openclose_args == NULL) {
dev_err(xpc_chan, "can't get memory for local connect args\n");
retval = xpNoMemory;
- goto out_3;
- }
-
- part->remote_openclose_args =
- xpc_kzalloc_cacheline_aligned_sn2(XPC_OPENCLOSE_ARGS_SIZE,
- GFP_KERNEL,
- &part->remote_openclose_args_base);
- if (part->remote_openclose_args == NULL) {
- dev_err(xpc_chan, "can't get memory for remote connect args\n");
- retval = xpNoMemory;
- goto out_4;
+ goto out_2;
}
part_sn2->remote_openclose_args_pa = 0;
part_sn2->local_chctl_amo_va = xpc_init_IRQ_amo_sn2(partid);
- part->chctl.all_flags = 0;
- spin_lock_init(&part->chctl_lock);
part_sn2->notify_IRQ_nasid = 0;
part_sn2->notify_IRQ_phys_cpuid = 0;
part_sn2->remote_chctl_amo_va = NULL;
- atomic_set(&part->channel_mgr_requests, 1);
- init_waitqueue_head(&part->channel_mgr_wq);
-
sprintf(part_sn2->notify_IRQ_owner, "xpc%02d", partid);
ret = request_irq(SGI_XPC_NOTIFY, xpc_handle_notify_IRQ_sn2,
IRQF_SHARED, part_sn2->notify_IRQ_owner,
@@ -1212,7 +1191,7 @@ xpc_setup_infrastructure_sn2(struct xpc_partition *part)
dev_err(xpc_chan, "can't register NOTIFY IRQ handler, "
"errno=%d\n", -ret);
retval = xpLackOfResources;
- goto out_5;
+ goto out_3;
}
/* Setup a timer to check for dropped notify IRQs */
@@ -1224,45 +1203,17 @@ xpc_setup_infrastructure_sn2(struct xpc_partition *part)
timer->expires = jiffies + XPC_DROPPED_NOTIFY_IRQ_WAIT_INTERVAL;
add_timer(timer);
- part->nchannels = XPC_MAX_NCHANNELS;
-
- atomic_set(&part->nchannels_active, 0);
- atomic_set(&part->nchannels_engaged, 0);
-
for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
- ch = &part->channels[ch_number];
-
- ch->partid = partid;
- ch->number = ch_number;
- ch->flags = XPC_C_DISCONNECTED;
-
- ch->sn.sn2.local_GP = &part_sn2->local_GPs[ch_number];
- ch->local_openclose_args =
- &part->local_openclose_args[ch_number];
-
- atomic_set(&ch->kthreads_assigned, 0);
- atomic_set(&ch->kthreads_idle, 0);
- atomic_set(&ch->kthreads_active, 0);
+ ch_sn2 = &part->channels[ch_number].sn.sn2;
- atomic_set(&ch->references, 0);
- atomic_set(&ch->n_to_notify, 0);
+ ch_sn2->local_GP = &part_sn2->local_GPs[ch_number];
+ ch_sn2->local_openclose_args =
+ &part_sn2->local_openclose_args[ch_number];
- spin_lock_init(&ch->lock);
- mutex_init(&ch->sn.sn2.msg_to_pull_mutex);
- init_completion(&ch->wdisconnect_wait);
-
- atomic_set(&ch->n_on_msg_allocate_wq, 0);
- init_waitqueue_head(&ch->msg_allocate_wq);
- init_waitqueue_head(&ch->idle_wq);
+ mutex_init(&ch_sn2->msg_to_pull_mutex);
}
/*
- * With the setting of the partition setup_state to XPC_P_SS_SETUP,
- * we're declaring that this partition is ready to go.
- */
- part->setup_state = XPC_P_SS_SETUP;
-
- /*
* Setup the per partition specific variables required by the
* remote partition to establish channel connections with us.
*
@@ -1271,7 +1222,7 @@ xpc_setup_infrastructure_sn2(struct xpc_partition *part)
*/
xpc_vars_part_sn2[partid].GPs_pa = xp_pa(part_sn2->local_GPs);
xpc_vars_part_sn2[partid].openclose_args_pa =
- xp_pa(part->local_openclose_args);
+ xp_pa(part_sn2->local_openclose_args);
xpc_vars_part_sn2[partid].chctl_amo_pa =
xp_pa(part_sn2->local_chctl_amo_va);
cpuid = raw_smp_processor_id(); /* any CPU in this partition will do */
@@ -1279,80 +1230,48 @@ xpc_setup_infrastructure_sn2(struct xpc_partition *part)
xpc_vars_part_sn2[partid].notify_IRQ_phys_cpuid =
cpu_physical_id(cpuid);
xpc_vars_part_sn2[partid].nchannels = part->nchannels;
- xpc_vars_part_sn2[partid].magic = XPC_VP_MAGIC1;
+ xpc_vars_part_sn2[partid].magic = XPC_VP_MAGIC1_SN2;
return xpSuccess;
- /* setup of infrastructure failed */
-out_5:
- kfree(part->remote_openclose_args_base);
- part->remote_openclose_args = NULL;
-out_4:
- kfree(part->local_openclose_args_base);
- part->local_openclose_args = NULL;
+ /* setup of ch structures failed */
out_3:
+ kfree(part_sn2->local_openclose_args_base);
+ part_sn2->local_openclose_args = NULL;
+out_2:
kfree(part_sn2->remote_GPs_base);
part_sn2->remote_GPs = NULL;
-out_2:
+out_1:
kfree(part_sn2->local_GPs_base);
part_sn2->local_GPs = NULL;
-out_1:
- kfree(part->channels);
- part->channels = NULL;
return retval;
}
/*
- * Teardown the infrastructure necessary to support XPartition Communication
- * between the specified remote partition and the local one.
+ * Teardown the channel structures that are sn2 specific.
*/
static void
-xpc_teardown_infrastructure_sn2(struct xpc_partition *part)
+xpc_teardown_ch_structures_sn_sn2(struct xpc_partition *part)
{
struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
short partid = XPC_PARTID(part);
/*
- * We start off by making this partition inaccessible to local
- * processes by marking it as no longer setup. Then we make it
- * inaccessible to remote processes by clearing the XPC per partition
- * specific variable's magic # (which indicates that these variables
- * are no longer valid) and by ignoring all XPC notify IRQs sent to
- * this partition.
+ * Indicate that the variables specific to the remote partition are no
+ * longer available for its use.
*/
-
- DBUG_ON(atomic_read(&part->nchannels_engaged) != 0);
- DBUG_ON(atomic_read(&part->nchannels_active) != 0);
- DBUG_ON(part->setup_state != XPC_P_SS_SETUP);
- part->setup_state = XPC_P_SS_WTEARDOWN;
-
xpc_vars_part_sn2[partid].magic = 0;
- free_irq(SGI_XPC_NOTIFY, (void *)(u64)partid);
-
- /*
- * Before proceeding with the teardown we have to wait until all
- * existing references cease.
- */
- wait_event(part->teardown_wq, (atomic_read(&part->references) == 0));
-
- /* now we can begin tearing down the infrastructure */
-
- part->setup_state = XPC_P_SS_TORNDOWN;
-
/* in case we've still got outstanding timers registered... */
del_timer_sync(&part_sn2->dropped_notify_IRQ_timer);
+ free_irq(SGI_XPC_NOTIFY, (void *)(u64)partid);
- kfree(part->remote_openclose_args_base);
- part->remote_openclose_args = NULL;
- kfree(part->local_openclose_args_base);
- part->local_openclose_args = NULL;
+ kfree(part_sn2->local_openclose_args_base);
+ part_sn2->local_openclose_args = NULL;
kfree(part_sn2->remote_GPs_base);
part_sn2->remote_GPs = NULL;
kfree(part_sn2->local_GPs_base);
part_sn2->local_GPs = NULL;
- kfree(part->channels);
- part->channels = NULL;
part_sn2->local_chctl_amo_va = NULL;
}
@@ -1429,8 +1348,8 @@ xpc_pull_remote_vars_part_sn2(struct xpc_partition *part)
/* see if they've been set up yet */
- if (pulled_entry->magic != XPC_VP_MAGIC1 &&
- pulled_entry->magic != XPC_VP_MAGIC2) {
+ if (pulled_entry->magic != XPC_VP_MAGIC1_SN2 &&
+ pulled_entry->magic != XPC_VP_MAGIC2_SN2) {
if (pulled_entry->magic != 0) {
dev_dbg(xpc_chan, "partition %d's XPC vars_part for "
@@ -1443,7 +1362,7 @@ xpc_pull_remote_vars_part_sn2(struct xpc_partition *part)
return xpRetry;
}
- if (xpc_vars_part_sn2[partid].magic == XPC_VP_MAGIC1) {
+ if (xpc_vars_part_sn2[partid].magic == XPC_VP_MAGIC1_SN2) {
/* validate the variables */
@@ -1473,10 +1392,10 @@ xpc_pull_remote_vars_part_sn2(struct xpc_partition *part)
/* let the other side know that we've pulled their variables */
- xpc_vars_part_sn2[partid].magic = XPC_VP_MAGIC2;
+ xpc_vars_part_sn2[partid].magic = XPC_VP_MAGIC2_SN2;
}
- if (pulled_entry->magic == XPC_VP_MAGIC1)
+ if (pulled_entry->magic == XPC_VP_MAGIC1_SN2)
return xpRetry;
return xpSuccess;
@@ -1605,6 +1524,7 @@ xpc_get_chctl_all_flags_sn2(struct xpc_partition *part)
static enum xp_retval
xpc_allocate_local_msgqueue_sn2(struct xpc_channel *ch)
{
+ struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
unsigned long irq_flags;
int nentries;
size_t nbytes;
@@ -1612,17 +1532,17 @@ xpc_allocate_local_msgqueue_sn2(struct xpc_channel *ch)
for (nentries = ch->local_nentries; nentries > 0; nentries--) {
nbytes = nentries * ch->msg_size;
- ch->local_msgqueue =
- xpc_kzalloc_cacheline_aligned_sn2(nbytes, GFP_KERNEL,
- &ch->local_msgqueue_base);
- if (ch->local_msgqueue == NULL)
+ ch_sn2->local_msgqueue =
+ xpc_kzalloc_cacheline_aligned(nbytes, GFP_KERNEL,
+ &ch_sn2->local_msgqueue_base);
+ if (ch_sn2->local_msgqueue == NULL)
continue;
nbytes = nentries * sizeof(struct xpc_notify);
- ch->notify_queue = kzalloc(nbytes, GFP_KERNEL);
- if (ch->notify_queue == NULL) {
- kfree(ch->local_msgqueue_base);
- ch->local_msgqueue = NULL;
+ ch_sn2->notify_queue = kzalloc(nbytes, GFP_KERNEL);
+ if (ch_sn2->notify_queue == NULL) {
+ kfree(ch_sn2->local_msgqueue_base);
+ ch_sn2->local_msgqueue = NULL;
continue;
}
@@ -1649,6 +1569,7 @@ xpc_allocate_local_msgqueue_sn2(struct xpc_channel *ch)
static enum xp_retval
xpc_allocate_remote_msgqueue_sn2(struct xpc_channel *ch)
{
+ struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
unsigned long irq_flags;
int nentries;
size_t nbytes;
@@ -1658,10 +1579,10 @@ xpc_allocate_remote_msgqueue_sn2(struct xpc_channel *ch)
for (nentries = ch->remote_nentries; nentries > 0; nentries--) {
nbytes = nentries * ch->msg_size;
- ch->remote_msgqueue =
- xpc_kzalloc_cacheline_aligned_sn2(nbytes, GFP_KERNEL,
- &ch->remote_msgqueue_base);
- if (ch->remote_msgqueue == NULL)
+ ch_sn2->remote_msgqueue =
+ xpc_kzalloc_cacheline_aligned(nbytes, GFP_KERNEL, &ch_sn2->
+ remote_msgqueue_base);
+ if (ch_sn2->remote_msgqueue == NULL)
continue;
spin_lock_irqsave(&ch->lock, irq_flags);
@@ -1687,8 +1608,9 @@ xpc_allocate_remote_msgqueue_sn2(struct xpc_channel *ch)
* Note: Assumes all of the channel sizes are filled in.
*/
static enum xp_retval
-xpc_allocate_msgqueues_sn2(struct xpc_channel *ch)
+xpc_setup_msg_structures_sn2(struct xpc_channel *ch)
{
+ struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
enum xp_retval ret;
DBUG_ON(ch->flags & XPC_C_SETUP);
@@ -1698,10 +1620,10 @@ xpc_allocate_msgqueues_sn2(struct xpc_channel *ch)
ret = xpc_allocate_remote_msgqueue_sn2(ch);
if (ret != xpSuccess) {
- kfree(ch->local_msgqueue_base);
- ch->local_msgqueue = NULL;
- kfree(ch->notify_queue);
- ch->notify_queue = NULL;
+ kfree(ch_sn2->local_msgqueue_base);
+ ch_sn2->local_msgqueue = NULL;
+ kfree(ch_sn2->notify_queue);
+ ch_sn2->notify_queue = NULL;
}
}
return ret;
@@ -1715,21 +1637,13 @@ xpc_allocate_msgqueues_sn2(struct xpc_channel *ch)
* they're cleared when XPC_C_DISCONNECTED is cleared.
*/
static void
-xpc_free_msgqueues_sn2(struct xpc_channel *ch)
+xpc_teardown_msg_structures_sn2(struct xpc_channel *ch)
{
struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
DBUG_ON(!spin_is_locked(&ch->lock));
- DBUG_ON(atomic_read(&ch->n_to_notify) != 0);
- ch->remote_msgqueue_pa = 0;
- ch->func = NULL;
- ch->key = NULL;
- ch->msg_size = 0;
- ch->local_nentries = 0;
- ch->remote_nentries = 0;
- ch->kthreads_assigned_limit = 0;
- ch->kthreads_idle_limit = 0;
+ ch_sn2->remote_msgqueue_pa = 0;
ch_sn2->local_GP->get = 0;
ch_sn2->local_GP->put = 0;
@@ -1745,12 +1659,12 @@ xpc_free_msgqueues_sn2(struct xpc_channel *ch)
dev_dbg(xpc_chan, "ch->flags=0x%x, partid=%d, channel=%d\n",
ch->flags, ch->partid, ch->number);
- kfree(ch->local_msgqueue_base);
- ch->local_msgqueue = NULL;
- kfree(ch->remote_msgqueue_base);
- ch->remote_msgqueue = NULL;
- kfree(ch->notify_queue);
- ch->notify_queue = NULL;
+ kfree(ch_sn2->local_msgqueue_base);
+ ch_sn2->local_msgqueue = NULL;
+ kfree(ch_sn2->remote_msgqueue_base);
+ ch_sn2->remote_msgqueue = NULL;
+ kfree(ch_sn2->notify_queue);
+ ch_sn2->notify_queue = NULL;
}
}
@@ -1766,7 +1680,7 @@ xpc_notify_senders_sn2(struct xpc_channel *ch, enum xp_retval reason, s64 put)
while (++get < put && atomic_read(&ch->n_to_notify) > 0) {
- notify = &ch->notify_queue[get % ch->local_nentries];
+ notify = &ch->sn.sn2.notify_queue[get % ch->local_nentries];
/*
* See if the notify entry indicates it was associated with
@@ -1818,7 +1732,7 @@ xpc_clear_local_msgqueue_flags_sn2(struct xpc_channel *ch)
get = ch_sn2->w_remote_GP.get;
do {
- msg = (struct xpc_msg *)((u64)ch->local_msgqueue +
+ msg = (struct xpc_msg *)((u64)ch_sn2->local_msgqueue +
(get % ch->local_nentries) *
ch->msg_size);
msg->flags = 0;
@@ -1837,7 +1751,7 @@ xpc_clear_remote_msgqueue_flags_sn2(struct xpc_channel *ch)
put = ch_sn2->w_remote_GP.put;
do {
- msg = (struct xpc_msg *)((u64)ch->remote_msgqueue +
+ msg = (struct xpc_msg *)((u64)ch_sn2->remote_msgqueue +
(put % ch->remote_nentries) *
ch->msg_size);
msg->flags = 0;
@@ -1976,8 +1890,9 @@ xpc_pull_remote_msg_sn2(struct xpc_channel *ch, s64 get)
}
msg_offset = msg_index * ch->msg_size;
- msg = (struct xpc_msg *)((u64)ch->remote_msgqueue + msg_offset);
- remote_msg_pa = ch->remote_msgqueue_pa + msg_offset;
+ msg = (struct xpc_msg *)((u64)ch_sn2->remote_msgqueue +
+ msg_offset);
+ remote_msg_pa = ch_sn2->remote_msgqueue_pa + msg_offset;
ret = xpc_pull_remote_cachelines_sn2(part, msg, remote_msg_pa,
nmsgs * ch->msg_size);
@@ -2001,7 +1916,7 @@ xpc_pull_remote_msg_sn2(struct xpc_channel *ch, s64 get)
/* return the message we were looking for */
msg_offset = (get % ch->remote_nentries) * ch->msg_size;
- msg = (struct xpc_msg *)((u64)ch->remote_msgqueue + msg_offset);
+ msg = (struct xpc_msg *)((u64)ch_sn2->remote_msgqueue + msg_offset);
return msg;
}
@@ -2080,7 +1995,7 @@ xpc_send_msgs_sn2(struct xpc_channel *ch, s64 initial_put)
if (put == ch_sn2->w_local_GP.put)
break;
- msg = (struct xpc_msg *)((u64)ch->local_msgqueue +
+ msg = (struct xpc_msg *)((u64)ch_sn2->local_msgqueue +
(put % ch->local_nentries) *
ch->msg_size);
@@ -2182,7 +2097,7 @@ xpc_allocate_msg_sn2(struct xpc_channel *ch, u32 flags,
}
/* get the message's address and initialize it */
- msg = (struct xpc_msg *)((u64)ch->local_msgqueue +
+ msg = (struct xpc_msg *)((u64)ch_sn2->local_msgqueue +
(put % ch->local_nentries) * ch->msg_size);
DBUG_ON(msg->flags != 0);
@@ -2207,6 +2122,7 @@ xpc_send_msg_sn2(struct xpc_channel *ch, u32 flags, void *payload,
void *key)
{
enum xp_retval ret = xpSuccess;
+ struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
struct xpc_msg *msg = msg;
struct xpc_notify *notify = notify;
s64 msg_number;
@@ -2243,7 +2159,7 @@ xpc_send_msg_sn2(struct xpc_channel *ch, u32 flags, void *payload,
atomic_inc(&ch->n_to_notify);
- notify = &ch->notify_queue[msg_number % ch->local_nentries];
+ notify = &ch_sn2->notify_queue[msg_number % ch->local_nentries];
notify->func = func;
notify->key = key;
notify->type = notify_type;
@@ -2279,7 +2195,7 @@ xpc_send_msg_sn2(struct xpc_channel *ch, u32 flags, void *payload,
/* see if the message is next in line to be sent, if so send it */
- put = ch->sn.sn2.local_GP->put;
+ put = ch_sn2->local_GP->put;
if (put == msg_number)
xpc_send_msgs_sn2(ch, put);
@@ -2307,7 +2223,7 @@ xpc_acknowledge_msgs_sn2(struct xpc_channel *ch, s64 initial_get, u8 msg_flags)
if (get == ch_sn2->w_local_GP.get)
break;
- msg = (struct xpc_msg *)((u64)ch->remote_msgqueue +
+ msg = (struct xpc_msg *)((u64)ch_sn2->remote_msgqueue +
(get % ch->remote_nentries) *
ch->msg_size);
@@ -2385,8 +2301,9 @@ xpc_init_sn2(void)
int ret;
size_t buf_size;
+ xpc_setup_partitions_sn = xpc_setup_partitions_sn_sn2;
xpc_get_partition_rsvd_page_pa = xpc_get_partition_rsvd_page_pa_sn2;
- xpc_rsvd_page_init = xpc_rsvd_page_init_sn2;
+ xpc_setup_rsvd_page_sn = xpc_setup_rsvd_page_sn_sn2;
xpc_increment_heartbeat = xpc_increment_heartbeat_sn2;
xpc_offline_heartbeat = xpc_offline_heartbeat_sn2;
xpc_online_heartbeat = xpc_online_heartbeat_sn2;
@@ -2403,29 +2320,33 @@ xpc_init_sn2(void)
xpc_cancel_partition_deactivation_request_sn2;
xpc_process_activate_IRQ_rcvd = xpc_process_activate_IRQ_rcvd_sn2;
- xpc_setup_infrastructure = xpc_setup_infrastructure_sn2;
- xpc_teardown_infrastructure = xpc_teardown_infrastructure_sn2;
+ xpc_setup_ch_structures_sn = xpc_setup_ch_structures_sn_sn2;
+ xpc_teardown_ch_structures_sn = xpc_teardown_ch_structures_sn_sn2;
xpc_make_first_contact = xpc_make_first_contact_sn2;
+
xpc_get_chctl_all_flags = xpc_get_chctl_all_flags_sn2;
- xpc_allocate_msgqueues = xpc_allocate_msgqueues_sn2;
- xpc_free_msgqueues = xpc_free_msgqueues_sn2;
+ xpc_send_chctl_closerequest = xpc_send_chctl_closerequest_sn2;
+ xpc_send_chctl_closereply = xpc_send_chctl_closereply_sn2;
+ xpc_send_chctl_openrequest = xpc_send_chctl_openrequest_sn2;
+ xpc_send_chctl_openreply = xpc_send_chctl_openreply_sn2;
+
+ xpc_save_remote_msgqueue_pa = xpc_save_remote_msgqueue_pa_sn2;
+
+ xpc_setup_msg_structures = xpc_setup_msg_structures_sn2;
+ xpc_teardown_msg_structures = xpc_teardown_msg_structures_sn2;
+
xpc_notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_sn2;
xpc_process_msg_chctl_flags = xpc_process_msg_chctl_flags_sn2;
xpc_n_of_deliverable_msgs = xpc_n_of_deliverable_msgs_sn2;
xpc_get_deliverable_msg = xpc_get_deliverable_msg_sn2;
xpc_indicate_partition_engaged = xpc_indicate_partition_engaged_sn2;
- xpc_partition_engaged = xpc_partition_engaged_sn2;
- xpc_any_partition_engaged = xpc_any_partition_engaged_sn2;
xpc_indicate_partition_disengaged =
xpc_indicate_partition_disengaged_sn2;
+ xpc_partition_engaged = xpc_partition_engaged_sn2;
+ xpc_any_partition_engaged = xpc_any_partition_engaged_sn2;
xpc_assume_partition_disengaged = xpc_assume_partition_disengaged_sn2;
- xpc_send_chctl_closerequest = xpc_send_chctl_closerequest_sn2;
- xpc_send_chctl_closereply = xpc_send_chctl_closereply_sn2;
- xpc_send_chctl_openrequest = xpc_send_chctl_openrequest_sn2;
- xpc_send_chctl_openreply = xpc_send_chctl_openreply_sn2;
-
xpc_send_msg = xpc_send_msg_sn2;
xpc_received_msg = xpc_received_msg_sn2;
OpenPOWER on IntegriCloud