aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/ulp
diff options
context:
space:
mode:
authorYosef Etigin <yosefe@voltaire.com>2007-05-19 11:51:54 -0400
committerRoland Dreier <rolandd@cisco.com>2007-05-19 11:51:54 -0400
commit26bbf13ce1ca21ec69175bcc4b995cb8ffdf8593 (patch)
tree4bcad0db9ad75fe820c4f7f31155d984a03d2a7a /drivers/infiniband/ulp
parent1af4c435f3ab9cdf72ce86c35a455c8bef1d6536 (diff)
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>
Diffstat (limited to 'drivers/infiniband/ulp')
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h7
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c85
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c7
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_verbs.c38
4 files changed, 92 insertions, 45 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 87310eeb6df0..93d4a9a1e1dd 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -201,15 +201,17 @@ struct ipoib_dev_priv {
201 struct list_head multicast_list; 201 struct list_head multicast_list;
202 struct rb_root multicast_tree; 202 struct rb_root multicast_tree;
203 203
204 struct delayed_work pkey_task; 204 struct delayed_work pkey_poll_task;
205 struct delayed_work mcast_task; 205 struct delayed_work mcast_task;
206 struct work_struct flush_task; 206 struct work_struct flush_task;
207 struct work_struct restart_task; 207 struct work_struct restart_task;
208 struct delayed_work ah_reap_task; 208 struct delayed_work ah_reap_task;
209 struct work_struct pkey_event_task;
209 210
210 struct ib_device *ca; 211 struct ib_device *ca;
211 u8 port; 212 u8 port;
212 u16 pkey; 213 u16 pkey;
214 u16 pkey_index;
213 struct ib_pd *pd; 215 struct ib_pd *pd;
214 struct ib_mr *mr; 216 struct ib_mr *mr;
215 struct ib_cq *cq; 217 struct ib_cq *cq;
@@ -333,12 +335,13 @@ struct ipoib_dev_priv *ipoib_intf_alloc(const char *format);
333 335
334int ipoib_ib_dev_init(struct net_device *dev, struct ib_device *ca, int port); 336int ipoib_ib_dev_init(struct net_device *dev, struct ib_device *ca, int port);
335void ipoib_ib_dev_flush(struct work_struct *work); 337void ipoib_ib_dev_flush(struct work_struct *work);
338void ipoib_pkey_event(struct work_struct *work);
336void ipoib_ib_dev_cleanup(struct net_device *dev); 339void ipoib_ib_dev_cleanup(struct net_device *dev);
337 340
338int ipoib_ib_dev_open(struct net_device *dev); 341int ipoib_ib_dev_open(struct net_device *dev);
339int ipoib_ib_dev_up(struct net_device *dev); 342int ipoib_ib_dev_up(struct net_device *dev);
340int ipoib_ib_dev_down(struct net_device *dev, int flush); 343int ipoib_ib_dev_down(struct net_device *dev, int flush);
341int ipoib_ib_dev_stop(struct net_device *dev); 344int ipoib_ib_dev_stop(struct net_device *dev, int flush);
342 345
343int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port); 346int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port);
344void ipoib_dev_cleanup(struct net_device *dev); 347void ipoib_dev_cleanup(struct net_device *dev);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 68d72c6f7ffb..e3b0937011d1 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -448,6 +448,13 @@ int ipoib_ib_dev_open(struct net_device *dev)
448 struct ipoib_dev_priv *priv = netdev_priv(dev); 448 struct ipoib_dev_priv *priv = netdev_priv(dev);
449 int ret; 449 int ret;
450 450
451 if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &priv->pkey_index)) {
452 ipoib_warn(priv, "P_Key 0x%04x not found\n", priv->pkey);
453 clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
454 return -1;
455 }
456 set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
457
451 ret = ipoib_init_qp(dev); 458 ret = ipoib_init_qp(dev);
452 if (ret) { 459 if (ret) {
453 ipoib_warn(priv, "ipoib_init_qp returned %d\n", ret); 460 ipoib_warn(priv, "ipoib_init_qp returned %d\n", ret);
@@ -457,14 +464,14 @@ int ipoib_ib_dev_open(struct net_device *dev)
457 ret = ipoib_ib_post_receives(dev); 464 ret = ipoib_ib_post_receives(dev);
458 if (ret) { 465 if (ret) {
459 ipoib_warn(priv, "ipoib_ib_post_receives returned %d\n", ret); 466 ipoib_warn(priv, "ipoib_ib_post_receives returned %d\n", ret);
460 ipoib_ib_dev_stop(dev); 467 ipoib_ib_dev_stop(dev, 1);
461 return -1; 468 return -1;
462 } 469 }
463 470
464 ret = ipoib_cm_dev_open(dev); 471 ret = ipoib_cm_dev_open(dev);
465 if (ret) { 472 if (ret) {
466 ipoib_warn(priv, "ipoib_ib_post_receives returned %d\n", ret); 473 ipoib_warn(priv, "ipoib_ib_post_receives returned %d\n", ret);
467 ipoib_ib_dev_stop(dev); 474 ipoib_ib_dev_stop(dev, 1);
468 return -1; 475 return -1;
469 } 476 }
470 477
@@ -516,7 +523,7 @@ int ipoib_ib_dev_down(struct net_device *dev, int flush)
516 if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) { 523 if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) {
517 mutex_lock(&pkey_mutex); 524 mutex_lock(&pkey_mutex);
518 set_bit(IPOIB_PKEY_STOP, &priv->flags); 525 set_bit(IPOIB_PKEY_STOP, &priv->flags);
519 cancel_delayed_work(&priv->pkey_task); 526 cancel_delayed_work(&priv->pkey_poll_task);
520 mutex_unlock(&pkey_mutex); 527 mutex_unlock(&pkey_mutex);
521 if (flush) 528 if (flush)
522 flush_workqueue(ipoib_workqueue); 529 flush_workqueue(ipoib_workqueue);
@@ -543,7 +550,7 @@ static int recvs_pending(struct net_device *dev)
543 return pending; 550 return pending;
544} 551}
545 552
546int ipoib_ib_dev_stop(struct net_device *dev) 553int ipoib_ib_dev_stop(struct net_device *dev, int flush)
547{ 554{
548 struct ipoib_dev_priv *priv = netdev_priv(dev); 555 struct ipoib_dev_priv *priv = netdev_priv(dev);
549 struct ib_qp_attr qp_attr; 556 struct ib_qp_attr qp_attr;
@@ -629,7 +636,8 @@ timeout:
629 /* Wait for all AHs to be reaped */ 636 /* Wait for all AHs to be reaped */
630 set_bit(IPOIB_STOP_REAPER, &priv->flags); 637 set_bit(IPOIB_STOP_REAPER, &priv->flags);
631 cancel_delayed_work(&priv->ah_reap_task); 638 cancel_delayed_work(&priv->ah_reap_task);
632 flush_workqueue(ipoib_workqueue); 639 if (flush)
640 flush_workqueue(ipoib_workqueue);
633 641
634 begin = jiffies; 642 begin = jiffies;
635 643
@@ -673,13 +681,24 @@ int ipoib_ib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
673 return 0; 681 return 0;
674} 682}
675 683
676void ipoib_ib_dev_flush(struct work_struct *work) 684static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, int pkey_event)
677{ 685{
678 struct ipoib_dev_priv *cpriv, *priv = 686 struct ipoib_dev_priv *cpriv;
679 container_of(work, struct ipoib_dev_priv, flush_task);
680 struct net_device *dev = priv->dev; 687 struct net_device *dev = priv->dev;
688 u16 new_index;
689
690 mutex_lock(&priv->vlan_mutex);
681 691
682 if (!test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags) ) { 692 /*
693 * Flush any child interfaces too -- they might be up even if
694 * the parent is down.
695 */
696 list_for_each_entry(cpriv, &priv->child_intfs, list)
697 __ipoib_ib_dev_flush(cpriv, pkey_event);
698
699 mutex_unlock(&priv->vlan_mutex);
700
701 if (!test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags)) {
683 ipoib_dbg(priv, "Not flushing - IPOIB_FLAG_INITIALIZED not set.\n"); 702 ipoib_dbg(priv, "Not flushing - IPOIB_FLAG_INITIALIZED not set.\n");
684 return; 703 return;
685 } 704 }
@@ -689,10 +708,32 @@ void ipoib_ib_dev_flush(struct work_struct *work)
689 return; 708 return;
690 } 709 }
691 710
711 if (pkey_event) {
712 if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &new_index)) {
713 clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
714 ipoib_ib_dev_down(dev, 0);
715 ipoib_pkey_dev_delay_open(dev);
716 return;
717 }
718 set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
719
720 /* restart QP only if P_Key index is changed */
721 if (new_index == priv->pkey_index) {
722 ipoib_dbg(priv, "Not flushing - P_Key index not changed.\n");
723 return;
724 }
725 priv->pkey_index = new_index;
726 }
727
692 ipoib_dbg(priv, "flushing\n"); 728 ipoib_dbg(priv, "flushing\n");
693 729
694 ipoib_ib_dev_down(dev, 0); 730 ipoib_ib_dev_down(dev, 0);
695 731
732 if (pkey_event) {
733 ipoib_ib_dev_stop(dev, 0);
734 ipoib_ib_dev_open(dev);
735 }
736
696 /* 737 /*
697 * The device could have been brought down between the start and when 738 * The device could have been brought down between the start and when
698 * we get here, don't bring it back up if it's not configured up 739 * we get here, don't bring it back up if it's not configured up
@@ -701,14 +742,24 @@ void ipoib_ib_dev_flush(struct work_struct *work)
701 ipoib_ib_dev_up(dev); 742 ipoib_ib_dev_up(dev);
702 ipoib_mcast_restart_task(&priv->restart_task); 743 ipoib_mcast_restart_task(&priv->restart_task);
703 } 744 }
745}
704 746
705 mutex_lock(&priv->vlan_mutex); 747void ipoib_ib_dev_flush(struct work_struct *work)
748{
749 struct ipoib_dev_priv *priv =
750 container_of(work, struct ipoib_dev_priv, flush_task);
706 751
707 /* Flush any child interfaces too */ 752 ipoib_dbg(priv, "Flushing %s\n", priv->dev->name);
708 list_for_each_entry(cpriv, &priv->child_intfs, list) 753 __ipoib_ib_dev_flush(priv, 0);
709 ipoib_ib_dev_flush(&cpriv->flush_task); 754}
710 755
711 mutex_unlock(&priv->vlan_mutex); 756void ipoib_pkey_event(struct work_struct *work)
757{
758 struct ipoib_dev_priv *priv =
759 container_of(work, struct ipoib_dev_priv, pkey_event_task);
760
761 ipoib_dbg(priv, "Flushing %s and restarting its QP\n", priv->dev->name);
762 __ipoib_ib_dev_flush(priv, 1);
712} 763}
713 764
714void ipoib_ib_dev_cleanup(struct net_device *dev) 765void ipoib_ib_dev_cleanup(struct net_device *dev)
@@ -736,7 +787,7 @@ void ipoib_ib_dev_cleanup(struct net_device *dev)
736void ipoib_pkey_poll(struct work_struct *work) 787void ipoib_pkey_poll(struct work_struct *work)
737{ 788{
738 struct ipoib_dev_priv *priv = 789 struct ipoib_dev_priv *priv =
739 container_of(work, struct ipoib_dev_priv, pkey_task.work); 790 container_of(work, struct ipoib_dev_priv, pkey_poll_task.work);
740 struct net_device *dev = priv->dev; 791 struct net_device *dev = priv->dev;
741 792
742 ipoib_pkey_dev_check_presence(dev); 793 ipoib_pkey_dev_check_presence(dev);
@@ -747,7 +798,7 @@ void ipoib_pkey_poll(struct work_struct *work)
747 mutex_lock(&pkey_mutex); 798 mutex_lock(&pkey_mutex);
748 if (!test_bit(IPOIB_PKEY_STOP, &priv->flags)) 799 if (!test_bit(IPOIB_PKEY_STOP, &priv->flags))
749 queue_delayed_work(ipoib_workqueue, 800 queue_delayed_work(ipoib_workqueue,
750 &priv->pkey_task, 801 &priv->pkey_poll_task,
751 HZ); 802 HZ);
752 mutex_unlock(&pkey_mutex); 803 mutex_unlock(&pkey_mutex);
753 } 804 }
@@ -766,7 +817,7 @@ int ipoib_pkey_dev_delay_open(struct net_device *dev)
766 mutex_lock(&pkey_mutex); 817 mutex_lock(&pkey_mutex);
767 clear_bit(IPOIB_PKEY_STOP, &priv->flags); 818 clear_bit(IPOIB_PKEY_STOP, &priv->flags);
768 queue_delayed_work(ipoib_workqueue, 819 queue_delayed_work(ipoib_workqueue,
769 &priv->pkey_task, 820 &priv->pkey_poll_task,
770 HZ); 821 HZ);
771 mutex_unlock(&pkey_mutex); 822 mutex_unlock(&pkey_mutex);
772 return 1; 823 return 1;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 0a428f2b05c7..894b1dcdf3eb 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -107,7 +107,7 @@ int ipoib_open(struct net_device *dev)
107 return -EINVAL; 107 return -EINVAL;
108 108
109 if (ipoib_ib_dev_up(dev)) { 109 if (ipoib_ib_dev_up(dev)) {
110 ipoib_ib_dev_stop(dev); 110 ipoib_ib_dev_stop(dev, 1);
111 return -EINVAL; 111 return -EINVAL;
112 } 112 }
113 113
@@ -152,7 +152,7 @@ static int ipoib_stop(struct net_device *dev)
152 flush_workqueue(ipoib_workqueue); 152 flush_workqueue(ipoib_workqueue);
153 153
154 ipoib_ib_dev_down(dev, 1); 154 ipoib_ib_dev_down(dev, 1);
155 ipoib_ib_dev_stop(dev); 155 ipoib_ib_dev_stop(dev, 1);
156 156
157 if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { 157 if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) {
158 struct ipoib_dev_priv *cpriv; 158 struct ipoib_dev_priv *cpriv;
@@ -988,7 +988,8 @@ static void ipoib_setup(struct net_device *dev)
988 INIT_LIST_HEAD(&priv->dead_ahs); 988 INIT_LIST_HEAD(&priv->dead_ahs);
989 INIT_LIST_HEAD(&priv->multicast_list); 989 INIT_LIST_HEAD(&priv->multicast_list);
990 990
991 INIT_DELAYED_WORK(&priv->pkey_task, ipoib_pkey_poll); 991 INIT_DELAYED_WORK(&priv->pkey_poll_task, ipoib_pkey_poll);
992 INIT_WORK(&priv->pkey_event_task, ipoib_pkey_event);
992 INIT_DELAYED_WORK(&priv->mcast_task, ipoib_mcast_join_task); 993 INIT_DELAYED_WORK(&priv->mcast_task, ipoib_mcast_join_task);
993 INIT_WORK(&priv->flush_task, ipoib_ib_dev_flush); 994 INIT_WORK(&priv->flush_task, ipoib_ib_dev_flush);
994 INIT_WORK(&priv->restart_task, ipoib_mcast_restart_task); 995 INIT_WORK(&priv->restart_task, ipoib_mcast_restart_task);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
index 5c3c6a43a52b..791252621b26 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
@@ -33,8 +33,6 @@
33 * $Id: ipoib_verbs.c 1349 2004-12-16 21:09:43Z roland $ 33 * $Id: ipoib_verbs.c 1349 2004-12-16 21:09:43Z roland $
34 */ 34 */
35 35
36#include <rdma/ib_cache.h>
37
38#include "ipoib.h" 36#include "ipoib.h"
39 37
40int ipoib_mcast_attach(struct net_device *dev, u16 mlid, union ib_gid *mgid) 38int 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)
49 if (!qp_attr) 47 if (!qp_attr)
50 goto out; 48 goto out;
51 49
52 if (ib_find_cached_pkey(priv->ca, priv->port, priv->pkey, &pkey_index)) { 50 if (ib_find_pkey(priv->ca, priv->port, priv->pkey, &pkey_index)) {
53 clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags); 51 clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
54 ret = -ENXIO; 52 ret = -ENXIO;
55 goto out; 53 goto out;
@@ -94,26 +92,16 @@ int ipoib_init_qp(struct net_device *dev)
94{ 92{
95 struct ipoib_dev_priv *priv = netdev_priv(dev); 93 struct ipoib_dev_priv *priv = netdev_priv(dev);
96 int ret; 94 int ret;
97 u16 pkey_index;
98 struct ib_qp_attr qp_attr; 95 struct ib_qp_attr qp_attr;
99 int attr_mask; 96 int attr_mask;
100 97
101 /* 98 if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags))
102 * Search through the port P_Key table for the requested pkey value. 99 return -1;
103 * The port has to be assigned to the respective IB partition in
104 * advance.
105 */
106 ret = ib_find_cached_pkey(priv->ca, priv->port, priv->pkey, &pkey_index);
107 if (ret) {
108 clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
109 return ret;
110 }
111 set_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
112 100
113 qp_attr.qp_state = IB_QPS_INIT; 101 qp_attr.qp_state = IB_QPS_INIT;
114 qp_attr.qkey = 0; 102 qp_attr.qkey = 0;
115 qp_attr.port_num = priv->port; 103 qp_attr.port_num = priv->port;
116 qp_attr.pkey_index = pkey_index; 104 qp_attr.pkey_index = priv->pkey_index;
117 attr_mask = 105 attr_mask =
118 IB_QP_QKEY | 106 IB_QP_QKEY |
119 IB_QP_PORT | 107 IB_QP_PORT |
@@ -259,14 +247,18 @@ void ipoib_event(struct ib_event_handler *handler,
259 struct ipoib_dev_priv *priv = 247 struct ipoib_dev_priv *priv =
260 container_of(handler, struct ipoib_dev_priv, event_handler); 248 container_of(handler, struct ipoib_dev_priv, event_handler);
261 249
262 if ((record->event == IB_EVENT_PORT_ERR || 250 if (record->element.port_num != priv->port)
263 record->event == IB_EVENT_PKEY_CHANGE || 251 return;
264 record->event == IB_EVENT_PORT_ACTIVE || 252
265 record->event == IB_EVENT_LID_CHANGE || 253 if (record->event == IB_EVENT_PORT_ERR ||
266 record->event == IB_EVENT_SM_CHANGE || 254 record->event == IB_EVENT_PORT_ACTIVE ||
267 record->event == IB_EVENT_CLIENT_REREGISTER) && 255 record->event == IB_EVENT_LID_CHANGE ||
268 record->element.port_num == priv->port) { 256 record->event == IB_EVENT_SM_CHANGE ||
257 record->event == IB_EVENT_CLIENT_REREGISTER) {
269 ipoib_dbg(priv, "Port state change event\n"); 258 ipoib_dbg(priv, "Port state change event\n");
270 queue_work(ipoib_workqueue, &priv->flush_task); 259 queue_work(ipoib_workqueue, &priv->flush_task);
260 } else if (record->event == IB_EVENT_PKEY_CHANGE) {
261 ipoib_dbg(priv, "P_Key change event on port:%d\n", priv->port);
262 queue_work(ipoib_workqueue, &priv->pkey_event_task);
271 } 263 }
272} 264}