diff options
author | Shahed Shaikh <shahed.shaikh@qlogic.com> | 2013-08-30 13:51:19 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-08-31 22:34:43 -0400 |
commit | 890b6e023bd7ff9b5fc89750d9ab2cd414fa302e (patch) | |
tree | 13a33a89110cc81c7b5c3c3796679cdac65c8dd5 /drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c | |
parent | 7010bb65ce01278abe6709fe90407183abc6cbef (diff) |
qlcnic: Store firmware dump state in CAMRAM register
-Use CAMRAM register to store firmware dump state in adapter
instead of maintaining it in each function driver separately.
-Return appropriate error code on failure
Signed-off-by: Shahed Shaikh <shahed.shaikh@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c')
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c | 152 |
1 files changed, 124 insertions, 28 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c index 7b0c90efb365..332aa71798f6 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c @@ -1509,6 +1509,68 @@ static void qlcnic_set_msglevel(struct net_device *netdev, u32 msglvl) adapter->ahw->msg_enable = msglvl; } +int qlcnic_enable_fw_dump_state(struct qlcnic_adapter *adapter) +{ + struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; + u32 val; + + if (qlcnic_84xx_check(adapter)) { + if (qlcnic_83xx_lock_driver(adapter)) + return -EBUSY; + + val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL); + val &= ~QLC_83XX_IDC_DISABLE_FW_DUMP; + QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val); + + qlcnic_83xx_unlock_driver(adapter); + } else { + fw_dump->enable = true; + } + + dev_info(&adapter->pdev->dev, "FW dump enabled\n"); + + return 0; +} + +static int qlcnic_disable_fw_dump_state(struct qlcnic_adapter *adapter) +{ + struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; + u32 val; + + if (qlcnic_84xx_check(adapter)) { + if (qlcnic_83xx_lock_driver(adapter)) + return -EBUSY; + + val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL); + val |= QLC_83XX_IDC_DISABLE_FW_DUMP; + QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val); + + qlcnic_83xx_unlock_driver(adapter); + } else { + fw_dump->enable = false; + } + + dev_info(&adapter->pdev->dev, "FW dump disabled\n"); + + return 0; +} + +bool qlcnic_check_fw_dump_state(struct qlcnic_adapter *adapter) +{ + struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; + bool state; + u32 val; + + if (qlcnic_84xx_check(adapter)) { + val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL); + state = (val & QLC_83XX_IDC_DISABLE_FW_DUMP) ? false : true; + } else { + state = fw_dump->enable; + } + + return state; +} + static int qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump) { @@ -1525,7 +1587,7 @@ qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump) else dump->len = 0; - if (!fw_dump->enable) + if (!qlcnic_check_fw_dump_state(adapter)) dump->flag = ETH_FW_DUMP_DISABLE; else dump->flag = fw_dump->tmpl_hdr->drv_cap_mask; @@ -1573,77 +1635,111 @@ qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump, return 0; } +static int qlcnic_set_dump_mask(struct qlcnic_adapter *adapter, u32 mask) +{ + struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; + struct net_device *netdev = adapter->netdev; + + if (!qlcnic_check_fw_dump_state(adapter)) { + netdev_info(netdev, + "Can not change driver mask to 0x%x. FW dump not enabled\n", + mask); + return -EOPNOTSUPP; + } + + fw_dump->tmpl_hdr->drv_cap_mask = mask; + netdev_info(netdev, "Driver mask changed to: 0x%x\n", mask); + return 0; +} + static int qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val) { - int i; struct qlcnic_adapter *adapter = netdev_priv(netdev); struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; + bool valid_mask = false; + int i, ret = 0; u32 state; switch (val->flag) { case QLCNIC_FORCE_FW_DUMP_KEY: if (!fw_dump->tmpl_hdr) { netdev_err(netdev, "FW dump not supported\n"); - return -ENOTSUPP; + ret = -EOPNOTSUPP; + break; } - if (!fw_dump->enable) { + + if (!qlcnic_check_fw_dump_state(adapter)) { netdev_info(netdev, "FW dump not enabled\n"); - return 0; + ret = -EOPNOTSUPP; + break; } + if (fw_dump->clr) { netdev_info(netdev, - "Previous dump not cleared, not forcing dump\n"); - return 0; + "Previous dump not cleared, not forcing dump\n"); + break; } + netdev_info(netdev, "Forcing a FW dump\n"); qlcnic_dev_request_reset(adapter, val->flag); break; case QLCNIC_DISABLE_FW_DUMP: - if (fw_dump->enable && fw_dump->tmpl_hdr) { - netdev_info(netdev, "Disabling FW dump\n"); - fw_dump->enable = 0; + if (!fw_dump->tmpl_hdr) { + netdev_err(netdev, "FW dump not supported\n"); + ret = -EOPNOTSUPP; + break; } - return 0; + + ret = qlcnic_disable_fw_dump_state(adapter); + break; + case QLCNIC_ENABLE_FW_DUMP: if (!fw_dump->tmpl_hdr) { netdev_err(netdev, "FW dump not supported\n"); - return -ENOTSUPP; - } - if (!fw_dump->enable) { - netdev_info(netdev, "Enabling FW dump\n"); - fw_dump->enable = 1; + ret = -EOPNOTSUPP; + break; } - return 0; + + ret = qlcnic_enable_fw_dump_state(adapter); + break; + case QLCNIC_FORCE_FW_RESET: netdev_info(netdev, "Forcing a FW reset\n"); qlcnic_dev_request_reset(adapter, val->flag); adapter->flags &= ~QLCNIC_FW_RESET_OWNER; - return 0; + break; +; case QLCNIC_SET_QUIESCENT: case QLCNIC_RESET_QUIESCENT: state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE); if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) netdev_info(netdev, "Device in FAILED state\n"); - return 0; + break; + default: if (!fw_dump->tmpl_hdr) { netdev_err(netdev, "FW dump not supported\n"); - return -ENOTSUPP; + ret = -EOPNOTSUPP; + break; } + for (i = 0; i < ARRAY_SIZE(qlcnic_fw_dump_level); i++) { if (val->flag == qlcnic_fw_dump_level[i]) { - fw_dump->tmpl_hdr->drv_cap_mask = - val->flag; - netdev_info(netdev, "Driver mask changed to: 0x%x\n", - fw_dump->tmpl_hdr->drv_cap_mask); - return 0; + valid_mask = true; + break; } } - netdev_info(netdev, "Invalid dump level: 0x%x\n", val->flag); - return -EINVAL; + + if (valid_mask) { + ret = qlcnic_set_dump_mask(adapter, val->flag); + } else { + netdev_info(netdev, "Invalid dump level: 0x%x\n", + val->flag); + ret = -EINVAL; + } } - return 0; + return ret; } const struct ethtool_ops qlcnic_ethtool_ops = { |