aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/sgi-xp/xpc_channel.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/sgi-xp/xpc_channel.c')
-rw-r--r--drivers/misc/sgi-xp/xpc_channel.c214
1 files changed, 17 insertions, 197 deletions
diff --git a/drivers/misc/sgi-xp/xpc_channel.c b/drivers/misc/sgi-xp/xpc_channel.c
index 55182c8dd32a..48b16136305e 100644
--- a/drivers/misc/sgi-xp/xpc_channel.c
+++ b/drivers/misc/sgi-xp/xpc_channel.c
@@ -201,7 +201,7 @@ xpc_process_connect(struct xpc_channel *ch, unsigned long *irq_flags)
201 201
202 if (!(ch->flags & XPC_C_OPENREPLY)) { 202 if (!(ch->flags & XPC_C_OPENREPLY)) {
203 ch->flags |= XPC_C_OPENREPLY; 203 ch->flags |= XPC_C_OPENREPLY;
204 xpc_IPI_send_openreply(ch, irq_flags); 204 xpc_send_channel_openreply(ch, irq_flags);
205 } 205 }
206 206
207 if (!(ch->flags & XPC_C_ROPENREPLY)) 207 if (!(ch->flags & XPC_C_ROPENREPLY))
@@ -220,52 +220,6 @@ xpc_process_connect(struct xpc_channel *ch, unsigned long *irq_flags)
220} 220}
221 221
222/* 222/*
223 * Notify those who wanted to be notified upon delivery of their message.
224 */
225static void
226xpc_notify_senders(struct xpc_channel *ch, enum xp_retval reason, s64 put)
227{
228 struct xpc_notify *notify;
229 u8 notify_type;
230 s64 get = ch->w_remote_GP.get - 1;
231
232 while (++get < put && atomic_read(&ch->n_to_notify) > 0) {
233
234 notify = &ch->notify_queue[get % ch->local_nentries];
235
236 /*
237 * See if the notify entry indicates it was associated with
238 * a message who's sender wants to be notified. It is possible
239 * that it is, but someone else is doing or has done the
240 * notification.
241 */
242 notify_type = notify->type;
243 if (notify_type == 0 ||
244 cmpxchg(&notify->type, notify_type, 0) != notify_type) {
245 continue;
246 }
247
248 DBUG_ON(notify_type != XPC_N_CALL);
249
250 atomic_dec(&ch->n_to_notify);
251
252 if (notify->func != NULL) {
253 dev_dbg(xpc_chan, "notify->func() called, notify=0x%p, "
254 "msg_number=%ld, partid=%d, channel=%d\n",
255 (void *)notify, get, ch->partid, ch->number);
256
257 notify->func(reason, ch->partid, ch->number,
258 notify->key);
259
260 dev_dbg(xpc_chan, "notify->func() returned, "
261 "notify=0x%p, msg_number=%ld, partid=%d, "
262 "channel=%d\n", (void *)notify, get,
263 ch->partid, ch->number);
264 }
265 }
266}
267
268/*
269 * Free up message queues and other stuff that were allocated for the specified 223 * Free up message queues and other stuff that were allocated for the specified
270 * channel. 224 * channel.
271 * 225 *
@@ -275,6 +229,8 @@ xpc_notify_senders(struct xpc_channel *ch, enum xp_retval reason, s64 put)
275static void 229static void
276xpc_free_msgqueues(struct xpc_channel *ch) 230xpc_free_msgqueues(struct xpc_channel *ch)
277{ 231{
232 struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
233
278 DBUG_ON(!spin_is_locked(&ch->lock)); 234 DBUG_ON(!spin_is_locked(&ch->lock));
279 DBUG_ON(atomic_read(&ch->n_to_notify) != 0); 235 DBUG_ON(atomic_read(&ch->n_to_notify) != 0);
280 236
@@ -287,15 +243,15 @@ xpc_free_msgqueues(struct xpc_channel *ch)
287 ch->kthreads_assigned_limit = 0; 243 ch->kthreads_assigned_limit = 0;
288 ch->kthreads_idle_limit = 0; 244 ch->kthreads_idle_limit = 0;
289 245
290 ch->local_GP->get = 0; 246 ch_sn2->local_GP->get = 0;
291 ch->local_GP->put = 0; 247 ch_sn2->local_GP->put = 0;
292 ch->remote_GP.get = 0; 248 ch_sn2->remote_GP.get = 0;
293 ch->remote_GP.put = 0; 249 ch_sn2->remote_GP.put = 0;
294 ch->w_local_GP.get = 0; 250 ch_sn2->w_local_GP.get = 0;
295 ch->w_local_GP.put = 0; 251 ch_sn2->w_local_GP.put = 0;
296 ch->w_remote_GP.get = 0; 252 ch_sn2->w_remote_GP.get = 0;
297 ch->w_remote_GP.put = 0; 253 ch_sn2->w_remote_GP.put = 0;
298 ch->next_msg_to_pull = 0; 254 ch_sn2->next_msg_to_pull = 0;
299 255
300 if (ch->flags & XPC_C_SETUP) { 256 if (ch->flags & XPC_C_SETUP) {
301 ch->flags &= ~XPC_C_SETUP; 257 ch->flags &= ~XPC_C_SETUP;
@@ -339,7 +295,7 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
339 295
340 if (part->act_state == XPC_P_DEACTIVATING) { 296 if (part->act_state == XPC_P_DEACTIVATING) {
341 /* can't proceed until the other side disengages from us */ 297 /* can't proceed until the other side disengages from us */
342 if (xpc_partition_engaged(1UL << ch->partid)) 298 if (xpc_partition_engaged(ch->partid))
343 return; 299 return;
344 300
345 } else { 301 } else {
@@ -351,7 +307,7 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
351 307
352 if (!(ch->flags & XPC_C_CLOSEREPLY)) { 308 if (!(ch->flags & XPC_C_CLOSEREPLY)) {
353 ch->flags |= XPC_C_CLOSEREPLY; 309 ch->flags |= XPC_C_CLOSEREPLY;
354 xpc_IPI_send_closereply(ch, irq_flags); 310 xpc_send_channel_closereply(ch, irq_flags);
355 } 311 }
356 312
357 if (!(ch->flags & XPC_C_RCLOSEREPLY)) 313 if (!(ch->flags & XPC_C_RCLOSEREPLY))
@@ -361,7 +317,7 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
361 /* wake those waiting for notify completion */ 317 /* wake those waiting for notify completion */
362 if (atomic_read(&ch->n_to_notify) > 0) { 318 if (atomic_read(&ch->n_to_notify) > 0) {
363 /* >>> we do callout while holding ch->lock */ 319 /* >>> we do callout while holding ch->lock */
364 xpc_notify_senders(ch, ch->reason, ch->w_local_GP.put); 320 xpc_notify_senders_of_disconnect(ch);
365 } 321 }
366 322
367 /* both sides are disconnected now */ 323 /* both sides are disconnected now */
@@ -734,7 +690,7 @@ xpc_connect_channel(struct xpc_channel *ch)
734 /* initiate the connection */ 690 /* initiate the connection */
735 691
736 ch->flags |= (XPC_C_OPENREQUEST | XPC_C_CONNECTING); 692 ch->flags |= (XPC_C_OPENREQUEST | XPC_C_CONNECTING);
737 xpc_IPI_send_openrequest(ch, &irq_flags); 693 xpc_send_channel_openrequest(ch, &irq_flags);
738 694
739 xpc_process_connect(ch, &irq_flags); 695 xpc_process_connect(ch, &irq_flags);
740 696
@@ -743,142 +699,6 @@ xpc_connect_channel(struct xpc_channel *ch)
743 return xpSuccess; 699 return xpSuccess;
744} 700}
745 701
746/*
747 * Clear some of the msg flags in the local message queue.
748 */
749static inline void
750xpc_clear_local_msgqueue_flags(struct xpc_channel *ch)
751{
752 struct xpc_msg *msg;
753 s64 get;
754
755 get = ch->w_remote_GP.get;
756 do {
757 msg = (struct xpc_msg *)((u64)ch->local_msgqueue +
758 (get % ch->local_nentries) *
759 ch->msg_size);
760 msg->flags = 0;
761 } while (++get < ch->remote_GP.get);
762}
763
764/*
765 * Clear some of the msg flags in the remote message queue.
766 */
767static inline void
768xpc_clear_remote_msgqueue_flags(struct xpc_channel *ch)
769{
770 struct xpc_msg *msg;
771 s64 put;
772
773 put = ch->w_remote_GP.put;
774 do {
775 msg = (struct xpc_msg *)((u64)ch->remote_msgqueue +
776 (put % ch->remote_nentries) *
777 ch->msg_size);
778 msg->flags = 0;
779 } while (++put < ch->remote_GP.put);
780}
781
782static void
783xpc_process_msg_IPI(struct xpc_partition *part, int ch_number)
784{
785 struct xpc_channel *ch = &part->channels[ch_number];
786 int nmsgs_sent;
787
788 ch->remote_GP = part->remote_GPs[ch_number];
789
790 /* See what, if anything, has changed for each connected channel */
791
792 xpc_msgqueue_ref(ch);
793
794 if (ch->w_remote_GP.get == ch->remote_GP.get &&
795 ch->w_remote_GP.put == ch->remote_GP.put) {
796 /* nothing changed since GPs were last pulled */
797 xpc_msgqueue_deref(ch);
798 return;
799 }
800
801 if (!(ch->flags & XPC_C_CONNECTED)) {
802 xpc_msgqueue_deref(ch);
803 return;
804 }
805
806 /*
807 * First check to see if messages recently sent by us have been
808 * received by the other side. (The remote GET value will have
809 * changed since we last looked at it.)
810 */
811
812 if (ch->w_remote_GP.get != ch->remote_GP.get) {
813
814 /*
815 * We need to notify any senders that want to be notified
816 * that their sent messages have been received by their
817 * intended recipients. We need to do this before updating
818 * w_remote_GP.get so that we don't allocate the same message
819 * queue entries prematurely (see xpc_allocate_msg()).
820 */
821 if (atomic_read(&ch->n_to_notify) > 0) {
822 /*
823 * Notify senders that messages sent have been
824 * received and delivered by the other side.
825 */
826 xpc_notify_senders(ch, xpMsgDelivered,
827 ch->remote_GP.get);
828 }
829
830 /*
831 * Clear msg->flags in previously sent messages, so that
832 * they're ready for xpc_allocate_msg().
833 */
834 xpc_clear_local_msgqueue_flags(ch);
835
836 ch->w_remote_GP.get = ch->remote_GP.get;
837
838 dev_dbg(xpc_chan, "w_remote_GP.get changed to %ld, partid=%d, "
839 "channel=%d\n", ch->w_remote_GP.get, ch->partid,
840 ch->number);
841
842 /*
843 * If anyone was waiting for message queue entries to become
844 * available, wake them up.
845 */
846 if (atomic_read(&ch->n_on_msg_allocate_wq) > 0)
847 wake_up(&ch->msg_allocate_wq);
848 }
849
850 /*
851 * Now check for newly sent messages by the other side. (The remote
852 * PUT value will have changed since we last looked at it.)
853 */
854
855 if (ch->w_remote_GP.put != ch->remote_GP.put) {
856 /*
857 * Clear msg->flags in previously received messages, so that
858 * they're ready for xpc_get_deliverable_msg().
859 */
860 xpc_clear_remote_msgqueue_flags(ch);
861
862 ch->w_remote_GP.put = ch->remote_GP.put;
863
864 dev_dbg(xpc_chan, "w_remote_GP.put changed to %ld, partid=%d, "
865 "channel=%d\n", ch->w_remote_GP.put, ch->partid,
866 ch->number);
867
868 nmsgs_sent = ch->w_remote_GP.put - ch->w_local_GP.get;
869 if (nmsgs_sent > 0) {
870 dev_dbg(xpc_chan, "msgs waiting to be copied and "
871 "delivered=%d, partid=%d, channel=%d\n",
872 nmsgs_sent, ch->partid, ch->number);
873
874 if (ch->flags & XPC_C_CONNECTEDCALLOUT_MADE)
875 xpc_activate_kthreads(ch, nmsgs_sent);
876 }
877 }
878
879 xpc_msgqueue_deref(ch);
880}
881
882void 702void
883xpc_process_channel_activity(struct xpc_partition *part) 703xpc_process_channel_activity(struct xpc_partition *part)
884{ 704{
@@ -1117,7 +937,7 @@ xpc_disconnect_channel(const int line, struct xpc_channel *ch,
1117 XPC_C_ROPENREQUEST | XPC_C_ROPENREPLY | 937 XPC_C_ROPENREQUEST | XPC_C_ROPENREPLY |
1118 XPC_C_CONNECTING | XPC_C_CONNECTED); 938 XPC_C_CONNECTING | XPC_C_CONNECTED);
1119 939
1120 xpc_IPI_send_closerequest(ch, irq_flags); 940 xpc_send_channel_closerequest(ch, irq_flags);
1121 941
1122 if (channel_was_connected) 942 if (channel_was_connected)
1123 ch->flags |= XPC_C_WASCONNECTED; 943 ch->flags |= XPC_C_WASCONNECTED;