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: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com> Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
445b62dfd9
commit
10ee0faed9
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
|
||||
if (!active || err)
|
||||
clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
|
||||
|
||||
return -EIO;
|
||||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue