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

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
...@@ -36,8 +36,8 @@ ...@@ -36,8 +36,8 @@
#define _QLCNIC_LINUX_MAJOR 5 #define _QLCNIC_LINUX_MAJOR 5
#define _QLCNIC_LINUX_MINOR 0 #define _QLCNIC_LINUX_MINOR 0
#define _QLCNIC_LINUX_SUBVERSION 24 #define _QLCNIC_LINUX_SUBVERSION 25
#define QLCNIC_LINUX_VERSIONID "5.0.24" #define QLCNIC_LINUX_VERSIONID "5.0.25"
#define QLCNIC_DRV_IDC_VER 0x01 #define QLCNIC_DRV_IDC_VER 0x01
#define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ #define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\
(_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
......
...@@ -935,31 +935,49 @@ static int qlcnic_set_led(struct net_device *dev, ...@@ -935,31 +935,49 @@ static int qlcnic_set_led(struct net_device *dev,
{ {
struct qlcnic_adapter *adapter = netdev_priv(dev); struct qlcnic_adapter *adapter = netdev_priv(dev);
int max_sds_rings = adapter->max_sds_rings; 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) { switch (state) {
case ETHTOOL_ID_ACTIVE: case ETHTOOL_ID_ACTIVE:
if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state))
return -EBUSY; return -EBUSY;
if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) { if (test_bit(__QLCNIC_RESETTING, &adapter->state))
if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) break;
return -EIO;
if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST)) { if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
clear_bit(__QLCNIC_RESETTING, &adapter->state); if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST))
return -EIO; break;
}
set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state); set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
} }
if (adapter->nic_ops->config_led(adapter, 1, 0xf) == 0) if (adapter->nic_ops->config_led(adapter, 1, 0xf) == 0) {
return 0; err = 0;
break;
}
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"Failed to set LED blink state.\n"); "Failed to set LED blink state.\n");
break; break;
case ETHTOOL_ID_INACTIVE: 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)) if (adapter->nic_ops->config_led(adapter, 0, 0xf))
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"Failed to reset LED blink state.\n"); "Failed to reset LED blink state.\n");
...@@ -970,14 +988,13 @@ static int qlcnic_set_led(struct net_device *dev, ...@@ -970,14 +988,13 @@ static int qlcnic_set_led(struct net_device *dev,
return -EINVAL; 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); qlcnic_diag_free_res(dev, max_sds_rings);
clear_bit(__QLCNIC_RESETTING, &adapter->state);
}
clear_bit(__QLCNIC_LED_ENABLE, &adapter->state); if (!active || err)
clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
return -EIO; return err;
} }
static void static void
......
...@@ -3504,11 +3504,16 @@ qlcnic_store_beacon(struct device *dev, ...@@ -3504,11 +3504,16 @@ qlcnic_store_beacon(struct device *dev,
{ {
struct qlcnic_adapter *adapter = dev_get_drvdata(dev); struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
int max_sds_rings = adapter->max_sds_rings; int max_sds_rings = adapter->max_sds_rings;
int dev_down = 0;
u16 beacon; u16 beacon;
u8 b_state, b_rate; u8 b_state, b_rate;
int err; 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)) if (len != sizeof(u16))
return QL_STATUS_INVALID_PARAM; return QL_STATUS_INVALID_PARAM;
...@@ -3520,36 +3525,40 @@ qlcnic_store_beacon(struct device *dev, ...@@ -3520,36 +3525,40 @@ qlcnic_store_beacon(struct device *dev,
if (adapter->ahw->beacon_state == b_state) if (adapter->ahw->beacon_state == b_state)
return len; return len;
rtnl_lock();
if (!adapter->ahw->beacon_state) 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; return -EBUSY;
}
if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
err = -EIO;
goto out;
}
if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) { 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); err = qlcnic_diag_alloc_res(adapter->netdev, QLCNIC_LED_TEST);
if (err) { if (err)
clear_bit(__QLCNIC_RESETTING, &adapter->state); goto out;
clear_bit(__QLCNIC_LED_ENABLE, &adapter->state); set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
return err;
}
dev_down = 1;
} }
err = qlcnic_config_led(adapter, b_state, b_rate); err = qlcnic_config_led(adapter, b_state, b_rate);
if (!err) { if (!err) {
adapter->ahw->beacon_state = b_state;
err = len; 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); 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); clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
rtnl_unlock();
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment