|
@@ -79,6 +79,8 @@ struct ipoib_device {
|
79
|
79
|
struct net_device *netdev;
|
80
|
80
|
/** Underlying Infiniband device */
|
81
|
81
|
struct ib_device *ibdev;
|
|
82
|
+ /** List of IPoIB devices */
|
|
83
|
+ struct list_head list;
|
82
|
84
|
/** Completion queue */
|
83
|
85
|
struct ib_completion_queue *cq;
|
84
|
86
|
/** Queue pair */
|
|
@@ -116,6 +118,9 @@ struct errortab ipoib_errors[] __errortab = {
|
116
|
118
|
__einfo_errortab ( EINFO_EINPROGRESS_JOINING ),
|
117
|
119
|
};
|
118
|
120
|
|
|
121
|
+/** List of all IPoIB devices */
|
|
122
|
+static LIST_HEAD ( ipoib_devices );
|
|
123
|
+
|
119
|
124
|
static struct net_device_operations ipoib_operations;
|
120
|
125
|
|
121
|
126
|
/****************************************************************************
|
|
@@ -783,11 +788,11 @@ static void ipoib_leave_broadcast_group ( struct ipoib_device *ipoib ) {
|
783
|
788
|
/**
|
784
|
789
|
* Handle link status change
|
785
|
790
|
*
|
786
|
|
- * @v ibdev Infiniband device
|
|
791
|
+ * @v ipoib IPoIB device
|
787
|
792
|
*/
|
788
|
|
-static void ipoib_link_state_changed ( struct ib_device *ibdev ) {
|
789
|
|
- struct net_device *netdev = ib_get_ownerdata ( ibdev );
|
790
|
|
- struct ipoib_device *ipoib = netdev->priv;
|
|
793
|
+static void ipoib_link_state_changed ( struct ipoib_device *ipoib ) {
|
|
794
|
+ struct ib_device *ibdev = ipoib->ibdev;
|
|
795
|
+ struct net_device *netdev = ipoib->netdev;
|
791
|
796
|
int rc;
|
792
|
797
|
|
793
|
798
|
/* Leave existing broadcast group */
|
|
@@ -862,7 +867,7 @@ static int ipoib_open ( struct net_device *netdev ) {
|
862
|
867
|
ib_refill_recv ( ibdev, ipoib->qp );
|
863
|
868
|
|
864
|
869
|
/* Fake a link status change to join the broadcast group */
|
865
|
|
- ipoib_link_state_changed ( ibdev );
|
|
870
|
+ ipoib_link_state_changed ( ipoib );
|
866
|
871
|
|
867
|
872
|
return 0;
|
868
|
873
|
|
|
@@ -928,7 +933,6 @@ static int ipoib_probe ( struct ib_device *ibdev ) {
|
928
|
933
|
return -ENOMEM;
|
929
|
934
|
netdev_init ( netdev, &ipoib_operations );
|
930
|
935
|
ipoib = netdev->priv;
|
931
|
|
- ib_set_ownerdata ( ibdev, netdev );
|
932
|
936
|
netdev->dev = ibdev->dev;
|
933
|
937
|
memset ( ipoib, 0, sizeof ( *ipoib ) );
|
934
|
938
|
ipoib->netdev = netdev;
|
|
@@ -947,35 +951,65 @@ static int ipoib_probe ( struct ib_device *ibdev ) {
|
947
|
951
|
memcpy ( &ipoib->broadcast, &ipoib_broadcast,
|
948
|
952
|
sizeof ( ipoib->broadcast ) );
|
949
|
953
|
|
|
954
|
+ /* Add to list of IPoIB devices */
|
|
955
|
+ list_add_tail ( &ipoib->list, &ipoib_devices );
|
|
956
|
+
|
950
|
957
|
/* Register network device */
|
951
|
958
|
if ( ( rc = register_netdev ( netdev ) ) != 0 )
|
952
|
959
|
goto err_register_netdev;
|
953
|
960
|
|
954
|
961
|
return 0;
|
955
|
962
|
|
|
963
|
+ unregister_netdev ( netdev );
|
956
|
964
|
err_register_netdev:
|
|
965
|
+ list_del ( &ipoib->list );
|
957
|
966
|
netdev_nullify ( netdev );
|
958
|
967
|
netdev_put ( netdev );
|
959
|
968
|
return rc;
|
960
|
969
|
}
|
961
|
970
|
|
|
971
|
+/**
|
|
972
|
+ * Handle device or link status change
|
|
973
|
+ *
|
|
974
|
+ * @v ibdev Infiniband device
|
|
975
|
+ */
|
|
976
|
+static void ipoib_notify ( struct ib_device *ibdev ) {
|
|
977
|
+ struct ipoib_device *ipoib;
|
|
978
|
+
|
|
979
|
+ /* Handle link status change for any attached IPoIB devices */
|
|
980
|
+ list_for_each_entry ( ipoib, &ipoib_devices, list ) {
|
|
981
|
+ if ( ipoib->ibdev != ibdev )
|
|
982
|
+ continue;
|
|
983
|
+ ipoib_link_state_changed ( ipoib );
|
|
984
|
+ }
|
|
985
|
+}
|
|
986
|
+
|
962
|
987
|
/**
|
963
|
988
|
* Remove IPoIB device
|
964
|
989
|
*
|
965
|
990
|
* @v ibdev Infiniband device
|
966
|
991
|
*/
|
967
|
992
|
static void ipoib_remove ( struct ib_device *ibdev ) {
|
968
|
|
- struct net_device *netdev = ib_get_ownerdata ( ibdev );
|
|
993
|
+ struct ipoib_device *ipoib;
|
|
994
|
+ struct ipoib_device *tmp;
|
|
995
|
+ struct net_device *netdev;
|
969
|
996
|
|
970
|
|
- unregister_netdev ( netdev );
|
971
|
|
- netdev_nullify ( netdev );
|
972
|
|
- netdev_put ( netdev );
|
|
997
|
+ /* Remove any attached IPoIB devices */
|
|
998
|
+ list_for_each_entry_safe ( ipoib, tmp, &ipoib_devices, list ) {
|
|
999
|
+ if ( ipoib->ibdev != ibdev )
|
|
1000
|
+ continue;
|
|
1001
|
+ netdev = ipoib->netdev;
|
|
1002
|
+ unregister_netdev ( netdev );
|
|
1003
|
+ list_del ( &ipoib->list );
|
|
1004
|
+ netdev_nullify ( netdev );
|
|
1005
|
+ netdev_put ( netdev );
|
|
1006
|
+ }
|
973
|
1007
|
}
|
974
|
1008
|
|
975
|
1009
|
/** IPoIB driver */
|
976
|
1010
|
struct ib_driver ipoib_driver __ib_driver = {
|
977
|
1011
|
.name = "IPoIB",
|
978
|
1012
|
.probe = ipoib_probe,
|
979
|
|
- .notify = ipoib_link_state_changed,
|
|
1013
|
+ .notify = ipoib_notify,
|
980
|
1014
|
.remove = ipoib_remove,
|
981
|
1015
|
};
|