bnxt_re: Remove RTNL lock dependency in bnxt_re_query_port
When there is a NETDEV_UNREGISTER event, bnxt_re driver calls ib_unregister_device() (RTNL lock held). ib_unregister_device attempts to flush a worker queue scheduled by ib_core and that queue might have a pending ib_query_port(). ib_query_port in turn calls bnxt_re_query_port(), which while querying the link speed using ib_get_eth_speed(), tries to acquire the rtnl_lock() which was already held by NETDEV_UNREGISTER. Fixing the issue by removing the link speed query from bnxt_re_query_port() Now the speed is queried post a successful ib_register_device or whenever there is a NETDEV_CHANGE event. Signed-off-by: Somnath Kotur <somnath.kotur@broadcom.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
This commit is contained in:
parent
d5917307bb
commit
74828b1281
|
@ -110,6 +110,8 @@ struct bnxt_re_dev {
|
|||
|
||||
struct delayed_work worker;
|
||||
u8 cur_prio_map;
|
||||
u8 active_speed;
|
||||
u8 active_width;
|
||||
|
||||
/* FP Notification Queue (CQ & SRQ) */
|
||||
struct tasklet_struct nq_task;
|
||||
|
|
|
@ -259,14 +259,9 @@ int bnxt_re_query_port(struct ib_device *ibdev, u8 port_num,
|
|||
port_attr->sm_sl = 0;
|
||||
port_attr->subnet_timeout = 0;
|
||||
port_attr->init_type_reply = 0;
|
||||
/* call the underlying netdev's ethtool hooks to query speed settings
|
||||
* for which we acquire rtnl_lock _only_ if it's registered with
|
||||
* IB stack to avoid race in the NETDEV_UNREG path
|
||||
*/
|
||||
if (test_bit(BNXT_RE_FLAG_IBDEV_REGISTERED, &rdev->flags))
|
||||
if (ib_get_eth_speed(ibdev, port_num, &port_attr->active_speed,
|
||||
&port_attr->active_width))
|
||||
return -EINVAL;
|
||||
port_attr->active_speed = rdev->active_speed;
|
||||
port_attr->active_width = rdev->active_width;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1161,6 +1161,8 @@ static int bnxt_re_ib_reg(struct bnxt_re_dev *rdev)
|
|||
}
|
||||
}
|
||||
set_bit(BNXT_RE_FLAG_IBDEV_REGISTERED, &rdev->flags);
|
||||
ib_get_eth_speed(&rdev->ibdev, 1, &rdev->active_speed,
|
||||
&rdev->active_width);
|
||||
bnxt_re_dispatch_event(&rdev->ibdev, NULL, 1, IB_EVENT_PORT_ACTIVE);
|
||||
bnxt_re_dispatch_event(&rdev->ibdev, NULL, 1, IB_EVENT_GID_CHANGE);
|
||||
|
||||
|
@ -1255,6 +1257,8 @@ static void bnxt_re_task(struct work_struct *work)
|
|||
else if (netif_carrier_ok(rdev->netdev))
|
||||
bnxt_re_dispatch_event(&rdev->ibdev, NULL, 1,
|
||||
IB_EVENT_PORT_ACTIVE);
|
||||
ib_get_eth_speed(&rdev->ibdev, 1, &rdev->active_speed,
|
||||
&rdev->active_width);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue