diff options
Diffstat (limited to 'drivers/infiniband/hw/ehca/ehca_irq.c')
-rw-r--r-- | drivers/infiniband/hw/ehca/ehca_irq.c | 40 |
1 files changed, 35 insertions, 5 deletions
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c index 3f617b27b954..b5ca94c6b8d9 100644 --- a/drivers/infiniband/hw/ehca/ehca_irq.c +++ b/drivers/infiniband/hw/ehca/ehca_irq.c | |||
@@ -62,6 +62,7 @@ | |||
62 | #define NEQE_PORT_NUMBER EHCA_BMASK_IBM( 8, 15) | 62 | #define NEQE_PORT_NUMBER EHCA_BMASK_IBM( 8, 15) |
63 | #define NEQE_PORT_AVAILABILITY EHCA_BMASK_IBM(16, 16) | 63 | #define NEQE_PORT_AVAILABILITY EHCA_BMASK_IBM(16, 16) |
64 | #define NEQE_DISRUPTIVE EHCA_BMASK_IBM(16, 16) | 64 | #define NEQE_DISRUPTIVE EHCA_BMASK_IBM(16, 16) |
65 | #define NEQE_SPECIFIC_EVENT EHCA_BMASK_IBM(16, 23) | ||
65 | 66 | ||
66 | #define ERROR_DATA_LENGTH EHCA_BMASK_IBM(52, 63) | 67 | #define ERROR_DATA_LENGTH EHCA_BMASK_IBM(52, 63) |
67 | #define ERROR_DATA_TYPE EHCA_BMASK_IBM( 0, 7) | 68 | #define ERROR_DATA_TYPE EHCA_BMASK_IBM( 0, 7) |
@@ -354,17 +355,34 @@ static void parse_ec(struct ehca_shca *shca, u64 eqe) | |||
354 | { | 355 | { |
355 | u8 ec = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe); | 356 | u8 ec = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe); |
356 | u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe); | 357 | u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe); |
358 | u8 spec_event; | ||
359 | struct ehca_sport *sport = &shca->sport[port - 1]; | ||
360 | unsigned long flags; | ||
357 | 361 | ||
358 | switch (ec) { | 362 | switch (ec) { |
359 | case 0x30: /* port availability change */ | 363 | case 0x30: /* port availability change */ |
360 | if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) { | 364 | if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) { |
361 | shca->sport[port - 1].port_state = IB_PORT_ACTIVE; | 365 | int suppress_event; |
366 | /* replay modify_qp for sqps */ | ||
367 | spin_lock_irqsave(&sport->mod_sqp_lock, flags); | ||
368 | suppress_event = !sport->ibqp_sqp[IB_QPT_GSI]; | ||
369 | if (sport->ibqp_sqp[IB_QPT_SMI]) | ||
370 | ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_SMI]); | ||
371 | if (!suppress_event) | ||
372 | ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_GSI]); | ||
373 | spin_unlock_irqrestore(&sport->mod_sqp_lock, flags); | ||
374 | |||
375 | /* AQP1 was destroyed, ignore this event */ | ||
376 | if (suppress_event) | ||
377 | break; | ||
378 | |||
379 | sport->port_state = IB_PORT_ACTIVE; | ||
362 | dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE, | 380 | dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE, |
363 | "is active"); | 381 | "is active"); |
364 | ehca_query_sma_attr(shca, port, | 382 | ehca_query_sma_attr(shca, port, |
365 | &shca->sport[port - 1].saved_attr); | 383 | &sport->saved_attr); |
366 | } else { | 384 | } else { |
367 | shca->sport[port - 1].port_state = IB_PORT_DOWN; | 385 | sport->port_state = IB_PORT_DOWN; |
368 | dispatch_port_event(shca, port, IB_EVENT_PORT_ERR, | 386 | dispatch_port_event(shca, port, IB_EVENT_PORT_ERR, |
369 | "is inactive"); | 387 | "is inactive"); |
370 | } | 388 | } |
@@ -378,13 +396,15 @@ static void parse_ec(struct ehca_shca *shca, u64 eqe) | |||
378 | ehca_warn(&shca->ib_device, "disruptive port " | 396 | ehca_warn(&shca->ib_device, "disruptive port " |
379 | "%d configuration change", port); | 397 | "%d configuration change", port); |
380 | 398 | ||
381 | shca->sport[port - 1].port_state = IB_PORT_DOWN; | 399 | sport->port_state = IB_PORT_DOWN; |
382 | dispatch_port_event(shca, port, IB_EVENT_PORT_ERR, | 400 | dispatch_port_event(shca, port, IB_EVENT_PORT_ERR, |
383 | "is inactive"); | 401 | "is inactive"); |
384 | 402 | ||
385 | shca->sport[port - 1].port_state = IB_PORT_ACTIVE; | 403 | sport->port_state = IB_PORT_ACTIVE; |
386 | dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE, | 404 | dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE, |
387 | "is active"); | 405 | "is active"); |
406 | ehca_query_sma_attr(shca, port, | ||
407 | &sport->saved_attr); | ||
388 | } else | 408 | } else |
389 | notify_port_conf_change(shca, port); | 409 | notify_port_conf_change(shca, port); |
390 | break; | 410 | break; |
@@ -394,6 +414,16 @@ static void parse_ec(struct ehca_shca *shca, u64 eqe) | |||
394 | case 0x33: /* trace stopped */ | 414 | case 0x33: /* trace stopped */ |
395 | ehca_err(&shca->ib_device, "Traced stopped."); | 415 | ehca_err(&shca->ib_device, "Traced stopped."); |
396 | break; | 416 | break; |
417 | case 0x34: /* util async event */ | ||
418 | spec_event = EHCA_BMASK_GET(NEQE_SPECIFIC_EVENT, eqe); | ||
419 | if (spec_event == 0x80) /* client reregister required */ | ||
420 | dispatch_port_event(shca, port, | ||
421 | IB_EVENT_CLIENT_REREGISTER, | ||
422 | "client reregister req."); | ||
423 | else | ||
424 | ehca_warn(&shca->ib_device, "Unknown util async " | ||
425 | "event %x on port %x", spec_event, port); | ||
426 | break; | ||
397 | default: | 427 | default: |
398 | ehca_err(&shca->ib_device, "Unknown event code: %x on %s.", | 428 | ehca_err(&shca->ib_device, "Unknown event code: %x on %s.", |
399 | ec, shca->ib_device.name); | 429 | ec, shca->ib_device.name); |