diff options
| author | Stefan Roscher <ossrosch@linux.vnet.ibm.com> | 2008-11-11 18:44:22 -0500 |
|---|---|---|
| committer | Roland Dreier <rolandd@cisco.com> | 2008-11-11 18:44:22 -0500 |
| commit | fad96ab62d38b94efbdb4c3c5fc55cb90d57937d (patch) | |
| tree | 0e5e9e6427540ed4e9958fc192fb5f0e6a166754 | |
| parent | 332edc2f7fa58b818dfed1cede60272eecc27c0a (diff) | |
IB/ehca: Remove reference to special QP in case of port activation failure
If the initialization of a special QP (e.g. AQP1) fails due to a
software timeout, we have to remove the reference to that special QP
struct from the port struct to stop the driver from accessing the QP,
since it will be/has been destroyed by the caller, eg in this case
ib_mad.
Signed-off-by: Stefan Roscher <stefan.roscher@de.ibm.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
| -rw-r--r-- | drivers/infiniband/hw/ehca/ehca_irq.c | 44 | ||||
| -rw-r--r-- | drivers/infiniband/hw/ehca/ehca_qp.c | 5 |
2 files changed, 33 insertions, 16 deletions
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c index cb55be04442c..757035ea246f 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, |
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c index 4d54b9f64567..9e05ee2db39b 100644 --- a/drivers/infiniband/hw/ehca/ehca_qp.c +++ b/drivers/infiniband/hw/ehca/ehca_qp.c | |||
| @@ -860,6 +860,11 @@ static struct ehca_qp *internal_create_qp( | |||
| 860 | if (qp_type == IB_QPT_GSI) { | 860 | if (qp_type == IB_QPT_GSI) { |
| 861 | h_ret = ehca_define_sqp(shca, my_qp, init_attr); | 861 | h_ret = ehca_define_sqp(shca, my_qp, init_attr); |
| 862 | if (h_ret != H_SUCCESS) { | 862 | if (h_ret != H_SUCCESS) { |
| 863 | kfree(my_qp->mod_qp_parm); | ||
| 864 | my_qp->mod_qp_parm = NULL; | ||
| 865 | /* the QP pointer is no longer valid */ | ||
| 866 | shca->sport[init_attr->port_num - 1].ibqp_sqp[qp_type] = | ||
| 867 | NULL; | ||
| 863 | ret = ehca2ib_return_code(h_ret); | 868 | ret = ehca2ib_return_code(h_ret); |
| 864 | goto create_qp_exit6; | 869 | goto create_qp_exit6; |
| 865 | } | 870 | } |
