Commit fad96ab6 authored by Stefan Roscher's avatar Stefan Roscher Committed by Roland Dreier

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: default avatarStefan Roscher <stefan.roscher@de.ibm.com>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent 332edc2f
...@@ -359,36 +359,48 @@ static void notify_port_conf_change(struct ehca_shca *shca, int port_num) ...@@ -359,36 +359,48 @@ static void notify_port_conf_change(struct ehca_shca *shca, int port_num)
*old_attr = new_attr; *old_attr = new_attr;
} }
/* replay modify_qp for sqps -- return 0 if all is well, 1 if AQP1 destroyed */
static int replay_modify_qp(struct ehca_sport *sport)
{
int aqp1_destroyed;
unsigned long flags;
spin_lock_irqsave(&sport->mod_sqp_lock, flags);
aqp1_destroyed = !sport->ibqp_sqp[IB_QPT_GSI];
if (sport->ibqp_sqp[IB_QPT_SMI])
ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_SMI]);
if (!aqp1_destroyed)
ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_GSI]);
spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
return aqp1_destroyed;
}
static void parse_ec(struct ehca_shca *shca, u64 eqe) static void parse_ec(struct ehca_shca *shca, u64 eqe)
{ {
u8 ec = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe); u8 ec = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe);
u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe); u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe);
u8 spec_event; u8 spec_event;
struct ehca_sport *sport = &shca->sport[port - 1]; struct ehca_sport *sport = &shca->sport[port - 1];
unsigned long flags;
switch (ec) { switch (ec) {
case 0x30: /* port availability change */ case 0x30: /* port availability change */
if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) { if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) {
int suppress_event; /* only replay modify_qp calls in autodetect mode;
/* replay modify_qp for sqps */ * if AQP1 was destroyed, the port is already down
spin_lock_irqsave(&sport->mod_sqp_lock, flags); * again and we can drop the event.
suppress_event = !sport->ibqp_sqp[IB_QPT_GSI]; */
if (sport->ibqp_sqp[IB_QPT_SMI]) if (ehca_nr_ports < 0)
ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_SMI]); if (replay_modify_qp(sport))
if (!suppress_event)
ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_GSI]);
spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
/* AQP1 was destroyed, ignore this event */
if (suppress_event)
break; break;
sport->port_state = IB_PORT_ACTIVE; sport->port_state = IB_PORT_ACTIVE;
dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE, dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE,
"is active"); "is active");
ehca_query_sma_attr(shca, port, ehca_query_sma_attr(shca, port, &sport->saved_attr);
&sport->saved_attr);
} else { } else {
sport->port_state = IB_PORT_DOWN; sport->port_state = IB_PORT_DOWN;
dispatch_port_event(shca, port, IB_EVENT_PORT_ERR, dispatch_port_event(shca, port, IB_EVENT_PORT_ERR,
......
...@@ -860,6 +860,11 @@ static struct ehca_qp *internal_create_qp( ...@@ -860,6 +860,11 @@ static struct ehca_qp *internal_create_qp(
if (qp_type == IB_QPT_GSI) { if (qp_type == IB_QPT_GSI) {
h_ret = ehca_define_sqp(shca, my_qp, init_attr); h_ret = ehca_define_sqp(shca, my_qp, init_attr);
if (h_ret != H_SUCCESS) { if (h_ret != H_SUCCESS) {
kfree(my_qp->mod_qp_parm);
my_qp->mod_qp_parm = NULL;
/* the QP pointer is no longer valid */
shca->sport[init_attr->port_num - 1].ibqp_sqp[qp_type] =
NULL;
ret = ehca2ib_return_code(h_ret); ret = ehca2ib_return_code(h_ret);
goto create_qp_exit6; goto create_qp_exit6;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment