@@ -547,6 +547,12 @@ int ib_register_device(struct ib_device *device,
device->reg_state = IB_DEV_REGISTERED;
+ if (device->enable_driver) {
+ ret = device->enable_driver(device);
+ if (ret)
+ goto sysfs_cleanup;
+ }
+
list_for_each_entry(client, &client_list, list)
if (!add_client_context(device, client) && client->add)
client->add(device);
@@ -558,6 +564,8 @@ int ib_register_device(struct ib_device *device,
mutex_unlock(&device_mutex);
return 0;
+sysfs_cleanup:
+ ib_device_unregister_sysfs(device);
cg_cleanup:
ib_device_unregister_rdmacg(device);
cache_cleanup:
@@ -551,27 +551,27 @@ enum rdma_link_layer rxe_link_layer(struct rxe_dev *rxe, unsigned int port_num)
return IB_LINK_LAYER_ETHERNET;
}
-struct rxe_dev *rxe_net_add(struct net_device *ndev)
+int rxe_net_add(struct net_device *ndev)
{
int err;
struct rxe_dev *rxe = NULL;
rxe = (struct rxe_dev *)ib_alloc_device(sizeof(*rxe));
if (!rxe)
- return NULL;
+ return -ENOMEM;
rxe->ndev = ndev;
err = rxe_add(rxe, ndev->mtu);
if (err) {
ib_dealloc_device(&rxe->ib_dev);
- return NULL;
+ return err;
}
spin_lock_bh(&dev_list_lock);
list_add_tail(&rxe->list, &rxe_dev_list);
spin_unlock_bh(&dev_list_lock);
- return rxe;
+ return 0;
}
void rxe_remove_all(void)
@@ -47,7 +47,7 @@ extern struct rxe_recv_sockets recv_sockets;
extern struct notifier_block rxe_net_notifier;
void rxe_release_udp_tunnel(struct socket *sk);
-struct rxe_dev *rxe_net_add(struct net_device *ndev);
+int rxe_net_add(struct net_device *ndev);
int rxe_net_init(void);
void rxe_net_exit(void);
@@ -75,7 +75,6 @@ static int rxe_param_set_add(const char *val, const struct kernel_param *kp)
int err = 0;
char intf[32];
struct net_device *ndev = NULL;
- struct rxe_dev *rxe;
len = sanitize_arg(val, intf, sizeof(intf));
if (!len) {
@@ -97,15 +96,12 @@ static int rxe_param_set_add(const char *val, const struct kernel_param *kp)
goto err;
}
- rxe = rxe_net_add(ndev);
- if (!rxe) {
+ err = rxe_net_add(ndev);
+ if (err) {
pr_err("failed to add %s\n", intf);
- err = -EINVAL;
goto err;
}
- rxe_set_port_state(ndev);
- pr_info("added %s to %s\n", rxe->ib_dev.name, intf);
err:
if (ndev)
dev_put(ndev);
@@ -1188,6 +1188,15 @@ static struct device_attribute *rxe_dev_attributes[] = {
&dev_attr_parent,
};
+static int rxe_enable_driver(struct ib_device *ib_dev)
+{
+ struct rxe_dev *rxe = container_of(ib_dev, struct rxe_dev, ib_dev);
+
+ rxe_set_port_state(rxe);
+ dev_info(&rxe->ib_dev.dev, "added %s\n", netdev_name(rxe->ndev));
+ return 0;
+}
+
int rxe_register_device(struct rxe_dev *rxe)
{
int err;
@@ -1290,6 +1299,7 @@ int rxe_register_device(struct rxe_dev *rxe)
dev->detach_mcast = rxe_detach_mcast;
dev->get_hw_stats = rxe_ib_get_hw_stats;
dev->alloc_hw_stats = rxe_ib_alloc_hw_stats;
+ dev->enable_driver = rxe_enable_driver;
tfm = crypto_alloc_shash("crc32", 0, 0);
if (IS_ERR(tfm)) {
@@ -1321,6 +1331,10 @@ int rxe_register_device(struct rxe_dev *rxe)
err1:
crypto_free_shash(rxe->tfm);
+ /*
+ * Note that rxe may be invalid at this point if another thread
+ * unregistered it.
+ */
return err;
}
@@ -2317,6 +2317,11 @@ struct ib_device {
struct ib_rwq_ind_table_init_attr *init_attr,
struct ib_udata *udata);
int (*destroy_rwq_ind_table)(struct ib_rwq_ind_table *wq_ind_table);
+ /*
+ * Called after the device becomes registered, before clients are
+ * attached
+ */
+ int (*enable_driver)(struct ib_device *device);
/**
* rdma netdev operation
*