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_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,
|
||||||
{
|
{
|
||||||
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,
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (!active || err)
|
||||||
clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
|
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,
|
||||||
{
|
{
|
||||||
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,
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue