aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/qlcnic/qlcnic_ethtool.c81
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
968static int
969qlcnic_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
980static int
981qlcnic_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
1017static int
1018qlcnic_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 }
1042out:
1043 return ret;
1044}
1045
968const struct ethtool_ops qlcnic_ethtool_ops = { 1046const 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};