aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/sgi-xp
diff options
context:
space:
mode:
authorDean Nelson <dcn@sgi.com>2008-07-30 01:34:19 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-30 12:41:50 -0400
commitbd3e64c1759e4930315ebf022611468ee9621486 (patch)
tree314f4f8a80788b181aa03714d952854c8e2a1866 /drivers/misc/sgi-xp
parent5b8669dfd110a62a74eea525a009342f73987ea0 (diff)
sgi-xp: setup the notify GRU message queue
Setup the notify GRU message queue that is used for sending user messages 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')
-rw-r--r--drivers/misc/sgi-xp/xp.h45
-rw-r--r--drivers/misc/sgi-xp/xp_main.c7
-rw-r--r--drivers/misc/sgi-xp/xpc.h140
-rw-r--r--drivers/misc/sgi-xp/xpc_channel.c63
-rw-r--r--drivers/misc/sgi-xp/xpc_main.c21
-rw-r--r--drivers/misc/sgi-xp/xpc_sn2.c178
-rw-r--r--drivers/misc/sgi-xp/xpc_uv.c951
-rw-r--r--drivers/misc/sgi-xp/xpnet.c11
8 files changed, 1032 insertions, 384 deletions
diff --git a/drivers/misc/sgi-xp/xp.h b/drivers/misc/sgi-xp/xp.h
index 9ac5758f4d08..859a5281c61b 100644
--- a/drivers/misc/sgi-xp/xp.h
+++ b/drivers/misc/sgi-xp/xp.h
@@ -87,39 +87,18 @@
87#endif 87#endif
88 88
89/* 89/*
90 * The format of an XPC message is as follows: 90 * Define macro, XPC_MSG_SIZE(), is provided for the user
91 *
92 * +-------+--------------------------------+
93 * | flags |////////////////////////////////|
94 * +-------+--------------------------------+
95 * | message # |
96 * +----------------------------------------+
97 * | payload (user-defined message) |
98 * | |
99 * :
100 * | |
101 * +----------------------------------------+
102 *
103 * The size of the payload is defined by the user via xpc_connect(). A user-
104 * defined message resides in the payload area.
105 *
106 * The size of a message entry (within a message queue) must be a cacheline
107 * sized multiple in order to facilitate the BTE transfer of messages from one
108 * message queue to another. A macro, XPC_MSG_SIZE(), is provided for the user
109 * that wants to fit as many msg entries as possible in a given memory size 91 * that wants to fit as many msg entries as possible in a given memory size
110 * (e.g. a memory page). 92 * (e.g. a memory page).
111 */ 93 */
112struct xpc_msg { 94#define XPC_MSG_MAX_SIZE 128
113 u8 flags; /* FOR XPC INTERNAL USE ONLY */ 95#define XPC_MSG_HDR_MAX_SIZE 16
114 u8 reserved[7]; /* FOR XPC INTERNAL USE ONLY */ 96#define XPC_MSG_PAYLOAD_MAX_SIZE (XPC_MSG_MAX_SIZE - XPC_MSG_HDR_MAX_SIZE)
115 s64 number; /* FOR XPC INTERNAL USE ONLY */
116
117 u64 payload; /* user defined portion of message */
118};
119 97
120#define XPC_MSG_PAYLOAD_OFFSET (u64) (&((struct xpc_msg *)0)->payload)
121#define XPC_MSG_SIZE(_payload_size) \ 98#define XPC_MSG_SIZE(_payload_size) \
122 L1_CACHE_ALIGN(XPC_MSG_PAYLOAD_OFFSET + (_payload_size)) 99 ALIGN(XPC_MSG_HDR_MAX_SIZE + (_payload_size), \
100 is_uv() ? 64 : 128)
101
123 102
124/* 103/*
125 * Define the return values and values passed to user's callout functions. 104 * Define the return values and values passed to user's callout functions.
@@ -210,7 +189,10 @@ enum xp_retval {
210 xpGruCopyError, /* 58: gru_copy_gru() returned error */ 189 xpGruCopyError, /* 58: gru_copy_gru() returned error */
211 xpGruSendMqError, /* 59: gru send message queue related error */ 190 xpGruSendMqError, /* 59: gru send message queue related error */
212 191
213 xpUnknownReason /* 60: unknown reason - must be last in enum */ 192 xpBadChannelNumber, /* 60: invalid channel number */
193 xpBadMsgType, /* 60: invalid message type */
194
195 xpUnknownReason /* 61: unknown reason - must be last in enum */
214}; 196};
215 197
216/* 198/*
@@ -261,6 +243,9 @@ typedef void (*xpc_channel_func) (enum xp_retval reason, short partid,
261 * calling xpc_received(). 243 * calling xpc_received().
262 * 244 *
263 * All other reason codes indicate failure. 245 * All other reason codes indicate failure.
246 *
247 * NOTE: The user defined function must be callable by an interrupt handler
248 * and thus cannot block.
264 */ 249 */
265typedef void (*xpc_notify_func) (enum xp_retval reason, short partid, 250typedef void (*xpc_notify_func) (enum xp_retval reason, short partid,
266 int ch_number, void *key); 251 int ch_number, void *key);
@@ -284,7 +269,7 @@ struct xpc_registration {
284 xpc_channel_func func; /* function to call */ 269 xpc_channel_func func; /* function to call */
285 void *key; /* pointer to user's key */ 270 void *key; /* pointer to user's key */
286 u16 nentries; /* #of msg entries in local msg queue */ 271 u16 nentries; /* #of msg entries in local msg queue */
287 u16 msg_size; /* message queue's message size */ 272 u16 entry_size; /* message queue's message entry size */
288 u32 assigned_limit; /* limit on #of assigned kthreads */ 273 u32 assigned_limit; /* limit on #of assigned kthreads */
289 u32 idle_limit; /* limit on #of idle kthreads */ 274 u32 idle_limit; /* limit on #of idle kthreads */
290} ____cacheline_aligned; 275} ____cacheline_aligned;
diff --git a/drivers/misc/sgi-xp/xp_main.c b/drivers/misc/sgi-xp/xp_main.c
index f86ad3af26b7..66a1d19e08ad 100644
--- a/drivers/misc/sgi-xp/xp_main.c
+++ b/drivers/misc/sgi-xp/xp_main.c
@@ -154,6 +154,9 @@ xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size,
154 DBUG_ON(func == NULL); 154 DBUG_ON(func == NULL);
155 DBUG_ON(assigned_limit == 0 || idle_limit > assigned_limit); 155 DBUG_ON(assigned_limit == 0 || idle_limit > assigned_limit);
156 156
157 if (XPC_MSG_SIZE(payload_size) > XPC_MSG_MAX_SIZE)
158 return xpPayloadTooBig;
159
157 registration = &xpc_registrations[ch_number]; 160 registration = &xpc_registrations[ch_number];
158 161
159 if (mutex_lock_interruptible(&registration->mutex) != 0) 162 if (mutex_lock_interruptible(&registration->mutex) != 0)
@@ -166,7 +169,7 @@ xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size,
166 } 169 }
167 170
168 /* register the channel for connection */ 171 /* register the channel for connection */
169 registration->msg_size = XPC_MSG_SIZE(payload_size); 172 registration->entry_size = XPC_MSG_SIZE(payload_size);
170 registration->nentries = nentries; 173 registration->nentries = nentries;
171 registration->assigned_limit = assigned_limit; 174 registration->assigned_limit = assigned_limit;
172 registration->idle_limit = idle_limit; 175 registration->idle_limit = idle_limit;
@@ -220,7 +223,7 @@ xpc_disconnect(int ch_number)
220 registration->func = NULL; 223 registration->func = NULL;
221 registration->key = NULL; 224 registration->key = NULL;
222 registration->nentries = 0; 225 registration->nentries = 0;
223 registration->msg_size = 0; 226 registration->entry_size = 0;
224 registration->assigned_limit = 0; 227 registration->assigned_limit = 0;
225 registration->idle_limit = 0; 228 registration->idle_limit = 0;
226 229
diff --git a/drivers/misc/sgi-xp/xpc.h b/drivers/misc/sgi-xp/xpc.h
index 4c26181defff..619208d61862 100644
--- a/drivers/misc/sgi-xp/xpc.h
+++ b/drivers/misc/sgi-xp/xpc.h
@@ -181,8 +181,8 @@ struct xpc_vars_part_sn2 {
181 xpc_nasid_mask_nlongs)) 181 xpc_nasid_mask_nlongs))
182 182
183/* 183/*
184 * The activate_mq is used to send/receive messages that affect XPC's heartbeat, 184 * The activate_mq is used to send/receive GRU messages that affect XPC's
185 * partition active state, and channel state. This is UV only. 185 * heartbeat, partition active state, and channel state. This is UV only.
186 */ 186 */
187struct xpc_activate_mq_msghdr_uv { 187struct xpc_activate_mq_msghdr_uv {
188 short partid; /* sender's partid */ 188 short partid; /* sender's partid */
@@ -209,45 +209,45 @@ struct xpc_activate_mq_msghdr_uv {
209#define XPC_ACTIVATE_MQ_MSG_MARK_DISENGAGED_UV 11 209#define XPC_ACTIVATE_MQ_MSG_MARK_DISENGAGED_UV 11
210 210
211struct xpc_activate_mq_msg_uv { 211struct xpc_activate_mq_msg_uv {
212 struct xpc_activate_mq_msghdr_uv header; 212 struct xpc_activate_mq_msghdr_uv hdr;
213}; 213};
214 214
215struct xpc_activate_mq_msg_heartbeat_req_uv { 215struct xpc_activate_mq_msg_heartbeat_req_uv {
216 struct xpc_activate_mq_msghdr_uv header; 216 struct xpc_activate_mq_msghdr_uv hdr;
217 u64 heartbeat; 217 u64 heartbeat;
218}; 218};
219 219
220struct xpc_activate_mq_msg_activate_req_uv { 220struct xpc_activate_mq_msg_activate_req_uv {
221 struct xpc_activate_mq_msghdr_uv header; 221 struct xpc_activate_mq_msghdr_uv hdr;
222 unsigned long rp_gpa; 222 unsigned long rp_gpa;
223 unsigned long activate_mq_gpa; 223 unsigned long activate_mq_gpa;
224}; 224};
225 225
226struct xpc_activate_mq_msg_deactivate_req_uv { 226struct xpc_activate_mq_msg_deactivate_req_uv {
227 struct xpc_activate_mq_msghdr_uv header; 227 struct xpc_activate_mq_msghdr_uv hdr;
228 enum xp_retval reason; 228 enum xp_retval reason;
229}; 229};
230 230
231struct xpc_activate_mq_msg_chctl_closerequest_uv { 231struct xpc_activate_mq_msg_chctl_closerequest_uv {
232 struct xpc_activate_mq_msghdr_uv header; 232 struct xpc_activate_mq_msghdr_uv hdr;
233 short ch_number; 233 short ch_number;
234 enum xp_retval reason; 234 enum xp_retval reason;
235}; 235};
236 236
237struct xpc_activate_mq_msg_chctl_closereply_uv { 237struct xpc_activate_mq_msg_chctl_closereply_uv {
238 struct xpc_activate_mq_msghdr_uv header; 238 struct xpc_activate_mq_msghdr_uv hdr;
239 short ch_number; 239 short ch_number;
240}; 240};
241 241
242struct xpc_activate_mq_msg_chctl_openrequest_uv { 242struct xpc_activate_mq_msg_chctl_openrequest_uv {
243 struct xpc_activate_mq_msghdr_uv header; 243 struct xpc_activate_mq_msghdr_uv hdr;
244 short ch_number; 244 short ch_number;
245 short msg_size; /* size of notify_mq's messages */ 245 short entry_size; /* size of notify_mq's GRU messages */
246 short local_nentries; /* ??? Is this needed? What is? */ 246 short local_nentries; /* ??? Is this needed? What is? */
247}; 247};
248 248
249struct xpc_activate_mq_msg_chctl_openreply_uv { 249struct xpc_activate_mq_msg_chctl_openreply_uv {
250 struct xpc_activate_mq_msghdr_uv header; 250 struct xpc_activate_mq_msghdr_uv hdr;
251 short ch_number; 251 short ch_number;
252 short remote_nentries; /* ??? Is this needed? What is? */ 252 short remote_nentries; /* ??? Is this needed? What is? */
253 short local_nentries; /* ??? Is this needed? What is? */ 253 short local_nentries; /* ??? Is this needed? What is? */
@@ -284,7 +284,7 @@ struct xpc_gp_sn2 {
284 */ 284 */
285struct xpc_openclose_args { 285struct xpc_openclose_args {
286 u16 reason; /* reason why channel is closing */ 286 u16 reason; /* reason why channel is closing */
287 u16 msg_size; /* sizeof each message entry */ 287 u16 entry_size; /* sizeof each message entry */
288 u16 remote_nentries; /* #of message entries in remote msg queue */ 288 u16 remote_nentries; /* #of message entries in remote msg queue */
289 u16 local_nentries; /* #of message entries in local msg queue */ 289 u16 local_nentries; /* #of message entries in local msg queue */
290 unsigned long local_msgqueue_pa; /* phys addr of local message queue */ 290 unsigned long local_msgqueue_pa; /* phys addr of local message queue */
@@ -294,22 +294,79 @@ struct xpc_openclose_args {
294 L1_CACHE_ALIGN(sizeof(struct xpc_openclose_args) * \ 294 L1_CACHE_ALIGN(sizeof(struct xpc_openclose_args) * \
295 XPC_MAX_NCHANNELS) 295 XPC_MAX_NCHANNELS)
296 296
297/* struct xpc_msg flags */
298 297
299#define XPC_M_DONE 0x01 /* msg has been received/consumed */ 298/*
300#define XPC_M_READY 0x02 /* msg is ready to be sent */ 299 * Structures to define a fifo singly-linked list.
301#define XPC_M_INTERRUPT 0x04 /* send interrupt when msg consumed */ 300 */
301
302struct xpc_fifo_entry_uv {
303 struct xpc_fifo_entry_uv *next;
304};
305
306struct xpc_fifo_head_uv {
307 struct xpc_fifo_entry_uv *first;
308 struct xpc_fifo_entry_uv *last;
309 spinlock_t lock;
310 int n_entries;
311};
312
313/*
314 * Define a sn2 styled message.
315 *
316 * A user-defined message resides in the payload area. The max size of the
317 * payload is defined by the user via xpc_connect().
318 *
319 * The size of a message entry (within a message queue) must be a 128-byte
320 * cacheline sized multiple in order to facilitate the BTE transfer of messages
321 * from one message queue to another.
322 */
323struct xpc_msg_sn2 {
324 u8 flags; /* FOR XPC INTERNAL USE ONLY */
325 u8 reserved[7]; /* FOR XPC INTERNAL USE ONLY */
326 s64 number; /* FOR XPC INTERNAL USE ONLY */
327
328 u64 payload; /* user defined portion of message */
329};
330
331/* struct xpc_msg_sn2 flags */
332
333#define XPC_M_SN2_DONE 0x01 /* msg has been received/consumed */
334#define XPC_M_SN2_READY 0x02 /* msg is ready to be sent */
335#define XPC_M_SN2_INTERRUPT 0x04 /* send interrupt when msg consumed */
336
337/*
338 * The format of a uv XPC notify_mq GRU message is as follows:
339 *
340 * A user-defined message resides in the payload area. The max size of the
341 * payload is defined by the user via xpc_connect().
342 *
343 * The size of a message (payload and header) sent via the GRU must be either 1
344 * or 2 GRU_CACHE_LINE_BYTES in length.
345 */
302 346
303#define XPC_MSG_ADDRESS(_payload) \ 347struct xpc_notify_mq_msghdr_uv {
304 ((struct xpc_msg *)((u8 *)(_payload) - XPC_MSG_PAYLOAD_OFFSET)) 348 union {
349 unsigned int gru_msg_hdr; /* FOR GRU INTERNAL USE ONLY */
350 struct xpc_fifo_entry_uv next; /* FOR XPC INTERNAL USE ONLY */
351 } u;
352 short partid; /* FOR XPC INTERNAL USE ONLY */
353 u8 ch_number; /* FOR XPC INTERNAL USE ONLY */
354 u8 size; /* FOR XPC INTERNAL USE ONLY */
355 unsigned int msg_slot_number; /* FOR XPC INTERNAL USE ONLY */
356};
357
358struct xpc_notify_mq_msg_uv {
359 struct xpc_notify_mq_msghdr_uv hdr;
360 unsigned long payload;
361};
305 362
306/* 363/*
307 * Defines notify entry. 364 * Define sn2's notify entry.
308 * 365 *
309 * This is used to notify a message's sender that their message was received 366 * This is used to notify a message's sender that their message was received
310 * and consumed by the intended recipient. 367 * and consumed by the intended recipient.
311 */ 368 */
312struct xpc_notify { 369struct xpc_notify_sn2 {
313 u8 type; /* type of notification */ 370 u8 type; /* type of notification */
314 371
315 /* the following two fields are only used if type == XPC_N_CALL */ 372 /* the following two fields are only used if type == XPC_N_CALL */
@@ -317,9 +374,20 @@ struct xpc_notify {
317 void *key; /* pointer to user's key */ 374 void *key; /* pointer to user's key */
318}; 375};
319 376
320/* struct xpc_notify type of notification */ 377/* struct xpc_notify_sn2 type of notification */
321 378
322#define XPC_N_CALL 0x01 /* notify function provided by user */ 379#define XPC_N_CALL 0x01 /* notify function provided by user */
380
381/*
382 * Define uv's version of the notify entry. It additionally is used to allocate
383 * a msg slot on the remote partition into which is copied a sent message.
384 */
385struct xpc_send_msg_slot_uv {
386 struct xpc_fifo_entry_uv next;
387 unsigned int msg_slot_number;
388 xpc_notify_func func; /* user's notify function */
389 void *key; /* pointer to user's key */
390};
323 391
324/* 392/*
325 * Define the structure that manages all the stuff required by a channel. In 393 * Define the structure that manages all the stuff required by a channel. In
@@ -409,14 +477,14 @@ struct xpc_channel_sn2 {
409 /* opening or closing of channel */ 477 /* opening or closing of channel */
410 478
411 void *local_msgqueue_base; /* base address of kmalloc'd space */ 479 void *local_msgqueue_base; /* base address of kmalloc'd space */
412 struct xpc_msg *local_msgqueue; /* local message queue */ 480 struct xpc_msg_sn2 *local_msgqueue; /* local message queue */
413 void *remote_msgqueue_base; /* base address of kmalloc'd space */ 481 void *remote_msgqueue_base; /* base address of kmalloc'd space */
414 struct xpc_msg *remote_msgqueue; /* cached copy of remote partition's */ 482 struct xpc_msg_sn2 *remote_msgqueue; /* cached copy of remote */
415 /* local message queue */ 483 /* partition's local message queue */
416 unsigned long remote_msgqueue_pa; /* phys addr of remote partition's */ 484 unsigned long remote_msgqueue_pa; /* phys addr of remote partition's */
417 /* local message queue */ 485 /* local message queue */
418 486
419 struct xpc_notify *notify_queue; /* notify queue for messages sent */ 487 struct xpc_notify_sn2 *notify_queue;/* notify queue for messages sent */
420 488
421 /* various flavors of local and remote Get/Put values */ 489 /* various flavors of local and remote Get/Put values */
422 490
@@ -432,6 +500,12 @@ struct xpc_channel_sn2 {
432struct xpc_channel_uv { 500struct xpc_channel_uv {
433 unsigned long remote_notify_mq_gpa; /* gru phys address of remote */ 501 unsigned long remote_notify_mq_gpa; /* gru phys address of remote */
434 /* partition's notify mq */ 502 /* partition's notify mq */
503
504 struct xpc_send_msg_slot_uv *send_msg_slots;
505 struct xpc_notify_mq_msg_uv *recv_msg_slots;
506
507 struct xpc_fifo_head_uv msg_slot_free_list;
508 struct xpc_fifo_head_uv recv_msg_list; /* deliverable payloads */
435}; 509};
436 510
437struct xpc_channel { 511struct xpc_channel {
@@ -444,7 +518,7 @@ struct xpc_channel {
444 518
445 u16 number; /* channel # */ 519 u16 number; /* channel # */
446 520
447 u16 msg_size; /* sizeof each msg entry */ 521 u16 entry_size; /* sizeof each msg entry */
448 u16 local_nentries; /* #of msg entries in local msg queue */ 522 u16 local_nentries; /* #of msg entries in local msg queue */
449 u16 remote_nentries; /* #of msg entries in remote msg queue */ 523 u16 remote_nentries; /* #of msg entries in remote msg queue */
450 524
@@ -733,8 +807,8 @@ extern enum xp_retval (*xpc_setup_msg_structures) (struct xpc_channel *);
733extern void (*xpc_teardown_msg_structures) (struct xpc_channel *); 807extern void (*xpc_teardown_msg_structures) (struct xpc_channel *);
734extern void (*xpc_notify_senders_of_disconnect) (struct xpc_channel *); 808extern void (*xpc_notify_senders_of_disconnect) (struct xpc_channel *);
735extern void (*xpc_process_msg_chctl_flags) (struct xpc_partition *, int); 809extern void (*xpc_process_msg_chctl_flags) (struct xpc_partition *, int);
736extern int (*xpc_n_of_deliverable_msgs) (struct xpc_channel *); 810extern int (*xpc_n_of_deliverable_payloads) (struct xpc_channel *);
737extern struct xpc_msg *(*xpc_get_deliverable_msg) (struct xpc_channel *); 811extern void *(*xpc_get_deliverable_payload) (struct xpc_channel *);
738extern void (*xpc_request_partition_activation) (struct xpc_rsvd_page *, 812extern void (*xpc_request_partition_activation) (struct xpc_rsvd_page *,
739 unsigned long, int); 813 unsigned long, int);
740extern void (*xpc_request_partition_reactivation) (struct xpc_partition *); 814extern void (*xpc_request_partition_reactivation) (struct xpc_partition *);
@@ -762,9 +836,9 @@ extern void (*xpc_send_chctl_openreply) (struct xpc_channel *, unsigned long *);
762extern void (*xpc_save_remote_msgqueue_pa) (struct xpc_channel *, 836extern void (*xpc_save_remote_msgqueue_pa) (struct xpc_channel *,
763 unsigned long); 837 unsigned long);
764 838
765extern enum xp_retval (*xpc_send_msg) (struct xpc_channel *, u32, void *, u16, 839extern enum xp_retval (*xpc_send_payload) (struct xpc_channel *, u32, void *,
766 u8, xpc_notify_func, void *); 840 u16, u8, xpc_notify_func, void *);
767extern void (*xpc_received_msg) (struct xpc_channel *, struct xpc_msg *); 841extern void (*xpc_received_payload) (struct xpc_channel *, void *);
768 842
769/* found in xpc_sn2.c */ 843/* found in xpc_sn2.c */
770extern int xpc_init_sn2(void); 844extern int xpc_init_sn2(void);
@@ -805,7 +879,7 @@ extern enum xp_retval xpc_initiate_send_notify(short, int, u32, void *, u16,
805extern void xpc_initiate_received(short, int, void *); 879extern void xpc_initiate_received(short, int, void *);
806extern void xpc_process_sent_chctl_flags(struct xpc_partition *); 880extern void xpc_process_sent_chctl_flags(struct xpc_partition *);
807extern void xpc_connected_callout(struct xpc_channel *); 881extern void xpc_connected_callout(struct xpc_channel *);
808extern void xpc_deliver_msg(struct xpc_channel *); 882extern void xpc_deliver_payload(struct xpc_channel *);
809extern void xpc_disconnect_channel(const int, struct xpc_channel *, 883extern void xpc_disconnect_channel(const int, struct xpc_channel *,
810 enum xp_retval, unsigned long *); 884 enum xp_retval, unsigned long *);
811extern void xpc_disconnect_callout(struct xpc_channel *, enum xp_retval); 885extern void xpc_disconnect_callout(struct xpc_channel *, enum xp_retval);
diff --git a/drivers/misc/sgi-xp/xpc_channel.c b/drivers/misc/sgi-xp/xpc_channel.c
index 73df9fb5ee66..9cd2ebe2a3b6 100644
--- a/drivers/misc/sgi-xp/xpc_channel.c
+++ b/drivers/misc/sgi-xp/xpc_channel.c
@@ -139,7 +139,7 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
139 139
140 ch->func = NULL; 140 ch->func = NULL;
141 ch->key = NULL; 141 ch->key = NULL;
142 ch->msg_size = 0; 142 ch->entry_size = 0;
143 ch->local_nentries = 0; 143 ch->local_nentries = 0;
144 ch->remote_nentries = 0; 144 ch->remote_nentries = 0;
145 ch->kthreads_assigned_limit = 0; 145 ch->kthreads_assigned_limit = 0;
@@ -315,9 +315,9 @@ again:
315 315
316 if (chctl_flags & XPC_CHCTL_OPENREQUEST) { 316 if (chctl_flags & XPC_CHCTL_OPENREQUEST) {
317 317
318 dev_dbg(xpc_chan, "XPC_CHCTL_OPENREQUEST (msg_size=%d, " 318 dev_dbg(xpc_chan, "XPC_CHCTL_OPENREQUEST (entry_size=%d, "
319 "local_nentries=%d) received from partid=%d, " 319 "local_nentries=%d) received from partid=%d, "
320 "channel=%d\n", args->msg_size, args->local_nentries, 320 "channel=%d\n", args->entry_size, args->local_nentries,
321 ch->partid, ch->number); 321 ch->partid, ch->number);
322 322
323 if (part->act_state == XPC_P_AS_DEACTIVATING || 323 if (part->act_state == XPC_P_AS_DEACTIVATING ||
@@ -338,10 +338,10 @@ again:
338 338
339 /* 339 /*
340 * The meaningful OPENREQUEST connection state fields are: 340 * The meaningful OPENREQUEST connection state fields are:
341 * msg_size = size of channel's messages in bytes 341 * entry_size = size of channel's messages in bytes
342 * local_nentries = remote partition's local_nentries 342 * local_nentries = remote partition's local_nentries
343 */ 343 */
344 if (args->msg_size == 0 || args->local_nentries == 0) { 344 if (args->entry_size == 0 || args->local_nentries == 0) {
345 /* assume OPENREQUEST was delayed by mistake */ 345 /* assume OPENREQUEST was delayed by mistake */
346 spin_unlock_irqrestore(&ch->lock, irq_flags); 346 spin_unlock_irqrestore(&ch->lock, irq_flags);
347 return; 347 return;
@@ -351,14 +351,14 @@ again:
351 ch->remote_nentries = args->local_nentries; 351 ch->remote_nentries = args->local_nentries;
352 352
353 if (ch->flags & XPC_C_OPENREQUEST) { 353 if (ch->flags & XPC_C_OPENREQUEST) {
354 if (args->msg_size != ch->msg_size) { 354 if (args->entry_size != ch->entry_size) {
355 XPC_DISCONNECT_CHANNEL(ch, xpUnequalMsgSizes, 355 XPC_DISCONNECT_CHANNEL(ch, xpUnequalMsgSizes,
356 &irq_flags); 356 &irq_flags);
357 spin_unlock_irqrestore(&ch->lock, irq_flags); 357 spin_unlock_irqrestore(&ch->lock, irq_flags);
358 return; 358 return;
359 } 359 }
360 } else { 360 } else {
361 ch->msg_size = args->msg_size; 361 ch->entry_size = args->entry_size;
362 362
363 XPC_SET_REASON(ch, 0, 0); 363 XPC_SET_REASON(ch, 0, 0);
364 ch->flags &= ~XPC_C_DISCONNECTED; 364 ch->flags &= ~XPC_C_DISCONNECTED;
@@ -473,7 +473,7 @@ xpc_connect_channel(struct xpc_channel *ch)
473 ch->local_nentries = registration->nentries; 473 ch->local_nentries = registration->nentries;
474 474
475 if (ch->flags & XPC_C_ROPENREQUEST) { 475 if (ch->flags & XPC_C_ROPENREQUEST) {
476 if (registration->msg_size != ch->msg_size) { 476 if (registration->entry_size != ch->entry_size) {
477 /* the local and remote sides aren't the same */ 477 /* the local and remote sides aren't the same */
478 478
479 /* 479 /*
@@ -492,7 +492,7 @@ xpc_connect_channel(struct xpc_channel *ch)
492 return xpUnequalMsgSizes; 492 return xpUnequalMsgSizes;
493 } 493 }
494 } else { 494 } else {
495 ch->msg_size = registration->msg_size; 495 ch->entry_size = registration->entry_size;
496 496
497 XPC_SET_REASON(ch, 0, 0); 497 XPC_SET_REASON(ch, 0, 0);
498 ch->flags &= ~XPC_C_DISCONNECTED; 498 ch->flags &= ~XPC_C_DISCONNECTED;
@@ -859,8 +859,8 @@ xpc_initiate_send(short partid, int ch_number, u32 flags, void *payload,
859 DBUG_ON(payload == NULL); 859 DBUG_ON(payload == NULL);
860 860
861 if (xpc_part_ref(part)) { 861 if (xpc_part_ref(part)) {
862 ret = xpc_send_msg(&part->channels[ch_number], flags, payload, 862 ret = xpc_send_payload(&part->channels[ch_number], flags,
863 payload_size, 0, NULL, NULL); 863 payload, payload_size, 0, NULL, NULL);
864 xpc_part_deref(part); 864 xpc_part_deref(part);
865 } 865 }
866 866
@@ -911,23 +911,24 @@ xpc_initiate_send_notify(short partid, int ch_number, u32 flags, void *payload,
911 DBUG_ON(func == NULL); 911 DBUG_ON(func == NULL);
912 912
913 if (xpc_part_ref(part)) { 913 if (xpc_part_ref(part)) {
914 ret = xpc_send_msg(&part->channels[ch_number], flags, payload, 914 ret = xpc_send_payload(&part->channels[ch_number], flags,
915 payload_size, XPC_N_CALL, func, key); 915 payload, payload_size, XPC_N_CALL, func,
916 key);
916 xpc_part_deref(part); 917 xpc_part_deref(part);
917 } 918 }
918 return ret; 919 return ret;
919} 920}
920 921
921/* 922/*
922 * Deliver a message to its intended recipient. 923 * Deliver a message's payload to its intended recipient.
923 */ 924 */
924void 925void
925xpc_deliver_msg(struct xpc_channel *ch) 926xpc_deliver_payload(struct xpc_channel *ch)
926{ 927{
927 struct xpc_msg *msg; 928 void *payload;
928 929
929 msg = xpc_get_deliverable_msg(ch); 930 payload = xpc_get_deliverable_payload(ch);
930 if (msg != NULL) { 931 if (payload != NULL) {
931 932
932 /* 933 /*
933 * This ref is taken to protect the payload itself from being 934 * This ref is taken to protect the payload itself from being
@@ -939,18 +940,16 @@ xpc_deliver_msg(struct xpc_channel *ch)
939 atomic_inc(&ch->kthreads_active); 940 atomic_inc(&ch->kthreads_active);
940 941
941 if (ch->func != NULL) { 942 if (ch->func != NULL) {
942 dev_dbg(xpc_chan, "ch->func() called, msg=0x%p, " 943 dev_dbg(xpc_chan, "ch->func() called, payload=0x%p "
943 "msg_number=%ld, partid=%d, channel=%d\n", 944 "partid=%d channel=%d\n", payload, ch->partid,
944 msg, (signed long)msg->number, ch->partid,
945 ch->number); 945 ch->number);
946 946
947 /* deliver the message to its intended recipient */ 947 /* deliver the message to its intended recipient */
948 ch->func(xpMsgReceived, ch->partid, ch->number, 948 ch->func(xpMsgReceived, ch->partid, ch->number, payload,
949 &msg->payload, ch->key); 949 ch->key);
950 950
951 dev_dbg(xpc_chan, "ch->func() returned, msg=0x%p, " 951 dev_dbg(xpc_chan, "ch->func() returned, payload=0x%p "
952 "msg_number=%ld, partid=%d, channel=%d\n", 952 "partid=%d channel=%d\n", payload, ch->partid,
953 msg, (signed long)msg->number, ch->partid,
954 ch->number); 953 ch->number);
955 } 954 }
956 955
@@ -959,14 +958,11 @@ xpc_deliver_msg(struct xpc_channel *ch)
959} 958}
960 959
961/* 960/*
962 * Acknowledge receipt of a delivered message. 961 * Acknowledge receipt of a delivered message's payload.
963 *
964 * If a message has XPC_M_INTERRUPT set, send an interrupt to the partition
965 * that sent the message.
966 * 962 *
967 * This function, although called by users, does not call xpc_part_ref() to 963 * This function, although called by users, does not call xpc_part_ref() to
968 * ensure that the partition infrastructure is in place. It relies on the 964 * ensure that the partition infrastructure is in place. It relies on the
969 * fact that we called xpc_msgqueue_ref() in xpc_deliver_msg(). 965 * fact that we called xpc_msgqueue_ref() in xpc_deliver_payload().
970 * 966 *
971 * Arguments: 967 * Arguments:
972 * 968 *
@@ -980,14 +976,13 @@ xpc_initiate_received(short partid, int ch_number, void *payload)
980{ 976{
981 struct xpc_partition *part = &xpc_partitions[partid]; 977 struct xpc_partition *part = &xpc_partitions[partid];
982 struct xpc_channel *ch; 978 struct xpc_channel *ch;
983 struct xpc_msg *msg = XPC_MSG_ADDRESS(payload);
984 979
985 DBUG_ON(partid < 0 || partid >= xp_max_npartitions); 980 DBUG_ON(partid < 0 || partid >= xp_max_npartitions);
986 DBUG_ON(ch_number < 0 || ch_number >= part->nchannels); 981 DBUG_ON(ch_number < 0 || ch_number >= part->nchannels);
987 982
988 ch = &part->channels[ch_number]; 983 ch = &part->channels[ch_number];
989 xpc_received_msg(ch, msg); 984 xpc_received_payload(ch, payload);
990 985
991 /* the call to xpc_msgqueue_ref() was done by xpc_deliver_msg() */ 986 /* the call to xpc_msgqueue_ref() was done by xpc_deliver_payload() */
992 xpc_msgqueue_deref(ch); 987 xpc_msgqueue_deref(ch);
993} 988}
diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c
index 13ec47928994..46325fc84811 100644
--- a/drivers/misc/sgi-xp/xpc_main.c
+++ b/drivers/misc/sgi-xp/xpc_main.c
@@ -188,8 +188,8 @@ u64 (*xpc_get_chctl_all_flags) (struct xpc_partition *part);
188enum xp_retval (*xpc_setup_msg_structures) (struct xpc_channel *ch); 188enum xp_retval (*xpc_setup_msg_structures) (struct xpc_channel *ch);
189void (*xpc_teardown_msg_structures) (struct xpc_channel *ch); 189void (*xpc_teardown_msg_structures) (struct xpc_channel *ch);
190void (*xpc_process_msg_chctl_flags) (struct xpc_partition *part, int ch_number); 190void (*xpc_process_msg_chctl_flags) (struct xpc_partition *part, int ch_number);
191int (*xpc_n_of_deliverable_msgs) (struct xpc_channel *ch); 191int (*xpc_n_of_deliverable_payloads) (struct xpc_channel *ch);
192struct xpc_msg *(*xpc_get_deliverable_msg) (struct xpc_channel *ch); 192void *(*xpc_get_deliverable_payload) (struct xpc_channel *ch);
193 193
194void (*xpc_request_partition_activation) (struct xpc_rsvd_page *remote_rp, 194void (*xpc_request_partition_activation) (struct xpc_rsvd_page *remote_rp,
195 unsigned long remote_rp_pa, 195 unsigned long remote_rp_pa,
@@ -220,10 +220,11 @@ void (*xpc_send_chctl_openreply) (struct xpc_channel *ch,
220void (*xpc_save_remote_msgqueue_pa) (struct xpc_channel *ch, 220void (*xpc_save_remote_msgqueue_pa) (struct xpc_channel *ch,
221 unsigned long msgqueue_pa); 221 unsigned long msgqueue_pa);
222 222
223enum xp_retval (*xpc_send_msg) (struct xpc_channel *ch, u32 flags, 223enum xp_retval (*xpc_send_payload) (struct xpc_channel *ch, u32 flags,
224 void *payload, u16 payload_size, u8 notify_type, 224 void *payload, u16 payload_size,
225 xpc_notify_func func, void *key); 225 u8 notify_type, xpc_notify_func func,
226void (*xpc_received_msg) (struct xpc_channel *ch, struct xpc_msg *msg); 226 void *key);
227void (*xpc_received_payload) (struct xpc_channel *ch, void *payload);
227 228
228/* 229/*
229 * Timer function to enforce the timelimit on the partition disengage. 230 * Timer function to enforce the timelimit on the partition disengage.
@@ -714,9 +715,9 @@ xpc_kthread_waitmsgs(struct xpc_partition *part, struct xpc_channel *ch)
714 do { 715 do {
715 /* deliver messages to their intended recipients */ 716 /* deliver messages to their intended recipients */
716 717
717 while (xpc_n_of_deliverable_msgs(ch) > 0 && 718 while (xpc_n_of_deliverable_payloads(ch) > 0 &&
718 !(ch->flags & XPC_C_DISCONNECTING)) { 719 !(ch->flags & XPC_C_DISCONNECTING)) {
719 xpc_deliver_msg(ch); 720 xpc_deliver_payload(ch);
720 } 721 }
721 722
722 if (atomic_inc_return(&ch->kthreads_idle) > 723 if (atomic_inc_return(&ch->kthreads_idle) >
@@ -730,7 +731,7 @@ xpc_kthread_waitmsgs(struct xpc_partition *part, struct xpc_channel *ch)
730 "wait_event_interruptible_exclusive()\n"); 731 "wait_event_interruptible_exclusive()\n");
731 732
732 (void)wait_event_interruptible_exclusive(ch->idle_wq, 733 (void)wait_event_interruptible_exclusive(ch->idle_wq,
733 (xpc_n_of_deliverable_msgs(ch) > 0 || 734 (xpc_n_of_deliverable_payloads(ch) > 0 ||
734 (ch->flags & XPC_C_DISCONNECTING))); 735 (ch->flags & XPC_C_DISCONNECTING)));
735 736
736 atomic_dec(&ch->kthreads_idle); 737 atomic_dec(&ch->kthreads_idle);
@@ -775,7 +776,7 @@ xpc_kthread_start(void *args)
775 * additional kthreads to help deliver them. We only 776 * additional kthreads to help deliver them. We only
776 * need one less than total #of messages to deliver. 777 * need one less than total #of messages to deliver.
777 */ 778 */
778 n_needed = xpc_n_of_deliverable_msgs(ch) - 1; 779 n_needed = xpc_n_of_deliverable_payloads(ch) - 1;
779 if (n_needed > 0 && !(ch->flags & XPC_C_DISCONNECTING)) 780 if (n_needed > 0 && !(ch->flags & XPC_C_DISCONNECTING))
780 xpc_activate_kthreads(ch, n_needed); 781 xpc_activate_kthreads(ch, n_needed);
781 782
diff --git a/drivers/misc/sgi-xp/xpc_sn2.c b/drivers/misc/sgi-xp/xpc_sn2.c
index 8b4b0653d9e9..b4882ccf6344 100644
--- a/drivers/misc/sgi-xp/xpc_sn2.c
+++ b/drivers/misc/sgi-xp/xpc_sn2.c
@@ -408,7 +408,7 @@ xpc_send_chctl_openrequest_sn2(struct xpc_channel *ch, unsigned long *irq_flags)
408{ 408{
409 struct xpc_openclose_args *args = ch->sn.sn2.local_openclose_args; 409 struct xpc_openclose_args *args = ch->sn.sn2.local_openclose_args;
410 410
411 args->msg_size = ch->msg_size; 411 args->entry_size = ch->entry_size;
412 args->local_nentries = ch->local_nentries; 412 args->local_nentries = ch->local_nentries;
413 XPC_SEND_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_OPENREQUEST, irq_flags); 413 XPC_SEND_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_OPENREQUEST, irq_flags);
414} 414}
@@ -1531,14 +1531,14 @@ xpc_allocate_local_msgqueue_sn2(struct xpc_channel *ch)
1531 1531
1532 for (nentries = ch->local_nentries; nentries > 0; nentries--) { 1532 for (nentries = ch->local_nentries; nentries > 0; nentries--) {
1533 1533
1534 nbytes = nentries * ch->msg_size; 1534 nbytes = nentries * ch->entry_size;
1535 ch_sn2->local_msgqueue = 1535 ch_sn2->local_msgqueue =
1536 xpc_kzalloc_cacheline_aligned(nbytes, GFP_KERNEL, 1536 xpc_kzalloc_cacheline_aligned(nbytes, GFP_KERNEL,
1537 &ch_sn2->local_msgqueue_base); 1537 &ch_sn2->local_msgqueue_base);
1538 if (ch_sn2->local_msgqueue == NULL) 1538 if (ch_sn2->local_msgqueue == NULL)
1539 continue; 1539 continue;
1540 1540
1541 nbytes = nentries * sizeof(struct xpc_notify); 1541 nbytes = nentries * sizeof(struct xpc_notify_sn2);
1542 ch_sn2->notify_queue = kzalloc(nbytes, GFP_KERNEL); 1542 ch_sn2->notify_queue = kzalloc(nbytes, GFP_KERNEL);
1543 if (ch_sn2->notify_queue == NULL) { 1543 if (ch_sn2->notify_queue == NULL) {
1544 kfree(ch_sn2->local_msgqueue_base); 1544 kfree(ch_sn2->local_msgqueue_base);
@@ -1578,7 +1578,7 @@ xpc_allocate_remote_msgqueue_sn2(struct xpc_channel *ch)
1578 1578
1579 for (nentries = ch->remote_nentries; nentries > 0; nentries--) { 1579 for (nentries = ch->remote_nentries; nentries > 0; nentries--) {
1580 1580
1581 nbytes = nentries * ch->msg_size; 1581 nbytes = nentries * ch->entry_size;
1582 ch_sn2->remote_msgqueue = 1582 ch_sn2->remote_msgqueue =
1583 xpc_kzalloc_cacheline_aligned(nbytes, GFP_KERNEL, &ch_sn2-> 1583 xpc_kzalloc_cacheline_aligned(nbytes, GFP_KERNEL, &ch_sn2->
1584 remote_msgqueue_base); 1584 remote_msgqueue_base);
@@ -1632,9 +1632,6 @@ xpc_setup_msg_structures_sn2(struct xpc_channel *ch)
1632/* 1632/*
1633 * Free up message queues and other stuff that were allocated for the specified 1633 * Free up message queues and other stuff that were allocated for the specified
1634 * channel. 1634 * channel.
1635 *
1636 * Note: ch->reason and ch->reason_line are left set for debugging purposes,
1637 * they're cleared when XPC_C_DISCONNECTED is cleared.
1638 */ 1635 */
1639static void 1636static void
1640xpc_teardown_msg_structures_sn2(struct xpc_channel *ch) 1637xpc_teardown_msg_structures_sn2(struct xpc_channel *ch)
@@ -1674,7 +1671,7 @@ xpc_teardown_msg_structures_sn2(struct xpc_channel *ch)
1674static void 1671static void
1675xpc_notify_senders_sn2(struct xpc_channel *ch, enum xp_retval reason, s64 put) 1672xpc_notify_senders_sn2(struct xpc_channel *ch, enum xp_retval reason, s64 put)
1676{ 1673{
1677 struct xpc_notify *notify; 1674 struct xpc_notify_sn2 *notify;
1678 u8 notify_type; 1675 u8 notify_type;
1679 s64 get = ch->sn.sn2.w_remote_GP.get - 1; 1676 s64 get = ch->sn.sn2.w_remote_GP.get - 1;
1680 1677
@@ -1699,17 +1696,16 @@ xpc_notify_senders_sn2(struct xpc_channel *ch, enum xp_retval reason, s64 put)
1699 atomic_dec(&ch->n_to_notify); 1696 atomic_dec(&ch->n_to_notify);
1700 1697
1701 if (notify->func != NULL) { 1698 if (notify->func != NULL) {
1702 dev_dbg(xpc_chan, "notify->func() called, notify=0x%p, " 1699 dev_dbg(xpc_chan, "notify->func() called, notify=0x%p "
1703 "msg_number=%ld, partid=%d, channel=%d\n", 1700 "msg_number=%ld partid=%d channel=%d\n",
1704 (void *)notify, get, ch->partid, ch->number); 1701 (void *)notify, get, ch->partid, ch->number);
1705 1702
1706 notify->func(reason, ch->partid, ch->number, 1703 notify->func(reason, ch->partid, ch->number,
1707 notify->key); 1704 notify->key);
1708 1705
1709 dev_dbg(xpc_chan, "notify->func() returned, " 1706 dev_dbg(xpc_chan, "notify->func() returned, notify=0x%p"
1710 "notify=0x%p, msg_number=%ld, partid=%d, " 1707 " msg_number=%ld partid=%d channel=%d\n",
1711 "channel=%d\n", (void *)notify, get, 1708 (void *)notify, get, ch->partid, ch->number);
1712 ch->partid, ch->number);
1713 } 1709 }
1714 } 1710 }
1715} 1711}
@@ -1727,14 +1723,14 @@ static inline void
1727xpc_clear_local_msgqueue_flags_sn2(struct xpc_channel *ch) 1723xpc_clear_local_msgqueue_flags_sn2(struct xpc_channel *ch)
1728{ 1724{
1729 struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2; 1725 struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
1730 struct xpc_msg *msg; 1726 struct xpc_msg_sn2 *msg;
1731 s64 get; 1727 s64 get;
1732 1728
1733 get = ch_sn2->w_remote_GP.get; 1729 get = ch_sn2->w_remote_GP.get;
1734 do { 1730 do {
1735 msg = (struct xpc_msg *)((u64)ch_sn2->local_msgqueue + 1731 msg = (struct xpc_msg_sn2 *)((u64)ch_sn2->local_msgqueue +
1736 (get % ch->local_nentries) * 1732 (get % ch->local_nentries) *
1737 ch->msg_size); 1733 ch->entry_size);
1738 msg->flags = 0; 1734 msg->flags = 0;
1739 } while (++get < ch_sn2->remote_GP.get); 1735 } while (++get < ch_sn2->remote_GP.get);
1740} 1736}
@@ -1746,24 +1742,30 @@ static inline void
1746xpc_clear_remote_msgqueue_flags_sn2(struct xpc_channel *ch) 1742xpc_clear_remote_msgqueue_flags_sn2(struct xpc_channel *ch)
1747{ 1743{
1748 struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2; 1744 struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
1749 struct xpc_msg *msg; 1745 struct xpc_msg_sn2 *msg;
1750 s64 put; 1746 s64 put;
1751 1747
1752 put = ch_sn2->w_remote_GP.put; 1748 put = ch_sn2->w_remote_GP.put;
1753 do { 1749 do {
1754 msg = (struct xpc_msg *)((u64)ch_sn2->remote_msgqueue + 1750 msg = (struct xpc_msg_sn2 *)((u64)ch_sn2->remote_msgqueue +
1755 (put % ch->remote_nentries) * 1751 (put % ch->remote_nentries) *
1756 ch->msg_size); 1752 ch->entry_size);
1757 msg->flags = 0; 1753 msg->flags = 0;
1758 } while (++put < ch_sn2->remote_GP.put); 1754 } while (++put < ch_sn2->remote_GP.put);
1759} 1755}
1760 1756
1757static int
1758xpc_n_of_deliverable_payloads_sn2(struct xpc_channel *ch)
1759{
1760 return ch->sn.sn2.w_remote_GP.put - ch->sn.sn2.w_local_GP.get;
1761}
1762
1761static void 1763static void
1762xpc_process_msg_chctl_flags_sn2(struct xpc_partition *part, int ch_number) 1764xpc_process_msg_chctl_flags_sn2(struct xpc_partition *part, int ch_number)
1763{ 1765{
1764 struct xpc_channel *ch = &part->channels[ch_number]; 1766 struct xpc_channel *ch = &part->channels[ch_number];
1765 struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2; 1767 struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
1766 int nmsgs_sent; 1768 int npayloads_sent;
1767 1769
1768 ch_sn2->remote_GP = part->sn.sn2.remote_GPs[ch_number]; 1770 ch_sn2->remote_GP = part->sn.sn2.remote_GPs[ch_number];
1769 1771
@@ -1835,7 +1837,7 @@ xpc_process_msg_chctl_flags_sn2(struct xpc_partition *part, int ch_number)
1835 if (ch_sn2->w_remote_GP.put != ch_sn2->remote_GP.put) { 1837 if (ch_sn2->w_remote_GP.put != ch_sn2->remote_GP.put) {
1836 /* 1838 /*
1837 * Clear msg->flags in previously received messages, so that 1839 * Clear msg->flags in previously received messages, so that
1838 * they're ready for xpc_get_deliverable_msg(). 1840 * they're ready for xpc_get_deliverable_payload_sn2().
1839 */ 1841 */
1840 xpc_clear_remote_msgqueue_flags_sn2(ch); 1842 xpc_clear_remote_msgqueue_flags_sn2(ch);
1841 1843
@@ -1845,27 +1847,27 @@ xpc_process_msg_chctl_flags_sn2(struct xpc_partition *part, int ch_number)
1845 "channel=%d\n", ch_sn2->w_remote_GP.put, ch->partid, 1847 "channel=%d\n", ch_sn2->w_remote_GP.put, ch->partid,
1846 ch->number); 1848 ch->number);
1847 1849
1848 nmsgs_sent = ch_sn2->w_remote_GP.put - ch_sn2->w_local_GP.get; 1850 npayloads_sent = xpc_n_of_deliverable_payloads_sn2(ch);
1849 if (nmsgs_sent > 0) { 1851 if (npayloads_sent > 0) {
1850 dev_dbg(xpc_chan, "msgs waiting to be copied and " 1852 dev_dbg(xpc_chan, "msgs waiting to be copied and "
1851 "delivered=%d, partid=%d, channel=%d\n", 1853 "delivered=%d, partid=%d, channel=%d\n",
1852 nmsgs_sent, ch->partid, ch->number); 1854 npayloads_sent, ch->partid, ch->number);
1853 1855
1854 if (ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) 1856 if (ch->flags & XPC_C_CONNECTEDCALLOUT_MADE)
1855 xpc_activate_kthreads(ch, nmsgs_sent); 1857 xpc_activate_kthreads(ch, npayloads_sent);
1856 } 1858 }
1857 } 1859 }
1858 1860
1859 xpc_msgqueue_deref(ch); 1861 xpc_msgqueue_deref(ch);
1860} 1862}
1861 1863
1862static struct xpc_msg * 1864static struct xpc_msg_sn2 *
1863xpc_pull_remote_msg_sn2(struct xpc_channel *ch, s64 get) 1865xpc_pull_remote_msg_sn2(struct xpc_channel *ch, s64 get)
1864{ 1866{
1865 struct xpc_partition *part = &xpc_partitions[ch->partid]; 1867 struct xpc_partition *part = &xpc_partitions[ch->partid];
1866 struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2; 1868 struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
1867 unsigned long remote_msg_pa; 1869 unsigned long remote_msg_pa;
1868 struct xpc_msg *msg; 1870 struct xpc_msg_sn2 *msg;
1869 u32 msg_index; 1871 u32 msg_index;
1870 u32 nmsgs; 1872 u32 nmsgs;
1871 u64 msg_offset; 1873 u64 msg_offset;
@@ -1889,13 +1891,13 @@ xpc_pull_remote_msg_sn2(struct xpc_channel *ch, s64 get)
1889 nmsgs = ch->remote_nentries - msg_index; 1891 nmsgs = ch->remote_nentries - msg_index;
1890 } 1892 }
1891 1893
1892 msg_offset = msg_index * ch->msg_size; 1894 msg_offset = msg_index * ch->entry_size;
1893 msg = (struct xpc_msg *)((u64)ch_sn2->remote_msgqueue + 1895 msg = (struct xpc_msg_sn2 *)((u64)ch_sn2->remote_msgqueue +
1894 msg_offset); 1896 msg_offset);
1895 remote_msg_pa = ch_sn2->remote_msgqueue_pa + msg_offset; 1897 remote_msg_pa = ch_sn2->remote_msgqueue_pa + msg_offset;
1896 1898
1897 ret = xpc_pull_remote_cachelines_sn2(part, msg, remote_msg_pa, 1899 ret = xpc_pull_remote_cachelines_sn2(part, msg, remote_msg_pa,
1898 nmsgs * ch->msg_size); 1900 nmsgs * ch->entry_size);
1899 if (ret != xpSuccess) { 1901 if (ret != xpSuccess) {
1900 1902
1901 dev_dbg(xpc_chan, "failed to pull %d msgs starting with" 1903 dev_dbg(xpc_chan, "failed to pull %d msgs starting with"
@@ -1915,26 +1917,21 @@ xpc_pull_remote_msg_sn2(struct xpc_channel *ch, s64 get)
1915 mutex_unlock(&ch_sn2->msg_to_pull_mutex); 1917 mutex_unlock(&ch_sn2->msg_to_pull_mutex);
1916 1918
1917 /* return the message we were looking for */ 1919 /* return the message we were looking for */
1918 msg_offset = (get % ch->remote_nentries) * ch->msg_size; 1920 msg_offset = (get % ch->remote_nentries) * ch->entry_size;
1919 msg = (struct xpc_msg *)((u64)ch_sn2->remote_msgqueue + msg_offset); 1921 msg = (struct xpc_msg_sn2 *)((u64)ch_sn2->remote_msgqueue + msg_offset);
1920 1922
1921 return msg; 1923 return msg;
1922} 1924}
1923 1925
1924static int
1925xpc_n_of_deliverable_msgs_sn2(struct xpc_channel *ch)
1926{
1927 return ch->sn.sn2.w_remote_GP.put - ch->sn.sn2.w_local_GP.get;
1928}
1929
1930/* 1926/*
1931 * Get a message to be delivered. 1927 * Get the next deliverable message's payload.
1932 */ 1928 */
1933static struct xpc_msg * 1929static void *
1934xpc_get_deliverable_msg_sn2(struct xpc_channel *ch) 1930xpc_get_deliverable_payload_sn2(struct xpc_channel *ch)
1935{ 1931{
1936 struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2; 1932 struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
1937 struct xpc_msg *msg = NULL; 1933 struct xpc_msg_sn2 *msg;
1934 void *payload = NULL;
1938 s64 get; 1935 s64 get;
1939 1936
1940 do { 1937 do {
@@ -1965,15 +1962,16 @@ xpc_get_deliverable_msg_sn2(struct xpc_channel *ch)
1965 msg = xpc_pull_remote_msg_sn2(ch, get); 1962 msg = xpc_pull_remote_msg_sn2(ch, get);
1966 1963
1967 DBUG_ON(msg != NULL && msg->number != get); 1964 DBUG_ON(msg != NULL && msg->number != get);
1968 DBUG_ON(msg != NULL && (msg->flags & XPC_M_DONE)); 1965 DBUG_ON(msg != NULL && (msg->flags & XPC_M_SN2_DONE));
1969 DBUG_ON(msg != NULL && !(msg->flags & XPC_M_READY)); 1966 DBUG_ON(msg != NULL && !(msg->flags & XPC_M_SN2_READY));
1970 1967
1968 payload = &msg->payload;
1971 break; 1969 break;
1972 } 1970 }
1973 1971
1974 } while (1); 1972 } while (1);
1975 1973
1976 return msg; 1974 return payload;
1977} 1975}
1978 1976
1979/* 1977/*
@@ -1985,7 +1983,7 @@ static void
1985xpc_send_msgs_sn2(struct xpc_channel *ch, s64 initial_put) 1983xpc_send_msgs_sn2(struct xpc_channel *ch, s64 initial_put)
1986{ 1984{
1987 struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2; 1985 struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
1988 struct xpc_msg *msg; 1986 struct xpc_msg_sn2 *msg;
1989 s64 put = initial_put + 1; 1987 s64 put = initial_put + 1;
1990 int send_msgrequest = 0; 1988 int send_msgrequest = 0;
1991 1989
@@ -1995,11 +1993,12 @@ xpc_send_msgs_sn2(struct xpc_channel *ch, s64 initial_put)
1995 if (put == ch_sn2->w_local_GP.put) 1993 if (put == ch_sn2->w_local_GP.put)
1996 break; 1994 break;
1997 1995
1998 msg = (struct xpc_msg *)((u64)ch_sn2->local_msgqueue + 1996 msg = (struct xpc_msg_sn2 *)((u64)ch_sn2->
1999 (put % ch->local_nentries) * 1997 local_msgqueue + (put %
2000 ch->msg_size); 1998 ch->local_nentries) *
1999 ch->entry_size);
2001 2000
2002 if (!(msg->flags & XPC_M_READY)) 2001 if (!(msg->flags & XPC_M_SN2_READY))
2003 break; 2002 break;
2004 2003
2005 put++; 2004 put++;
@@ -2026,7 +2025,7 @@ xpc_send_msgs_sn2(struct xpc_channel *ch, s64 initial_put)
2026 2025
2027 /* 2026 /*
2028 * We need to ensure that the message referenced by 2027 * We need to ensure that the message referenced by
2029 * local_GP->put is not XPC_M_READY or that local_GP->put 2028 * local_GP->put is not XPC_M_SN2_READY or that local_GP->put
2030 * equals w_local_GP.put, so we'll go have a look. 2029 * equals w_local_GP.put, so we'll go have a look.
2031 */ 2030 */
2032 initial_put = put; 2031 initial_put = put;
@@ -2042,10 +2041,10 @@ xpc_send_msgs_sn2(struct xpc_channel *ch, s64 initial_put)
2042 */ 2041 */
2043static enum xp_retval 2042static enum xp_retval
2044xpc_allocate_msg_sn2(struct xpc_channel *ch, u32 flags, 2043xpc_allocate_msg_sn2(struct xpc_channel *ch, u32 flags,
2045 struct xpc_msg **address_of_msg) 2044 struct xpc_msg_sn2 **address_of_msg)
2046{ 2045{
2047 struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2; 2046 struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
2048 struct xpc_msg *msg; 2047 struct xpc_msg_sn2 *msg;
2049 enum xp_retval ret; 2048 enum xp_retval ret;
2050 s64 put; 2049 s64 put;
2051 2050
@@ -2097,8 +2096,9 @@ xpc_allocate_msg_sn2(struct xpc_channel *ch, u32 flags,
2097 } 2096 }
2098 2097
2099 /* get the message's address and initialize it */ 2098 /* get the message's address and initialize it */
2100 msg = (struct xpc_msg *)((u64)ch_sn2->local_msgqueue + 2099 msg = (struct xpc_msg_sn2 *)((u64)ch_sn2->local_msgqueue +
2101 (put % ch->local_nentries) * ch->msg_size); 2100 (put % ch->local_nentries) *
2101 ch->entry_size);
2102 2102
2103 DBUG_ON(msg->flags != 0); 2103 DBUG_ON(msg->flags != 0);
2104 msg->number = put; 2104 msg->number = put;
@@ -2117,20 +2117,20 @@ xpc_allocate_msg_sn2(struct xpc_channel *ch, u32 flags,
2117 * partition the message is being sent to. 2117 * partition the message is being sent to.
2118 */ 2118 */
2119static enum xp_retval 2119static enum xp_retval
2120xpc_send_msg_sn2(struct xpc_channel *ch, u32 flags, void *payload, 2120xpc_send_payload_sn2(struct xpc_channel *ch, u32 flags, void *payload,
2121 u16 payload_size, u8 notify_type, xpc_notify_func func, 2121 u16 payload_size, u8 notify_type, xpc_notify_func func,
2122 void *key) 2122 void *key)
2123{ 2123{
2124 enum xp_retval ret = xpSuccess; 2124 enum xp_retval ret = xpSuccess;
2125 struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2; 2125 struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
2126 struct xpc_msg *msg = msg; 2126 struct xpc_msg_sn2 *msg = msg;
2127 struct xpc_notify *notify = notify; 2127 struct xpc_notify_sn2 *notify = notify;
2128 s64 msg_number; 2128 s64 msg_number;
2129 s64 put; 2129 s64 put;
2130 2130
2131 DBUG_ON(notify_type == XPC_N_CALL && func == NULL); 2131 DBUG_ON(notify_type == XPC_N_CALL && func == NULL);
2132 2132
2133 if (XPC_MSG_SIZE(payload_size) > ch->msg_size) 2133 if (XPC_MSG_SIZE(payload_size) > ch->entry_size)
2134 return xpPayloadTooBig; 2134 return xpPayloadTooBig;
2135 2135
2136 xpc_msgqueue_ref(ch); 2136 xpc_msgqueue_ref(ch);
@@ -2155,7 +2155,7 @@ xpc_send_msg_sn2(struct xpc_channel *ch, u32 flags, void *payload,
2155 * Tell the remote side to send an ACK interrupt when the 2155 * Tell the remote side to send an ACK interrupt when the
2156 * message has been delivered. 2156 * message has been delivered.
2157 */ 2157 */
2158 msg->flags |= XPC_M_INTERRUPT; 2158 msg->flags |= XPC_M_SN2_INTERRUPT;
2159 2159
2160 atomic_inc(&ch->n_to_notify); 2160 atomic_inc(&ch->n_to_notify);
2161 2161
@@ -2185,7 +2185,7 @@ xpc_send_msg_sn2(struct xpc_channel *ch, u32 flags, void *payload,
2185 2185
2186 memcpy(&msg->payload, payload, payload_size); 2186 memcpy(&msg->payload, payload, payload_size);
2187 2187
2188 msg->flags |= XPC_M_READY; 2188 msg->flags |= XPC_M_SN2_READY;
2189 2189
2190 /* 2190 /*
2191 * The preceding store of msg->flags must occur before the following 2191 * The preceding store of msg->flags must occur before the following
@@ -2208,12 +2208,15 @@ out_1:
2208 * Now we actually acknowledge the messages that have been delivered and ack'd 2208 * Now we actually acknowledge the messages that have been delivered and ack'd
2209 * by advancing the cached remote message queue's Get value and if requested 2209 * by advancing the cached remote message queue's Get value and if requested
2210 * send a chctl msgrequest to the message sender's partition. 2210 * send a chctl msgrequest to the message sender's partition.
2211 *
2212 * If a message has XPC_M_SN2_INTERRUPT set, send an interrupt to the partition
2213 * that sent the message.
2211 */ 2214 */
2212static void 2215static void
2213xpc_acknowledge_msgs_sn2(struct xpc_channel *ch, s64 initial_get, u8 msg_flags) 2216xpc_acknowledge_msgs_sn2(struct xpc_channel *ch, s64 initial_get, u8 msg_flags)
2214{ 2217{
2215 struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2; 2218 struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
2216 struct xpc_msg *msg; 2219 struct xpc_msg_sn2 *msg;
2217 s64 get = initial_get + 1; 2220 s64 get = initial_get + 1;
2218 int send_msgrequest = 0; 2221 int send_msgrequest = 0;
2219 2222
@@ -2223,11 +2226,12 @@ xpc_acknowledge_msgs_sn2(struct xpc_channel *ch, s64 initial_get, u8 msg_flags)
2223 if (get == ch_sn2->w_local_GP.get) 2226 if (get == ch_sn2->w_local_GP.get)
2224 break; 2227 break;
2225 2228
2226 msg = (struct xpc_msg *)((u64)ch_sn2->remote_msgqueue + 2229 msg = (struct xpc_msg_sn2 *)((u64)ch_sn2->
2227 (get % ch->remote_nentries) * 2230 remote_msgqueue + (get %
2228 ch->msg_size); 2231 ch->remote_nentries) *
2232 ch->entry_size);
2229 2233
2230 if (!(msg->flags & XPC_M_DONE)) 2234 if (!(msg->flags & XPC_M_SN2_DONE))
2231 break; 2235 break;
2232 2236
2233 msg_flags |= msg->flags; 2237 msg_flags |= msg->flags;
@@ -2251,11 +2255,11 @@ xpc_acknowledge_msgs_sn2(struct xpc_channel *ch, s64 initial_get, u8 msg_flags)
2251 dev_dbg(xpc_chan, "local_GP->get changed to %ld, partid=%d, " 2255 dev_dbg(xpc_chan, "local_GP->get changed to %ld, partid=%d, "
2252 "channel=%d\n", get, ch->partid, ch->number); 2256 "channel=%d\n", get, ch->partid, ch->number);
2253 2257
2254 send_msgrequest = (msg_flags & XPC_M_INTERRUPT); 2258 send_msgrequest = (msg_flags & XPC_M_SN2_INTERRUPT);
2255 2259
2256 /* 2260 /*
2257 * We need to ensure that the message referenced by 2261 * We need to ensure that the message referenced by
2258 * local_GP->get is not XPC_M_DONE or that local_GP->get 2262 * local_GP->get is not XPC_M_SN2_DONE or that local_GP->get
2259 * equals w_local_GP.get, so we'll go have a look. 2263 * equals w_local_GP.get, so we'll go have a look.
2260 */ 2264 */
2261 initial_get = get; 2265 initial_get = get;
@@ -2266,19 +2270,23 @@ xpc_acknowledge_msgs_sn2(struct xpc_channel *ch, s64 initial_get, u8 msg_flags)
2266} 2270}
2267 2271
2268static void 2272static void
2269xpc_received_msg_sn2(struct xpc_channel *ch, struct xpc_msg *msg) 2273xpc_received_payload_sn2(struct xpc_channel *ch, void *payload)
2270{ 2274{
2275 struct xpc_msg_sn2 *msg;
2276 s64 msg_number;
2271 s64 get; 2277 s64 get;
2272 s64 msg_number = msg->number; 2278
2279 msg = container_of(payload, struct xpc_msg_sn2, payload);
2280 msg_number = msg->number;
2273 2281
2274 dev_dbg(xpc_chan, "msg=0x%p, msg_number=%ld, partid=%d, channel=%d\n", 2282 dev_dbg(xpc_chan, "msg=0x%p, msg_number=%ld, partid=%d, channel=%d\n",
2275 (void *)msg, msg_number, ch->partid, ch->number); 2283 (void *)msg, msg_number, ch->partid, ch->number);
2276 2284
2277 DBUG_ON((((u64)msg - (u64)ch->remote_msgqueue) / ch->msg_size) != 2285 DBUG_ON((((u64)msg - (u64)ch->remote_msgqueue) / ch->entry_size) !=
2278 msg_number % ch->remote_nentries); 2286 msg_number % ch->remote_nentries);
2279 DBUG_ON(msg->flags & XPC_M_DONE); 2287 DBUG_ON(msg->flags & XPC_M_SN2_DONE);
2280 2288
2281 msg->flags |= XPC_M_DONE; 2289 msg->flags |= XPC_M_SN2_DONE;
2282 2290
2283 /* 2291 /*
2284 * The preceding store of msg->flags must occur before the following 2292 * The preceding store of msg->flags must occur before the following
@@ -2337,8 +2345,8 @@ xpc_init_sn2(void)
2337 2345
2338 xpc_notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_sn2; 2346 xpc_notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_sn2;
2339 xpc_process_msg_chctl_flags = xpc_process_msg_chctl_flags_sn2; 2347 xpc_process_msg_chctl_flags = xpc_process_msg_chctl_flags_sn2;
2340 xpc_n_of_deliverable_msgs = xpc_n_of_deliverable_msgs_sn2; 2348 xpc_n_of_deliverable_payloads = xpc_n_of_deliverable_payloads_sn2;
2341 xpc_get_deliverable_msg = xpc_get_deliverable_msg_sn2; 2349 xpc_get_deliverable_payload = xpc_get_deliverable_payload_sn2;
2342 2350
2343 xpc_indicate_partition_engaged = xpc_indicate_partition_engaged_sn2; 2351 xpc_indicate_partition_engaged = xpc_indicate_partition_engaged_sn2;
2344 xpc_indicate_partition_disengaged = 2352 xpc_indicate_partition_disengaged =
@@ -2347,8 +2355,14 @@ xpc_init_sn2(void)
2347 xpc_any_partition_engaged = xpc_any_partition_engaged_sn2; 2355 xpc_any_partition_engaged = xpc_any_partition_engaged_sn2;
2348 xpc_assume_partition_disengaged = xpc_assume_partition_disengaged_sn2; 2356 xpc_assume_partition_disengaged = xpc_assume_partition_disengaged_sn2;
2349 2357
2350 xpc_send_msg = xpc_send_msg_sn2; 2358 xpc_send_payload = xpc_send_payload_sn2;
2351 xpc_received_msg = xpc_received_msg_sn2; 2359 xpc_received_payload = xpc_received_payload_sn2;
2360
2361 if (offsetof(struct xpc_msg_sn2, payload) > XPC_MSG_HDR_MAX_SIZE) {
2362 dev_err(xpc_part, "header portion of struct xpc_msg_sn2 is "
2363 "larger than %d\n", XPC_MSG_HDR_MAX_SIZE);
2364 return -E2BIG;
2365 }
2352 2366
2353 buf_size = max(XPC_RP_VARS_SIZE, 2367 buf_size = max(XPC_RP_VARS_SIZE,
2354 XPC_RP_HEADER_SIZE + XP_NASID_MASK_BYTES_SN2); 2368 XPC_RP_HEADER_SIZE + XP_NASID_MASK_BYTES_SN2);
diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c
index 689cb5c68ccf..1ac694c01623 100644
--- a/drivers/misc/sgi-xp/xpc_uv.c
+++ b/drivers/misc/sgi-xp/xpc_uv.c
@@ -66,8 +66,11 @@ xpc_create_gru_mq_uv(unsigned int mq_size, int cpuid, unsigned int irq,
66 mq_order = get_order(mq_size); 66 mq_order = get_order(mq_size);
67 page = alloc_pages_node(nid, GFP_KERNEL | __GFP_ZERO | GFP_THISNODE, 67 page = alloc_pages_node(nid, GFP_KERNEL | __GFP_ZERO | GFP_THISNODE,
68 mq_order); 68 mq_order);
69 if (page == NULL) 69 if (page == NULL) {
70 dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to alloc %d "
71 "bytes of memory on nid=%d for GRU mq\n", mq_size, nid);
70 return NULL; 72 return NULL;
73 }
71 74
72 mq = page_address(page); 75 mq = page_address(page);
73 ret = gru_create_message_queue(mq, mq_size); 76 ret = gru_create_message_queue(mq, mq_size);
@@ -193,202 +196,226 @@ xpc_process_activate_IRQ_rcvd_uv(void)
193 196
194} 197}
195 198
196static irqreturn_t 199static void
197xpc_handle_activate_IRQ_uv(int irq, void *dev_id) 200xpc_handle_activate_mq_msg_uv(struct xpc_partition *part,
201 struct xpc_activate_mq_msghdr_uv *msg_hdr,
202 int *wakeup_hb_checker)
198{ 203{
199 unsigned long irq_flags; 204 unsigned long irq_flags;
200 struct xpc_activate_mq_msghdr_uv *msg_hdr; 205 struct xpc_partition_uv *part_uv = &part->sn.uv;
201 short partid;
202 struct xpc_partition *part;
203 struct xpc_partition_uv *part_uv;
204 struct xpc_openclose_args *args; 206 struct xpc_openclose_args *args;
205 int wakeup_hb_checker = 0;
206 207
207 while ((msg_hdr = gru_get_next_message(xpc_activate_mq_uv)) != NULL) { 208 part_uv->remote_act_state = msg_hdr->act_state;
208 209
209 partid = msg_hdr->partid; 210 switch (msg_hdr->type) {
210 if (partid < 0 || partid >= XP_MAX_NPARTITIONS_UV) { 211 case XPC_ACTIVATE_MQ_MSG_SYNC_ACT_STATE_UV:
211 dev_err(xpc_part, "xpc_handle_activate_IRQ_uv() invalid" 212 /* syncing of remote_act_state was just done above */
212 "partid=0x%x passed in message\n", partid); 213 break;
213 gru_free_message(xpc_activate_mq_uv, msg_hdr);
214 continue;
215 }
216 part = &xpc_partitions[partid];
217 part_uv = &part->sn.uv;
218 214
219 part_uv->remote_act_state = msg_hdr->act_state; 215 case XPC_ACTIVATE_MQ_MSG_INC_HEARTBEAT_UV: {
216 struct xpc_activate_mq_msg_heartbeat_req_uv *msg;
220 217
221 switch (msg_hdr->type) { 218 msg = container_of(msg_hdr,
222 case XPC_ACTIVATE_MQ_MSG_SYNC_ACT_STATE_UV: 219 struct xpc_activate_mq_msg_heartbeat_req_uv,
223 /* syncing of remote_act_state was just done above */ 220 hdr);
224 break; 221 part_uv->heartbeat = msg->heartbeat;
222 break;
223 }
224 case XPC_ACTIVATE_MQ_MSG_OFFLINE_HEARTBEAT_UV: {
225 struct xpc_activate_mq_msg_heartbeat_req_uv *msg;
226
227 msg = container_of(msg_hdr,
228 struct xpc_activate_mq_msg_heartbeat_req_uv,
229 hdr);
230 part_uv->heartbeat = msg->heartbeat;
231
232 spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
233 part_uv->flags |= XPC_P_HEARTBEAT_OFFLINE_UV;
234 spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
235 break;
236 }
237 case XPC_ACTIVATE_MQ_MSG_ONLINE_HEARTBEAT_UV: {
238 struct xpc_activate_mq_msg_heartbeat_req_uv *msg;
239
240 msg = container_of(msg_hdr,
241 struct xpc_activate_mq_msg_heartbeat_req_uv,
242 hdr);
243 part_uv->heartbeat = msg->heartbeat;
244
245 spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
246 part_uv->flags &= ~XPC_P_HEARTBEAT_OFFLINE_UV;
247 spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
248 break;
249 }
250 case XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV: {
251 struct xpc_activate_mq_msg_activate_req_uv *msg;
225 252
226 case XPC_ACTIVATE_MQ_MSG_INC_HEARTBEAT_UV: { 253 /*
227 struct xpc_activate_mq_msg_heartbeat_req_uv *msg; 254 * ??? Do we deal here with ts_jiffies being different
255 * ??? if act_state != XPC_P_AS_INACTIVE instead of
256 * ??? below?
257 */
258 msg = container_of(msg_hdr, struct
259 xpc_activate_mq_msg_activate_req_uv, hdr);
228 260
229 msg = (struct xpc_activate_mq_msg_heartbeat_req_uv *) 261 spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
230 msg_hdr; 262 if (part_uv->act_state_req == 0)
231 part_uv->heartbeat = msg->heartbeat; 263 xpc_activate_IRQ_rcvd++;
232 break; 264 part_uv->act_state_req = XPC_P_ASR_ACTIVATE_UV;
233 } 265 part->remote_rp_pa = msg->rp_gpa; /* !!! _pa is _gpa */
234 case XPC_ACTIVATE_MQ_MSG_OFFLINE_HEARTBEAT_UV: { 266 part->remote_rp_ts_jiffies = msg_hdr->rp_ts_jiffies;
235 struct xpc_activate_mq_msg_heartbeat_req_uv *msg; 267 part_uv->remote_activate_mq_gpa = msg->activate_mq_gpa;
236 268 spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
237 msg = (struct xpc_activate_mq_msg_heartbeat_req_uv *)
238 msg_hdr;
239 part_uv->heartbeat = msg->heartbeat;
240 spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
241 part_uv->flags |= XPC_P_HEARTBEAT_OFFLINE_UV;
242 spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
243 break;
244 }
245 case XPC_ACTIVATE_MQ_MSG_ONLINE_HEARTBEAT_UV: {
246 struct xpc_activate_mq_msg_heartbeat_req_uv *msg;
247
248 msg = (struct xpc_activate_mq_msg_heartbeat_req_uv *)
249 msg_hdr;
250 part_uv->heartbeat = msg->heartbeat;
251 spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
252 part_uv->flags &= ~XPC_P_HEARTBEAT_OFFLINE_UV;
253 spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
254 break;
255 }
256 case XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV: {
257 struct xpc_activate_mq_msg_activate_req_uv *msg;
258
259 /*
260 * ??? Do we deal here with ts_jiffies being different
261 * ??? if act_state != XPC_P_AS_INACTIVE instead of
262 * ??? below?
263 */
264 msg = (struct xpc_activate_mq_msg_activate_req_uv *)
265 msg_hdr;
266 spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock,
267 irq_flags);
268 if (part_uv->act_state_req == 0)
269 xpc_activate_IRQ_rcvd++;
270 part_uv->act_state_req = XPC_P_ASR_ACTIVATE_UV;
271 part->remote_rp_pa = msg->rp_gpa; /* !!! _pa is _gpa */
272 part->remote_rp_ts_jiffies = msg_hdr->rp_ts_jiffies;
273 part_uv->remote_activate_mq_gpa = msg->activate_mq_gpa;
274 spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock,
275 irq_flags);
276 wakeup_hb_checker++;
277 break;
278 }
279 case XPC_ACTIVATE_MQ_MSG_DEACTIVATE_REQ_UV: {
280 struct xpc_activate_mq_msg_deactivate_req_uv *msg;
281
282 msg = (struct xpc_activate_mq_msg_deactivate_req_uv *)
283 msg_hdr;
284 spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock,
285 irq_flags);
286 if (part_uv->act_state_req == 0)
287 xpc_activate_IRQ_rcvd++;
288 part_uv->act_state_req = XPC_P_ASR_DEACTIVATE_UV;
289 part_uv->reason = msg->reason;
290 spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock,
291 irq_flags);
292 wakeup_hb_checker++;
293 break;
294 }
295 case XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREQUEST_UV: {
296 struct xpc_activate_mq_msg_chctl_closerequest_uv *msg;
297 269
298 msg = (struct xpc_activate_mq_msg_chctl_closerequest_uv 270 (*wakeup_hb_checker)++;
299 *)msg_hdr; 271 break;
300 args = &part->remote_openclose_args[msg->ch_number]; 272 }
301 args->reason = msg->reason; 273 case XPC_ACTIVATE_MQ_MSG_DEACTIVATE_REQ_UV: {
274 struct xpc_activate_mq_msg_deactivate_req_uv *msg;
302 275
303 spin_lock_irqsave(&part->chctl_lock, irq_flags); 276 msg = container_of(msg_hdr, struct
304 part->chctl.flags[msg->ch_number] |= 277 xpc_activate_mq_msg_deactivate_req_uv, hdr);
305 XPC_CHCTL_CLOSEREQUEST;
306 spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
307 278
308 xpc_wakeup_channel_mgr(part); 279 spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
309 break; 280 if (part_uv->act_state_req == 0)
310 } 281 xpc_activate_IRQ_rcvd++;
311 case XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREPLY_UV: { 282 part_uv->act_state_req = XPC_P_ASR_DEACTIVATE_UV;
312 struct xpc_activate_mq_msg_chctl_closereply_uv *msg; 283 part_uv->reason = msg->reason;
284 spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
285
286 (*wakeup_hb_checker)++;
287 return;
288 }
289 case XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREQUEST_UV: {
290 struct xpc_activate_mq_msg_chctl_closerequest_uv *msg;
313 291
314 msg = (struct xpc_activate_mq_msg_chctl_closereply_uv *) 292 msg = container_of(msg_hdr, struct
315 msg_hdr; 293 xpc_activate_mq_msg_chctl_closerequest_uv,
294 hdr);
295 args = &part->remote_openclose_args[msg->ch_number];
296 args->reason = msg->reason;
316 297
317 spin_lock_irqsave(&part->chctl_lock, irq_flags); 298 spin_lock_irqsave(&part->chctl_lock, irq_flags);
318 part->chctl.flags[msg->ch_number] |= 299 part->chctl.flags[msg->ch_number] |= XPC_CHCTL_CLOSEREQUEST;
319 XPC_CHCTL_CLOSEREPLY; 300 spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
320 spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
321 301
322 xpc_wakeup_channel_mgr(part); 302 xpc_wakeup_channel_mgr(part);
323 break; 303 break;
324 } 304 }
325 case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREQUEST_UV: { 305 case XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREPLY_UV: {
326 struct xpc_activate_mq_msg_chctl_openrequest_uv *msg; 306 struct xpc_activate_mq_msg_chctl_closereply_uv *msg;
327 307
328 msg = (struct xpc_activate_mq_msg_chctl_openrequest_uv 308 msg = container_of(msg_hdr, struct
329 *)msg_hdr; 309 xpc_activate_mq_msg_chctl_closereply_uv,
330 args = &part->remote_openclose_args[msg->ch_number]; 310 hdr);
331 args->msg_size = msg->msg_size;
332 args->local_nentries = msg->local_nentries;
333 311
334 spin_lock_irqsave(&part->chctl_lock, irq_flags); 312 spin_lock_irqsave(&part->chctl_lock, irq_flags);
335 part->chctl.flags[msg->ch_number] |= 313 part->chctl.flags[msg->ch_number] |= XPC_CHCTL_CLOSEREPLY;
336 XPC_CHCTL_OPENREQUEST; 314 spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
337 spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
338 315
339 xpc_wakeup_channel_mgr(part); 316 xpc_wakeup_channel_mgr(part);
340 break; 317 break;
341 } 318 }
342 case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV: { 319 case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREQUEST_UV: {
343 struct xpc_activate_mq_msg_chctl_openreply_uv *msg; 320 struct xpc_activate_mq_msg_chctl_openrequest_uv *msg;
344 321
345 msg = (struct xpc_activate_mq_msg_chctl_openreply_uv *) 322 msg = container_of(msg_hdr, struct
346 msg_hdr; 323 xpc_activate_mq_msg_chctl_openrequest_uv,
347 args = &part->remote_openclose_args[msg->ch_number]; 324 hdr);
348 args->remote_nentries = msg->remote_nentries; 325 args = &part->remote_openclose_args[msg->ch_number];
349 args->local_nentries = msg->local_nentries; 326 args->entry_size = msg->entry_size;
350 args->local_msgqueue_pa = msg->local_notify_mq_gpa; 327 args->local_nentries = msg->local_nentries;
351 328
352 spin_lock_irqsave(&part->chctl_lock, irq_flags); 329 spin_lock_irqsave(&part->chctl_lock, irq_flags);
353 part->chctl.flags[msg->ch_number] |= 330 part->chctl.flags[msg->ch_number] |= XPC_CHCTL_OPENREQUEST;
354 XPC_CHCTL_OPENREPLY; 331 spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
355 spin_unlock_irqrestore(&part->chctl_lock, irq_flags); 332
356 333 xpc_wakeup_channel_mgr(part);
357 xpc_wakeup_channel_mgr(part); 334 break;
358 break; 335 }
359 } 336 case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV: {
360 case XPC_ACTIVATE_MQ_MSG_MARK_ENGAGED_UV: 337 struct xpc_activate_mq_msg_chctl_openreply_uv *msg;
361 spin_lock_irqsave(&part_uv->flags_lock, irq_flags); 338
362 part_uv->flags |= XPC_P_ENGAGED_UV; 339 msg = container_of(msg_hdr, struct
363 spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags); 340 xpc_activate_mq_msg_chctl_openreply_uv, hdr);
364 break; 341 args = &part->remote_openclose_args[msg->ch_number];
342 args->remote_nentries = msg->remote_nentries;
343 args->local_nentries = msg->local_nentries;
344 args->local_msgqueue_pa = msg->local_notify_mq_gpa;
345
346 spin_lock_irqsave(&part->chctl_lock, irq_flags);
347 part->chctl.flags[msg->ch_number] |= XPC_CHCTL_OPENREPLY;
348 spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
349
350 xpc_wakeup_channel_mgr(part);
351 break;
352 }
353 case XPC_ACTIVATE_MQ_MSG_MARK_ENGAGED_UV:
354 spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
355 part_uv->flags |= XPC_P_ENGAGED_UV;
356 spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
357 break;
358
359 case XPC_ACTIVATE_MQ_MSG_MARK_DISENGAGED_UV:
360 spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
361 part_uv->flags &= ~XPC_P_ENGAGED_UV;
362 spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
363 break;
364
365 default:
366 dev_err(xpc_part, "received unknown activate_mq msg type=%d "
367 "from partition=%d\n", msg_hdr->type, XPC_PARTID(part));
368
369 /* get hb checker to deactivate from the remote partition */
370 spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
371 if (part_uv->act_state_req == 0)
372 xpc_activate_IRQ_rcvd++;
373 part_uv->act_state_req = XPC_P_ASR_DEACTIVATE_UV;
374 part_uv->reason = xpBadMsgType;
375 spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
365 376
366 case XPC_ACTIVATE_MQ_MSG_MARK_DISENGAGED_UV: 377 (*wakeup_hb_checker)++;
367 spin_lock_irqsave(&part_uv->flags_lock, irq_flags); 378 return;
368 part_uv->flags &= ~XPC_P_ENGAGED_UV; 379 }
369 spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
370 break;
371 380
372 default: 381 if (msg_hdr->rp_ts_jiffies != part->remote_rp_ts_jiffies &&
373 dev_err(xpc_part, "received unknown activate_mq msg " 382 part->remote_rp_ts_jiffies != 0) {
374 "type=%d from partition=%d\n", msg_hdr->type, 383 /*
375 partid); 384 * ??? Does what we do here need to be sensitive to
376 } 385 * ??? act_state or remote_act_state?
386 */
387 spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
388 if (part_uv->act_state_req == 0)
389 xpc_activate_IRQ_rcvd++;
390 part_uv->act_state_req = XPC_P_ASR_REACTIVATE_UV;
391 spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
377 392
378 if (msg_hdr->rp_ts_jiffies != part->remote_rp_ts_jiffies && 393 (*wakeup_hb_checker)++;
379 part->remote_rp_ts_jiffies != 0) { 394 }
380 /* 395}
381 * ??? Does what we do here need to be sensitive to 396
382 * ??? act_state or remote_act_state? 397static irqreturn_t
383 */ 398xpc_handle_activate_IRQ_uv(int irq, void *dev_id)
384 spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, 399{
385 irq_flags); 400 struct xpc_activate_mq_msghdr_uv *msg_hdr;
386 if (part_uv->act_state_req == 0) 401 short partid;
387 xpc_activate_IRQ_rcvd++; 402 struct xpc_partition *part;
388 part_uv->act_state_req = XPC_P_ASR_REACTIVATE_UV; 403 int wakeup_hb_checker = 0;
389 spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, 404
390 irq_flags); 405 while ((msg_hdr = gru_get_next_message(xpc_activate_mq_uv)) != NULL) {
391 wakeup_hb_checker++; 406
407 partid = msg_hdr->partid;
408 if (partid < 0 || partid >= XP_MAX_NPARTITIONS_UV) {
409 dev_err(xpc_part, "xpc_handle_activate_IRQ_uv() "
410 "received invalid partid=0x%x in message\n",
411 partid);
412 } else {
413 part = &xpc_partitions[partid];
414 if (xpc_part_ref(part)) {
415 xpc_handle_activate_mq_msg_uv(part, msg_hdr,
416 &wakeup_hb_checker);
417 xpc_part_deref(part);
418 }
392 } 419 }
393 420
394 gru_free_message(xpc_activate_mq_uv, msg_hdr); 421 gru_free_message(xpc_activate_mq_uv, msg_hdr);
@@ -616,14 +643,82 @@ xpc_request_partition_deactivation_uv(struct xpc_partition *part)
616 } 643 }
617} 644}
618 645
646static void
647xpc_cancel_partition_deactivation_request_uv(struct xpc_partition *part)
648{
649 /* nothing needs to be done */
650 return;
651}
652
653static void
654xpc_init_fifo_uv(struct xpc_fifo_head_uv *head)
655{
656 head->first = NULL;
657 head->last = NULL;
658 spin_lock_init(&head->lock);
659 head->n_entries = 0;
660}
661
662static void *
663xpc_get_fifo_entry_uv(struct xpc_fifo_head_uv *head)
664{
665 unsigned long irq_flags;
666 struct xpc_fifo_entry_uv *first;
667
668 spin_lock_irqsave(&head->lock, irq_flags);
669 first = head->first;
670 if (head->first != NULL) {
671 head->first = first->next;
672 if (head->first == NULL)
673 head->last = NULL;
674 }
675 head->n_entries++;
676 spin_unlock_irqrestore(&head->lock, irq_flags);
677 first->next = NULL;
678 return first;
679}
680
681static void
682xpc_put_fifo_entry_uv(struct xpc_fifo_head_uv *head,
683 struct xpc_fifo_entry_uv *last)
684{
685 unsigned long irq_flags;
686
687 last->next = NULL;
688 spin_lock_irqsave(&head->lock, irq_flags);
689 if (head->last != NULL)
690 head->last->next = last;
691 else
692 head->first = last;
693 head->last = last;
694 head->n_entries--;
695 BUG_ON(head->n_entries < 0);
696 spin_unlock_irqrestore(&head->lock, irq_flags);
697}
698
699static int
700xpc_n_of_fifo_entries_uv(struct xpc_fifo_head_uv *head)
701{
702 return head->n_entries;
703}
704
619/* 705/*
620 * Setup the channel structures that are uv specific. 706 * Setup the channel structures that are uv specific.
621 */ 707 */
622static enum xp_retval 708static enum xp_retval
623xpc_setup_ch_structures_sn_uv(struct xpc_partition *part) 709xpc_setup_ch_structures_sn_uv(struct xpc_partition *part)
624{ 710{
625 /* !!! this function needs fleshing out */ 711 struct xpc_channel_uv *ch_uv;
626 return xpUnsupported; 712 int ch_number;
713
714 for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
715 ch_uv = &part->channels[ch_number].sn.uv;
716
717 xpc_init_fifo_uv(&ch_uv->msg_slot_free_list);
718 xpc_init_fifo_uv(&ch_uv->recv_msg_list);
719 }
720
721 return xpSuccess;
627} 722}
628 723
629/* 724/*
@@ -632,7 +727,7 @@ xpc_setup_ch_structures_sn_uv(struct xpc_partition *part)
632static void 727static void
633xpc_teardown_ch_structures_sn_uv(struct xpc_partition *part) 728xpc_teardown_ch_structures_sn_uv(struct xpc_partition *part)
634{ 729{
635 /* !!! this function needs fleshing out */ 730 /* nothing needs to be done */
636 return; 731 return;
637} 732}
638 733
@@ -680,20 +775,114 @@ xpc_get_chctl_all_flags_uv(struct xpc_partition *part)
680} 775}
681 776
682static enum xp_retval 777static enum xp_retval
778xpc_allocate_send_msg_slot_uv(struct xpc_channel *ch)
779{
780 struct xpc_channel_uv *ch_uv = &ch->sn.uv;
781 struct xpc_send_msg_slot_uv *msg_slot;
782 unsigned long irq_flags;
783 int nentries;
784 int entry;
785 size_t nbytes;
786
787 for (nentries = ch->local_nentries; nentries > 0; nentries--) {
788 nbytes = nentries * sizeof(struct xpc_send_msg_slot_uv);
789 ch_uv->send_msg_slots = kzalloc(nbytes, GFP_KERNEL);
790 if (ch_uv->send_msg_slots == NULL)
791 continue;
792
793 for (entry = 0; entry < nentries; entry++) {
794 msg_slot = &ch_uv->send_msg_slots[entry];
795
796 msg_slot->msg_slot_number = entry;
797 xpc_put_fifo_entry_uv(&ch_uv->msg_slot_free_list,
798 &msg_slot->next);
799 }
800
801 spin_lock_irqsave(&ch->lock, irq_flags);
802 if (nentries < ch->local_nentries)
803 ch->local_nentries = nentries;
804 spin_unlock_irqrestore(&ch->lock, irq_flags);
805 return xpSuccess;
806 }
807
808 return xpNoMemory;
809}
810
811static enum xp_retval
812xpc_allocate_recv_msg_slot_uv(struct xpc_channel *ch)
813{
814 struct xpc_channel_uv *ch_uv = &ch->sn.uv;
815 struct xpc_notify_mq_msg_uv *msg_slot;
816 unsigned long irq_flags;
817 int nentries;
818 int entry;
819 size_t nbytes;
820
821 for (nentries = ch->remote_nentries; nentries > 0; nentries--) {
822 nbytes = nentries * ch->entry_size;
823 ch_uv->recv_msg_slots = kzalloc(nbytes, GFP_KERNEL);
824 if (ch_uv->recv_msg_slots == NULL)
825 continue;
826
827 for (entry = 0; entry < nentries; entry++) {
828 msg_slot = ch_uv->recv_msg_slots + entry *
829 ch->entry_size;
830
831 msg_slot->hdr.msg_slot_number = entry;
832 }
833
834 spin_lock_irqsave(&ch->lock, irq_flags);
835 if (nentries < ch->remote_nentries)
836 ch->remote_nentries = nentries;
837 spin_unlock_irqrestore(&ch->lock, irq_flags);
838 return xpSuccess;
839 }
840
841 return xpNoMemory;
842}
843
844/*
845 * Allocate msg_slots associated with the channel.
846 */
847static enum xp_retval
683xpc_setup_msg_structures_uv(struct xpc_channel *ch) 848xpc_setup_msg_structures_uv(struct xpc_channel *ch)
684{ 849{
685 /* !!! this function needs fleshing out */ 850 static enum xp_retval ret;
686 return xpUnsupported; 851 struct xpc_channel_uv *ch_uv = &ch->sn.uv;
852
853 DBUG_ON(ch->flags & XPC_C_SETUP);
854
855 ret = xpc_allocate_send_msg_slot_uv(ch);
856 if (ret == xpSuccess) {
857
858 ret = xpc_allocate_recv_msg_slot_uv(ch);
859 if (ret != xpSuccess) {
860 kfree(ch_uv->send_msg_slots);
861 xpc_init_fifo_uv(&ch_uv->msg_slot_free_list);
862 }
863 }
864 return ret;
687} 865}
688 866
867/*
868 * Free up msg_slots and clear other stuff that were setup for the specified
869 * channel.
870 */
689static void 871static void
690xpc_teardown_msg_structures_uv(struct xpc_channel *ch) 872xpc_teardown_msg_structures_uv(struct xpc_channel *ch)
691{ 873{
692 struct xpc_channel_uv *ch_uv = &ch->sn.uv; 874 struct xpc_channel_uv *ch_uv = &ch->sn.uv;
693 875
876 DBUG_ON(!spin_is_locked(&ch->lock));
877
694 ch_uv->remote_notify_mq_gpa = 0; 878 ch_uv->remote_notify_mq_gpa = 0;
695 879
696 /* !!! this function needs fleshing out */ 880 if (ch->flags & XPC_C_SETUP) {
881 xpc_init_fifo_uv(&ch_uv->msg_slot_free_list);
882 kfree(ch_uv->send_msg_slots);
883 xpc_init_fifo_uv(&ch_uv->recv_msg_list);
884 kfree(ch_uv->recv_msg_slots);
885 }
697} 886}
698 887
699static void 888static void
@@ -723,7 +912,7 @@ xpc_send_chctl_openrequest_uv(struct xpc_channel *ch, unsigned long *irq_flags)
723 struct xpc_activate_mq_msg_chctl_openrequest_uv msg; 912 struct xpc_activate_mq_msg_chctl_openrequest_uv msg;
724 913
725 msg.ch_number = ch->number; 914 msg.ch_number = ch->number;
726 msg.msg_size = ch->msg_size; 915 msg.entry_size = ch->entry_size;
727 msg.local_nentries = ch->local_nentries; 916 msg.local_nentries = ch->local_nentries;
728 xpc_send_activate_IRQ_ch_uv(ch, irq_flags, &msg, sizeof(msg), 917 xpc_send_activate_IRQ_ch_uv(ch, irq_flags, &msg, sizeof(msg),
729 XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREQUEST_UV); 918 XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREQUEST_UV);
@@ -743,6 +932,18 @@ xpc_send_chctl_openreply_uv(struct xpc_channel *ch, unsigned long *irq_flags)
743} 932}
744 933
745static void 934static void
935xpc_send_chctl_local_msgrequest_uv(struct xpc_partition *part, int ch_number)
936{
937 unsigned long irq_flags;
938
939 spin_lock_irqsave(&part->chctl_lock, irq_flags);
940 part->chctl.flags[ch_number] |= XPC_CHCTL_MSGREQUEST;
941 spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
942
943 xpc_wakeup_channel_mgr(part);
944}
945
946static void
746xpc_save_remote_msgqueue_pa_uv(struct xpc_channel *ch, 947xpc_save_remote_msgqueue_pa_uv(struct xpc_channel *ch,
747 unsigned long msgqueue_pa) 948 unsigned long msgqueue_pa)
748{ 949{
@@ -798,11 +999,358 @@ xpc_any_partition_engaged_uv(void)
798 return 0; 999 return 0;
799} 1000}
800 1001
801static struct xpc_msg * 1002static enum xp_retval
802xpc_get_deliverable_msg_uv(struct xpc_channel *ch) 1003xpc_allocate_msg_slot_uv(struct xpc_channel *ch, u32 flags,
1004 struct xpc_send_msg_slot_uv **address_of_msg_slot)
1005{
1006 enum xp_retval ret;
1007 struct xpc_send_msg_slot_uv *msg_slot;
1008 struct xpc_fifo_entry_uv *entry;
1009
1010 while (1) {
1011 entry = xpc_get_fifo_entry_uv(&ch->sn.uv.msg_slot_free_list);
1012 if (entry != NULL)
1013 break;
1014
1015 if (flags & XPC_NOWAIT)
1016 return xpNoWait;
1017
1018 ret = xpc_allocate_msg_wait(ch);
1019 if (ret != xpInterrupted && ret != xpTimeout)
1020 return ret;
1021 }
1022
1023 msg_slot = container_of(entry, struct xpc_send_msg_slot_uv, next);
1024 *address_of_msg_slot = msg_slot;
1025 return xpSuccess;
1026}
1027
1028static void
1029xpc_free_msg_slot_uv(struct xpc_channel *ch,
1030 struct xpc_send_msg_slot_uv *msg_slot)
1031{
1032 xpc_put_fifo_entry_uv(&ch->sn.uv.msg_slot_free_list, &msg_slot->next);
1033
1034 /* wakeup anyone waiting for a free msg slot */
1035 if (atomic_read(&ch->n_on_msg_allocate_wq) > 0)
1036 wake_up(&ch->msg_allocate_wq);
1037}
1038
1039static void
1040xpc_notify_sender_uv(struct xpc_channel *ch,
1041 struct xpc_send_msg_slot_uv *msg_slot,
1042 enum xp_retval reason)
1043{
1044 xpc_notify_func func = msg_slot->func;
1045
1046 if (func != NULL && cmpxchg(&msg_slot->func, func, NULL) == func) {
1047
1048 atomic_dec(&ch->n_to_notify);
1049
1050 dev_dbg(xpc_chan, "msg_slot->func() called, msg_slot=0x%p "
1051 "msg_slot_number=%d partid=%d channel=%d\n", msg_slot,
1052 msg_slot->msg_slot_number, ch->partid, ch->number);
1053
1054 func(reason, ch->partid, ch->number, msg_slot->key);
1055
1056 dev_dbg(xpc_chan, "msg_slot->func() returned, msg_slot=0x%p "
1057 "msg_slot_number=%d partid=%d channel=%d\n", msg_slot,
1058 msg_slot->msg_slot_number, ch->partid, ch->number);
1059 }
1060}
1061
1062static void
1063xpc_handle_notify_mq_ack_uv(struct xpc_channel *ch,
1064 struct xpc_notify_mq_msg_uv *msg)
1065{
1066 struct xpc_send_msg_slot_uv *msg_slot;
1067 int entry = msg->hdr.msg_slot_number % ch->local_nentries;
1068
1069 msg_slot = &ch->sn.uv.send_msg_slots[entry];
1070
1071 BUG_ON(msg_slot->msg_slot_number != msg->hdr.msg_slot_number);
1072 msg_slot->msg_slot_number += ch->local_nentries;
1073
1074 if (msg_slot->func != NULL)
1075 xpc_notify_sender_uv(ch, msg_slot, xpMsgDelivered);
1076
1077 xpc_free_msg_slot_uv(ch, msg_slot);
1078}
1079
1080static void
1081xpc_handle_notify_mq_msg_uv(struct xpc_partition *part,
1082 struct xpc_notify_mq_msg_uv *msg)
1083{
1084 struct xpc_partition_uv *part_uv = &part->sn.uv;
1085 struct xpc_channel *ch;
1086 struct xpc_channel_uv *ch_uv;
1087 struct xpc_notify_mq_msg_uv *msg_slot;
1088 unsigned long irq_flags;
1089 int ch_number = msg->hdr.ch_number;
1090
1091 if (unlikely(ch_number >= part->nchannels)) {
1092 dev_err(xpc_part, "xpc_handle_notify_IRQ_uv() received invalid "
1093 "channel number=0x%x in message from partid=%d\n",
1094 ch_number, XPC_PARTID(part));
1095
1096 /* get hb checker to deactivate from the remote partition */
1097 spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
1098 if (part_uv->act_state_req == 0)
1099 xpc_activate_IRQ_rcvd++;
1100 part_uv->act_state_req = XPC_P_ASR_DEACTIVATE_UV;
1101 part_uv->reason = xpBadChannelNumber;
1102 spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
1103
1104 wake_up_interruptible(&xpc_activate_IRQ_wq);
1105 return;
1106 }
1107
1108 ch = &part->channels[ch_number];
1109 xpc_msgqueue_ref(ch);
1110
1111 if (!(ch->flags & XPC_C_CONNECTED)) {
1112 xpc_msgqueue_deref(ch);
1113 return;
1114 }
1115
1116 /* see if we're really dealing with an ACK for a previously sent msg */
1117 if (msg->hdr.size == 0) {
1118 xpc_handle_notify_mq_ack_uv(ch, msg);
1119 xpc_msgqueue_deref(ch);
1120 return;
1121 }
1122
1123 /* we're dealing with a normal message sent via the notify_mq */
1124 ch_uv = &ch->sn.uv;
1125
1126 msg_slot = (struct xpc_notify_mq_msg_uv *)((u64)ch_uv->recv_msg_slots +
1127 (msg->hdr.msg_slot_number % ch->remote_nentries) *
1128 ch->entry_size);
1129
1130 BUG_ON(msg->hdr.msg_slot_number != msg_slot->hdr.msg_slot_number);
1131 BUG_ON(msg_slot->hdr.size != 0);
1132
1133 memcpy(msg_slot, msg, msg->hdr.size);
1134
1135 xpc_put_fifo_entry_uv(&ch_uv->recv_msg_list, &msg_slot->hdr.u.next);
1136
1137 if (ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) {
1138 /*
1139 * If there is an existing idle kthread get it to deliver
1140 * the payload, otherwise we'll have to get the channel mgr
1141 * for this partition to create a kthread to do the delivery.
1142 */
1143 if (atomic_read(&ch->kthreads_idle) > 0)
1144 wake_up_nr(&ch->idle_wq, 1);
1145 else
1146 xpc_send_chctl_local_msgrequest_uv(part, ch->number);
1147 }
1148 xpc_msgqueue_deref(ch);
1149}
1150
1151static irqreturn_t
1152xpc_handle_notify_IRQ_uv(int irq, void *dev_id)
1153{
1154 struct xpc_notify_mq_msg_uv *msg;
1155 short partid;
1156 struct xpc_partition *part;
1157
1158 while ((msg = gru_get_next_message(xpc_notify_mq_uv)) != NULL) {
1159
1160 partid = msg->hdr.partid;
1161 if (partid < 0 || partid >= XP_MAX_NPARTITIONS_UV) {
1162 dev_err(xpc_part, "xpc_handle_notify_IRQ_uv() received "
1163 "invalid partid=0x%x in message\n", partid);
1164 } else {
1165 part = &xpc_partitions[partid];
1166
1167 if (xpc_part_ref(part)) {
1168 xpc_handle_notify_mq_msg_uv(part, msg);
1169 xpc_part_deref(part);
1170 }
1171 }
1172
1173 gru_free_message(xpc_notify_mq_uv, msg);
1174 }
1175
1176 return IRQ_HANDLED;
1177}
1178
1179static int
1180xpc_n_of_deliverable_payloads_uv(struct xpc_channel *ch)
1181{
1182 return xpc_n_of_fifo_entries_uv(&ch->sn.uv.recv_msg_list);
1183}
1184
1185static void
1186xpc_process_msg_chctl_flags_uv(struct xpc_partition *part, int ch_number)
1187{
1188 struct xpc_channel *ch = &part->channels[ch_number];
1189 int ndeliverable_payloads;
1190
1191 xpc_msgqueue_ref(ch);
1192
1193 ndeliverable_payloads = xpc_n_of_deliverable_payloads_uv(ch);
1194
1195 if (ndeliverable_payloads > 0 &&
1196 (ch->flags & XPC_C_CONNECTED) &&
1197 (ch->flags & XPC_C_CONNECTEDCALLOUT_MADE)) {
1198
1199 xpc_activate_kthreads(ch, ndeliverable_payloads);
1200 }
1201
1202 xpc_msgqueue_deref(ch);
1203}
1204
1205static enum xp_retval
1206xpc_send_payload_uv(struct xpc_channel *ch, u32 flags, void *payload,
1207 u16 payload_size, u8 notify_type, xpc_notify_func func,
1208 void *key)
1209{
1210 enum xp_retval ret = xpSuccess;
1211 struct xpc_send_msg_slot_uv *msg_slot = NULL;
1212 struct xpc_notify_mq_msg_uv *msg;
1213 u8 msg_buffer[XPC_NOTIFY_MSG_SIZE_UV];
1214 size_t msg_size;
1215
1216 DBUG_ON(notify_type != XPC_N_CALL);
1217
1218 msg_size = sizeof(struct xpc_notify_mq_msghdr_uv) + payload_size;
1219 if (msg_size > ch->entry_size)
1220 return xpPayloadTooBig;
1221
1222 xpc_msgqueue_ref(ch);
1223
1224 if (ch->flags & XPC_C_DISCONNECTING) {
1225 ret = ch->reason;
1226 goto out_1;
1227 }
1228 if (!(ch->flags & XPC_C_CONNECTED)) {
1229 ret = xpNotConnected;
1230 goto out_1;
1231 }
1232
1233 ret = xpc_allocate_msg_slot_uv(ch, flags, &msg_slot);
1234 if (ret != xpSuccess)
1235 goto out_1;
1236
1237 if (func != NULL) {
1238 atomic_inc(&ch->n_to_notify);
1239
1240 msg_slot->key = key;
1241 wmb(); /* a non-NULL func must hit memory after the key */
1242 msg_slot->func = func;
1243
1244 if (ch->flags & XPC_C_DISCONNECTING) {
1245 ret = ch->reason;
1246 goto out_2;
1247 }
1248 }
1249
1250 msg = (struct xpc_notify_mq_msg_uv *)&msg_buffer;
1251 msg->hdr.partid = xp_partition_id;
1252 msg->hdr.ch_number = ch->number;
1253 msg->hdr.size = msg_size;
1254 msg->hdr.msg_slot_number = msg_slot->msg_slot_number;
1255 memcpy(&msg->payload, payload, payload_size);
1256
1257 ret = xpc_send_gru_msg(ch->sn.uv.remote_notify_mq_gpa, msg, msg_size);
1258 if (ret == xpSuccess)
1259 goto out_1;
1260
1261 XPC_DEACTIVATE_PARTITION(&xpc_partitions[ch->partid], ret);
1262out_2:
1263 if (func != NULL) {
1264 /*
1265 * Try to NULL the msg_slot's func field. If we fail, then
1266 * xpc_notify_senders_of_disconnect_uv() beat us to it, in which
1267 * case we need to pretend we succeeded to send the message
1268 * since the user will get a callout for the disconnect error
1269 * by xpc_notify_senders_of_disconnect_uv(), and to also get an
1270 * error returned here will confuse them. Additionally, since
1271 * in this case the channel is being disconnected we don't need
1272 * to put the the msg_slot back on the free list.
1273 */
1274 if (cmpxchg(&msg_slot->func, func, NULL) != func) {
1275 ret = xpSuccess;
1276 goto out_1;
1277 }
1278
1279 msg_slot->key = NULL;
1280 atomic_dec(&ch->n_to_notify);
1281 }
1282 xpc_free_msg_slot_uv(ch, msg_slot);
1283out_1:
1284 xpc_msgqueue_deref(ch);
1285 return ret;
1286}
1287
1288/*
1289 * Tell the callers of xpc_send_notify() that the status of their payloads
1290 * is unknown because the channel is now disconnecting.
1291 *
1292 * We don't worry about putting these msg_slots on the free list since the
1293 * msg_slots themselves are about to be kfree'd.
1294 */
1295static void
1296xpc_notify_senders_of_disconnect_uv(struct xpc_channel *ch)
1297{
1298 struct xpc_send_msg_slot_uv *msg_slot;
1299 int entry;
1300
1301 DBUG_ON(!(ch->flags & XPC_C_DISCONNECTING));
1302
1303 for (entry = 0; entry < ch->local_nentries; entry++) {
1304
1305 if (atomic_read(&ch->n_to_notify) == 0)
1306 break;
1307
1308 msg_slot = &ch->sn.uv.send_msg_slots[entry];
1309 if (msg_slot->func != NULL)
1310 xpc_notify_sender_uv(ch, msg_slot, ch->reason);
1311 }
1312}
1313
1314/*
1315 * Get the next deliverable message's payload.
1316 */
1317static void *
1318xpc_get_deliverable_payload_uv(struct xpc_channel *ch)
1319{
1320 struct xpc_fifo_entry_uv *entry;
1321 struct xpc_notify_mq_msg_uv *msg;
1322 void *payload = NULL;
1323
1324 if (!(ch->flags & XPC_C_DISCONNECTING)) {
1325 entry = xpc_get_fifo_entry_uv(&ch->sn.uv.recv_msg_list);
1326 if (entry != NULL) {
1327 msg = container_of(entry, struct xpc_notify_mq_msg_uv,
1328 hdr.u.next);
1329 payload = &msg->payload;
1330 }
1331 }
1332 return payload;
1333}
1334
1335static void
1336xpc_received_payload_uv(struct xpc_channel *ch, void *payload)
803{ 1337{
804 /* !!! this function needs fleshing out */ 1338 struct xpc_notify_mq_msg_uv *msg;
805 return NULL; 1339 enum xp_retval ret;
1340
1341 msg = container_of(payload, struct xpc_notify_mq_msg_uv, payload);
1342
1343 /* return an ACK to the sender of this message */
1344
1345 msg->hdr.partid = xp_partition_id;
1346 msg->hdr.size = 0; /* size of zero indicates this is an ACK */
1347
1348 ret = xpc_send_gru_msg(ch->sn.uv.remote_notify_mq_gpa, msg,
1349 sizeof(struct xpc_notify_mq_msghdr_uv));
1350 if (ret != xpSuccess)
1351 XPC_DEACTIVATE_PARTITION(&xpc_partitions[ch->partid], ret);
1352
1353 msg->hdr.msg_slot_number += ch->remote_nentries;
806} 1354}
807 1355
808int 1356int
@@ -824,6 +1372,8 @@ xpc_init_uv(void)
824 xpc_request_partition_reactivation_uv; 1372 xpc_request_partition_reactivation_uv;
825 xpc_request_partition_deactivation = 1373 xpc_request_partition_deactivation =
826 xpc_request_partition_deactivation_uv; 1374 xpc_request_partition_deactivation_uv;
1375 xpc_cancel_partition_deactivation_request =
1376 xpc_cancel_partition_deactivation_request_uv;
827 1377
828 xpc_setup_ch_structures_sn = xpc_setup_ch_structures_sn_uv; 1378 xpc_setup_ch_structures_sn = xpc_setup_ch_structures_sn_uv;
829 xpc_teardown_ch_structures_sn = xpc_teardown_ch_structures_sn_uv; 1379 xpc_teardown_ch_structures_sn = xpc_teardown_ch_structures_sn_uv;
@@ -848,7 +1398,18 @@ xpc_init_uv(void)
848 xpc_partition_engaged = xpc_partition_engaged_uv; 1398 xpc_partition_engaged = xpc_partition_engaged_uv;
849 xpc_any_partition_engaged = xpc_any_partition_engaged_uv; 1399 xpc_any_partition_engaged = xpc_any_partition_engaged_uv;
850 1400
851 xpc_get_deliverable_msg = xpc_get_deliverable_msg_uv; 1401 xpc_n_of_deliverable_payloads = xpc_n_of_deliverable_payloads_uv;
1402 xpc_process_msg_chctl_flags = xpc_process_msg_chctl_flags_uv;
1403 xpc_send_payload = xpc_send_payload_uv;
1404 xpc_notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_uv;
1405 xpc_get_deliverable_payload = xpc_get_deliverable_payload_uv;
1406 xpc_received_payload = xpc_received_payload_uv;
1407
1408 if (sizeof(struct xpc_notify_mq_msghdr_uv) > XPC_MSG_HDR_MAX_SIZE) {
1409 dev_err(xpc_part, "xpc_notify_mq_msghdr_uv is larger than %d\n",
1410 XPC_MSG_HDR_MAX_SIZE);
1411 return -E2BIG;
1412 }
852 1413
853 /* ??? The cpuid argument's value is 0, is that what we want? */ 1414 /* ??? The cpuid argument's value is 0, is that what we want? */
854 /* !!! The irq argument's value isn't correct. */ 1415 /* !!! The irq argument's value isn't correct. */
@@ -857,6 +1418,17 @@ xpc_init_uv(void)
857 if (xpc_activate_mq_uv == NULL) 1418 if (xpc_activate_mq_uv == NULL)
858 return -ENOMEM; 1419 return -ENOMEM;
859 1420
1421 /* ??? The cpuid argument's value is 0, is that what we want? */
1422 /* !!! The irq argument's value isn't correct. */
1423 xpc_notify_mq_uv = xpc_create_gru_mq_uv(XPC_NOTIFY_MQ_SIZE_UV, 0, 0,
1424 xpc_handle_notify_IRQ_uv);
1425 if (xpc_notify_mq_uv == NULL) {
1426 /* !!! The irq argument's value isn't correct. */
1427 xpc_destroy_gru_mq_uv(xpc_activate_mq_uv,
1428 XPC_ACTIVATE_MQ_SIZE_UV, 0);
1429 return -ENOMEM;
1430 }
1431
860 return 0; 1432 return 0;
861} 1433}
862 1434
@@ -864,5 +1436,8 @@ void
864xpc_exit_uv(void) 1436xpc_exit_uv(void)
865{ 1437{
866 /* !!! The irq argument's value isn't correct. */ 1438 /* !!! The irq argument's value isn't correct. */
1439 xpc_destroy_gru_mq_uv(xpc_notify_mq_uv, XPC_NOTIFY_MQ_SIZE_UV, 0);
1440
1441 /* !!! The irq argument's value isn't correct. */
867 xpc_destroy_gru_mq_uv(xpc_activate_mq_uv, XPC_ACTIVATE_MQ_SIZE_UV, 0); 1442 xpc_destroy_gru_mq_uv(xpc_activate_mq_uv, XPC_ACTIVATE_MQ_SIZE_UV, 0);
868} 1443}
diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c
index 4f5d62230116..71513b3af708 100644
--- a/drivers/misc/sgi-xp/xpnet.c
+++ b/drivers/misc/sgi-xp/xpnet.c
@@ -57,11 +57,10 @@ struct xpnet_message {
57 * 57 *
58 * XPC expects each message to exist in an individual cacheline. 58 * XPC expects each message to exist in an individual cacheline.
59 */ 59 */
60#define XPNET_MSG_SIZE (L1_CACHE_BYTES - XPC_MSG_PAYLOAD_OFFSET) 60#define XPNET_MSG_SIZE XPC_MSG_PAYLOAD_MAX_SIZE
61#define XPNET_MSG_DATA_MAX \ 61#define XPNET_MSG_DATA_MAX \
62 (XPNET_MSG_SIZE - (u64)(&((struct xpnet_message *)0)->data)) 62 (XPNET_MSG_SIZE - offsetof(struct xpnet_message, data))
63#define XPNET_MSG_ALIGNED_SIZE (L1_CACHE_ALIGN(XPNET_MSG_SIZE)) 63#define XPNET_MSG_NENTRIES (PAGE_SIZE / XPC_MSG_MAX_SIZE)
64#define XPNET_MSG_NENTRIES (PAGE_SIZE / XPNET_MSG_ALIGNED_SIZE)
65 64
66#define XPNET_MAX_KTHREADS (XPNET_MSG_NENTRIES + 1) 65#define XPNET_MAX_KTHREADS (XPNET_MSG_NENTRIES + 1)
67#define XPNET_MAX_IDLE_KTHREADS (XPNET_MSG_NENTRIES + 1) 66#define XPNET_MAX_IDLE_KTHREADS (XPNET_MSG_NENTRIES + 1)
@@ -408,6 +407,7 @@ xpnet_send(struct sk_buff *skb, struct xpnet_pending_msg *queued_msg,
408{ 407{
409 u8 msg_buffer[XPNET_MSG_SIZE]; 408 u8 msg_buffer[XPNET_MSG_SIZE];
410 struct xpnet_message *msg = (struct xpnet_message *)&msg_buffer; 409 struct xpnet_message *msg = (struct xpnet_message *)&msg_buffer;
410 u16 msg_size = sizeof(struct xpnet_message);
411 enum xp_retval ret; 411 enum xp_retval ret;
412 412
413 msg->embedded_bytes = embedded_bytes; 413 msg->embedded_bytes = embedded_bytes;
@@ -417,6 +417,7 @@ xpnet_send(struct sk_buff *skb, struct xpnet_pending_msg *queued_msg,
417 &msg->data, skb->data, (size_t)embedded_bytes); 417 &msg->data, skb->data, (size_t)embedded_bytes);
418 skb_copy_from_linear_data(skb, &msg->data, 418 skb_copy_from_linear_data(skb, &msg->data,
419 (size_t)embedded_bytes); 419 (size_t)embedded_bytes);
420 msg_size += embedded_bytes - 1;
420 } else { 421 } else {
421 msg->version = XPNET_VERSION; 422 msg->version = XPNET_VERSION;
422 } 423 }
@@ -435,7 +436,7 @@ xpnet_send(struct sk_buff *skb, struct xpnet_pending_msg *queued_msg,
435 atomic_inc(&queued_msg->use_count); 436 atomic_inc(&queued_msg->use_count);
436 437
437 ret = xpc_send_notify(dest_partid, XPC_NET_CHANNEL, XPC_NOWAIT, msg, 438 ret = xpc_send_notify(dest_partid, XPC_NET_CHANNEL, XPC_NOWAIT, msg,
438 XPNET_MSG_SIZE, xpnet_send_completed, queued_msg); 439 msg_size, xpnet_send_completed, queued_msg);
439 if (unlikely(ret != xpSuccess)) 440 if (unlikely(ret != xpSuccess))
440 atomic_dec(&queued_msg->use_count); 441 atomic_dec(&queued_msg->use_count);
441} 442}