struct net_device *netdev;
/** Underlying Infiniband device */
struct ib_device *ibdev;
+ /** List of IPoIB devices */
+ struct list_head list;
/** Completion queue */
struct ib_completion_queue *cq;
/** Queue pair */
__einfo_errortab ( EINFO_EINPROGRESS_JOINING ),
};
+/** List of all IPoIB devices */
+static LIST_HEAD ( ipoib_devices );
+
static struct net_device_operations ipoib_operations;
/****************************************************************************
/**
* Handle link status change
*
- * @v ibdev Infiniband device
+ * @v ipoib IPoIB device
*/
-static void ipoib_link_state_changed ( struct ib_device *ibdev ) {
- struct net_device *netdev = ib_get_ownerdata ( ibdev );
- struct ipoib_device *ipoib = netdev->priv;
+static void ipoib_link_state_changed ( struct ipoib_device *ipoib ) {
+ struct ib_device *ibdev = ipoib->ibdev;
+ struct net_device *netdev = ipoib->netdev;
int rc;
/* Leave existing broadcast group */
ib_refill_recv ( ibdev, ipoib->qp );
/* Fake a link status change to join the broadcast group */
- ipoib_link_state_changed ( ibdev );
+ ipoib_link_state_changed ( ipoib );
return 0;
return -ENOMEM;
netdev_init ( netdev, &ipoib_operations );
ipoib = netdev->priv;
- ib_set_ownerdata ( ibdev, netdev );
netdev->dev = ibdev->dev;
memset ( ipoib, 0, sizeof ( *ipoib ) );
ipoib->netdev = netdev;
memcpy ( &ipoib->broadcast, &ipoib_broadcast,
sizeof ( ipoib->broadcast ) );
+ /* Add to list of IPoIB devices */
+ list_add_tail ( &ipoib->list, &ipoib_devices );
+
/* Register network device */
if ( ( rc = register_netdev ( netdev ) ) != 0 )
goto err_register_netdev;
return 0;
+ unregister_netdev ( netdev );
err_register_netdev:
+ list_del ( &ipoib->list );
netdev_nullify ( netdev );
netdev_put ( netdev );
return rc;
}
+/**
+ * Handle device or link status change
+ *
+ * @v ibdev Infiniband device
+ */
+static void ipoib_notify ( struct ib_device *ibdev ) {
+ struct ipoib_device *ipoib;
+
+ /* Handle link status change for any attached IPoIB devices */
+ list_for_each_entry ( ipoib, &ipoib_devices, list ) {
+ if ( ipoib->ibdev != ibdev )
+ continue;
+ ipoib_link_state_changed ( ipoib );
+ }
+}
+
/**
* Remove IPoIB device
*
* @v ibdev Infiniband device
*/
static void ipoib_remove ( struct ib_device *ibdev ) {
- struct net_device *netdev = ib_get_ownerdata ( ibdev );
+ struct ipoib_device *ipoib;
+ struct ipoib_device *tmp;
+ struct net_device *netdev;
- unregister_netdev ( netdev );
- netdev_nullify ( netdev );
- netdev_put ( netdev );
+ /* Remove any attached IPoIB devices */
+ list_for_each_entry_safe ( ipoib, tmp, &ipoib_devices, list ) {
+ if ( ipoib->ibdev != ibdev )
+ continue;
+ netdev = ipoib->netdev;
+ unregister_netdev ( netdev );
+ list_del ( &ipoib->list );
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+ }
}
/** IPoIB driver */
struct ib_driver ipoib_driver __ib_driver = {
.name = "IPoIB",
.probe = ipoib_probe,
- .notify = ipoib_link_state_changed,
+ .notify = ipoib_notify,
.remove = ipoib_remove,
};
/** Driver private data */
void *drv_priv;
- /** Owner private data */
- void *owner_priv;
};
/** An Infiniband upper-layer driver */
return ibdev->drv_priv;
}
-/**
- * Set Infiniband device owner-private data
- *
- * @v ibdev Infiniband device
- * @v priv Private data
- */
-static inline __always_inline void
-ib_set_ownerdata ( struct ib_device *ibdev, void *priv ) {
- ibdev->owner_priv = priv;
-}
-
-/**
- * Get Infiniband device owner-private data
- *
- * @v ibdev Infiniband device
- * @ret priv Private data
- */
-static inline __always_inline void *
-ib_get_ownerdata ( struct ib_device *ibdev ) {
- return ibdev->owner_priv;
-}
-
#endif /* _IPXE_INFINIBAND_H */