Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 3 Jan 2011 03:34:59 +0000 (UTC)
From:      Jeff Roberson <jeff@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r216905 - in projects/ofed/head/sys/ofed: drivers/infiniband/core drivers/infiniband/hw/mlx4 include/linux
Message-ID:  <201101030334.p033YxgH072125@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jeff
Date: Mon Jan  3 03:34:59 2011
New Revision: 216905
URL: http://svn.freebsd.org/changeset/base/216905

Log:
   - Add netdevice notifiers and re-enable their appropriate handlers in
     the core stack and drivers.  These are network events for
     adding and removing network devices along with link state changes, etc.
  
  Sponsored by:	Isilon Systems, iX Systems, and Panasas.

Modified:
  projects/ofed/head/sys/ofed/drivers/infiniband/core/cma.c
  projects/ofed/head/sys/ofed/drivers/infiniband/hw/mlx4/main.c
  projects/ofed/head/sys/ofed/include/linux/netdevice.h
  projects/ofed/head/sys/ofed/include/linux/notifier.h

Modified: projects/ofed/head/sys/ofed/drivers/infiniband/core/cma.c
==============================================================================
--- projects/ofed/head/sys/ofed/drivers/infiniband/core/cma.c	Mon Jan  3 03:08:08 2011	(r216904)
+++ projects/ofed/head/sys/ofed/drivers/infiniband/core/cma.c	Mon Jan  3 03:34:59 2011	(r216905)
@@ -1681,8 +1681,6 @@ out:
 	kfree(work);
 }
 
-#ifdef __linux__
-/* XXX I need to add an EVENTHANDLER based system for handling these events. */
 static void cma_ndev_work_handler(struct work_struct *_work)
 {
 	struct cma_ndev_work *work = container_of(_work, struct cma_ndev_work, work);
@@ -1706,7 +1704,6 @@ out:
 		rdma_destroy_id(&id_priv->id);
 	kfree(work);
 }
