diff options
Diffstat (limited to 'drivers/misc/sgi-xp/xpc_channel.c')
-rw-r--r-- | drivers/misc/sgi-xp/xpc_channel.c | 214 |
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 | */ | ||
225 | static void | ||
226 | xpc_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(¬ify->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) | |||
275 | static void | 229 | static void |
276 | xpc_free_msgqueues(struct xpc_channel *ch) | 230 | xpc_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 | */ | ||
749 | static inline void | ||
750 | xpc_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 | */ | ||
767 | static inline void | ||
768 | xpc_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 | |||
782 | static void | ||
783 | xpc_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 | |||
882 | void | 702 | void |
883 | xpc_process_channel_activity(struct xpc_partition *part) | 703 | xpc_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; |