IPoIB: Handle P_Key table reordering
SM reconfiguration or failover possibly causes a shuffling of the values in the P_Key table. Right now, IPoIB only queries for the P_Key index once when it creates the device QP, and hence there are problems if the index of a P_Key value changes. Fix this by using the PKEY_CHANGE event to trigger a recheck of the P_Key index. Signed-off-by: Yosef Etigin <yosefe@voltaire.com> Acked-by: Michael S. Tsirkin <mst@dev.mellanox.co.il> Signed-off-by: Roland Dreier <rolandd@cisco.com>
This commit is contained in:

committed by
Roland Dreier

parent
1af4c435f3
commit
26bbf13ce1
@@ -33,8 +33,6 @@
|
||||
* $Id: ipoib_verbs.c 1349 2004-12-16 21:09:43Z roland $
|
||||
*/
|
||||
|
||||
#include <rdma/ib_cache.h>
|
||||
|
||||
#include "ipoib.h"
|
||||
|
||||
int ipoib_mcast_attach(struct net_device *dev, u16 mlid, union ib_gid *mgid)
|
||||
@@ -49,7 +47,7 @@ int ipoib_mcast_attach(struct net_device *dev, u16 mlid, union ib_gid *mgid)
|
||||
if (!qp_attr)
|
||||
goto out;
|
||||
|
||||
if (ib_find_cached_pkey(priv->ca, priv->port, priv->pkey, &pkey_index)) {
|
||||
if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &pkey_index)) {
|
||||
clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
|
||||
ret = -ENXIO;
|
||||
goto out;
|
||||
@@ -94,26 +92,16 @@ int ipoib_init_qp(struct net_device *dev)
|
||||
{
|
||||
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
||||
int ret;
|
||||
u16 pkey_index;
|
||||
struct ib_qp_attr qp_attr;
|
||||
int attr_mask;
|
||||
|
||||
/*
|
||||
* Search through the port P_Key table for the requested pkey value.
|
||||
* The port has to be assigned to the respective IB partition in
|
||||
* advance.
|
||||
*/
|
||||
ret = ib_find_cached_pkey(priv->ca, priv->port, priv->pkey, &pkey_index);
|
||||
if (ret) {
|
||||
clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
|
||||
return ret;
|
||||
}
|
||||
set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
|
||||
if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags))
|
||||
return -1;
|
||||
|
||||
qp_attr.qp_state = IB_QPS_INIT;
|
||||
qp_attr.qkey = 0;
|
||||
qp_attr.port_num = priv->port;
|
||||
qp_attr.pkey_index = pkey_index;
|
||||
qp_attr.pkey_index = priv->pkey_index;
|
||||
attr_mask =
|
||||
IB_QP_QKEY |
|
||||
IB_QP_PORT |
|
||||
@@ -259,14 +247,18 @@ void ipoib_event(struct ib_event_handler *handler,
|
||||
struct ipoib_dev_priv *priv =
|
||||
container_of(handler, struct ipoib_dev_priv, event_handler);
|
||||
|
||||
if ((record->event == IB_EVENT_PORT_ERR ||
|
||||
record->event == IB_EVENT_PKEY_CHANGE ||
|
||||
record->event == IB_EVENT_PORT_ACTIVE ||
|
||||
record->event == IB_EVENT_LID_CHANGE ||
|
||||
record->event == IB_EVENT_SM_CHANGE ||
|
||||
record->event == IB_EVENT_CLIENT_REREGISTER) &&
|
||||
record->element.port_num == priv->port) {
|
||||
if (record->element.port_num != priv->port)
|
||||
return;
|
||||
|
||||
if (record->event == IB_EVENT_PORT_ERR ||
|
||||
record->event == IB_EVENT_PORT_ACTIVE ||
|
||||
record->event == IB_EVENT_LID_CHANGE ||
|
||||
record->event == IB_EVENT_SM_CHANGE ||
|
||||
record->event == IB_EVENT_CLIENT_REREGISTER) {
|
||||
ipoib_dbg(priv, "Port state change event\n");
|
||||
queue_work(ipoib_workqueue, &priv->flush_task);
|
||||
} else if (record->event == IB_EVENT_PKEY_CHANGE) {
|
||||
ipoib_dbg(priv, "P_Key change event on port:%d\n", priv->port);
|
||||
queue_work(ipoib_workqueue, &priv->pkey_event_task);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user