@@ -965,6 +965,84 @@ static void qlcnic_set_msglevel(struct net_device *netdev, u32 msglvl)
965
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
1046
const struct ethtool_ops qlcnic_ethtool_ops = {
969
1047
.get_settings = qlcnic_get_settings ,
970
1048
.set_settings = qlcnic_set_settings ,
@@ -991,4 +1069,7 @@ const struct ethtool_ops qlcnic_ethtool_ops = {
991
1069
.set_phys_id = qlcnic_set_led ,
992
1070
.set_msglevel = qlcnic_set_msglevel ,
993
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
};
0 commit comments