|
@@ -840,3 +840,55 @@ void notify_error_qp(struct rvt_qp *qp)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * hfi1_error_port_qps - put a port's RC/UC qps into error state
|
|
|
+ * @ibp: the ibport.
|
|
|
+ * @sl: the service level.
|
|
|
+ *
|
|
|
+ * This function places all RC/UC qps with a given service level into error
|
|
|
+ * state. It is generally called to force upper lay apps to abandon stale qps
|
|
|
+ * after an sl->sc mapping change.
|
|
|
+ */
|
|
|
+void hfi1_error_port_qps(struct hfi1_ibport *ibp, u8 sl)
|
|
|
+{
|
|
|
+ struct rvt_qp *qp = NULL;
|
|
|
+ struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
|
|
|
+ struct hfi1_ibdev *dev = &ppd->dd->verbs_dev;
|
|
|
+ int n;
|
|
|
+ int lastwqe;
|
|
|
+ struct ib_event ev;
|
|
|
+
|
|
|
+ rcu_read_lock();
|
|
|
+
|
|
|
+ /* Deal only with RC/UC qps that use the given SL. */
|
|
|
+ for (n = 0; n < dev->rdi.qp_dev->qp_table_size; n++) {
|
|
|
+ for (qp = rcu_dereference(dev->rdi.qp_dev->qp_table[n]); qp;
|
|
|
+ qp = rcu_dereference(qp->next)) {
|
|
|
+ if (qp->port_num == ppd->port &&
|
|
|
+ (qp->ibqp.qp_type == IB_QPT_UC ||
|
|
|
+ qp->ibqp.qp_type == IB_QPT_RC) &&
|
|
|
+ qp->remote_ah_attr.sl == sl &&
|
|
|
+ (ib_rvt_state_ops[qp->state] &
|
|
|
+ RVT_POST_SEND_OK)) {
|
|
|
+ spin_lock_irq(&qp->r_lock);
|
|
|
+ spin_lock(&qp->s_hlock);
|
|
|
+ spin_lock(&qp->s_lock);
|
|
|
+ lastwqe = rvt_error_qp(qp,
|
|
|
+ IB_WC_WR_FLUSH_ERR);
|
|
|
+ spin_unlock(&qp->s_lock);
|
|
|
+ spin_unlock(&qp->s_hlock);
|
|
|
+ spin_unlock_irq(&qp->r_lock);
|
|
|
+ if (lastwqe) {
|
|
|
+ ev.device = qp->ibqp.device;
|
|
|
+ ev.element.qp = &qp->ibqp;
|
|
|
+ ev.event =
|
|
|
+ IB_EVENT_QP_LAST_WQE_REACHED;
|
|
|
+ qp->ibqp.event_handler(&ev,
|
|
|
+ qp->ibqp.qp_context);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ rcu_read_unlock();
|
|
|
+}
|