From 69b3bb65fa97a1e8563518dbbc35cd57beefb2d4 Mon Sep 17 00:00:00 2001 From: Robin Holt Date: Thu, 29 Jan 2009 14:25:06 -0800 Subject: sgi-xpc: ensure flags are updated before bte_copy The clearing of the msg->flags needs a barrier between it and the notify of the channel threads that the messages are cleaned and ready for use. Signed-off-by: Robin Holt Signed-off-by: Dean Nelson Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/sgi-xp/xpc_sn2.c | 9 +++++---- drivers/misc/sgi-xp/xpc_uv.c | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/misc/sgi-xp') diff --git a/drivers/misc/sgi-xp/xpc_sn2.c b/drivers/misc/sgi-xp/xpc_sn2.c index 82fb995..7aafb8a 100644 --- a/drivers/misc/sgi-xp/xpc_sn2.c +++ b/drivers/misc/sgi-xp/xpc_sn2.c @@ -1836,6 +1836,7 @@ xpc_process_msg_chctl_flags_sn2(struct xpc_partition *part, int ch_number) */ xpc_clear_remote_msgqueue_flags_sn2(ch); + smp_wmb(); /* ensure flags have been cleared before bte_copy */ ch_sn2->w_remote_GP.put = ch_sn2->remote_GP.put; dev_dbg(xpc_chan, "w_remote_GP.put changed to %ld, partid=%d, " @@ -1934,7 +1935,7 @@ xpc_get_deliverable_payload_sn2(struct xpc_channel *ch) break; get = ch_sn2->w_local_GP.get; - rmb(); /* guarantee that .get loads before .put */ + smp_rmb(); /* guarantee that .get loads before .put */ if (get == ch_sn2->w_remote_GP.put) break; @@ -2053,7 +2054,7 @@ xpc_allocate_msg_sn2(struct xpc_channel *ch, u32 flags, while (1) { put = ch_sn2->w_local_GP.put; - rmb(); /* guarantee that .put loads before .get */ + smp_rmb(); /* guarantee that .put loads before .get */ if (put - ch_sn2->w_remote_GP.get < ch->local_nentries) { /* There are available message entries. We need to try @@ -2186,7 +2187,7 @@ xpc_send_payload_sn2(struct xpc_channel *ch, u32 flags, void *payload, * The preceding store of msg->flags must occur before the following * load of local_GP->put. */ - mb(); + smp_mb(); /* see if the message is next in line to be sent, if so send it */ @@ -2287,7 +2288,7 @@ xpc_received_payload_sn2(struct xpc_channel *ch, void *payload) * The preceding store of msg->flags must occur before the following * load of local_GP->get. */ - mb(); + smp_mb(); /* * See if this message is next in line to be acknowledged as having diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c index 91a55b1..f17f7d4 100644 --- a/drivers/misc/sgi-xp/xpc_uv.c +++ b/drivers/misc/sgi-xp/xpc_uv.c @@ -1423,7 +1423,7 @@ xpc_send_payload_uv(struct xpc_channel *ch, u32 flags, void *payload, atomic_inc(&ch->n_to_notify); msg_slot->key = key; - wmb(); /* a non-NULL func must hit memory after the key */ + smp_wmb(); /* a non-NULL func must hit memory after the key */ msg_slot->func = func; if (ch->flags & XPC_C_DISCONNECTING) { -- cgit v1.1 From 17e2161654da4e6bdfd8d53d4f52e820ee93f423 Mon Sep 17 00:00:00 2001 From: Robin Holt Date: Thu, 29 Jan 2009 14:25:07 -0800 Subject: sgi-xpc: Remove NULL pointer dereference. If the bte copy fails, the attempt to retrieve payloads merely returns a null pointer deref and not NULL as was expected. Signed-off-by: Robin Holt Signed-off-by: Dean Nelson Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/sgi-xp/xpc_sn2.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/misc/sgi-xp') diff --git a/drivers/misc/sgi-xp/xpc_sn2.c b/drivers/misc/sgi-xp/xpc_sn2.c index 7aafb8a..7d05fb5 100644 --- a/drivers/misc/sgi-xp/xpc_sn2.c +++ b/drivers/misc/sgi-xp/xpc_sn2.c @@ -1957,11 +1957,13 @@ xpc_get_deliverable_payload_sn2(struct xpc_channel *ch) msg = xpc_pull_remote_msg_sn2(ch, get); - DBUG_ON(msg != NULL && msg->number != get); - DBUG_ON(msg != NULL && (msg->flags & XPC_M_SN2_DONE)); - DBUG_ON(msg != NULL && !(msg->flags & XPC_M_SN2_READY)); + if (msg != NULL) { + DBUG_ON(msg->number != get); + DBUG_ON(msg->flags & XPC_M_SN2_DONE); + DBUG_ON(!(msg->flags & XPC_M_SN2_READY)); - payload = &msg->payload; + payload = &msg->payload; + } break; } -- cgit v1.1 From 252523ef2421b803de4810876223e4d695f23ec6 Mon Sep 17 00:00:00 2001 From: Robin Holt Date: Thu, 29 Jan 2009 14:25:07 -0800 Subject: sgi-xpc: fix up stale DBUG_ON statements Clean up the stale DBUG_ON checks and add a couple new ones. Signed-off-by: Robin Holt Signed-off-by: Dean Nelson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/sgi-xp/xpc_channel.c | 3 --- drivers/misc/sgi-xp/xpc_sn2.c | 15 +++++++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) (limited to 'drivers/misc/sgi-xp') diff --git a/drivers/misc/sgi-xp/xpc_channel.c b/drivers/misc/sgi-xp/xpc_channel.c index 9cd2ebe..45fd653 100644 --- a/drivers/misc/sgi-xp/xpc_channel.c +++ b/drivers/misc/sgi-xp/xpc_channel.c @@ -49,9 +49,6 @@ xpc_process_connect(struct xpc_channel *ch, unsigned long *irq_flags) if (ch->flags & (XPC_C_CONNECTED | XPC_C_DISCONNECTING)) return; - - DBUG_ON(ch->local_msgqueue == NULL); - DBUG_ON(ch->remote_msgqueue == NULL); } if (!(ch->flags & XPC_C_OPENREPLY)) { diff --git a/drivers/misc/sgi-xp/xpc_sn2.c b/drivers/misc/sgi-xp/xpc_sn2.c index 7d05fb5..2e97576 100644 --- a/drivers/misc/sgi-xp/xpc_sn2.c +++ b/drivers/misc/sgi-xp/xpc_sn2.c @@ -1106,8 +1106,6 @@ xpc_process_activate_IRQ_rcvd_sn2(void) 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; @@ -1726,6 +1724,7 @@ xpc_clear_local_msgqueue_flags_sn2(struct xpc_channel *ch) msg = (struct xpc_msg_sn2 *)((u64)ch_sn2->local_msgqueue + (get % ch->local_nentries) * ch->entry_size); + DBUG_ON(!(msg->flags & XPC_M_SN2_READY)); msg->flags = 0; } while (++get < ch_sn2->remote_GP.get); } @@ -1740,11 +1739,18 @@ xpc_clear_remote_msgqueue_flags_sn2(struct xpc_channel *ch) struct xpc_msg_sn2 *msg; s64 put; - put = ch_sn2->w_remote_GP.put; + /* flags are zeroed when the buffer is allocated */ + if (ch_sn2->remote_GP.put < ch->remote_nentries) + return; + + put = max(ch_sn2->w_remote_GP.put, ch->remote_nentries); do { msg = (struct xpc_msg_sn2 *)((u64)ch_sn2->remote_msgqueue + (put % ch->remote_nentries) * ch->entry_size); + DBUG_ON(!(msg->flags & XPC_M_SN2_READY)); + DBUG_ON(!(msg->flags & XPC_M_SN2_DONE)); + DBUG_ON(msg->number != put - ch->remote_nentries); msg->flags = 0; } while (++put < ch_sn2->remote_GP.put); } @@ -2280,8 +2286,9 @@ xpc_received_payload_sn2(struct xpc_channel *ch, void *payload) dev_dbg(xpc_chan, "msg=0x%p, msg_number=%ld, partid=%d, channel=%d\n", (void *)msg, msg_number, ch->partid, ch->number); - DBUG_ON((((u64)msg - (u64)ch->remote_msgqueue) / ch->entry_size) != + DBUG_ON((((u64)msg - (u64)ch->sn.sn2.remote_msgqueue) / ch->entry_size) != msg_number % ch->remote_nentries); + DBUG_ON(!(msg->flags & XPC_M_SN2_READY)); DBUG_ON(msg->flags & XPC_M_SN2_DONE); msg->flags |= XPC_M_SN2_DONE; -- cgit v1.1