diff options
Diffstat (limited to 'drivers/misc/sgi-xp/xpc_channel.c')
-rw-r--r-- | drivers/misc/sgi-xp/xpc_channel.c | 97 |
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 | |||
452 | out: | ||
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 | } |