-#endif
 
 static int cma_resolve_ib_route(struct rdma_id_private *id_priv, int timeout_ms)
 {
@@ -3183,7 +3180,6 @@ void rdma_leave_multicast(struct rdma_cm
 }
 EXPORT_SYMBOL(rdma_leave_multicast);
 
-#ifdef __linux__
 static int cma_netdev_change(struct net_device *ndev, struct rdma_id_private *id_priv)
 {
 	struct rdma_dev_addr *dev_addr;
@@ -3191,10 +3187,17 @@ static int cma_netdev_change(struct net_
 
 	dev_addr = &id_priv->id.route.addr.dev_addr;
 
+#ifdef __linux__
 	if ((dev_addr->bound_dev_if == ndev->ifindex) &&
 	    memcmp(dev_addr->src_dev_addr, ndev->dev_addr, ndev->addr_len)) {
 		printk(KERN_INFO "RDMA CM addr change for ndev %s used by id %p\n",
 		       ndev->name, &id_priv->id);
+#else
+	if ((dev_addr->bound_dev_if == ndev->if_index) &&
+	    memcmp(dev_addr->src_dev_addr, IF_LLADDR(ndev), ndev->if_addrlen)) {
+		printk(KERN_INFO "RDMA CM addr change for ndev %s used by id %p\n",
+		       ndev->if_xname, &id_priv->id);
+#endif
 		work = kzalloc(sizeof *work, GFP_KERNEL);
 		if (!work)
 			return -ENOMEM;
@@ -3217,6 +3220,7 @@ static int cma_netdev_callback(struct no
 	struct rdma_id_private *id_priv;
 	int ret = NOTIFY_DONE;
 
+#ifdef __linux__
 	if (dev_net(ndev) != &init_net)
 		return NOTIFY_DONE;
 
@@ -3225,6 +3229,10 @@ static int cma_netdev_callback(struct no
 
 	if (!(ndev->flags & IFF_MASTER) || !(ndev->priv_flags & IFF_BONDING))
 		return NOTIFY_DONE;
+#else
+	if (event != NETDEV_DOWN && event != NETDEV_UNREGISTER)
+		return NOTIFY_DONE;
+#endif
 
 	mutex_lock(&lock);
 	list_for_each_entry(cma_dev, &dev_list, list)
@@ -3242,7 +3250,6 @@ out:
 static struct notifier_block cma_nb = {
 	.notifier_call = cma_netdev_callback
 };
-#endif
 
 static void cma_add_one(struct ib_device *device)
 {
@@ -3352,9 +3359,7 @@ static int cma_init(void)
 
 	ib_sa_register_client(&sa_client);
 	rdma_addr_register_client(&addr_client);
-#ifdef __linux__
 	register_netdevice_notifier(&cma_nb);
-#endif
 
 	ret = ib_register_client(&cma_client);
 	if (ret)
@@ -3362,9 +3367,7 @@ static int cma_init(void)
 	return 0;
 
 err:
-#ifdef __linux__
 	unregister_netdevice_notifier(&cma_nb);
-#endif
 	rdma_addr_unregister_client(&addr_client);
 	ib_sa_unregister_client(&sa_client);
 	destroy_workqueue(cma_wq);
@@ -3374,9 +3377,7 @@ err:
 static void cma_cleanup(void)
 {
 	ib_unregister_client(&cma_client);
-#ifdef __linux__
 	unregister_netdevice_notifier(&cma_nb);
-#endif
 	rdma_addr_unregister_client(&addr_client);
 	ib_sa_unregister_client(&sa_client);
 	destroy_workqueue(cma_wq);

Modified: projects/ofed/head/sys/ofed/drivers/infiniband/hw/mlx4/main.c
==============================================================================
--- projects/ofed/head/sys/ofed/drivers/infiniband/hw/mlx4/main.c	Mon Jan  3 03:08:08 2011	(r216904)
+++ projects/ofed/head/sys/ofed/drivers/infiniband/hw/mlx4/main.c	Mon Jan  3 03:34:59 2011	(r216905)
@@ -94,9 +94,7 @@ static void init_query_mad(struct ib_smp
 	mad->method	   = IB_MGMT_METHOD_GET;
 }
 
-#ifdef __linux__
 static union ib_gid zgid;
-#endif
 
 static int mlx4_ib_query_device(struct ib_device *ibdev,
 				struct ib_device_attr *props)
@@ -664,10 +662,9 @@ static int add_gid_entry(struct ib_qp *i
 int mlx4_ib_add_mc(struct mlx4_ib_dev *mdev, struct mlx4_ib_qp *mqp,
 		   union ib_gid *gid)
 {
-	int ret = 0;
-#ifdef __linux__
 	u8 mac[6];
 	struct net_device *ndev;
+	int ret = 0;
 
 	if (!mqp->port)
 		return 0;
@@ -684,7 +681,6 @@ int mlx4_ib_add_mc(struct mlx4_ib_dev *m
 		rtnl_unlock();
 		dev_put(ndev);
 	}
-#endif
 
 	return ret;
 }
@@ -732,10 +728,8 @@ static int mlx4_ib_mcg_detach(struct ib_
 	int err;
 	struct mlx4_ib_dev *mdev = to_mdev(ibqp->device);
 	struct mlx4_ib_qp *mqp = to_mqp(ibqp);
-#ifdef __linux__
 	u8 mac[6];
 	struct net_device *ndev;
-#endif
 	struct gid_entry *ge;
 
 	err = mlx4_multicast_detach(mdev->dev,
@@ -746,7 +740,6 @@ static int mlx4_ib_mcg_detach(struct ib_
 	mutex_lock(&mqp->mutex);
 	ge = find_gid_entry(mqp, gid->raw);
 	if (ge) {
-#ifdef __linux__
 		spin_lock(&mdev->iboe.lock);
 		ndev = ge->added ? mdev->iboe.netdevs[ge->port - 1] : NULL;
 		if (ndev)
@@ -759,7 +752,6 @@ static int mlx4_ib_mcg_detach(struct ib_
 			rtnl_unlock();
 			dev_put(ndev);
 		}
-#endif
 		list_del(&ge->list);
 		kfree(ge);
 	} else
@@ -1056,7 +1048,6 @@ struct attribute_group diag_counters_gro
 	.attrs  = diag_rprt_attrs
 };
 
-#ifdef __linux__
 static void mlx4_addrconf_ifid_eui48(u8 *eui, int is_vlan, u16 vlan_id, struct net_device *dev)
 {
 #ifdef __linux__
@@ -1114,12 +1105,14 @@ static int update_ipv6_gids(struct mlx4_
 {
 	struct net_device *ndev = dev->iboe.netdevs[port - 1];
 	struct update_gid_work *work;
+#ifdef __linux__
 	struct net_device *tmp;
+#endif
 	int i;
 	u8 *hits;
 	int ret;
 	union ib_gid gid;
-	int free = -1;
+	int tofree = -1;
 	int found;
 	int need_update = 0;
 	int is_vlan;
@@ -1135,15 +1128,17 @@ static int update_ipv6_gids(struct mlx4_
 		goto out;
 	}
 
-	/* XXX vlan */
+#ifdef __linux__
 	read_lock(&dev_base_lock);
 	for_each_netdev(&init_net, tmp) {
 		if (ndev && (tmp == ndev
+	/* XXX vlan */
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
 			 || vlan_dev_real_dev(tmp) == ndev)) {
 #else
 						)) {
 #endif
+#endif
 			gid.global.subnet_prefix = cpu_to_be64(0xfe80000000000000LL);
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
 			vid = vlan_dev_vlan_id(tmp);
@@ -1155,23 +1150,25 @@ static int update_ipv6_gids(struct mlx4_
 			mlx4_addrconf_ifid_eui48(&gid.raw[8], is_vlan, vid, ndev);
 			found = 0;
 			for (i = 0; i < 128; ++i) {
-				if (free < 0 &&
+				if (tofree < 0 &&
 				    !memcmp(&dev->iboe.gid_table[port - 1][i], &zgid, sizeof zgid))
-					free = i;
+					tofree = i;
 				if (!memcmp(&dev->iboe.gid_table[port - 1][i], &gid, sizeof gid)) {
 					hits[i] = 1;
 					found = 1;
 					break;
 				}
 			}
-			if (!found && free >= 0) {
-				dev->iboe.gid_table[port - 1][free] = gid;
-				hits[free] = 1;
+			if (!found && tofree >= 0) {
+				dev->iboe.gid_table[port - 1][tofree] = gid;
+				hits[tofree] = 1;
 				++need_update;
 			}
+#ifdef __linux__
 		}
 	}
 	read_unlock(&dev_base_lock);
+#endif
 
 	for (i = 0; i < 128; ++i)
 		if (!hits[i]) {
@@ -1221,7 +1218,6 @@ static void netdev_removed(struct mlx4_i
 	update_ipv6_gids(dev, port, 1);
 }
 
-/* XXX netdev event needed. */
 static int mlx4_ib_netdev_event(struct notifier_block *this, unsigned long event,
 				void *ptr)
 {
@@ -1231,8 +1227,10 @@ static int mlx4_ib_netdev_event(struct n
 	struct mlx4_ib_iboe *iboe;
 	int port;
 
+#ifdef __linux__
 	if (!net_eq(dev_net(dev), &init_net))
 		return NOTIFY_DONE;
+#endif
 
 	ibdev = container_of(this, struct mlx4_ib_dev, iboe.nb);
 	iboe = &ibdev->iboe;
@@ -1268,7 +1266,6 @@ static int mlx4_ib_netdev_event(struct n
 
 	return NOTIFY_DONE;
 }
-#endif
 
 static void *mlx4_ib_add(struct mlx4_dev *dev)
 {
@@ -1434,14 +1431,12 @@ static void *mlx4_ib_add(struct mlx4_dev
 
 	if (mlx4_ib_mad_init(ibdev))
 		goto err_reg;
-#ifdef __linux__
 	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_IBOE && !iboe->nb.notifier_call) {
 		iboe->nb.notifier_call = mlx4_ib_netdev_event;
 		err = register_netdevice_notifier(&iboe->nb);
 		if (err)
 			goto err_reg;
 	}
-#endif
 	for (i = 0; i < ARRAY_SIZE(mlx4_class_attributes); ++i) {
 		if (device_create_file(&ibdev->ib_dev.dev,
 				       mlx4_class_attributes[i]))
@@ -1456,10 +1451,8 @@ static void *mlx4_ib_add(struct mlx4_dev
 	return ibdev;
 
 err_notif:
-#ifdef __linux__
 	if (unregister_netdevice_notifier(&ibdev->iboe.nb))
 		printk(KERN_WARNING "failure unregistering notifier\n");
-#endif
 	flush_workqueue(wq);
 
 err_reg:
@@ -1498,9 +1491,7 @@ static void mlx4_ib_remove(struct mlx4_d
 		mlx4_counter_free(ibdev->dev, ibdev->counters[k]);
 
 	if (ibdev->iboe.nb.notifier_call) {
-#ifdef __linux__
 		unregister_netdevice_notifier(&ibdev->iboe.nb);
-#endif
 		flush_workqueue(wq);
 		ibdev->iboe.nb.notifier_call = NULL;
 	}

Modified: projects/ofed/head/sys/ofed/include/linux/netdevice.h
==============================================================================
--- projects/ofed/head/sys/ofed/include/linux/netdevice.h	Mon Jan  3 03:08:08 2011	(r216904)
+++ projects/ofed/head/sys/ofed/include/linux/netdevice.h	Mon Jan  3 03:34:59 2011	(r216905)
@@ -54,9 +54,99 @@ extern struct net init_net;
 #define	net_device	ifnet
 
 #define	dev_get_by_index(n, idx)	ifnet_byindex_ref((idx))
+#define	dev_hold(d)	if_ref((d))
 #define	dev_put(d)	if_rele((d))
 
 #define	netif_running(dev)	!!(dev->if_drv_flags & IFF_DRV_RUNNING)
 #define	netif_oper_up(dev)	!!(dev->if_flags & IFF_UP)
 
+static inline void
+_handle_ifnet_link_event(void *arg, struct ifnet *ifp, int linkstate)
+{
+	struct notifier_block *nb;
+
+	nb = arg;
+	if (linkstate == LINK_STATE_UP)
+		nb->notifier_call(nb, NETDEV_UP, ifp);
+	else
+		nb->notifier_call(nb, NETDEV_DOWN, ifp);
+}
+
+static inline void
+_handle_ifnet_arrival_event(void *arg, struct ifnet *ifp)
+{
+	struct notifier_block *nb;
+
+	nb = arg;
+	nb->notifier_call(nb, NETDEV_REGISTER, ifp);
+}
+
+static inline void
+_handle_ifnet_departure_event(void *arg, struct ifnet *ifp)
+{
+	struct notifier_block *nb;
+
+	nb = arg;
+	nb->notifier_call(nb, NETDEV_UNREGISTER, ifp);
+}
+
+static inline int
+register_netdevice_notifier(struct notifier_block *nb)
+{
+
+	nb->tags[NETDEV_UP] = EVENTHANDLER_REGISTER(
+	    ifnet_link_event, _handle_ifnet_link_event, nb, 0);
+	nb->tags[NETDEV_REGISTER] = EVENTHANDLER_REGISTER(
+	    ifnet_arrival_event, _handle_ifnet_arrival_event, nb, 0);
+	nb->tags[NETDEV_UNREGISTER] = EVENTHANDLER_REGISTER(
+	    ifnet_departure_event, _handle_ifnet_departure_event, nb, 0);
+	return (0);
+}
+
+static inline int
+unregister_netdevice_notifier(struct notifier_block *nb)
+{
+
+        EVENTHANDLER_DEREGISTER(ifnet_link_event, nb->tags[NETDEV_UP]);
+        EVENTHANDLER_DEREGISTER(ifnet_arrival_event, nb->tags[NETDEV_REGISTER]);
+        EVENTHANDLER_DEREGISTER(ifnet_departure_event,
+	    nb->tags[NETDEV_UNREGISTER]);
+	return (0);
+}
+
+#define	rtnl_lock()
+#define	rtnl_unlock()
+
+static inline int
+dev_mc_delete(struct net_device *dev, void *addr, int alen, int all)
+{
+	struct sockaddr_dl sdl;
+
+	if (alen > sizeof(sdl.sdl_data))
+		return (-EINVAL);
+	memset(&sdl, 0, sizeof(sdl));
+	sdl.sdl_len = sizeof(sdl);
+	sdl.sdl_family = AF_LINK;
+	sdl.sdl_alen = alen;
+	memcpy(&sdl.sdl_data, addr, alen);
+
+	return -if_delmulti(dev, (struct sockaddr *)&sdl);
+}
+
+static inline int
+dev_mc_add(struct net_device *dev, void *addr, int alen, int newonly)
+{
+	struct sockaddr_dl sdl;
+
+	if (alen > sizeof(sdl.sdl_data))
+		return (-EINVAL);
+	memset(&sdl, 0, sizeof(sdl));
+	sdl.sdl_len = sizeof(sdl);
+	sdl.sdl_family = AF_LINK;
+	sdl.sdl_alen = alen;
+	memcpy(&sdl.sdl_data, addr, alen);
+
+	return -if_addmulti(dev, (struct sockaddr *)&sdl, NULL);
+}
+
 #endif	/* _LINUX_NETDEVICE_H_ */

Modified: projects/ofed/head/sys/ofed/include/linux/notifier.h
==============================================================================
--- projects/ofed/head/sys/ofed/include/linux/notifier.h	Mon Jan  3 03:08:08 2011	(r216904)
+++ projects/ofed/head/sys/ofed/include/linux/notifier.h	Mon Jan  3 03:34:59 2011	(r216905)
@@ -34,13 +34,21 @@
 /*
  * Max number of FreeBSD events to map to Linux events per notify type.
  */
-#define	NB_COUNT	5
+#define	NOTIFY_DONE	0
+#define	_NOTIFY_COUNT	5
 
 struct notifier_block {
 	int (*notifier_call)(struct notifier_block *, unsigned long, void *);
 	struct notifier_block	*next;
 	int			priority;
-	eventhandler_tag	tags[NB_COUNT];
+	eventhandler_tag	tags[_NOTIFY_COUNT];
 };
 
+/* Values must be less than NOTIFY_COUNT */
+#define	NETDEV_UP		0x0001
+#define	NETDEV_DOWN		0x0002
+#define	NETDEV_REGISTER		0x0003
+#define	NETDEV_UNREGISTER	0x0004
+
+
 #endif	/* _LINUX_NOTIFIER_H_ */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201101030334.p033YxgH072125>