diff options
author | Sucheta Chakraborty <sucheta.chakraborty@qlogic.com> | 2011-10-28 08:57:15 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-10-30 03:09:41 -0400 |
commit | 10ee0faed92c8af4baebd633372136a6608a41ea (patch) | |
tree | bd9390dfecf81ec40c2cdb12f97d4c7e7224132e | |
parent | 445b62dfd934394807c12aee06d3f20cf70c93b4 (diff) |
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>
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c | 45 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 39 |
3 files changed, 57 insertions, 31 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 2fd1ba8fee4a..7ed53dbb8646 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | |||
@@ -36,8 +36,8 @@ | |||
36 | 36 | ||
37 | #define _QLCNIC_LINUX_MAJOR 5 | 37 | #define _QLCNIC_LINUX_MAJOR 5 |
38 | #define _QLCNIC_LINUX_MINOR 0 | 38 | #define _QLCNIC_LINUX_MINOR 0 |
39 | #define _QLCNIC_LINUX_SUBVERSION 24 | 39 | #define _QLCNIC_LINUX_SUBVERSION 25 |
40 | #define QLCNIC_LINUX_VERSIONID "5.0.24" | 40 | #define QLCNIC_LINUX_VERSIONID "5.0.25" |
41 | #define QLCNIC_DRV_IDC_VER 0x01 | 41 | #define QLCNIC_DRV_IDC_VER 0x01 |
42 | #define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ | 42 | #define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ |
43 | (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) | 43 | (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c index 5d8bec283267..8aa1c6e8667b 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c | |||
@@ -935,31 +935,49 @@ static int qlcnic_set_led(struct net_device *dev, | |||
935 | { | 935 | { |
936 | struct qlcnic_adapter *adapter = netdev_priv(dev); | 936 | struct qlcnic_adapter *adapter = netdev_priv(dev); |
937 | int max_sds_rings = adapter->max_sds_rings; | 937 | int max_sds_rings = adapter->max_sds_rings; |
938 | int err = -EIO, active = 1; | ||
939 | |||
940 | if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) { | ||
941 | netdev_warn(dev, "LED test not supported for non " | ||
942 | "privilege function\n"); | ||
943 | return -EOPNOTSUPP; | ||
944 | } | ||
938 | 945 | ||
939 | switch (state) { | 946 | switch (state) { |
940 | case ETHTOOL_ID_ACTIVE: | 947 | case ETHTOOL_ID_ACTIVE: |
941 | if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) | 948 | if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) |
942 | return -EBUSY; | 949 | return -EBUSY; |
943 | 950 | ||
944 | if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) { | 951 | if (test_bit(__QLCNIC_RESETTING, &adapter->state)) |
945 | if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) | 952 | break; |
946 | return -EIO; | ||
947 | 953 | ||
948 | if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST)) { | 954 | if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) { |
949 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | 955 | if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST)) |
950 | return -EIO; | 956 | break; |
951 | } | ||
952 | set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state); | 957 | set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state); |
953 | } | 958 | } |
954 | 959 | ||
955 | if (adapter->nic_ops->config_led(adapter, 1, 0xf) == 0) | 960 | if (adapter->nic_ops->config_led(adapter, 1, 0xf) == 0) { |
956 | return 0; | 961 | err = 0; |
962 | break; | ||
963 | } | ||
957 | 964 | ||
958 | dev_err(&adapter->pdev->dev, | 965 | dev_err(&adapter->pdev->dev, |
959 | "Failed to set LED blink state.\n"); | 966 | "Failed to set LED blink state.\n"); |
960 | break; | 967 | break; |
961 | 968 | ||
962 | case ETHTOOL_ID_INACTIVE: | 969 | case ETHTOOL_ID_INACTIVE: |
970 | active = 0; | ||
971 | |||
972 | if (test_bit(__QLCNIC_RESETTING, &adapter->state)) | ||
973 | break; | ||
974 | |||
975 | if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) { | ||
976 | if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST)) | ||
977 | break; | ||
978 | set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state); | ||
979 | } | ||
980 | |||
963 | if (adapter->nic_ops->config_led(adapter, 0, 0xf)) | 981 | if (adapter->nic_ops->config_led(adapter, 0, 0xf)) |
964 | dev_err(&adapter->pdev->dev, | 982 | dev_err(&adapter->pdev->dev, |
965 | "Failed to reset LED blink state.\n"); | 983 | "Failed to reset LED blink state.\n"); |
@@ -970,14 +988,13 @@ static int qlcnic_set_led(struct net_device *dev, | |||
970 | return -EINVAL; | 988 | return -EINVAL; |
971 | } | 989 | } |
972 | 990 | ||
973 | if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state)) { | 991 | if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state)) |
974 | qlcnic_diag_free_res(dev, max_sds_rings); | 992 | qlcnic_diag_free_res(dev, max_sds_rings); |
975 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | ||
976 | } | ||
977 | 993 | ||
978 | clear_bit(__QLCNIC_LED_ENABLE, &adapter->state); | 994 | if (!active || err) |
995 | clear_bit(__QLCNIC_LED_ENABLE, &adapter->state); | ||
979 | 996 | ||
980 | return -EIO; | 997 | return err; |
981 | } | 998 | } |
982 | 999 | ||
983 | static void | 1000 | static void |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 2edffcec930f..0bd163828e33 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | |||
@@ -3504,11 +3504,16 @@ qlcnic_store_beacon(struct device *dev, | |||
3504 | { | 3504 | { |
3505 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | 3505 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); |
3506 | int max_sds_rings = adapter->max_sds_rings; | 3506 | int max_sds_rings = adapter->max_sds_rings; |
3507 | int dev_down = 0; | ||
3508 | u16 beacon; | 3507 | u16 beacon; |
3509 | u8 b_state, b_rate; | 3508 | u8 b_state, b_rate; |
3510 | int err; | 3509 | int err; |
3511 | 3510 | ||
3511 | if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) { | ||
3512 | dev_warn(dev, "LED test not supported for non " | ||
3513 | "privilege function\n"); | ||
3514 | return -EOPNOTSUPP; | ||
3515 | } | ||
3516 | |||
3512 | if (len != sizeof(u16)) | 3517 | if (len != sizeof(u16)) |
3513 | return QL_STATUS_INVALID_PARAM; | 3518 | return QL_STATUS_INVALID_PARAM; |
3514 | 3519 | ||
@@ -3520,36 +3525,40 @@ qlcnic_store_beacon(struct device *dev, | |||
3520 | if (adapter->ahw->beacon_state == b_state) | 3525 | if (adapter->ahw->beacon_state == b_state) |
3521 | return len; | 3526 | return len; |
3522 | 3527 | ||
3528 | rtnl_lock(); | ||
3529 | |||
3523 | if (!adapter->ahw->beacon_state) | 3530 | if (!adapter->ahw->beacon_state) |
3524 | if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) | 3531 | if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) { |
3532 | rtnl_unlock(); | ||
3525 | return -EBUSY; | 3533 | return -EBUSY; |
3534 | } | ||
3535 | |||
3536 | if (test_bit(__QLCNIC_RESETTING, &adapter->state)) { | ||
3537 | err = -EIO; | ||
3538 | goto out; | ||
3539 | } | ||
3526 | 3540 | ||
3527 | if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) { | 3541 | if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) { |
3528 | if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) | ||
3529 | return -EIO; | ||
3530 | err = qlcnic_diag_alloc_res(adapter->netdev, QLCNIC_LED_TEST); | 3542 | err = qlcnic_diag_alloc_res(adapter->netdev, QLCNIC_LED_TEST); |
3531 | if (err) { | 3543 | if (err) |
3532 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | 3544 | goto out; |
3533 | clear_bit(__QLCNIC_LED_ENABLE, &adapter->state); | 3545 | set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state); |
3534 | return err; | ||
3535 | } | ||
3536 | dev_down = 1; | ||
3537 | } | 3546 | } |
3538 | 3547 | ||
3539 | err = qlcnic_config_led(adapter, b_state, b_rate); | 3548 | err = qlcnic_config_led(adapter, b_state, b_rate); |
3540 | 3549 | ||
3541 | if (!err) { | 3550 | if (!err) { |
3542 | adapter->ahw->beacon_state = b_state; | ||
3543 | err = len; | 3551 | err = len; |
3552 | adapter->ahw->beacon_state = b_state; | ||
3544 | } | 3553 | } |
3545 | 3554 | ||
3546 | if (dev_down) { | 3555 | if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state)) |
3547 | qlcnic_diag_free_res(adapter->netdev, max_sds_rings); | 3556 | qlcnic_diag_free_res(adapter->netdev, max_sds_rings); |
3548 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | ||
3549 | } | ||
3550 | 3557 | ||
3551 | if (!b_state) | 3558 | out: |
3559 | if (!adapter->ahw->beacon_state) | ||
3552 | clear_bit(__QLCNIC_LED_ENABLE, &adapter->state); | 3560 | clear_bit(__QLCNIC_LED_ENABLE, &adapter->state); |
3561 | rtnl_unlock(); | ||
3553 | 3562 | ||
3554 | return err; | 3563 | return err; |
3555 | } | 3564 | } |