diff options
author | Jack Steiner <steiner@sgi.com> | 2009-04-02 19:59:10 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-02 22:05:06 -0400 |
commit | 6f2584f47474d29ce829604bfc8b56c10b352fdb (patch) | |
tree | f5b5c63c7c73785a641c995c2fe48b4c5cc726eb /drivers/misc | |
parent | ecdaf2b55251f718a1fbaf4a3f72bfd6e25c582c (diff) |
sgi-gru: add support to the GRU driver for message queue interrupts
Add support to the GRU driver for message queue interrupts.
Signed-off-by: Jack Steiner <steiner@sgi.com>
Signed-off-by: Dean Nelson <dcn@sgi.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/sgi-gru/grukservices.c | 104 | ||||
-rw-r--r-- | drivers/misc/sgi-gru/grukservices.h | 33 | ||||
-rw-r--r-- | drivers/misc/sgi-xp/xpc.h | 33 | ||||
-rw-r--r-- | drivers/misc/sgi-xp/xpc_channel.c | 8 | ||||
-rw-r--r-- | drivers/misc/sgi-xp/xpc_main.c | 6 | ||||
-rw-r--r-- | drivers/misc/sgi-xp/xpc_sn2.c | 10 | ||||
-rw-r--r-- | drivers/misc/sgi-xp/xpc_uv.c | 229 |
7 files changed, 305 insertions, 118 deletions
diff --git a/drivers/misc/sgi-gru/grukservices.c b/drivers/misc/sgi-gru/grukservices.c index 247635d6d6e0..a37128431155 100644 --- a/drivers/misc/sgi-gru/grukservices.c +++ b/drivers/misc/sgi-gru/grukservices.c | |||
@@ -52,8 +52,10 @@ | |||
52 | */ | 52 | */ |
53 | 53 | ||
54 | /* Blade percpu resources PERMANENTLY reserved for kernel use */ | 54 | /* Blade percpu resources PERMANENTLY reserved for kernel use */ |
55 | #define GRU_NUM_KERNEL_CBR 1 | 55 | #define GRU_NUM_KERNEL_CBR 1 |
56 | #define GRU_NUM_KERNEL_DSR_BYTES 256 | 56 | #define GRU_NUM_KERNEL_DSR_BYTES 256 |
57 | #define GRU_NUM_KERNEL_DSR_CL (GRU_NUM_KERNEL_DSR_BYTES / \ | ||
58 | GRU_CACHE_LINE_BYTES) | ||
57 | #define KERNEL_CTXNUM 15 | 59 | #define KERNEL_CTXNUM 15 |
58 | 60 | ||
59 | /* GRU instruction attributes for all instructions */ | 61 | /* GRU instruction attributes for all instructions */ |
@@ -94,7 +96,6 @@ struct message_header { | |||
94 | char fill; | 96 | char fill; |
95 | }; | 97 | }; |
96 | 98 | ||
97 | #define QLINES(mq) ((mq) + offsetof(struct message_queue, qlines)) | ||
98 | #define HSTATUS(mq, h) ((mq) + offsetof(struct message_queue, hstatus[h])) | 99 | #define HSTATUS(mq, h) ((mq) + offsetof(struct message_queue, hstatus[h])) |
99 | 100 | ||
100 | static int gru_get_cpu_resources(int dsr_bytes, void **cb, void **dsr) | 101 | static int gru_get_cpu_resources(int dsr_bytes, void **cb, void **dsr) |
@@ -250,7 +251,8 @@ static inline void restore_present2(void *p, int val) | |||
250 | * Create a message queue. | 251 | * Create a message queue. |
251 | * qlines - message queue size in cache lines. Includes 2-line header. | 252 | * qlines - message queue size in cache lines. Includes 2-line header. |
252 | */ | 253 | */ |
253 | int gru_create_message_queue(void *p, unsigned int bytes) | 254 | int gru_create_message_queue(struct gru_message_queue_desc *mqd, |
255 | void *p, unsigned int bytes, int nasid, int vector, int apicid) | ||
254 | { | 256 | { |
255 | struct message_queue *mq = p; | 257 | struct message_queue *mq = p; |
256 | unsigned int qlines; | 258 | unsigned int qlines; |
@@ -265,6 +267,12 @@ int gru_create_message_queue(void *p, unsigned int bytes) | |||
265 | mq->hstatus[0] = 0; | 267 | mq->hstatus[0] = 0; |
266 | mq->hstatus[1] = 1; | 268 | mq->hstatus[1] = 1; |
267 | mq->head = gru_mesq_head(2, qlines / 2 + 1); | 269 | mq->head = gru_mesq_head(2, qlines / 2 + 1); |
270 | mqd->mq = mq; | ||
271 | mqd->mq_gpa = uv_gpa(mq); | ||
272 | mqd->qlines = qlines; | ||
273 | mqd->interrupt_pnode = UV_NASID_TO_PNODE(nasid); | ||
274 | mqd->interrupt_vector = vector; | ||
275 | mqd->interrupt_apicid = apicid; | ||
268 | return 0; | 276 | return 0; |
269 | } | 277 | } |
270 | EXPORT_SYMBOL_GPL(gru_create_message_queue); | 278 | EXPORT_SYMBOL_GPL(gru_create_message_queue); |
@@ -277,8 +285,8 @@ EXPORT_SYMBOL_GPL(gru_create_message_queue); | |||
277 | * -1 - if mesq sent successfully but queue not full | 285 | * -1 - if mesq sent successfully but queue not full |
278 | * >0 - unexpected error. MQE_xxx returned | 286 | * >0 - unexpected error. MQE_xxx returned |
279 | */ | 287 | */ |
280 | static int send_noop_message(void *cb, | 288 | static int send_noop_message(void *cb, struct gru_message_queue_desc *mqd, |
281 | unsigned long mq, void *mesg) | 289 | void *mesg) |
282 | { | 290 | { |
283 | const struct message_header noop_header = { | 291 | const struct message_header noop_header = { |
284 | .present = MQS_NOOP, .lines = 1}; | 292 | .present = MQS_NOOP, .lines = 1}; |
@@ -289,7 +297,7 @@ static int send_noop_message(void *cb, | |||
289 | STAT(mesq_noop); | 297 | STAT(mesq_noop); |
290 | save_mhdr = *mhdr; | 298 | save_mhdr = *mhdr; |
291 | *mhdr = noop_header; | 299 | *mhdr = noop_header; |
292 | gru_mesq(cb, mq, gru_get_tri(mhdr), 1, IMA); | 300 | gru_mesq(cb, mqd->mq_gpa, gru_get_tri(mhdr), 1, IMA); |
293 | ret = gru_wait(cb); | 301 | ret = gru_wait(cb); |
294 | 302 | ||
295 | if (ret) { | 303 | if (ret) { |
@@ -313,7 +321,7 @@ static int send_noop_message(void *cb, | |||
313 | break; | 321 | break; |
314 | case CBSS_PUT_NACKED: | 322 | case CBSS_PUT_NACKED: |
315 | STAT(mesq_noop_put_nacked); | 323 | STAT(mesq_noop_put_nacked); |
316 | m = mq + (gru_get_amo_value_head(cb) << 6); | 324 | m = mqd->mq_gpa + (gru_get_amo_value_head(cb) << 6); |
317 | gru_vstore(cb, m, gru_get_tri(mesg), XTYPE_CL, 1, 1, | 325 | gru_vstore(cb, m, gru_get_tri(mesg), XTYPE_CL, 1, 1, |
318 | IMA); | 326 | IMA); |
319 | if (gru_wait(cb) == CBS_IDLE) | 327 | if (gru_wait(cb) == CBS_IDLE) |
@@ -333,30 +341,20 @@ static int send_noop_message(void *cb, | |||
333 | /* | 341 | /* |
334 | * Handle a gru_mesq full. | 342 | * Handle a gru_mesq full. |
335 | */ | 343 | */ |
336 | static int send_message_queue_full(void *cb, | 344 | static int send_message_queue_full(void *cb, struct gru_message_queue_desc *mqd, |
337 | unsigned long mq, void *mesg, int lines) | 345 | void *mesg, int lines) |
338 | { | 346 | { |
339 | union gru_mesqhead mqh; | 347 | union gru_mesqhead mqh; |
340 | unsigned int limit, head; | 348 | unsigned int limit, head; |
341 | unsigned long avalue; | 349 | unsigned long avalue; |
342 | int half, qlines, save; | 350 | int half, qlines; |
343 | 351 | ||
344 | /* Determine if switching to first/second half of q */ | 352 | /* Determine if switching to first/second half of q */ |
345 | avalue = gru_get_amo_value(cb); | 353 | avalue = gru_get_amo_value(cb); |
346 | head = gru_get_amo_value_head(cb); | 354 | head = gru_get_amo_value_head(cb); |
347 | limit = gru_get_amo_value_limit(cb); | 355 | limit = gru_get_amo_value_limit(cb); |
348 | 356 | ||
349 | /* | 357 | qlines = mqd->qlines; |
350 | * Fetch "qlines" from the queue header. Since the queue may be | ||
351 | * in memory that can't be accessed using socket addresses, use | ||
352 | * the GRU to access the data. Use DSR space from the message. | ||
353 | */ | ||
354 | save = *(int *)mesg; | ||
355 | gru_vload(cb, QLINES(mq), gru_get_tri(mesg), XTYPE_W, 1, 1, IMA); | ||
356 | if (gru_wait(cb) != CBS_IDLE) | ||
357 | goto cberr; | ||
358 | qlines = *(int *)mesg; | ||
359 | *(int *)mesg = save; | ||
360 | half = (limit != qlines); | 358 | half = (limit != qlines); |
361 | 359 | ||
362 | if (half) | 360 | if (half) |
@@ -365,7 +363,7 @@ static int send_message_queue_full(void *cb, | |||
365 | mqh = gru_mesq_head(2, qlines / 2 + 1); | 363 | mqh = gru_mesq_head(2, qlines / 2 + 1); |
366 | 364 | ||
367 | /* Try to get lock for switching head pointer */ | 365 | /* Try to get lock for switching head pointer */ |
368 | gru_gamir(cb, EOP_IR_CLR, HSTATUS(mq, half), XTYPE_DW, IMA); | 366 | gru_gamir(cb, EOP_IR_CLR, HSTATUS(mqd->mq_gpa, half), XTYPE_DW, IMA); |
369 | if (gru_wait(cb) != CBS_IDLE) | 367 | if (gru_wait(cb) != CBS_IDLE) |
370 | goto cberr; | 368 | goto cberr; |
371 | if (!gru_get_amo_value(cb)) { | 369 | if (!gru_get_amo_value(cb)) { |
@@ -375,8 +373,8 @@ static int send_message_queue_full(void *cb, | |||
375 | 373 | ||
376 | /* Got the lock. Send optional NOP if queue not full, */ | 374 | /* Got the lock. Send optional NOP if queue not full, */ |
377 | if (head != limit) { | 375 | if (head != limit) { |
378 | if (send_noop_message(cb, mq, mesg)) { | 376 | if (send_noop_message(cb, mqd, mesg)) { |
379 | gru_gamir(cb, EOP_IR_INC, HSTATUS(mq, half), | 377 | gru_gamir(cb, EOP_IR_INC, HSTATUS(mqd->mq_gpa, half), |
380 | XTYPE_DW, IMA); | 378 | XTYPE_DW, IMA); |
381 | if (gru_wait(cb) != CBS_IDLE) | 379 | if (gru_wait(cb) != CBS_IDLE) |
382 | goto cberr; | 380 | goto cberr; |
@@ -387,14 +385,16 @@ static int send_message_queue_full(void *cb, | |||
387 | } | 385 | } |
388 | 386 | ||
389 | /* Then flip queuehead to other half of queue. */ | 387 | /* Then flip queuehead to other half of queue. */ |
390 | gru_gamer(cb, EOP_ERR_CSWAP, mq, XTYPE_DW, mqh.val, avalue, IMA); | 388 | gru_gamer(cb, EOP_ERR_CSWAP, mqd->mq_gpa, XTYPE_DW, mqh.val, avalue, |
389 | IMA); | ||
391 | if (gru_wait(cb) != CBS_IDLE) | 390 | if (gru_wait(cb) != CBS_IDLE) |
392 | goto cberr; | 391 | goto cberr; |
393 | 392 | ||
394 | /* If not successfully in swapping queue head, clear the hstatus lock */ | 393 | /* If not successfully in swapping queue head, clear the hstatus lock */ |
395 | if (gru_get_amo_value(cb) != avalue) { | 394 | if (gru_get_amo_value(cb) != avalue) { |
396 | STAT(mesq_qf_switch_head_failed); | 395 | STAT(mesq_qf_switch_head_failed); |
397 | gru_gamir(cb, EOP_IR_INC, HSTATUS(mq, half), XTYPE_DW, IMA); | 396 | gru_gamir(cb, EOP_IR_INC, HSTATUS(mqd->mq_gpa, half), XTYPE_DW, |
397 | IMA); | ||
398 | if (gru_wait(cb) != CBS_IDLE) | 398 | if (gru_wait(cb) != CBS_IDLE) |
399 | goto cberr; | 399 | goto cberr; |
400 | } | 400 | } |
@@ -404,15 +404,25 @@ cberr: | |||
404 | return MQE_UNEXPECTED_CB_ERR; | 404 | return MQE_UNEXPECTED_CB_ERR; |
405 | } | 405 | } |
406 | 406 | ||
407 | /* | ||
408 | * Send a cross-partition interrupt to the SSI that contains the target | ||
409 | * message queue. Normally, the interrupt is automatically delivered by hardware | ||
410 | * but some error conditions require explicit delivery. | ||
411 | */ | ||
412 | static void send_message_queue_interrupt(struct gru_message_queue_desc *mqd) | ||
413 | { | ||
414 | if (mqd->interrupt_vector) | ||
415 | uv_hub_send_ipi(mqd->interrupt_pnode, mqd->interrupt_apicid, | ||
416 | mqd->interrupt_vector); | ||
417 | } | ||
418 | |||
407 | 419 | ||
408 | /* | 420 | /* |
409 | * Handle a gru_mesq failure. Some of these failures are software recoverable | 421 | * Handle a gru_mesq failure. Some of these failures are software recoverable |
410 | * or retryable. | 422 | * or retryable. |
411 | */ | 423 | */ |
412 | static int send_message_failure(void *cb, | 424 | static int send_message_failure(void *cb, struct gru_message_queue_desc *mqd, |
413 | unsigned long mq, | 425 | void *mesg, int lines) |
414 | void *mesg, | ||
415 | int lines) | ||
416 | { | 426 | { |
417 | int substatus, ret = 0; | 427 | int substatus, ret = 0; |
418 | unsigned long m; | 428 | unsigned long m; |
@@ -429,7 +439,7 @@ static int send_message_failure(void *cb, | |||
429 | break; | 439 | break; |
430 | case CBSS_QLIMIT_REACHED: | 440 | case CBSS_QLIMIT_REACHED: |
431 | STAT(mesq_send_qlimit_reached); | 441 | STAT(mesq_send_qlimit_reached); |
432 | ret = send_message_queue_full(cb, mq, mesg, lines); | 442 | ret = send_message_queue_full(cb, mqd, mesg, lines); |
433 | break; | 443 | break; |
434 | case CBSS_AMO_NACKED: | 444 | case CBSS_AMO_NACKED: |
435 | STAT(mesq_send_amo_nacked); | 445 | STAT(mesq_send_amo_nacked); |
@@ -437,12 +447,14 @@ static int send_message_failure(void *cb, | |||
437 | break; | 447 | break; |
438 | case CBSS_PUT_NACKED: | 448 | case CBSS_PUT_NACKED: |
439 | STAT(mesq_send_put_nacked); | 449 | STAT(mesq_send_put_nacked); |
440 | m = mq + (gru_get_amo_value_head(cb) << 6); | 450 | m = mqd->mq_gpa + (gru_get_amo_value_head(cb) << 6); |
441 | gru_vstore(cb, m, gru_get_tri(mesg), XTYPE_CL, lines, 1, IMA); | 451 | gru_vstore(cb, m, gru_get_tri(mesg), XTYPE_CL, lines, 1, IMA); |
442 | if (gru_wait(cb) == CBS_IDLE) | 452 | if (gru_wait(cb) == CBS_IDLE) { |
443 | ret = MQE_OK; | 453 | ret = MQE_OK; |
444 | else | 454 | send_message_queue_interrupt(mqd); |
455 | } else { | ||
445 | ret = MQE_UNEXPECTED_CB_ERR; | 456 | ret = MQE_UNEXPECTED_CB_ERR; |
457 | } | ||
446 | break; | 458 | break; |
447 | default: | 459 | default: |
448 | BUG(); | 460 | BUG(); |
@@ -452,12 +464,12 @@ static int send_message_failure(void *cb, | |||
452 | 464 | ||
453 | /* | 465 | /* |
454 | * Send a message to a message queue | 466 | * Send a message to a message queue |
455 | * cb GRU control block to use to send message | 467 | * mqd message queue descriptor |
456 | * mq message queue | ||
457 | * mesg message. ust be vaddr within a GSEG | 468 | * mesg message. ust be vaddr within a GSEG |
458 | * bytes message size (<= 2 CL) | 469 | * bytes message size (<= 2 CL) |
459 | */ | 470 | */ |
460 | int gru_send_message_gpa(unsigned long mq, void *mesg, unsigned int bytes) | 471 | int gru_send_message_gpa(struct gru_message_queue_desc *mqd, void *mesg, |
472 | unsigned int bytes) | ||
461 | { | 473 | { |
462 | struct message_header *mhdr; | 474 | struct message_header *mhdr; |
463 | void *cb; | 475 | void *cb; |
@@ -481,10 +493,10 @@ int gru_send_message_gpa(unsigned long mq, void *mesg, unsigned int bytes) | |||
481 | 493 | ||
482 | do { | 494 | do { |
483 | ret = MQE_OK; | 495 | ret = MQE_OK; |
484 | gru_mesq(cb, mq, gru_get_tri(mhdr), clines, IMA); | 496 | gru_mesq(cb, mqd->mq_gpa, gru_get_tri(mhdr), clines, IMA); |
485 | istatus = gru_wait(cb); | 497 | istatus = gru_wait(cb); |
486 | if (istatus != CBS_IDLE) | 498 | if (istatus != CBS_IDLE) |
487 | ret = send_message_failure(cb, mq, dsr, clines); | 499 | ret = send_message_failure(cb, mqd, dsr, clines); |
488 | } while (ret == MQIE_AGAIN); | 500 | } while (ret == MQIE_AGAIN); |
489 | gru_free_cpu_resources(cb, dsr); | 501 | gru_free_cpu_resources(cb, dsr); |
490 | 502 | ||
@@ -497,9 +509,9 @@ EXPORT_SYMBOL_GPL(gru_send_message_gpa); | |||
497 | /* | 509 | /* |
498 | * Advance the receive pointer for the queue to the next message. | 510 | * Advance the receive pointer for the queue to the next message. |
499 | */ | 511 | */ |
500 | void gru_free_message(void *rmq, void *mesg) | 512 | void gru_free_message(struct gru_message_queue_desc *mqd, void *mesg) |
501 | { | 513 | { |
502 | struct message_queue *mq = rmq; | 514 | struct message_queue *mq = mqd->mq; |
503 | struct message_header *mhdr = mq->next; | 515 | struct message_header *mhdr = mq->next; |
504 | void *next, *pnext; | 516 | void *next, *pnext; |
505 | int half = -1; | 517 | int half = -1; |
@@ -529,16 +541,16 @@ EXPORT_SYMBOL_GPL(gru_free_message); | |||
529 | * present. User must call next_message() to move to next message. | 541 | * present. User must call next_message() to move to next message. |
530 | * rmq message queue | 542 | * rmq message queue |
531 | */ | 543 | */ |
532 | void *gru_get_next_message(void *rmq) | 544 | void *gru_get_next_message(struct gru_message_queue_desc *mqd) |
533 | { | 545 | { |
534 | struct message_queue *mq = rmq; | 546 | struct message_queue *mq = mqd->mq; |
535 | struct message_header *mhdr = mq->next; | 547 | struct message_header *mhdr = mq->next; |
536 | int present = mhdr->present; | 548 | int present = mhdr->present; |
537 | 549 | ||
538 | /* skip NOOP messages */ | 550 | /* skip NOOP messages */ |
539 | STAT(mesq_receive); | 551 | STAT(mesq_receive); |
540 | while (present == MQS_NOOP) { | 552 | while (present == MQS_NOOP) { |
541 | gru_free_message(rmq, mhdr); | 553 | gru_free_message(mqd, mhdr); |
542 | mhdr = mq->next; | 554 | mhdr = mq->next; |
543 | present = mhdr->present; | 555 | present = mhdr->present; |
544 | } | 556 | } |
@@ -576,7 +588,7 @@ int gru_copy_gpa(unsigned long dest_gpa, unsigned long src_gpa, | |||
576 | if (gru_get_cpu_resources(GRU_NUM_KERNEL_DSR_BYTES, &cb, &dsr)) | 588 | if (gru_get_cpu_resources(GRU_NUM_KERNEL_DSR_BYTES, &cb, &dsr)) |
577 | return MQE_BUG_NO_RESOURCES; | 589 | return MQE_BUG_NO_RESOURCES; |
578 | gru_bcopy(cb, src_gpa, dest_gpa, gru_get_tri(dsr), | 590 | gru_bcopy(cb, src_gpa, dest_gpa, gru_get_tri(dsr), |
579 | XTYPE_B, bytes, GRU_NUM_KERNEL_DSR_BYTES, IMA); | 591 | XTYPE_B, bytes, GRU_NUM_KERNEL_DSR_CL, IMA); |
580 | ret = gru_wait(cb); | 592 | ret = gru_wait(cb); |
581 | gru_free_cpu_resources(cb, dsr); | 593 | gru_free_cpu_resources(cb, dsr); |
582 | return ret; | 594 | return ret; |
@@ -611,7 +623,7 @@ static int quicktest(struct gru_state *gru) | |||
611 | 623 | ||
612 | if (word0 != word1 || word0 != MAGIC) { | 624 | if (word0 != word1 || word0 != MAGIC) { |
613 | printk | 625 | printk |
614 | ("GRU quicktest err: gru %d, found 0x%lx, expected 0x%lx\n", | 626 | ("GRU quicktest err: gid %d, found 0x%lx, expected 0x%lx\n", |
615 | gru->gs_gid, word1, MAGIC); | 627 | gru->gs_gid, word1, MAGIC); |
616 | BUG(); /* ZZZ should not be fatal */ | 628 | BUG(); /* ZZZ should not be fatal */ |
617 | } | 629 | } |
diff --git a/drivers/misc/sgi-gru/grukservices.h b/drivers/misc/sgi-gru/grukservices.h index eb17e0a3ac61..747ed315d56f 100644 --- a/drivers/misc/sgi-gru/grukservices.h +++ b/drivers/misc/sgi-gru/grukservices.h | |||
@@ -41,6 +41,15 @@ | |||
41 | * - gru_create_message_queue() needs interrupt vector info | 41 | * - gru_create_message_queue() needs interrupt vector info |
42 | */ | 42 | */ |
43 | 43 | ||
44 | struct gru_message_queue_desc { | ||
45 | void *mq; /* message queue vaddress */ | ||
46 | unsigned long mq_gpa; /* global address of mq */ | ||
47 | int qlines; /* queue size in CL */ | ||
48 | int interrupt_vector; /* interrupt vector */ | ||
49 | int interrupt_pnode; /* pnode for interrupt */ | ||
50 | int interrupt_apicid; /* lapicid for interrupt */ | ||
51 | }; | ||
52 | |||
44 | /* | 53 | /* |
45 | * Initialize a user allocated chunk of memory to be used as | 54 | * Initialize a user allocated chunk of memory to be used as |
46 | * a message queue. The caller must ensure that the queue is | 55 | * a message queue. The caller must ensure that the queue is |
@@ -51,14 +60,19 @@ | |||
51 | * to manage the queue. | 60 | * to manage the queue. |
52 | * | 61 | * |
53 | * Input: | 62 | * Input: |
54 | * p pointer to user allocated memory. | 63 | * mqd pointer to message queue descriptor |
64 | * p pointer to user allocated mesq memory. | ||
55 | * bytes size of message queue in bytes | 65 | * bytes size of message queue in bytes |
66 | * vector interrupt vector (zero if no interrupts) | ||
67 | * nasid nasid of blade where interrupt is delivered | ||
68 | * apicid apicid of cpu for interrupt | ||
56 | * | 69 | * |
57 | * Errors: | 70 | * Errors: |
58 | * 0 OK | 71 | * 0 OK |
59 | * >0 error | 72 | * >0 error |
60 | */ | 73 | */ |
61 | extern int gru_create_message_queue(void *p, unsigned int bytes); | 74 | extern int gru_create_message_queue(struct gru_message_queue_desc *mqd, |
75 | void *p, unsigned int bytes, int nasid, int vector, int apicid); | ||
62 | 76 | ||
63 | /* | 77 | /* |
64 | * Send a message to a message queue. | 78 | * Send a message to a message queue. |
@@ -68,7 +82,7 @@ extern int gru_create_message_queue(void *p, unsigned int bytes); | |||
68 | * | 82 | * |
69 | * | 83 | * |
70 | * Input: | 84 | * Input: |
71 | * xmq message queue - must be a UV global physical address | 85 | * mqd pointer to message queue descriptor |
72 | * mesg pointer to message. Must be 64-bit aligned | 86 | * mesg pointer to message. Must be 64-bit aligned |
73 | * bytes size of message in bytes | 87 | * bytes size of message in bytes |
74 | * | 88 | * |
@@ -77,8 +91,8 @@ extern int gru_create_message_queue(void *p, unsigned int bytes); | |||
77 | * >0 Send failure - see error codes below | 91 | * >0 Send failure - see error codes below |
78 | * | 92 | * |
79 | */ | 93 | */ |
80 | extern int gru_send_message_gpa(unsigned long mq_gpa, void *mesg, | 94 | extern int gru_send_message_gpa(struct gru_message_queue_desc *mqd, |
81 | unsigned int bytes); | 95 | void *mesg, unsigned int bytes); |
82 | 96 | ||
83 | /* Status values for gru_send_message() */ | 97 | /* Status values for gru_send_message() */ |
84 | #define MQE_OK 0 /* message sent successfully */ | 98 | #define MQE_OK 0 /* message sent successfully */ |
@@ -94,10 +108,11 @@ extern int gru_send_message_gpa(unsigned long mq_gpa, void *mesg, | |||
94 | * API extensions may allow for out-of-order freeing. | 108 | * API extensions may allow for out-of-order freeing. |
95 | * | 109 | * |
96 | * Input | 110 | * Input |
97 | * mq message queue | 111 | * mqd pointer to message queue descriptor |
98 | * mesq message being freed | 112 | * mesq message being freed |
99 | */ | 113 | */ |
100 | extern void gru_free_message(void *mq, void *mesq); | 114 | extern void gru_free_message(struct gru_message_queue_desc *mqd, |
115 | void *mesq); | ||
101 | 116 | ||
102 | /* | 117 | /* |
103 | * Get next message from message queue. Returns pointer to | 118 | * Get next message from message queue. Returns pointer to |
@@ -106,13 +121,13 @@ extern void gru_free_message(void *mq, void *mesq); | |||
106 | * in order to move the queue pointers to next message. | 121 | * in order to move the queue pointers to next message. |
107 | * | 122 | * |
108 | * Input | 123 | * Input |
109 | * mq message queue | 124 | * mqd pointer to message queue descriptor |
110 | * | 125 | * |
111 | * Output: | 126 | * Output: |
112 | * p pointer to message | 127 | * p pointer to message |
113 | * NULL no message available | 128 | * NULL no message available |
114 | */ | 129 | */ |
115 | extern void *gru_get_next_message(void *mq); | 130 | extern void *gru_get_next_message(struct gru_message_queue_desc *mqd); |
116 | 131 | ||
117 | 132 | ||
118 | /* | 133 | /* |
diff --git a/drivers/misc/sgi-xp/xpc.h b/drivers/misc/sgi-xp/xpc.h index 275b78896a73..114444cfd496 100644 --- a/drivers/misc/sgi-xp/xpc.h +++ b/drivers/misc/sgi-xp/xpc.h | |||
@@ -92,7 +92,9 @@ struct xpc_rsvd_page { | |||
92 | u8 pad1[3]; /* align to next u64 in 1st 64-byte cacheline */ | 92 | u8 pad1[3]; /* align to next u64 in 1st 64-byte cacheline */ |
93 | union { | 93 | union { |
94 | unsigned long vars_pa; /* phys address of struct xpc_vars */ | 94 | unsigned long vars_pa; /* phys address of struct xpc_vars */ |
95 | unsigned long activate_mq_gpa; /* gru phy addr of activate_mq */ | 95 | unsigned long activate_gru_mq_desc_gpa; /* phys addr of */ |
96 | /* activate mq's */ | ||
97 | /* gru mq descriptor */ | ||
96 | } sn; | 98 | } sn; |
97 | unsigned long ts_jiffies; /* timestamp when rsvd pg was setup by XPC */ | 99 | unsigned long ts_jiffies; /* timestamp when rsvd pg was setup by XPC */ |
98 | u64 pad2[10]; /* align to last u64 in 2nd 64-byte cacheline */ | 100 | u64 pad2[10]; /* align to last u64 in 2nd 64-byte cacheline */ |
@@ -189,7 +191,9 @@ struct xpc_gru_mq_uv { | |||
189 | int irq; /* irq raised when message is received in mq */ | 191 | int irq; /* irq raised when message is received in mq */ |
190 | int mmr_blade; /* blade where watchlist was allocated from */ | 192 | int mmr_blade; /* blade where watchlist was allocated from */ |
191 | unsigned long mmr_offset; /* offset of irq mmr located on mmr_blade */ | 193 | unsigned long mmr_offset; /* offset of irq mmr located on mmr_blade */ |
194 | unsigned long mmr_value; /* value of irq mmr located on mmr_blade */ | ||
192 | int watchlist_num; /* number of watchlist allocatd by BIOS */ | 195 | int watchlist_num; /* number of watchlist allocatd by BIOS */ |
196 | void *gru_mq_desc; /* opaque structure used by the GRU driver */ | ||
193 | }; | 197 | }; |
194 | 198 | ||
195 | /* | 199 | /* |
@@ -197,6 +201,7 @@ struct xpc_gru_mq_uv { | |||
197 | * heartbeat, partition active state, and channel state. This is UV only. | 201 | * heartbeat, partition active state, and channel state. This is UV only. |
198 | */ | 202 | */ |
199 | struct xpc_activate_mq_msghdr_uv { | 203 | struct xpc_activate_mq_msghdr_uv { |
204 | unsigned int gru_msg_hdr; /* FOR GRU INTERNAL USE ONLY */ | ||
200 | short partid; /* sender's partid */ | 205 | short partid; /* sender's partid */ |
201 | u8 act_state; /* sender's act_state at time msg sent */ | 206 | u8 act_state; /* sender's act_state at time msg sent */ |
202 | u8 type; /* message's type */ | 207 | u8 type; /* message's type */ |
@@ -232,7 +237,7 @@ struct xpc_activate_mq_msg_heartbeat_req_uv { | |||
232 | struct xpc_activate_mq_msg_activate_req_uv { | 237 | struct xpc_activate_mq_msg_activate_req_uv { |
233 | struct xpc_activate_mq_msghdr_uv hdr; | 238 | struct xpc_activate_mq_msghdr_uv hdr; |
234 | unsigned long rp_gpa; | 239 | unsigned long rp_gpa; |
235 | unsigned long activate_mq_gpa; | 240 | unsigned long activate_gru_mq_desc_gpa; |
236 | }; | 241 | }; |
237 | 242 | ||
238 | struct xpc_activate_mq_msg_deactivate_req_uv { | 243 | struct xpc_activate_mq_msg_deactivate_req_uv { |
@@ -263,7 +268,7 @@ struct xpc_activate_mq_msg_chctl_openreply_uv { | |||
263 | short ch_number; | 268 | short ch_number; |
264 | short remote_nentries; /* ??? Is this needed? What is? */ | 269 | short remote_nentries; /* ??? Is this needed? What is? */ |
265 | short local_nentries; /* ??? Is this needed? What is? */ | 270 | short local_nentries; /* ??? Is this needed? What is? */ |
266 | unsigned long local_notify_mq_gpa; | 271 | unsigned long notify_gru_mq_desc_gpa; |
267 | }; | 272 | }; |
268 | 273 | ||
269 | /* | 274 | /* |
@@ -510,8 +515,8 @@ struct xpc_channel_sn2 { | |||
510 | }; | 515 | }; |
511 | 516 | ||
512 | struct xpc_channel_uv { | 517 | struct xpc_channel_uv { |
513 | unsigned long remote_notify_mq_gpa; /* gru phys address of remote */ | 518 | void *cached_notify_gru_mq_desc; /* remote partition's notify mq's */ |
514 | /* partition's notify mq */ | 519 | /* gru mq descriptor */ |
515 | 520 | ||
516 | struct xpc_send_msg_slot_uv *send_msg_slots; | 521 | struct xpc_send_msg_slot_uv *send_msg_slots; |
517 | void *recv_msg_slots; /* each slot will hold a xpc_notify_mq_msg_uv */ | 522 | void *recv_msg_slots; /* each slot will hold a xpc_notify_mq_msg_uv */ |
@@ -682,8 +687,12 @@ struct xpc_partition_sn2 { | |||
682 | }; | 687 | }; |
683 | 688 | ||
684 | struct xpc_partition_uv { | 689 | struct xpc_partition_uv { |
685 | unsigned long remote_activate_mq_gpa; /* gru phys address of remote */ | 690 | unsigned long activate_gru_mq_desc_gpa; /* phys addr of parititon's */ |
686 | /* partition's activate mq */ | 691 | /* activate mq's gru mq */ |
692 | /* descriptor */ | ||
693 | void *cached_activate_gru_mq_desc; /* cached copy of partition's */ | ||
694 | /* activate mq's gru mq descriptor */ | ||
695 | struct mutex cached_activate_gru_mq_desc_mutex; | ||
687 | spinlock_t flags_lock; /* protect updating of flags */ | 696 | spinlock_t flags_lock; /* protect updating of flags */ |
688 | unsigned int flags; /* general flags */ | 697 | unsigned int flags; /* general flags */ |
689 | u8 remote_act_state; /* remote partition's act_state */ | 698 | u8 remote_act_state; /* remote partition's act_state */ |
@@ -694,8 +703,9 @@ struct xpc_partition_uv { | |||
694 | 703 | ||
695 | /* struct xpc_partition_uv flags */ | 704 | /* struct xpc_partition_uv flags */ |
696 | 705 | ||
697 | #define XPC_P_HEARTBEAT_OFFLINE_UV 0x00000001 | 706 | #define XPC_P_HEARTBEAT_OFFLINE_UV 0x00000001 |
698 | #define XPC_P_ENGAGED_UV 0x00000002 | 707 | #define XPC_P_ENGAGED_UV 0x00000002 |
708 | #define XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV 0x00000004 | ||
699 | 709 | ||
700 | /* struct xpc_partition_uv act_state change requests */ | 710 | /* struct xpc_partition_uv act_state change requests */ |
701 | 711 | ||
@@ -804,6 +814,7 @@ extern void xpc_activate_kthreads(struct xpc_channel *, int); | |||
804 | extern void xpc_create_kthreads(struct xpc_channel *, int, int); | 814 | extern void xpc_create_kthreads(struct xpc_channel *, int, int); |
805 | extern void xpc_disconnect_wait(int); | 815 | extern void xpc_disconnect_wait(int); |
806 | extern int (*xpc_setup_partitions_sn) (void); | 816 | extern int (*xpc_setup_partitions_sn) (void); |
817 | extern void (*xpc_teardown_partitions_sn) (void); | ||
807 | extern enum xp_retval (*xpc_get_partition_rsvd_page_pa) (void *, u64 *, | 818 | extern enum xp_retval (*xpc_get_partition_rsvd_page_pa) (void *, u64 *, |
808 | unsigned long *, | 819 | unsigned long *, |
809 | size_t *); | 820 | size_t *); |
@@ -846,8 +857,8 @@ extern void (*xpc_send_chctl_openrequest) (struct xpc_channel *, | |||
846 | unsigned long *); | 857 | unsigned long *); |
847 | extern void (*xpc_send_chctl_openreply) (struct xpc_channel *, unsigned long *); | 858 | extern void (*xpc_send_chctl_openreply) (struct xpc_channel *, unsigned long *); |
848 | 859 | ||
849 | extern void (*xpc_save_remote_msgqueue_pa) (struct xpc_channel *, | 860 | extern enum xp_retval (*xpc_save_remote_msgqueue_pa) (struct xpc_channel *, |
850 | unsigned long); | 861 | unsigned long); |
851 | 862 | ||
852 | extern enum xp_retval (*xpc_send_payload) (struct xpc_channel *, u32, void *, | 863 | extern enum xp_retval (*xpc_send_payload) (struct xpc_channel *, u32, void *, |
853 | u16, u8, xpc_notify_func, void *); | 864 | u16, u8, xpc_notify_func, void *); |
diff --git a/drivers/misc/sgi-xp/xpc_channel.c b/drivers/misc/sgi-xp/xpc_channel.c index 45fd653dbe31..99a2534c38a1 100644 --- a/drivers/misc/sgi-xp/xpc_channel.c +++ b/drivers/misc/sgi-xp/xpc_channel.c | |||
@@ -183,6 +183,7 @@ xpc_process_openclose_chctl_flags(struct xpc_partition *part, int ch_number, | |||
183 | &part->remote_openclose_args[ch_number]; | 183 | &part->remote_openclose_args[ch_number]; |
184 | struct xpc_channel *ch = &part->channels[ch_number]; | 184 | struct xpc_channel *ch = &part->channels[ch_number]; |
185 | enum xp_retval reason; | 185 | enum xp_retval reason; |
186 | enum xp_retval ret; | ||
186 | 187 | ||
187 | spin_lock_irqsave(&ch->lock, irq_flags); | 188 | spin_lock_irqsave(&ch->lock, irq_flags); |
188 | 189 | ||
@@ -399,8 +400,13 @@ again: | |||
399 | DBUG_ON(args->local_nentries == 0); | 400 | DBUG_ON(args->local_nentries == 0); |
400 | DBUG_ON(args->remote_nentries == 0); | 401 | DBUG_ON(args->remote_nentries == 0); |
401 | 402 | ||
403 | ret = xpc_save_remote_msgqueue_pa(ch, args->local_msgqueue_pa); | ||
404 | if (ret != xpSuccess) { | ||
405 | XPC_DISCONNECT_CHANNEL(ch, ret, &irq_flags); | ||
406 | spin_unlock_irqrestore(&ch->lock, irq_flags); | ||
407 | return; | ||
408 | } | ||
402 | ch->flags |= XPC_C_ROPENREPLY; | 409 | ch->flags |= XPC_C_ROPENREPLY; |
403 | xpc_save_remote_msgqueue_pa(ch, args->local_msgqueue_pa); | ||
404 | 410 | ||
405 | if (args->local_nentries < ch->remote_nentries) { | 411 | if (args->local_nentries < ch->remote_nentries) { |
406 | dev_dbg(xpc_chan, "XPC_CHCTL_OPENREPLY: new " | 412 | dev_dbg(xpc_chan, "XPC_CHCTL_OPENREPLY: new " |
diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c index 6576170de962..1ab9fda87fab 100644 --- a/drivers/misc/sgi-xp/xpc_main.c +++ b/drivers/misc/sgi-xp/xpc_main.c | |||
@@ -171,6 +171,7 @@ static struct notifier_block xpc_die_notifier = { | |||
171 | }; | 171 | }; |
172 | 172 | ||
173 | int (*xpc_setup_partitions_sn) (void); | 173 | int (*xpc_setup_partitions_sn) (void); |
174 | void (*xpc_teardown_partitions_sn) (void); | ||
174 | enum xp_retval (*xpc_get_partition_rsvd_page_pa) (void *buf, u64 *cookie, | 175 | enum xp_retval (*xpc_get_partition_rsvd_page_pa) (void *buf, u64 *cookie, |
175 | unsigned long *rp_pa, | 176 | unsigned long *rp_pa, |
176 | size_t *len); | 177 | size_t *len); |
@@ -217,8 +218,8 @@ void (*xpc_send_chctl_openrequest) (struct xpc_channel *ch, | |||
217 | void (*xpc_send_chctl_openreply) (struct xpc_channel *ch, | 218 | void (*xpc_send_chctl_openreply) (struct xpc_channel *ch, |
218 | unsigned long *irq_flags); | 219 | unsigned long *irq_flags); |
219 | 220 | ||
220 | void (*xpc_save_remote_msgqueue_pa) (struct xpc_channel *ch, | 221 | enum xp_retval (*xpc_save_remote_msgqueue_pa) (struct xpc_channel *ch, |
221 | unsigned long msgqueue_pa); | 222 | unsigned long msgqueue_pa); |
222 | 223 | ||
223 | enum xp_retval (*xpc_send_payload) (struct xpc_channel *ch, u32 flags, | 224 | enum xp_retval (*xpc_send_payload) (struct xpc_channel *ch, u32 flags, |
224 | void *payload, u16 payload_size, | 225 | void *payload, u16 payload_size, |
@@ -998,6 +999,7 @@ xpc_setup_partitions(void) | |||
998 | static void | 999 | static void |
999 | xpc_teardown_partitions(void) | 1000 | xpc_teardown_partitions(void) |
1000 | { | 1001 | { |
1002 | xpc_teardown_partitions_sn(); | ||
1001 | kfree(xpc_partitions); | 1003 | kfree(xpc_partitions); |
1002 | } | 1004 | } |
1003 | 1005 | ||
diff --git a/drivers/misc/sgi-xp/xpc_sn2.c b/drivers/misc/sgi-xp/xpc_sn2.c index 2e975762c32b..a760dd08e425 100644 --- a/drivers/misc/sgi-xp/xpc_sn2.c +++ b/drivers/misc/sgi-xp/xpc_sn2.c | |||
@@ -66,6 +66,12 @@ xpc_setup_partitions_sn_sn2(void) | |||
66 | return 0; | 66 | return 0; |
67 | } | 67 | } |
68 | 68 | ||
69 | static void | ||
70 | xpc_teardown_partitions_sn_sn2(void) | ||
71 | { | ||
72 | /* nothing needs to be done */ | ||
73 | } | ||
74 | |||
69 | /* SH_IPI_ACCESS shub register value on startup */ | 75 | /* SH_IPI_ACCESS shub register value on startup */ |
70 | static u64 xpc_sh1_IPI_access_sn2; | 76 | static u64 xpc_sh1_IPI_access_sn2; |
71 | static u64 xpc_sh2_IPI_access0_sn2; | 77 | static u64 xpc_sh2_IPI_access0_sn2; |
@@ -436,11 +442,12 @@ xpc_send_chctl_local_msgrequest_sn2(struct xpc_channel *ch) | |||
436 | XPC_SEND_LOCAL_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_MSGREQUEST); | 442 | XPC_SEND_LOCAL_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_MSGREQUEST); |
437 | } | 443 | } |
438 | 444 | ||
439 | static void | 445 | static enum xp_retval |
440 | xpc_save_remote_msgqueue_pa_sn2(struct xpc_channel *ch, | 446 | xpc_save_remote_msgqueue_pa_sn2(struct xpc_channel *ch, |
441 | unsigned long msgqueue_pa) | 447 | unsigned long msgqueue_pa) |
442 | { | 448 | { |
443 | ch->sn.sn2.remote_msgqueue_pa = msgqueue_pa; | 449 | ch->sn.sn2.remote_msgqueue_pa = msgqueue_pa; |
450 | return xpSuccess; | ||
444 | } | 451 | } |
445 | 452 | ||
446 | /* | 453 | /* |
@@ -2315,6 +2322,7 @@ xpc_init_sn2(void) | |||
2315 | size_t buf_size; | 2322 | size_t buf_size; |
2316 | 2323 | ||
2317 | xpc_setup_partitions_sn = xpc_setup_partitions_sn_sn2; | 2324 | xpc_setup_partitions_sn = xpc_setup_partitions_sn_sn2; |
2325 | xpc_teardown_partitions_sn = xpc_teardown_partitions_sn_sn2; | ||
2318 | xpc_get_partition_rsvd_page_pa = xpc_get_partition_rsvd_page_pa_sn2; | 2326 | xpc_get_partition_rsvd_page_pa = xpc_get_partition_rsvd_page_pa_sn2; |
2319 | xpc_setup_rsvd_page_sn = xpc_setup_rsvd_page_sn_sn2; | 2327 | xpc_setup_rsvd_page_sn = xpc_setup_rsvd_page_sn_sn2; |
2320 | xpc_increment_heartbeat = xpc_increment_heartbeat_sn2; | 2328 | xpc_increment_heartbeat = xpc_increment_heartbeat_sn2; |
diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c index 29c0502a96b2..f7fff4727edb 100644 --- a/drivers/misc/sgi-xp/xpc_uv.c +++ b/drivers/misc/sgi-xp/xpc_uv.c | |||
@@ -31,6 +31,21 @@ | |||
31 | #include "../sgi-gru/grukservices.h" | 31 | #include "../sgi-gru/grukservices.h" |
32 | #include "xpc.h" | 32 | #include "xpc.h" |
33 | 33 | ||
34 | #if defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV | ||
35 | struct uv_IO_APIC_route_entry { | ||
36 | __u64 vector : 8, | ||
37 | delivery_mode : 3, | ||
38 | dest_mode : 1, | ||
39 | delivery_status : 1, | ||
40 | polarity : 1, | ||
41 | __reserved_1 : 1, | ||
42 | trigger : 1, | ||
43 | mask : 1, | ||
44 | __reserved_2 : 15, | ||
45 | dest : 32; | ||
46 | }; | ||
47 | #endif | ||
48 | |||
34 | static atomic64_t xpc_heartbeat_uv; | 49 | static atomic64_t xpc_heartbeat_uv; |
35 | static DECLARE_BITMAP(xpc_heartbeating_to_mask_uv, XP_MAX_NPARTITIONS_UV); | 50 | static DECLARE_BITMAP(xpc_heartbeating_to_mask_uv, XP_MAX_NPARTITIONS_UV); |
36 | 51 | ||
@@ -56,26 +71,52 @@ xpc_setup_partitions_sn_uv(void) | |||
56 | for (partid = 0; partid < XP_MAX_NPARTITIONS_UV; partid++) { | 71 | for (partid = 0; partid < XP_MAX_NPARTITIONS_UV; partid++) { |
57 | part_uv = &xpc_partitions[partid].sn.uv; | 72 | part_uv = &xpc_partitions[partid].sn.uv; |
58 | 73 | ||
74 | mutex_init(&part_uv->cached_activate_gru_mq_desc_mutex); | ||
59 | spin_lock_init(&part_uv->flags_lock); | 75 | spin_lock_init(&part_uv->flags_lock); |
60 | part_uv->remote_act_state = XPC_P_AS_INACTIVE; | 76 | part_uv->remote_act_state = XPC_P_AS_INACTIVE; |
61 | } | 77 | } |
62 | return 0; | 78 | return 0; |
63 | } | 79 | } |
64 | 80 | ||
81 | static void | ||
82 | xpc_teardown_partitions_sn_uv(void) | ||
83 | { | ||
84 | short partid; | ||
85 | struct xpc_partition_uv *part_uv; | ||
86 | unsigned long irq_flags; | ||
87 | |||
88 | for (partid = 0; partid < XP_MAX_NPARTITIONS_UV; partid++) { | ||
89 | part_uv = &xpc_partitions[partid].sn.uv; | ||
90 | |||
91 | if (part_uv->cached_activate_gru_mq_desc != NULL) { | ||
92 | mutex_lock(&part_uv->cached_activate_gru_mq_desc_mutex); | ||
93 | spin_lock_irqsave(&part_uv->flags_lock, irq_flags); | ||
94 | part_uv->flags &= ~XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV; | ||
95 | spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags); | ||
96 | kfree(part_uv->cached_activate_gru_mq_desc); | ||
97 | part_uv->cached_activate_gru_mq_desc = NULL; | ||
98 | mutex_unlock(&part_uv-> | ||
99 | cached_activate_gru_mq_desc_mutex); | ||
100 | } | ||
101 | } | ||
102 | } | ||
103 | |||
65 | static int | 104 | static int |
66 | xpc_get_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq, int cpu, char *irq_name) | 105 | xpc_get_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq, int cpu, char *irq_name) |
67 | { | 106 | { |
107 | int mmr_pnode = uv_blade_to_pnode(mq->mmr_blade); | ||
108 | |||
68 | #if defined CONFIG_X86_64 | 109 | #if defined CONFIG_X86_64 |
69 | mq->irq = uv_setup_irq(irq_name, cpu, mq->mmr_blade, mq->mmr_offset); | 110 | mq->irq = uv_setup_irq(irq_name, cpu, mq->mmr_blade, mq->mmr_offset); |
70 | if (mq->irq < 0) { | 111 | if (mq->irq < 0) { |
71 | dev_err(xpc_part, "uv_setup_irq() returned error=%d\n", | 112 | dev_err(xpc_part, "uv_setup_irq() returned error=%d\n", |
72 | mq->irq); | 113 | -mq->irq); |
114 | return mq->irq; | ||
73 | } | 115 | } |
74 | 116 | ||
75 | #elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV | 117 | mq->mmr_value = uv_read_global_mmr64(mmr_pnode, mq->mmr_offset); |
76 | int mmr_pnode; | ||
77 | unsigned long mmr_value; | ||
78 | 118 | ||
119 | #elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV | ||
79 | if (strcmp(irq_name, XPC_ACTIVATE_IRQ_NAME) == 0) | 120 | if (strcmp(irq_name, XPC_ACTIVATE_IRQ_NAME) == 0) |
80 | mq->irq = SGI_XPC_ACTIVATE; | 121 | mq->irq = SGI_XPC_ACTIVATE; |
81 | else if (strcmp(irq_name, XPC_NOTIFY_IRQ_NAME) == 0) | 122 | else if (strcmp(irq_name, XPC_NOTIFY_IRQ_NAME) == 0) |
@@ -83,10 +124,8 @@ xpc_get_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq, int cpu, char *irq_name) | |||
83 | else | 124 | else |
84 | return -EINVAL; | 125 | return -EINVAL; |
85 | 126 | ||
86 | mmr_pnode = uv_blade_to_pnode(mq->mmr_blade); | 127 | mq->mmr_value = (unsigned long)cpu_physical_id(cpu) << 32 | mq->irq; |
87 | mmr_value = (unsigned long)cpu_physical_id(cpu) << 32 | mq->irq; | 128 | uv_write_global_mmr64(mmr_pnode, mq->mmr_offset, mq->mmr_value); |
88 | |||
89 | uv_write_global_mmr64(mmr_pnode, mq->mmr_offset, mmr_value); | ||
90 | #else | 129 | #else |
91 | #error not a supported configuration | 130 | #error not a supported configuration |
92 | #endif | 131 | #endif |
@@ -127,7 +166,7 @@ xpc_gru_mq_watchlist_alloc_uv(struct xpc_gru_mq_uv *mq) | |||
127 | return ret; | 166 | return ret; |
128 | } | 167 | } |
129 | #elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV | 168 | #elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV |
130 | ret = sn_mq_watchlist_alloc(mq->mmr_blade, uv_gpa(mq->address), | 169 | ret = sn_mq_watchlist_alloc(mq->mmr_blade, (void *)uv_gpa(mq->address), |
131 | mq->order, &mq->mmr_offset); | 170 | mq->order, &mq->mmr_offset); |
132 | if (ret < 0) { | 171 | if (ret < 0) { |
133 | dev_err(xpc_part, "sn_mq_watchlist_alloc() failed, ret=%d\n", | 172 | dev_err(xpc_part, "sn_mq_watchlist_alloc() failed, ret=%d\n", |
@@ -168,12 +207,22 @@ xpc_create_gru_mq_uv(unsigned int mq_size, int cpu, char *irq_name, | |||
168 | int pg_order; | 207 | int pg_order; |
169 | struct page *page; | 208 | struct page *page; |
170 | struct xpc_gru_mq_uv *mq; | 209 | struct xpc_gru_mq_uv *mq; |
210 | struct uv_IO_APIC_route_entry *mmr_value; | ||
171 | 211 | ||
172 | mq = kmalloc(sizeof(struct xpc_gru_mq_uv), GFP_KERNEL); | 212 | mq = kmalloc(sizeof(struct xpc_gru_mq_uv), GFP_KERNEL); |
173 | if (mq == NULL) { | 213 | if (mq == NULL) { |
174 | dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to kmalloc() " | 214 | dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to kmalloc() " |
175 | "a xpc_gru_mq_uv structure\n"); | 215 | "a xpc_gru_mq_uv structure\n"); |
176 | ret = -ENOMEM; | 216 | ret = -ENOMEM; |
217 | goto out_0; | ||
218 | } | ||
219 | |||
220 | mq->gru_mq_desc = kzalloc(sizeof(struct gru_message_queue_desc), | ||
221 | GFP_KERNEL); | ||
222 | if (mq->gru_mq_desc == NULL) { | ||
223 | dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to kmalloc() " | ||
224 | "a gru_message_queue_desc structure\n"); | ||
225 | ret = -ENOMEM; | ||
177 | goto out_1; | 226 | goto out_1; |
178 | } | 227 | } |
179 | 228 | ||
@@ -194,14 +243,6 @@ xpc_create_gru_mq_uv(unsigned int mq_size, int cpu, char *irq_name, | |||
194 | } | 243 | } |
195 | mq->address = page_address(page); | 244 | mq->address = page_address(page); |
196 | 245 | ||
197 | ret = gru_create_message_queue(mq->address, mq_size); | ||
198 | if (ret != 0) { | ||
199 | dev_err(xpc_part, "gru_create_message_queue() returned " | ||
200 | "error=%d\n", ret); | ||
201 | ret = -EINVAL; | ||
202 | goto out_3; | ||
203 | } | ||
204 | |||
205 | /* enable generation of irq when GRU mq operation occurs to this mq */ | 246 | /* enable generation of irq when GRU mq operation occurs to this mq */ |
206 | ret = xpc_gru_mq_watchlist_alloc_uv(mq); | 247 | ret = xpc_gru_mq_watchlist_alloc_uv(mq); |
207 | if (ret != 0) | 248 | if (ret != 0) |
@@ -214,10 +255,20 @@ xpc_create_gru_mq_uv(unsigned int mq_size, int cpu, char *irq_name, | |||
214 | ret = request_irq(mq->irq, irq_handler, 0, irq_name, NULL); | 255 | ret = request_irq(mq->irq, irq_handler, 0, irq_name, NULL); |
215 | if (ret != 0) { | 256 | if (ret != 0) { |
216 | dev_err(xpc_part, "request_irq(irq=%d) returned error=%d\n", | 257 | dev_err(xpc_part, "request_irq(irq=%d) returned error=%d\n", |
217 | mq->irq, ret); | 258 | mq->irq, -ret); |
218 | goto out_5; | 259 | goto out_5; |
219 | } | 260 | } |
220 | 261 | ||
262 | mmr_value = (struct uv_IO_APIC_route_entry *)&mq->mmr_value; | ||
263 | ret = gru_create_message_queue(mq->gru_mq_desc, mq->address, mq_size, | ||
264 | nid, mmr_value->vector, mmr_value->dest); | ||
265 | if (ret != 0) { | ||
266 | dev_err(xpc_part, "gru_create_message_queue() returned " | ||
267 | "error=%d\n", ret); | ||
268 | ret = -EINVAL; | ||
269 | goto out_6; | ||
270 | } | ||
271 | |||
221 | /* allow other partitions to access this GRU mq */ | 272 | /* allow other partitions to access this GRU mq */ |
222 | xp_ret = xp_expand_memprotect(xp_pa(mq->address), mq_size); | 273 | xp_ret = xp_expand_memprotect(xp_pa(mq->address), mq_size); |
223 | if (xp_ret != xpSuccess) { | 274 | if (xp_ret != xpSuccess) { |
@@ -237,8 +288,10 @@ out_4: | |||
237 | out_3: | 288 | out_3: |
238 | free_pages((unsigned long)mq->address, pg_order); | 289 | free_pages((unsigned long)mq->address, pg_order); |
239 | out_2: | 290 | out_2: |
240 | kfree(mq); | 291 | kfree(mq->gru_mq_desc); |
241 | out_1: | 292 | out_1: |
293 | kfree(mq); | ||
294 | out_0: | ||
242 | return ERR_PTR(ret); | 295 | return ERR_PTR(ret); |
243 | } | 296 | } |
244 | 297 | ||
@@ -268,13 +321,14 @@ xpc_destroy_gru_mq_uv(struct xpc_gru_mq_uv *mq) | |||
268 | } | 321 | } |
269 | 322 | ||
270 | static enum xp_retval | 323 | static enum xp_retval |
271 | xpc_send_gru_msg(unsigned long mq_gpa, void *msg, size_t msg_size) | 324 | xpc_send_gru_msg(struct gru_message_queue_desc *gru_mq_desc, void *msg, |
325 | size_t msg_size) | ||
272 | { | 326 | { |
273 | enum xp_retval xp_ret; | 327 | enum xp_retval xp_ret; |
274 | int ret; | 328 | int ret; |
275 | 329 | ||
276 | while (1) { | 330 | while (1) { |
277 | ret = gru_send_message_gpa(mq_gpa, msg, msg_size); | 331 | ret = gru_send_message_gpa(gru_mq_desc, msg, msg_size); |
278 | if (ret == MQE_OK) { | 332 | if (ret == MQE_OK) { |
279 | xp_ret = xpSuccess; | 333 | xp_ret = xpSuccess; |
280 | break; | 334 | break; |
@@ -421,7 +475,15 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, | |||
421 | part_uv->act_state_req = XPC_P_ASR_ACTIVATE_UV; | 475 | part_uv->act_state_req = XPC_P_ASR_ACTIVATE_UV; |
422 | part->remote_rp_pa = msg->rp_gpa; /* !!! _pa is _gpa */ | 476 | part->remote_rp_pa = msg->rp_gpa; /* !!! _pa is _gpa */ |
423 | part->remote_rp_ts_jiffies = msg_hdr->rp_ts_jiffies; | 477 | part->remote_rp_ts_jiffies = msg_hdr->rp_ts_jiffies; |
424 | part_uv->remote_activate_mq_gpa = msg->activate_mq_gpa; | 478 | |
479 | if (msg->activate_gru_mq_desc_gpa != | ||
480 | part_uv->activate_gru_mq_desc_gpa) { | ||
481 | spin_lock_irqsave(&part_uv->flags_lock, irq_flags); | ||
482 | part_uv->flags &= ~XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV; | ||
483 | spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags); | ||
484 | part_uv->activate_gru_mq_desc_gpa = | ||
485 | msg->activate_gru_mq_desc_gpa; | ||
486 | } | ||
425 | spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags); | 487 | spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags); |
426 | 488 | ||
427 | (*wakeup_hb_checker)++; | 489 | (*wakeup_hb_checker)++; |
@@ -498,7 +560,7 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, | |||
498 | args = &part->remote_openclose_args[msg->ch_number]; | 560 | args = &part->remote_openclose_args[msg->ch_number]; |
499 | args->remote_nentries = msg->remote_nentries; | 561 | args->remote_nentries = msg->remote_nentries; |
500 | args->local_nentries = msg->local_nentries; | 562 | args->local_nentries = msg->local_nentries; |
501 | args->local_msgqueue_pa = msg->local_notify_mq_gpa; | 563 | args->local_msgqueue_pa = msg->notify_gru_mq_desc_gpa; |
502 | 564 | ||
503 | spin_lock_irqsave(&part->chctl_lock, irq_flags); | 565 | spin_lock_irqsave(&part->chctl_lock, irq_flags); |
504 | part->chctl.flags[msg->ch_number] |= XPC_CHCTL_OPENREPLY; | 566 | part->chctl.flags[msg->ch_number] |= XPC_CHCTL_OPENREPLY; |
@@ -558,9 +620,10 @@ xpc_handle_activate_IRQ_uv(int irq, void *dev_id) | |||
558 | short partid; | 620 | short partid; |
559 | struct xpc_partition *part; | 621 | struct xpc_partition *part; |
560 | int wakeup_hb_checker = 0; | 622 | int wakeup_hb_checker = 0; |
623 | int part_referenced; | ||
561 | 624 | ||
562 | while (1) { | 625 | while (1) { |
563 | msg_hdr = gru_get_next_message(xpc_activate_mq_uv->address); | 626 | msg_hdr = gru_get_next_message(xpc_activate_mq_uv->gru_mq_desc); |
564 | if (msg_hdr == NULL) | 627 | if (msg_hdr == NULL) |
565 | break; | 628 | break; |
566 | 629 | ||
@@ -571,14 +634,15 @@ xpc_handle_activate_IRQ_uv(int irq, void *dev_id) | |||
571 | partid); | 634 | partid); |
572 | } else { | 635 | } else { |
573 | part = &xpc_partitions[partid]; | 636 | part = &xpc_partitions[partid]; |
574 | if (xpc_part_ref(part)) { | 637 | |
575 | xpc_handle_activate_mq_msg_uv(part, msg_hdr, | 638 | part_referenced = xpc_part_ref(part); |
576 | &wakeup_hb_checker); | 639 | xpc_handle_activate_mq_msg_uv(part, msg_hdr, |
640 | &wakeup_hb_checker); | ||
641 | if (part_referenced) | ||
577 | xpc_part_deref(part); | 642 | xpc_part_deref(part); |
578 | } | ||
579 | } | 643 | } |
580 | 644 | ||
581 | gru_free_message(xpc_activate_mq_uv->address, msg_hdr); | 645 | gru_free_message(xpc_activate_mq_uv->gru_mq_desc, msg_hdr); |
582 | } | 646 | } |
583 | 647 | ||
584 | if (wakeup_hb_checker) | 648 | if (wakeup_hb_checker) |
@@ -588,21 +652,73 @@ xpc_handle_activate_IRQ_uv(int irq, void *dev_id) | |||
588 | } | 652 | } |
589 | 653 | ||
590 | static enum xp_retval | 654 | static enum xp_retval |
655 | xpc_cache_remote_gru_mq_desc_uv(struct gru_message_queue_desc *gru_mq_desc, | ||
656 | unsigned long gru_mq_desc_gpa) | ||
657 | { | ||
658 | enum xp_retval ret; | ||
659 | |||
660 | ret = xp_remote_memcpy(uv_gpa(gru_mq_desc), gru_mq_desc_gpa, | ||
661 | sizeof(struct gru_message_queue_desc)); | ||
662 | if (ret == xpSuccess) | ||
663 | gru_mq_desc->mq = NULL; | ||
664 | |||
665 | return ret; | ||
666 | } | ||
667 | |||
668 | static enum xp_retval | ||
591 | xpc_send_activate_IRQ_uv(struct xpc_partition *part, void *msg, size_t msg_size, | 669 | xpc_send_activate_IRQ_uv(struct xpc_partition *part, void *msg, size_t msg_size, |
592 | int msg_type) | 670 | int msg_type) |
593 | { | 671 | { |
594 | struct xpc_activate_mq_msghdr_uv *msg_hdr = msg; | 672 | struct xpc_activate_mq_msghdr_uv *msg_hdr = msg; |
673 | struct xpc_partition_uv *part_uv = &part->sn.uv; | ||
674 | struct gru_message_queue_desc *gru_mq_desc; | ||
675 | unsigned long irq_flags; | ||
676 | enum xp_retval ret; | ||
595 | 677 | ||
596 | DBUG_ON(msg_size > XPC_ACTIVATE_MSG_SIZE_UV); | 678 | DBUG_ON(msg_size > XPC_ACTIVATE_MSG_SIZE_UV); |
597 | 679 | ||
598 | msg_hdr->type = msg_type; | 680 | msg_hdr->type = msg_type; |
599 | msg_hdr->partid = XPC_PARTID(part); | 681 | msg_hdr->partid = xp_partition_id; |
600 | msg_hdr->act_state = part->act_state; | 682 | msg_hdr->act_state = part->act_state; |
601 | msg_hdr->rp_ts_jiffies = xpc_rsvd_page->ts_jiffies; | 683 | msg_hdr->rp_ts_jiffies = xpc_rsvd_page->ts_jiffies; |
602 | 684 | ||
685 | mutex_lock(&part_uv->cached_activate_gru_mq_desc_mutex); | ||
686 | again: | ||
687 | if (!(part_uv->flags & XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV)) { | ||
688 | gru_mq_desc = part_uv->cached_activate_gru_mq_desc; | ||
689 | if (gru_mq_desc == NULL) { | ||
690 | gru_mq_desc = kmalloc(sizeof(struct | ||
691 | gru_message_queue_desc), | ||
692 | GFP_KERNEL); | ||
693 | if (gru_mq_desc == NULL) { | ||
694 | ret = xpNoMemory; | ||
695 | goto done; | ||
696 | } | ||
697 | part_uv->cached_activate_gru_mq_desc = gru_mq_desc; | ||
698 | } | ||
699 | |||
700 | ret = xpc_cache_remote_gru_mq_desc_uv(gru_mq_desc, | ||
701 | part_uv-> | ||
702 | activate_gru_mq_desc_gpa); | ||
703 | if (ret != xpSuccess) | ||
704 | goto done; | ||
705 | |||
706 | spin_lock_irqsave(&part_uv->flags_lock, irq_flags); | ||
707 | part_uv->flags |= XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV; | ||
708 | spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags); | ||
709 | } | ||
710 | |||
603 | /* ??? Is holding a spin_lock (ch->lock) during this call a bad idea? */ | 711 | /* ??? Is holding a spin_lock (ch->lock) during this call a bad idea? */ |
604 | return xpc_send_gru_msg(part->sn.uv.remote_activate_mq_gpa, msg, | 712 | ret = xpc_send_gru_msg(part_uv->cached_activate_gru_mq_desc, msg, |
605 | msg_size); | 713 | msg_size); |
714 | if (ret != xpSuccess) { | ||
715 | smp_rmb(); /* ensure a fresh copy of part_uv->flags */ | ||
716 | if (!(part_uv->flags & XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV)) | ||
717 | goto again; | ||
718 | } | ||
719 | done: | ||
720 | mutex_unlock(&part_uv->cached_activate_gru_mq_desc_mutex); | ||
721 | return ret; | ||
606 | } | 722 | } |
607 | 723 | ||
608 | static void | 724 | static void |
@@ -620,7 +736,7 @@ static void | |||
620 | xpc_send_activate_IRQ_ch_uv(struct xpc_channel *ch, unsigned long *irq_flags, | 736 | xpc_send_activate_IRQ_ch_uv(struct xpc_channel *ch, unsigned long *irq_flags, |
621 | void *msg, size_t msg_size, int msg_type) | 737 | void *msg, size_t msg_size, int msg_type) |
622 | { | 738 | { |
623 | struct xpc_partition *part = &xpc_partitions[ch->number]; | 739 | struct xpc_partition *part = &xpc_partitions[ch->partid]; |
624 | enum xp_retval ret; | 740 | enum xp_retval ret; |
625 | 741 | ||
626 | ret = xpc_send_activate_IRQ_uv(part, msg, msg_size, msg_type); | 742 | ret = xpc_send_activate_IRQ_uv(part, msg, msg_size, msg_type); |
@@ -692,7 +808,8 @@ xpc_get_partition_rsvd_page_pa_uv(void *buf, u64 *cookie, unsigned long *rp_pa, | |||
692 | static int | 808 | static int |
693 | xpc_setup_rsvd_page_sn_uv(struct xpc_rsvd_page *rp) | 809 | xpc_setup_rsvd_page_sn_uv(struct xpc_rsvd_page *rp) |
694 | { | 810 | { |
695 | rp->sn.activate_mq_gpa = uv_gpa(xpc_activate_mq_uv->address); | 811 | rp->sn.activate_gru_mq_desc_gpa = |
812 | uv_gpa(xpc_activate_mq_uv->gru_mq_desc); | ||
696 | return 0; | 813 | return 0; |
697 | } | 814 | } |
698 | 815 | ||
@@ -787,7 +904,8 @@ xpc_request_partition_activation_uv(struct xpc_rsvd_page *remote_rp, | |||
787 | 904 | ||
788 | part->remote_rp_pa = remote_rp_gpa; /* !!! _pa here is really _gpa */ | 905 | part->remote_rp_pa = remote_rp_gpa; /* !!! _pa here is really _gpa */ |
789 | part->remote_rp_ts_jiffies = remote_rp->ts_jiffies; | 906 | part->remote_rp_ts_jiffies = remote_rp->ts_jiffies; |
790 | part->sn.uv.remote_activate_mq_gpa = remote_rp->sn.activate_mq_gpa; | 907 | part->sn.uv.activate_gru_mq_desc_gpa = |
908 | remote_rp->sn.activate_gru_mq_desc_gpa; | ||
791 | 909 | ||
792 | /* | 910 | /* |
793 | * ??? Is it a good idea to make this conditional on what is | 911 | * ??? Is it a good idea to make this conditional on what is |
@@ -795,7 +913,8 @@ xpc_request_partition_activation_uv(struct xpc_rsvd_page *remote_rp, | |||
795 | */ | 913 | */ |
796 | if (part->sn.uv.remote_act_state == XPC_P_AS_INACTIVE) { | 914 | if (part->sn.uv.remote_act_state == XPC_P_AS_INACTIVE) { |
797 | msg.rp_gpa = uv_gpa(xpc_rsvd_page); | 915 | msg.rp_gpa = uv_gpa(xpc_rsvd_page); |
798 | msg.activate_mq_gpa = xpc_rsvd_page->sn.activate_mq_gpa; | 916 | msg.activate_gru_mq_desc_gpa = |
917 | xpc_rsvd_page->sn.activate_gru_mq_desc_gpa; | ||
799 | xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg), | 918 | xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg), |
800 | XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV); | 919 | XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV); |
801 | } | 920 | } |
@@ -857,7 +976,8 @@ xpc_get_fifo_entry_uv(struct xpc_fifo_head_uv *head) | |||
857 | if (head->first == NULL) | 976 | if (head->first == NULL) |
858 | head->last = NULL; | 977 | head->last = NULL; |
859 | } | 978 | } |
860 | head->n_entries++; | 979 | head->n_entries--; |
980 | BUG_ON(head->n_entries < 0); | ||
861 | spin_unlock_irqrestore(&head->lock, irq_flags); | 981 | spin_unlock_irqrestore(&head->lock, irq_flags); |
862 | first->next = NULL; | 982 | first->next = NULL; |
863 | return first; | 983 | return first; |
@@ -876,8 +996,7 @@ xpc_put_fifo_entry_uv(struct xpc_fifo_head_uv *head, | |||
876 | else | 996 | else |
877 | head->first = last; | 997 | head->first = last; |
878 | head->last = last; | 998 | head->last = last; |
879 | head->n_entries--; | 999 | head->n_entries++; |
880 | BUG_ON(head->n_entries < 0); | ||
881 | spin_unlock_irqrestore(&head->lock, irq_flags); | 1000 | spin_unlock_irqrestore(&head->lock, irq_flags); |
882 | } | 1001 | } |
883 | 1002 | ||
@@ -1037,6 +1156,12 @@ xpc_setup_msg_structures_uv(struct xpc_channel *ch) | |||
1037 | 1156 | ||
1038 | DBUG_ON(ch->flags & XPC_C_SETUP); | 1157 | DBUG_ON(ch->flags & XPC_C_SETUP); |
1039 | 1158 | ||
1159 | ch_uv->cached_notify_gru_mq_desc = kmalloc(sizeof(struct | ||
1160 | gru_message_queue_desc), | ||
1161 | GFP_KERNEL); | ||
1162 | if (ch_uv->cached_notify_gru_mq_desc == NULL) | ||
1163 | return xpNoMemory; | ||
1164 | |||
1040 | ret = xpc_allocate_send_msg_slot_uv(ch); | 1165 | ret = xpc_allocate_send_msg_slot_uv(ch); |
1041 | if (ret == xpSuccess) { | 1166 | if (ret == xpSuccess) { |
1042 | 1167 | ||
@@ -1060,7 +1185,8 @@ xpc_teardown_msg_structures_uv(struct xpc_channel *ch) | |||
1060 | 1185 | ||
1061 | DBUG_ON(!spin_is_locked(&ch->lock)); | 1186 | DBUG_ON(!spin_is_locked(&ch->lock)); |
1062 | 1187 | ||
1063 | ch_uv->remote_notify_mq_gpa = 0; | 1188 | kfree(ch_uv->cached_notify_gru_mq_desc); |
1189 | ch_uv->cached_notify_gru_mq_desc = NULL; | ||
1064 | 1190 | ||
1065 | if (ch->flags & XPC_C_SETUP) { | 1191 | if (ch->flags & XPC_C_SETUP) { |
1066 | xpc_init_fifo_uv(&ch_uv->msg_slot_free_list); | 1192 | xpc_init_fifo_uv(&ch_uv->msg_slot_free_list); |
@@ -1111,7 +1237,7 @@ xpc_send_chctl_openreply_uv(struct xpc_channel *ch, unsigned long *irq_flags) | |||
1111 | msg.ch_number = ch->number; | 1237 | msg.ch_number = ch->number; |
1112 | msg.local_nentries = ch->local_nentries; | 1238 | msg.local_nentries = ch->local_nentries; |
1113 | msg.remote_nentries = ch->remote_nentries; | 1239 | msg.remote_nentries = ch->remote_nentries; |
1114 | msg.local_notify_mq_gpa = uv_gpa(xpc_notify_mq_uv); | 1240 | msg.notify_gru_mq_desc_gpa = uv_gpa(xpc_notify_mq_uv->gru_mq_desc); |
1115 | xpc_send_activate_IRQ_ch_uv(ch, irq_flags, &msg, sizeof(msg), | 1241 | xpc_send_activate_IRQ_ch_uv(ch, irq_flags, &msg, sizeof(msg), |
1116 | XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV); | 1242 | XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV); |
1117 | } | 1243 | } |
@@ -1128,11 +1254,15 @@ xpc_send_chctl_local_msgrequest_uv(struct xpc_partition *part, int ch_number) | |||
1128 | xpc_wakeup_channel_mgr(part); | 1254 | xpc_wakeup_channel_mgr(part); |
1129 | } | 1255 | } |
1130 | 1256 | ||
1131 | static void | 1257 | static enum xp_retval |
1132 | xpc_save_remote_msgqueue_pa_uv(struct xpc_channel *ch, | 1258 | xpc_save_remote_msgqueue_pa_uv(struct xpc_channel *ch, |
1133 | unsigned long msgqueue_pa) | 1259 | unsigned long gru_mq_desc_gpa) |
1134 | { | 1260 | { |
1135 | ch->sn.uv.remote_notify_mq_gpa = msgqueue_pa; | 1261 | struct xpc_channel_uv *ch_uv = &ch->sn.uv; |
1262 | |||
1263 | DBUG_ON(ch_uv->cached_notify_gru_mq_desc == NULL); | ||
1264 | return xpc_cache_remote_gru_mq_desc_uv(ch_uv->cached_notify_gru_mq_desc, | ||
1265 | gru_mq_desc_gpa); | ||
1136 | } | 1266 | } |
1137 | 1267 | ||
1138 | static void | 1268 | static void |
@@ -1339,7 +1469,8 @@ xpc_handle_notify_IRQ_uv(int irq, void *dev_id) | |||
1339 | short partid; | 1469 | short partid; |
1340 | struct xpc_partition *part; | 1470 | struct xpc_partition *part; |
1341 | 1471 | ||
1342 | while ((msg = gru_get_next_message(xpc_notify_mq_uv)) != NULL) { | 1472 | while ((msg = gru_get_next_message(xpc_notify_mq_uv->gru_mq_desc)) != |
1473 | NULL) { | ||
1343 | 1474 | ||
1344 | partid = msg->hdr.partid; | 1475 | partid = msg->hdr.partid; |
1345 | if (partid < 0 || partid >= XP_MAX_NPARTITIONS_UV) { | 1476 | if (partid < 0 || partid >= XP_MAX_NPARTITIONS_UV) { |
@@ -1354,7 +1485,7 @@ xpc_handle_notify_IRQ_uv(int irq, void *dev_id) | |||
1354 | } | 1485 | } |
1355 | } | 1486 | } |
1356 | 1487 | ||
1357 | gru_free_message(xpc_notify_mq_uv, msg); | 1488 | gru_free_message(xpc_notify_mq_uv->gru_mq_desc, msg); |
1358 | } | 1489 | } |
1359 | 1490 | ||
1360 | return IRQ_HANDLED; | 1491 | return IRQ_HANDLED; |
@@ -1438,7 +1569,8 @@ xpc_send_payload_uv(struct xpc_channel *ch, u32 flags, void *payload, | |||
1438 | msg->hdr.msg_slot_number = msg_slot->msg_slot_number; | 1569 | msg->hdr.msg_slot_number = msg_slot->msg_slot_number; |
1439 | memcpy(&msg->payload, payload, payload_size); | 1570 | memcpy(&msg->payload, payload, payload_size); |
1440 | 1571 | ||
1441 | ret = xpc_send_gru_msg(ch->sn.uv.remote_notify_mq_gpa, msg, msg_size); | 1572 | ret = xpc_send_gru_msg(ch->sn.uv.cached_notify_gru_mq_desc, msg, |
1573 | msg_size); | ||
1442 | if (ret == xpSuccess) | 1574 | if (ret == xpSuccess) |
1443 | goto out_1; | 1575 | goto out_1; |
1444 | 1576 | ||
@@ -1529,7 +1661,7 @@ xpc_received_payload_uv(struct xpc_channel *ch, void *payload) | |||
1529 | msg->hdr.partid = xp_partition_id; | 1661 | msg->hdr.partid = xp_partition_id; |
1530 | msg->hdr.size = 0; /* size of zero indicates this is an ACK */ | 1662 | msg->hdr.size = 0; /* size of zero indicates this is an ACK */ |
1531 | 1663 | ||
1532 | ret = xpc_send_gru_msg(ch->sn.uv.remote_notify_mq_gpa, msg, | 1664 | ret = xpc_send_gru_msg(ch->sn.uv.cached_notify_gru_mq_desc, msg, |
1533 | sizeof(struct xpc_notify_mq_msghdr_uv)); | 1665 | sizeof(struct xpc_notify_mq_msghdr_uv)); |
1534 | if (ret != xpSuccess) | 1666 | if (ret != xpSuccess) |
1535 | XPC_DEACTIVATE_PARTITION(&xpc_partitions[ch->partid], ret); | 1667 | XPC_DEACTIVATE_PARTITION(&xpc_partitions[ch->partid], ret); |
@@ -1541,6 +1673,7 @@ int | |||
1541 | xpc_init_uv(void) | 1673 | xpc_init_uv(void) |
1542 | { | 1674 | { |
1543 | xpc_setup_partitions_sn = xpc_setup_partitions_sn_uv; | 1675 | xpc_setup_partitions_sn = xpc_setup_partitions_sn_uv; |
1676 | xpc_teardown_partitions_sn = xpc_teardown_partitions_sn_uv; | ||
1544 | xpc_process_activate_IRQ_rcvd = xpc_process_activate_IRQ_rcvd_uv; | 1677 | xpc_process_activate_IRQ_rcvd = xpc_process_activate_IRQ_rcvd_uv; |
1545 | xpc_get_partition_rsvd_page_pa = xpc_get_partition_rsvd_page_pa_uv; | 1678 | xpc_get_partition_rsvd_page_pa = xpc_get_partition_rsvd_page_pa_uv; |
1546 | xpc_setup_rsvd_page_sn = xpc_setup_rsvd_page_sn_uv; | 1679 | xpc_setup_rsvd_page_sn = xpc_setup_rsvd_page_sn_uv; |