diff options
| -rw-r--r-- | drivers/net/qlcnic/qlcnic_ethtool.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index c541461bc12c..9efc690a289f 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c | |||
| @@ -965,6 +965,84 @@ static void qlcnic_set_msglevel(struct net_device *netdev, u32 msglvl) | |||
| 965 | adapter->msg_enable = msglvl; | 965 | adapter->msg_enable = msglvl; |
| 966 | } | 966 | } |
| 967 | 967 | ||
| 968 | static int | ||
| 969 | qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump) | ||
| 970 | { | ||
| 971 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | ||
| 972 | struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; | ||
| 973 | |||
| 974 | dump->len = fw_dump->tmpl_hdr->size + fw_dump->size; | ||
| 975 | dump->flag = fw_dump->tmpl_hdr->drv_cap_mask; | ||
| 976 | dump->version = adapter->fw_version; | ||
| 977 | return 0; | ||
| 978 | } | ||
| 979 | |||
| 980 | static int | ||
| 981 | qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump, | ||
| 982 | void *buffer) | ||
| 983 | { | ||
| 984 | int i, copy_sz; | ||
| 985 | u32 *hdr_ptr, *data; | ||
| 986 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | ||
| 987 | struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; | ||
| 988 | |||
| 989 | if (qlcnic_api_lock(adapter)) | ||
| 990 | return -EIO; | ||
| 991 | if (!fw_dump->clr) { | ||
| 992 | netdev_info(netdev, "Dump not available\n"); | ||
| 993 | qlcnic_api_unlock(adapter); | ||
| 994 | return -EINVAL; | ||
| 995 | } | ||
| 996 | /* Copy template header first */ | ||
| 997 | copy_sz = fw_dump->tmpl_hdr->size; | ||
| 998 | hdr_ptr = (u32 *) fw_dump->tmpl_hdr; | ||
| 999 | data = (u32 *) buffer; | ||
| 1000 | for (i = 0; i < copy_sz/sizeof(u32); i++) | ||
| 1001 | *data++ = cpu_to_le32(*hdr_ptr++); | ||
| 1002 | |||
| 1003 | /* Copy captured dump data */ | ||
| 1004 | memcpy(buffer + copy_sz, fw_dump->data, fw_dump->size); | ||
| 1005 | dump->len = copy_sz + fw_dump->size; | ||
| 1006 | dump->flag = fw_dump->tmpl_hdr->drv_cap_mask; | ||
| 1007 | |||
| 1008 | /* Free dump area once data has been captured */ | ||
| 1009 | vfree(fw_dump->data); | ||
| 1010 | fw_dump->data = NULL; | ||
| 1011 | fw_dump->clr = 0; | ||
| 1012 | qlcnic_api_unlock(adapter); | ||
| 1013 | |||
| 1014 | return 0; | ||
| 1015 | } | ||
| 1016 | |||
| 1017 | static int | ||
| 1018 | qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val) | ||
| 1019 | { | ||
| 1020 | int ret = 0; | ||
| 1021 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | ||
| 1022 | struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; | ||
| 1023 | |||
| 1024 | if (val->flag == QLCNIC_FORCE_FW_DUMP_KEY) { | ||
| 1025 | netdev_info(netdev, "Forcing a FW dump\n"); | ||
| 1026 | qlcnic_dev_request_reset(adapter); | ||
| 1027 | } else { | ||
| 1028 | if (val->flag > QLCNIC_DUMP_MASK_MAX || | ||
| 1029 | val->flag < QLCNIC_DUMP_MASK_MIN) { | ||
| 1030 | netdev_info(netdev, | ||
| 1031 | "Invalid dump level: 0x%x\n", val->flag); | ||
| 1032 | ret = -EINVAL; | ||
| 1033 | goto out; | ||
| 1034 | } | ||
| 1035 | if (qlcnic_api_lock(adapter)) | ||
| 1036 | return -EIO; | ||
| 1037 | fw_dump->tmpl_hdr->drv_cap_mask = val->flag & 0xff; | ||
| 1038 | qlcnic_api_unlock(adapter); | ||
| 1039 | netdev_info(netdev, "Driver mask changed to: 0x%x\n", | ||
| 1040 | fw_dump->tmpl_hdr->drv_cap_mask); | ||
| 1041 | } | ||
| 1042 | out: | ||
| 1043 | return ret; | ||
| 1044 | } | ||
| 1045 | |||
| 968 | const struct ethtool_ops qlcnic_ethtool_ops = { | 1046 | const struct ethtool_ops qlcnic_ethtool_ops = { |
| 969 | .get_settings = qlcnic_get_settings, | 1047 | .get_settings = qlcnic_get_settings, |
| 970 | .set_settings = qlcnic_set_settings, | 1048 | .set_settings = qlcnic_set_settings, |
| @@ -991,4 +1069,7 @@ const struct ethtool_ops qlcnic_ethtool_ops = { | |||
| 991 | .set_phys_id = qlcnic_set_led, | 1069 | .set_phys_id = qlcnic_set_led, |
| 992 | .set_msglevel = qlcnic_set_msglevel, | 1070 | .set_msglevel = qlcnic_set_msglevel, |
| 993 | .get_msglevel = qlcnic_get_msglevel, | 1071 | .get_msglevel = qlcnic_get_msglevel, |
| 1072 | .get_dump_flag = qlcnic_get_dump_flag, | ||
| 1073 | .get_dump_data = qlcnic_get_dump_data, | ||
| 1074 | .set_dump = qlcnic_set_dump, | ||
| 994 | }; | 1075 | }; |
