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>

authored by Stefan Roscher and committed by Roland Dreier fad96ab6 332edc2f

+33 -16
+28 -16
drivers/infiniband/hw/ehca/ehca_irq.c
··· 359 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 382 static void parse_ec(struct ehca_shca *shca, u64 eqe) 363 383 { 364 384 u8 ec = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe); 365 385 u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe); 366 386 u8 spec_event; 367 387 struct ehca_sport *sport = &shca->sport[port - 1]; 368 - unsigned long flags; 369 388 370 389 switch (ec) { 371 390 case 0x30: /* port availability change */ 372 391 if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) { 373 - int suppress_event; 374 - /* replay modify_qp for sqps */ 375 - spin_lock_irqsave(&sport->mod_sqp_lock, flags); 376 - suppress_event = !sport->ibqp_sqp[IB_QPT_GSI]; 377 - if (sport->ibqp_sqp[IB_QPT_SMI]) 378 - ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_SMI]); 379 - if (!suppress_event) 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; 392 + /* only replay modify_qp calls in autodetect mode; 393 + * if AQP1 was destroyed, the port is already down 394 + * again and we can drop the event. 395 + */ 396 + if (ehca_nr_ports < 0) 397 + if (replay_modify_qp(sport)) 398 + break; 386 399 387 400 sport->port_state = IB_PORT_ACTIVE; 388 401 dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE, 389 402 "is active"); 390 - ehca_query_sma_attr(shca, port, 391 - &sport->saved_attr); 403 + ehca_query_sma_attr(shca, port, &sport->saved_attr); 392 404 } else { 393 405 sport->port_state = IB_PORT_DOWN; 394 406 dispatch_port_event(shca, port, IB_EVENT_PORT_ERR,
+5
drivers/infiniband/hw/ehca/ehca_qp.c
··· 860 860 if (qp_type == IB_QPT_GSI) { 861 861 h_ret = ehca_define_sqp(shca, my_qp, init_attr); 862 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 868 ret = ehca2ib_return_code(h_ret); 864 869 goto create_qp_exit6; 865 870 }