aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/sgi-xp/xpc_channel.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/sgi-xp/xpc_channel.c')
-rw-r--r--drivers/misc/sgi-xp/xpc_channel.c97
1 files changed, 58 insertions, 39 deletions
diff --git a/drivers/misc/sgi-xp/xpc_channel.c b/drivers/misc/sgi-xp/xpc_channel.c
index 99a2534c38a1..2eb3abff0e3a 100644
--- a/drivers/misc/sgi-xp/xpc_channel.c
+++ b/drivers/misc/sgi-xp/xpc_channel.c
@@ -3,7 +3,7 @@
3 * License. See the file "COPYING" in the main directory of this archive 3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details. 4 * for more details.
5 * 5 *
6 * Copyright (c) 2004-2008 Silicon Graphics, Inc. All Rights Reserved. 6 * Copyright (c) 2004-2009 Silicon Graphics, Inc. All Rights Reserved.
7 */ 7 */
8 8
9/* 9/*
@@ -44,10 +44,10 @@ xpc_process_connect(struct xpc_channel *ch, unsigned long *irq_flags)
44 44
45 if (ret != xpSuccess) 45 if (ret != xpSuccess)
46 XPC_DISCONNECT_CHANNEL(ch, ret, irq_flags); 46 XPC_DISCONNECT_CHANNEL(ch, ret, irq_flags);
47 else
48 ch->flags |= XPC_C_SETUP;
47 49
48 ch->flags |= XPC_C_SETUP; 50 if (ch->flags & XPC_C_DISCONNECTING)
49
50 if (ch->flags & (XPC_C_CONNECTED | XPC_C_DISCONNECTING))
51 return; 51 return;
52 } 52 }
53 53
@@ -59,14 +59,18 @@ xpc_process_connect(struct xpc_channel *ch, unsigned long *irq_flags)
59 if (!(ch->flags & XPC_C_ROPENREPLY)) 59 if (!(ch->flags & XPC_C_ROPENREPLY))
60 return; 60 return;
61 61
62 ch->flags = (XPC_C_CONNECTED | XPC_C_SETUP); /* clear all else */ 62 if (!(ch->flags & XPC_C_OPENCOMPLETE)) {
63 ch->flags |= (XPC_C_OPENCOMPLETE | XPC_C_CONNECTED);
64 xpc_send_chctl_opencomplete(ch, irq_flags);
65 }
66
67 if (!(ch->flags & XPC_C_ROPENCOMPLETE))
68 return;
63 69
64 dev_info(xpc_chan, "channel %d to partition %d connected\n", 70 dev_info(xpc_chan, "channel %d to partition %d connected\n",
65 ch->number, ch->partid); 71 ch->number, ch->partid);
66 72
67 spin_unlock_irqrestore(&ch->lock, *irq_flags); 73 ch->flags = (XPC_C_CONNECTED | XPC_C_SETUP); /* clear all else */
68 xpc_create_kthreads(ch, 1, 0);
69 spin_lock_irqsave(&ch->lock, *irq_flags);
70} 74}
71 75
72/* 76/*
@@ -184,6 +188,7 @@ xpc_process_openclose_chctl_flags(struct xpc_partition *part, int ch_number,
184 struct xpc_channel *ch = &part->channels[ch_number]; 188 struct xpc_channel *ch = &part->channels[ch_number];
185 enum xp_retval reason; 189 enum xp_retval reason;
186 enum xp_retval ret; 190 enum xp_retval ret;
191 int create_kthread = 0;
187 192
188 spin_lock_irqsave(&ch->lock, irq_flags); 193 spin_lock_irqsave(&ch->lock, irq_flags);
189 194
@@ -196,8 +201,7 @@ again:
196 * has had a chance to see that the channel is disconnected. 201 * has had a chance to see that the channel is disconnected.
197 */ 202 */
198 ch->delayed_chctl_flags |= chctl_flags; 203 ch->delayed_chctl_flags |= chctl_flags;
199 spin_unlock_irqrestore(&ch->lock, irq_flags); 204 goto out;
200 return;
201 } 205 }
202 206
203 if (chctl_flags & XPC_CHCTL_CLOSEREQUEST) { 207 if (chctl_flags & XPC_CHCTL_CLOSEREQUEST) {
@@ -239,8 +243,7 @@ again:
239 XPC_CHCTL_CLOSEREQUEST; 243 XPC_CHCTL_CLOSEREQUEST;
240 spin_unlock(&part->chctl_lock); 244 spin_unlock(&part->chctl_lock);
241 } 245 }
242 spin_unlock_irqrestore(&ch->lock, irq_flags); 246 goto out;
243 return;
244 } 247 }
245 248
246 XPC_SET_REASON(ch, 0, 0); 249 XPC_SET_REASON(ch, 0, 0);
@@ -250,7 +253,8 @@ again:
250 ch->flags |= (XPC_C_CONNECTING | XPC_C_ROPENREQUEST); 253 ch->flags |= (XPC_C_CONNECTING | XPC_C_ROPENREQUEST);
251 } 254 }
252 255
253 chctl_flags &= ~(XPC_CHCTL_OPENREQUEST | XPC_CHCTL_OPENREPLY); 256 chctl_flags &= ~(XPC_CHCTL_OPENREQUEST | XPC_CHCTL_OPENREPLY |
257 XPC_CHCTL_OPENCOMPLETE);
254 258
255 /* 259 /*
256 * The meaningful CLOSEREQUEST connection state fields are: 260 * The meaningful CLOSEREQUEST connection state fields are:
@@ -269,8 +273,7 @@ again:
269 XPC_DISCONNECT_CHANNEL(ch, reason, &irq_flags); 273 XPC_DISCONNECT_CHANNEL(ch, reason, &irq_flags);
270 274
271 DBUG_ON(chctl_flags & XPC_CHCTL_CLOSEREPLY); 275 DBUG_ON(chctl_flags & XPC_CHCTL_CLOSEREPLY);
272 spin_unlock_irqrestore(&ch->lock, irq_flags); 276 goto out;
273 return;
274 } 277 }
275 278
276 xpc_process_disconnect(ch, &irq_flags); 279 xpc_process_disconnect(ch, &irq_flags);
@@ -283,8 +286,7 @@ again:
283 286
284 if (ch->flags & XPC_C_DISCONNECTED) { 287 if (ch->flags & XPC_C_DISCONNECTED) {
285 DBUG_ON(part->act_state != XPC_P_AS_DEACTIVATING); 288 DBUG_ON(part->act_state != XPC_P_AS_DEACTIVATING);
286 spin_unlock_irqrestore(&ch->lock, irq_flags); 289 goto out;
287 return;
288 } 290 }
289 291
290 DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST)); 292 DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));
@@ -299,8 +301,7 @@ again:
299 XPC_CHCTL_CLOSEREPLY; 301 XPC_CHCTL_CLOSEREPLY;
300 spin_unlock(&part->chctl_lock); 302 spin_unlock(&part->chctl_lock);
301 } 303 }
302 spin_unlock_irqrestore(&ch->lock, irq_flags); 304 goto out;
303 return;
304 } 305 }
305 306
306 ch->flags |= XPC_C_RCLOSEREPLY; 307 ch->flags |= XPC_C_RCLOSEREPLY;
@@ -320,14 +321,12 @@ again:
320 321
321 if (part->act_state == XPC_P_AS_DEACTIVATING || 322 if (part->act_state == XPC_P_AS_DEACTIVATING ||
322 (ch->flags & XPC_C_ROPENREQUEST)) { 323 (ch->flags & XPC_C_ROPENREQUEST)) {
323 spin_unlock_irqrestore(&ch->lock, irq_flags); 324 goto out;
324 return;
325 } 325 }
326 326
327 if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_WDISCONNECT)) { 327 if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_WDISCONNECT)) {
328 ch->delayed_chctl_flags |= XPC_CHCTL_OPENREQUEST; 328 ch->delayed_chctl_flags |= XPC_CHCTL_OPENREQUEST;
329 spin_unlock_irqrestore(&ch->lock, irq_flags); 329 goto out;
330 return;
331 } 330 }
332 DBUG_ON(!(ch->flags & (XPC_C_DISCONNECTED | 331 DBUG_ON(!(ch->flags & (XPC_C_DISCONNECTED |
333 XPC_C_OPENREQUEST))); 332 XPC_C_OPENREQUEST)));
@@ -341,8 +340,7 @@ again:
341 */ 340 */
342 if (args->entry_size == 0 || args->local_nentries == 0) { 341 if (args->entry_size == 0 || args->local_nentries == 0) {
343 /* assume OPENREQUEST was delayed by mistake */ 342 /* assume OPENREQUEST was delayed by mistake */
344 spin_unlock_irqrestore(&ch->lock, irq_flags); 343 goto out;
345 return;
346 } 344 }
347 345
348 ch->flags |= (XPC_C_ROPENREQUEST | XPC_C_CONNECTING); 346 ch->flags |= (XPC_C_ROPENREQUEST | XPC_C_CONNECTING);
@@ -352,8 +350,7 @@ again:
352 if (args->entry_size != ch->entry_size) { 350 if (args->entry_size != ch->entry_size) {
353 XPC_DISCONNECT_CHANNEL(ch, xpUnequalMsgSizes, 351 XPC_DISCONNECT_CHANNEL(ch, xpUnequalMsgSizes,
354 &irq_flags); 352 &irq_flags);
355 spin_unlock_irqrestore(&ch->lock, irq_flags); 353 goto out;
356 return;
357 } 354 }
358 } else { 355 } else {
359 ch->entry_size = args->entry_size; 356 ch->entry_size = args->entry_size;
@@ -375,15 +372,13 @@ again:
375 args->local_msgqueue_pa, args->local_nentries, 372 args->local_msgqueue_pa, args->local_nentries,
376 args->remote_nentries, ch->partid, ch->number); 373 args->remote_nentries, ch->partid, ch->number);
377 374
378 if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_DISCONNECTED)) { 375 if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_DISCONNECTED))
379 spin_unlock_irqrestore(&ch->lock, irq_flags); 376 goto out;
380 return; 377
381 }
382 if (!(ch->flags & XPC_C_OPENREQUEST)) { 378 if (!(ch->flags & XPC_C_OPENREQUEST)) {
383 XPC_DISCONNECT_CHANNEL(ch, xpOpenCloseError, 379 XPC_DISCONNECT_CHANNEL(ch, xpOpenCloseError,
384 &irq_flags); 380 &irq_flags);
385 spin_unlock_irqrestore(&ch->lock, irq_flags); 381 goto out;
386 return;
387 } 382 }
388 383
389 DBUG_ON(!(ch->flags & XPC_C_ROPENREQUEST)); 384 DBUG_ON(!(ch->flags & XPC_C_ROPENREQUEST));
@@ -403,8 +398,7 @@ again:
403 ret = xpc_save_remote_msgqueue_pa(ch, args->local_msgqueue_pa); 398 ret = xpc_save_remote_msgqueue_pa(ch, args->local_msgqueue_pa);
404 if (ret != xpSuccess) { 399 if (ret != xpSuccess) {
405 XPC_DISCONNECT_CHANNEL(ch, ret, &irq_flags); 400 XPC_DISCONNECT_CHANNEL(ch, ret, &irq_flags);
406 spin_unlock_irqrestore(&ch->lock, irq_flags); 401 goto out;
407 return;
408 } 402 }
409 ch->flags |= XPC_C_ROPENREPLY; 403 ch->flags |= XPC_C_ROPENREPLY;
410 404
@@ -430,7 +424,36 @@ again:
430 xpc_process_connect(ch, &irq_flags); 424 xpc_process_connect(ch, &irq_flags);
431 } 425 }
432 426
427 if (chctl_flags & XPC_CHCTL_OPENCOMPLETE) {
428
429 dev_dbg(xpc_chan, "XPC_CHCTL_OPENCOMPLETE received from "
430 "partid=%d, channel=%d\n", ch->partid, ch->number);
431
432 if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_DISCONNECTED))
433 goto out;
434
435 if (!(ch->flags & XPC_C_OPENREQUEST) ||
436 !(ch->flags & XPC_C_OPENREPLY)) {
437 XPC_DISCONNECT_CHANNEL(ch, xpOpenCloseError,
438 &irq_flags);
439 goto out;
440 }
441
442 DBUG_ON(!(ch->flags & XPC_C_ROPENREQUEST));
443 DBUG_ON(!(ch->flags & XPC_C_ROPENREPLY));
444 DBUG_ON(!(ch->flags & XPC_C_CONNECTED));
445
446 ch->flags |= XPC_C_ROPENCOMPLETE;
447
448 xpc_process_connect(ch, &irq_flags);
449 create_kthread = 1;
450 }
451
452out:
433 spin_unlock_irqrestore(&ch->lock, irq_flags); 453 spin_unlock_irqrestore(&ch->lock, irq_flags);
454
455 if (create_kthread)
456 xpc_create_kthreads(ch, 1, 0);
434} 457}
435 458
436/* 459/*
@@ -564,10 +587,6 @@ xpc_process_sent_chctl_flags(struct xpc_partition *part)
564 if (!(ch_flags & XPC_C_OPENREQUEST)) { 587 if (!(ch_flags & XPC_C_OPENREQUEST)) {
565 DBUG_ON(ch_flags & XPC_C_SETUP); 588 DBUG_ON(ch_flags & XPC_C_SETUP);
566 (void)xpc_connect_channel(ch); 589 (void)xpc_connect_channel(ch);
567 } else {
568 spin_lock_irqsave(&ch->lock, irq_flags);
569 xpc_process_connect(ch, &irq_flags);
570 spin_unlock_irqrestore(&ch->lock, irq_flags);
571 } 590 }
572 continue; 591 continue;
573 } 592 }