mirror of
https://github.com/torvalds/linux.git
synced 2024-09-22 16:03:15 +00:00
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;
|
struct delayed_work worker;
|
||||||
u8 cur_prio_map;
|
u8 cur_prio_map;
|
||||||
|
u8 active_speed;
|
||||||
|
u8 active_width;
|
||||||
|
|
||||||
/* FP Notification Queue (CQ & SRQ) */
|
/* FP Notification Queue (CQ & SRQ) */
|
||||||
struct tasklet_struct nq_task;
|
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->sm_sl = 0;
|
||||||
port_attr->subnet_timeout = 0;
|
port_attr->subnet_timeout = 0;
|
||||||
port_attr->init_type_reply = 0;
|
port_attr->init_type_reply = 0;
|
||||||
/* call the underlying netdev's ethtool hooks to query speed settings
|
port_attr->active_speed = rdev->active_speed;
|
||||||
* for which we acquire rtnl_lock _only_ if it's registered with
|
port_attr->active_width = rdev->active_width;
|
||||||
* 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;
|
|
||||||
return 0;
|
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);
|
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_PORT_ACTIVE);
|
||||||
bnxt_re_dispatch_event(&rdev->ibdev, NULL, 1, IB_EVENT_GID_CHANGE);
|
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))
|
else if (netif_carrier_ok(rdev->netdev))
|
||||||
bnxt_re_dispatch_event(&rdev->ibdev, NULL, 1,
|
bnxt_re_dispatch_event(&rdev->ibdev, NULL, 1,
|
||||||
IB_EVENT_PORT_ACTIVE);
|
IB_EVENT_PORT_ACTIVE);
|
||||||
|
ib_get_eth_speed(&rdev->ibdev, 1, &rdev->active_speed,
|
||||||
|
&rdev->active_width);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user