aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/qlcnic
diff options
context:
space:
mode:
authorAnirban Chakraborty <anirban.chakraborty@qlogic.com>2011-05-12 08:48:34 -0400
committerDavid S. Miller <davem@davemloft.net>2011-05-13 14:44:14 -0400
commitb3c687317ff5d65017ee431de9ccf80ec1552e3e (patch)
treeafee7caa1197cc6bcfeed65f42b9ef18d1846366 /drivers/net/qlcnic
parent18f2f616be88736f5daf31d9d40e027abbd607ed (diff)
qlcnic: Take FW dump via ethtool
Driver checks if the previous dump has been cleared before taking the dump. It doesn't take the dump if it is not cleared. Changes from v2: Added lock to protect dump data structures from being mangled while dumping or setting them via ethtool. Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/qlcnic')
-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};