RDMA/bnxt_re: Refactor device add/remove functionalities

- bnxt_re_ib_reg() handles two main functionalities - initializing the
   device and registering with the IB stack.  Split it into 2 functions
   i.e. bnxt_re_dev_init() and bnxt_re_ib_init() to account for the same
   thereby improve modularity. Do the same for
   bnxt_re_ib_unreg()i.e. split into two functions - bnxt_re_dev_uninit()
   and bnxt_re_ib_uninit().

 - Simplify the code by combining the different steps to add and remove
   the device into two functions.

 - Report correct netdev link state during device register

Link: https://lore.kernel.org/r/1582731932-26574-2-git-send-email-selvin.xavier@broadcom.com
Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
This commit is contained in:
Selvin Xavier 2020-02-26 07:45:31 -08:00 committed by Jason Gunthorpe
parent ff6629f88c
commit c2b777a959

View File

@ -78,7 +78,8 @@ static struct list_head bnxt_re_dev_list = LIST_HEAD_INIT(bnxt_re_dev_list);
/* Mutex to protect the list of bnxt_re devices added */ /* Mutex to protect the list of bnxt_re devices added */
static DEFINE_MUTEX(bnxt_re_dev_lock); static DEFINE_MUTEX(bnxt_re_dev_lock);
static struct workqueue_struct *bnxt_re_wq; static struct workqueue_struct *bnxt_re_wq;
static void bnxt_re_ib_unreg(struct bnxt_re_dev *rdev); static void bnxt_re_remove_device(struct bnxt_re_dev *rdev);
static void bnxt_re_ib_uninit(struct bnxt_re_dev *rdev);
static void bnxt_re_destroy_chip_ctx(struct bnxt_re_dev *rdev) static void bnxt_re_destroy_chip_ctx(struct bnxt_re_dev *rdev)
{ {
@ -237,7 +238,9 @@ static void bnxt_re_shutdown(void *p)
if (!rdev) if (!rdev)
return; return;
bnxt_re_ib_unreg(rdev); bnxt_re_ib_uninit(rdev);
ASSERT_RTNL();
bnxt_re_remove_device(rdev);
} }
static void bnxt_re_stop_irq(void *handle) static void bnxt_re_stop_irq(void *handle)
@ -1317,7 +1320,41 @@ static void bnxt_re_query_hwrm_intf_version(struct bnxt_re_dev *rdev)
le16_to_cpu(resp.hwrm_intf_patch); le16_to_cpu(resp.hwrm_intf_patch);
} }
static void bnxt_re_ib_unreg(struct bnxt_re_dev *rdev) static void bnxt_re_ib_uninit(struct bnxt_re_dev *rdev)
{
/* Cleanup ib dev */
if (test_bit(BNXT_RE_FLAG_IBDEV_REGISTERED, &rdev->flags)) {
ib_unregister_device(&rdev->ibdev);
clear_bit(BNXT_RE_FLAG_IBDEV_REGISTERED, &rdev->flags);
}
}
int bnxt_re_ib_init(struct bnxt_re_dev *rdev)
{
int rc = 0;
u32 event;
/* Register ib dev */
rc = bnxt_re_register_ib(rdev);
if (rc) {
pr_err("Failed to register with IB: %#x\n", rc);
return rc;
}
set_bit(BNXT_RE_FLAG_IBDEV_REGISTERED, &rdev->flags);
dev_info(rdev_to_dev(rdev), "Device registered successfully");
ib_get_eth_speed(&rdev->ibdev, 1, &rdev->active_speed,
&rdev->active_width);
set_bit(BNXT_RE_FLAG_ISSUE_ROCE_STATS, &rdev->flags);
event = netif_running(rdev->netdev) && netif_carrier_ok(rdev->netdev) ?
IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR;
bnxt_re_dispatch_event(&rdev->ibdev, NULL, 1, event);
return rc;
}
static void bnxt_re_dev_uninit(struct bnxt_re_dev *rdev)
{ {
u8 type; u8 type;
int rc; int rc;
@ -1373,20 +1410,15 @@ static void bnxt_re_worker(struct work_struct *work)
schedule_delayed_work(&rdev->worker, msecs_to_jiffies(30000)); schedule_delayed_work(&rdev->worker, msecs_to_jiffies(30000));
} }
static int bnxt_re_ib_reg(struct bnxt_re_dev *rdev) static int bnxt_re_dev_init(struct bnxt_re_dev *rdev)
{ {
struct bnxt_qplib_creq_ctx *creq; struct bnxt_qplib_creq_ctx *creq;
struct bnxt_re_ring_attr rattr; struct bnxt_re_ring_attr rattr;
u32 db_offt; u32 db_offt;
bool locked;
int vid; int vid;
u8 type; u8 type;
int rc; int rc;
/* Acquire rtnl lock through out this function */
rtnl_lock();
locked = true;
/* Registered a new RoCE device instance to netdev */ /* Registered a new RoCE device instance to netdev */
memset(&rattr, 0, sizeof(rattr)); memset(&rattr, 0, sizeof(rattr));
rc = bnxt_re_register_netdev(rdev); rc = bnxt_re_register_netdev(rdev);
@ -1514,23 +1546,6 @@ static int bnxt_re_ib_reg(struct bnxt_re_dev *rdev)
schedule_delayed_work(&rdev->worker, msecs_to_jiffies(30000)); schedule_delayed_work(&rdev->worker, msecs_to_jiffies(30000));
} }
rtnl_unlock();
locked = false;
/* Register ib dev */
rc = bnxt_re_register_ib(rdev);
if (rc) {
ibdev_err(&rdev->ibdev,
"Failed to register with IB: %#x\n", rc);
goto fail;
}
set_bit(BNXT_RE_FLAG_IBDEV_REGISTERED, &rdev->flags);
ibdev_info(&rdev->ibdev, "Device registered successfully");
ib_get_eth_speed(&rdev->ibdev, 1, &rdev->active_speed,
&rdev->active_width);
set_bit(BNXT_RE_FLAG_ISSUE_ROCE_STATS, &rdev->flags);
bnxt_re_dispatch_event(&rdev->ibdev, NULL, 1, IB_EVENT_PORT_ACTIVE);
return 0; return 0;
free_sctx: free_sctx:
bnxt_re_net_stats_ctx_free(rdev, rdev->qplib_ctx.stats.fw_id); bnxt_re_net_stats_ctx_free(rdev, rdev->qplib_ctx.stats.fw_id);
@ -1544,10 +1559,7 @@ static int bnxt_re_ib_reg(struct bnxt_re_dev *rdev)
free_rcfw: free_rcfw:
bnxt_qplib_free_rcfw_channel(&rdev->rcfw); bnxt_qplib_free_rcfw_channel(&rdev->rcfw);
fail: fail:
if (!locked) bnxt_re_dev_uninit(rdev);
rtnl_lock();
bnxt_re_ib_unreg(rdev);
rtnl_unlock();
return rc; return rc;
} }
@ -1589,9 +1601,35 @@ static int bnxt_re_dev_reg(struct bnxt_re_dev **rdev, struct net_device *netdev)
return rc; return rc;
} }
static void bnxt_re_remove_one(struct bnxt_re_dev *rdev) static void bnxt_re_remove_device(struct bnxt_re_dev *rdev)
{ {
bnxt_re_dev_uninit(rdev);
pci_dev_put(rdev->en_dev->pdev); pci_dev_put(rdev->en_dev->pdev);
bnxt_re_dev_unreg(rdev);
}
static int bnxt_re_add_device(struct bnxt_re_dev **rdev,
struct net_device *netdev)
{
int rc;
rc = bnxt_re_dev_reg(rdev, netdev);
if (rc == -ENODEV)
return rc;
if (rc) {
pr_err("Failed to register with the device %s: %#x\n",
netdev->name, rc);
return rc;
}
pci_dev_get((*rdev)->en_dev->pdev);
rc = bnxt_re_dev_init(*rdev);
if (rc) {
pci_dev_put((*rdev)->en_dev->pdev);
bnxt_re_dev_unreg(*rdev);
}
return rc;
} }
/* Handle all deferred netevents tasks */ /* Handle all deferred netevents tasks */
@ -1606,16 +1644,17 @@ static void bnxt_re_task(struct work_struct *work)
if (re_work->event != NETDEV_REGISTER && if (re_work->event != NETDEV_REGISTER &&
!test_bit(BNXT_RE_FLAG_IBDEV_REGISTERED, &rdev->flags)) !test_bit(BNXT_RE_FLAG_IBDEV_REGISTERED, &rdev->flags))
return; goto done;
switch (re_work->event) { switch (re_work->event) {
case NETDEV_REGISTER: case NETDEV_REGISTER:
rc = bnxt_re_ib_reg(rdev); rc = bnxt_re_ib_init(rdev);
if (rc) { if (rc) {
ibdev_err(&rdev->ibdev, ibdev_err(&rdev->ibdev,
"Failed to register with IB: %#x", rc); "Failed to register with IB: %#x", rc);
bnxt_re_remove_one(rdev); rtnl_lock();
bnxt_re_dev_unreg(rdev); bnxt_re_remove_device(rdev);
rtnl_unlock();
goto exit; goto exit;
} }
break; break;
@ -1638,17 +1677,13 @@ static void bnxt_re_task(struct work_struct *work)
default: default:
break; break;
} }
done:
smp_mb__before_atomic(); smp_mb__before_atomic();
atomic_dec(&rdev->sched_count); atomic_dec(&rdev->sched_count);
exit: exit:
kfree(re_work); kfree(re_work);
} }
static void bnxt_re_init_one(struct bnxt_re_dev *rdev)
{
pci_dev_get(rdev->en_dev->pdev);
}
/* /*
* "Notifier chain callback can be invoked for the same chain from * "Notifier chain callback can be invoked for the same chain from
* different CPUs at the same time". * different CPUs at the same time".
@ -1686,17 +1721,9 @@ static int bnxt_re_netdev_event(struct notifier_block *notifier,
case NETDEV_REGISTER: case NETDEV_REGISTER:
if (rdev) if (rdev)
break; break;
rc = bnxt_re_dev_reg(&rdev, real_dev); rc = bnxt_re_add_device(&rdev, real_dev);
if (rc == -ENODEV) if (!rc)
break; sch_work = true;
if (rc) {
ibdev_err(&rdev->ibdev,
"Failed to register with the device %s: %#x\n",
real_dev->name, rc);
break;
}
bnxt_re_init_one(rdev);
sch_work = true;
break; break;
case NETDEV_UNREGISTER: case NETDEV_UNREGISTER:
@ -1705,9 +1732,8 @@ static int bnxt_re_netdev_event(struct notifier_block *notifier,
*/ */
if (atomic_read(&rdev->sched_count) > 0) if (atomic_read(&rdev->sched_count) > 0)
goto exit; goto exit;
bnxt_re_ib_unreg(rdev); bnxt_re_ib_uninit(rdev);
bnxt_re_remove_one(rdev); bnxt_re_remove_device(rdev);
bnxt_re_dev_unreg(rdev);
break; break;
default: default:
@ -1784,12 +1810,11 @@ static void __exit bnxt_re_mod_exit(void)
*/ */
flush_workqueue(bnxt_re_wq); flush_workqueue(bnxt_re_wq);
bnxt_re_dev_stop(rdev); bnxt_re_dev_stop(rdev);
bnxt_re_ib_uninit(rdev);
/* Acquire the rtnl_lock as the L2 resources are freed here */ /* Acquire the rtnl_lock as the L2 resources are freed here */
rtnl_lock(); rtnl_lock();
bnxt_re_ib_unreg(rdev); bnxt_re_remove_device(rdev);
rtnl_unlock(); rtnl_unlock();
bnxt_re_remove_one(rdev);
bnxt_re_dev_unreg(rdev);
} }
unregister_netdevice_notifier(&bnxt_re_netdev_notifier); unregister_netdevice_notifier(&bnxt_re_netdev_notifier);
if (bnxt_re_wq) if (bnxt_re_wq)