diff options
Diffstat (limited to 'drivers/infiniband/hw/ehca/ehca_irq.c')
| -rw-r--r-- | drivers/infiniband/hw/ehca/ehca_irq.c | 44 |
1 files changed, 28 insertions, 16 deletions
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c index cb55be04442..757035ea246 100644 --- a/drivers/infiniband/hw/ehca/ehca_irq.c +++ b/drivers/infiniband/hw/ehca/ehca_irq.c | |||
| @@ -359,36 +359,48 @@ static void notify_port_conf_change(struct ehca_shca *shca, int port_num) | |||
| 359 | *old_attr = new_attr; | 359 | *old_attr = new_attr; |
| 360 | } | 360 | } |
| 361 | 361 | ||
| 362 | /* replay modify_qp for sqps -- return 0 if all is well, 1 if AQP1 destroyed */ | ||
| 363 | static int replay_modify_qp(struct ehca_sport *sport) | ||
| 364 | { | ||
| 365 | int aqp1_destroyed; | ||
| 366 | unsigned long flags; | ||
| 367 | |||
| 368 | spin_lock_irqsave(&sport->mod_sqp_lock, flags); | ||
| 369 | |||
| 370 | aqp1_destroyed = !sport->ibqp_sqp[IB_QPT_GSI]; | ||
| 371 | |||
| 372 | if (sport->ibqp_sqp[IB_QPT_SMI]) | ||
| 373 | ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_SMI]); | ||
| 374 | if (!aqp1_destroyed) | ||
| 375 | ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_GSI]); | ||
| 376 | |||
| 377 | spin_unlock_irqrestore(&sport->mod_sqp_lock, flags); | ||
| 378 | |||
| 379 | return aqp1_destroyed; | ||
| 380 | } | ||
| 381 | |||
| 362 | static void parse_ec(struct ehca_shca *shca, u64 eqe) | 382 | static void parse_ec(struct ehca_shca *shca, u64 eqe) |
| 363 | { | 383 | { |
| 364 | u8 ec = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe); | 384 | u8 ec = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe); |
| 365 | u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe); | 385 | u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe); |
| 366 | u8 spec_event; | 386 | u8 spec_event; |
| 367 | struct ehca_sport *sport = &shca->sport[port - 1]; | 387 | struct ehca_sport *sport = &shca->sport[port - 1]; |
| 368 | unsigned long flags; | ||
| 369 | 388 | ||
| 370 | switch (ec) { | 389 | switch (ec) { |
| 371 | case 0x30: /* port availability change */ | 390 | case 0x30: /* port availability change */ |
| 372 | if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) { | 391 | if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) { |
| 373 | int suppress_event; | 392 | /* only replay modify_qp calls in autodetect mode; |
| 374 | /* replay modify_qp for sqps */ | 393 | * if AQP1 was destroyed, the port is already down |
| 375 | spin_lock_irqsave(&sport->mod_sqp_lock, flags); | 394 | * again and we can drop the event. |
| 376 | suppress_event = !sport->ibqp_sqp[IB_QPT_GSI]; | 395 | */ |
| 377 | if (sport->ibqp_sqp[IB_QPT_SMI]) | 396 | if (ehca_nr_ports < 0) |
| 378 | ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_SMI]); | 397 | if (replay_modify_qp(sport)) |
| 379 | if (!suppress_event) | 398 | break; |
| 380 | ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_GSI]); | ||
| 381 | spin_unlock_irqrestore(&sport->mod_sqp_lock, flags); | ||
| 382 | |||
| 383 | /* AQP1 was destroyed, ignore this event */ | ||
| 384 | if (suppress_event) | ||
| 385 | break; | ||
| 386 | 399 | ||
| 387 | sport->port_state = IB_PORT_ACTIVE; | 400 | sport->port_state = IB_PORT_ACTIVE; |
| 388 | dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE, | 401 | dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE, |
| 389 | "is active"); | 402 | "is active"); |
| 390 | ehca_query_sma_attr(shca, port, | 403 | ehca_query_sma_attr(shca, port, &sport->saved_attr); |
| 391 | &sport->saved_attr); | ||
| 392 | } else { | 404 | } else { |
| 393 | sport->port_state = IB_PORT_DOWN; | 405 | sport->port_state = IB_PORT_DOWN; |
| 394 | dispatch_port_event(shca, port, IB_EVENT_PORT_ERR, | 406 | dispatch_port_event(shca, port, IB_EVENT_PORT_ERR, |
