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 | } |
