Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 74828b12 authored by Somnath Kotur's avatar Somnath Kotur Committed by Doug Ledford
Browse files

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: default avatarSomnath Kotur <somnath.kotur@broadcom.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent d5917307
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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;
+3 −8
Original line number Diff line number Diff line
@@ -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;
}

+4 −0
Original line number Diff line number Diff line
@@ -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;