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

Commit 10ee0fae authored by Sucheta Chakraborty's avatar Sucheta Chakraborty Committed by David S. Miller
Browse files

qlcnic: fix beacon and LED test.



o Updated version number to 5.0.25

o Do not hold onto RESETTING_BIT for entire duration of LED/ beacon test.
  Instead, just checking for RESETTING_BIT not set before sending config_led
  command down to card.

o Take rtnl_lock instead of RESETTING_BIT for beacon test while sending
  config_led command down to make sure interface cannot be brought up/ down.

o Allocate and free resources if interface is down before
  sending the config_led command. This is to make sure config_led
  command sending doesn't fail.

o Clear QLCNIC_LED_ENABLE bit if beacon/ LED test fails to start.

Signed-off-by: default avatarSucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: default avatarAnirban Chakraborty <anirban.chakraborty@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 445b62df
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -36,8 +36,8 @@

#define _QLCNIC_LINUX_MAJOR 5
#define _QLCNIC_LINUX_MINOR 0
#define _QLCNIC_LINUX_SUBVERSION 24
#define QLCNIC_LINUX_VERSIONID  "5.0.24"
#define _QLCNIC_LINUX_SUBVERSION 25
#define QLCNIC_LINUX_VERSIONID  "5.0.25"
#define QLCNIC_DRV_IDC_VER  0x01
#define QLCNIC_DRIVER_VERSION  ((_QLCNIC_LINUX_MAJOR << 16) |\
		 (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
+31 −14
Original line number Diff line number Diff line
@@ -935,31 +935,49 @@ static int qlcnic_set_led(struct net_device *dev,
{
	struct qlcnic_adapter *adapter = netdev_priv(dev);
	int max_sds_rings = adapter->max_sds_rings;
	int err = -EIO, active = 1;

	if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
		netdev_warn(dev, "LED test not supported for non "
				"privilege function\n");
		return -EOPNOTSUPP;
	}

	switch (state) {
	case ETHTOOL_ID_ACTIVE:
		if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state))
			return -EBUSY;

		if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
			if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
				return -EIO;
		if (test_bit(__QLCNIC_RESETTING, &adapter->state))
			break;

			if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST)) {
				clear_bit(__QLCNIC_RESETTING, &adapter->state);
				return -EIO;
			}
		if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
			if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST))
				break;
			set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
		}

		if (adapter->nic_ops->config_led(adapter, 1, 0xf) == 0)
			return 0;
		if (adapter->nic_ops->config_led(adapter, 1, 0xf) == 0) {
			err = 0;
			break;
		}

		dev_err(&adapter->pdev->dev,
			"Failed to set LED blink state.\n");
		break;

	case ETHTOOL_ID_INACTIVE:
		active = 0;

		if (test_bit(__QLCNIC_RESETTING, &adapter->state))
			break;

		if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
			if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST))
				break;
			set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
		}

		if (adapter->nic_ops->config_led(adapter, 0, 0xf))
			dev_err(&adapter->pdev->dev,
				"Failed to reset LED blink state.\n");
@@ -970,14 +988,13 @@ static int qlcnic_set_led(struct net_device *dev,
		return -EINVAL;
	}

	if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state)) {
	if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
		qlcnic_diag_free_res(dev, max_sds_rings);
		clear_bit(__QLCNIC_RESETTING, &adapter->state);
	}

	if (!active || err)
		clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);

	return -EIO;
	return err;
}

static void
+24 −15
Original line number Diff line number Diff line
@@ -3504,11 +3504,16 @@ qlcnic_store_beacon(struct device *dev,
{
	struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
	int max_sds_rings = adapter->max_sds_rings;
	int dev_down = 0;
	u16 beacon;
	u8 b_state, b_rate;
	int err;

	if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
		dev_warn(dev, "LED test not supported for non "
				"privilege function\n");
		return -EOPNOTSUPP;
	}

	if (len != sizeof(u16))
		return QL_STATUS_INVALID_PARAM;

@@ -3520,36 +3525,40 @@ qlcnic_store_beacon(struct device *dev,
	if (adapter->ahw->beacon_state == b_state)
		return len;

	rtnl_lock();

	if (!adapter->ahw->beacon_state)
		if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state))
		if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) {
			rtnl_unlock();
			return -EBUSY;
		}

	if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
		err = -EIO;
		goto out;
	}

	if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
		if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
			return -EIO;
		err = qlcnic_diag_alloc_res(adapter->netdev, QLCNIC_LED_TEST);
		if (err) {
			clear_bit(__QLCNIC_RESETTING, &adapter->state);
			clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
			return err;
		}
		dev_down = 1;
		if (err)
			goto out;
		set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
	}

	err = qlcnic_config_led(adapter, b_state, b_rate);

	if (!err) {
		adapter->ahw->beacon_state = b_state;
		err = len;
		adapter->ahw->beacon_state = b_state;
	}

	if (dev_down) {
	if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
		qlcnic_diag_free_res(adapter->netdev, max_sds_rings);
		clear_bit(__QLCNIC_RESETTING, &adapter->state);
	}

	if (!b_state)
 out:
	if (!adapter->ahw->beacon_state)
		clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
	rtnl_unlock();

	return err;
}