1004b26b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2aa43c215SJeff Kirsher /*
3aa43c215SJeff Kirsher * QLogic qlcnic NIC Driver
4577ae39dSJitendra Kalsaria * Copyright (c) 2009-2013 QLogic Corporation
5aa43c215SJeff Kirsher */
6aa43c215SJeff Kirsher
7aa43c215SJeff Kirsher #include <linux/types.h>
8aa43c215SJeff Kirsher #include <linux/delay.h>
9aa43c215SJeff Kirsher #include <linux/pci.h>
10aa43c215SJeff Kirsher #include <linux/io.h>
11aa43c215SJeff Kirsher #include <linux/netdevice.h>
12aa43c215SJeff Kirsher #include <linux/ethtool.h>
13aa43c215SJeff Kirsher
14aa43c215SJeff Kirsher #include "qlcnic.h"
15aa43c215SJeff Kirsher
16aa43c215SJeff Kirsher struct qlcnic_stats {
17aa43c215SJeff Kirsher char stat_string[ETH_GSTRING_LEN];
18aa43c215SJeff Kirsher int sizeof_stat;
19aa43c215SJeff Kirsher int stat_offset;
20aa43c215SJeff Kirsher };
21aa43c215SJeff Kirsher
22c593642cSPankaj Bharadiya #define QLC_SIZEOF(m) sizeof_field(struct qlcnic_adapter, m)
23aa43c215SJeff Kirsher #define QLC_OFF(m) offsetof(struct qlcnic_adapter, m)
247e38d04bSSony Chacko static const u32 qlcnic_fw_dump_level[] = {
257e38d04bSSony Chacko 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff
267e38d04bSSony Chacko };
27aa43c215SJeff Kirsher
28aa43c215SJeff Kirsher static const struct qlcnic_stats qlcnic_gstrings_stats[] = {
29f27c75b3SHimanshu Madhani {"xmit_on", QLC_SIZEOF(stats.xmit_on), QLC_OFF(stats.xmit_on)},
30f27c75b3SHimanshu Madhani {"xmit_off", QLC_SIZEOF(stats.xmit_off), QLC_OFF(stats.xmit_off)},
317e38d04bSSony Chacko {"xmit_called", QLC_SIZEOF(stats.xmitcalled),
327e38d04bSSony Chacko QLC_OFF(stats.xmitcalled)},
337e38d04bSSony Chacko {"xmit_finished", QLC_SIZEOF(stats.xmitfinished),
347e38d04bSSony Chacko QLC_OFF(stats.xmitfinished)},
35aa43c215SJeff Kirsher {"tx dma map error", QLC_SIZEOF(stats.tx_dma_map_error),
36aa43c215SJeff Kirsher QLC_OFF(stats.tx_dma_map_error)},
37f27c75b3SHimanshu Madhani {"tx_bytes", QLC_SIZEOF(stats.txbytes), QLC_OFF(stats.txbytes)},
38f27c75b3SHimanshu Madhani {"tx_dropped", QLC_SIZEOF(stats.txdropped), QLC_OFF(stats.txdropped)},
39f27c75b3SHimanshu Madhani {"rx dma map error", QLC_SIZEOF(stats.rx_dma_map_error),
40f27c75b3SHimanshu Madhani QLC_OFF(stats.rx_dma_map_error)},
41f27c75b3SHimanshu Madhani {"rx_pkts", QLC_SIZEOF(stats.rx_pkts), QLC_OFF(stats.rx_pkts)},
42f27c75b3SHimanshu Madhani {"rx_bytes", QLC_SIZEOF(stats.rxbytes), QLC_OFF(stats.rxbytes)},
43f27c75b3SHimanshu Madhani {"rx_dropped", QLC_SIZEOF(stats.rxdropped), QLC_OFF(stats.rxdropped)},
44f27c75b3SHimanshu Madhani {"null rxbuf", QLC_SIZEOF(stats.null_rxbuf), QLC_OFF(stats.null_rxbuf)},
45f27c75b3SHimanshu Madhani {"csummed", QLC_SIZEOF(stats.csummed), QLC_OFF(stats.csummed)},
46f27c75b3SHimanshu Madhani {"lro_pkts", QLC_SIZEOF(stats.lro_pkts), QLC_OFF(stats.lro_pkts)},
47f27c75b3SHimanshu Madhani {"lrobytes", QLC_SIZEOF(stats.lrobytes), QLC_OFF(stats.lrobytes)},
48f27c75b3SHimanshu Madhani {"lso_frames", QLC_SIZEOF(stats.lso_frames), QLC_OFF(stats.lso_frames)},
49381709deSShahed Shaikh {"encap_lso_frames", QLC_SIZEOF(stats.encap_lso_frames),
50381709deSShahed Shaikh QLC_OFF(stats.encap_lso_frames)},
51381709deSShahed Shaikh {"encap_tx_csummed", QLC_SIZEOF(stats.encap_tx_csummed),
52381709deSShahed Shaikh QLC_OFF(stats.encap_tx_csummed)},
532b3d7b75SShahed Shaikh {"encap_rx_csummed", QLC_SIZEOF(stats.encap_rx_csummed),
542b3d7b75SShahed Shaikh QLC_OFF(stats.encap_rx_csummed)},
55f27c75b3SHimanshu Madhani {"skb_alloc_failure", QLC_SIZEOF(stats.skb_alloc_failure),
56f27c75b3SHimanshu Madhani QLC_OFF(stats.skb_alloc_failure)},
577e38d04bSSony Chacko {"mac_filter_limit_overrun", QLC_SIZEOF(stats.mac_filter_limit_overrun),
587e38d04bSSony Chacko QLC_OFF(stats.mac_filter_limit_overrun)},
597e38d04bSSony Chacko {"spurious intr", QLC_SIZEOF(stats.spurious_intr),
607e38d04bSSony Chacko QLC_OFF(stats.spurious_intr)},
61819bfe76SRajesh Borundia {"mbx spurious intr", QLC_SIZEOF(stats.mbx_spurious_intr),
62819bfe76SRajesh Borundia QLC_OFF(stats.mbx_spurious_intr)},
63aa43c215SJeff Kirsher };
64aa43c215SJeff Kirsher
65aa43c215SJeff Kirsher static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = {
66aa43c215SJeff Kirsher "tx unicast frames",
67aa43c215SJeff Kirsher "tx multicast frames",
68aa43c215SJeff Kirsher "tx broadcast frames",
69aa43c215SJeff Kirsher "tx dropped frames",
70aa43c215SJeff Kirsher "tx errors",
71aa43c215SJeff Kirsher "tx local frames",
72aa43c215SJeff Kirsher "tx numbytes",
73f27c75b3SHimanshu Madhani "rx unicast frames",
74f27c75b3SHimanshu Madhani "rx multicast frames",
75f27c75b3SHimanshu Madhani "rx broadcast frames",
76f27c75b3SHimanshu Madhani "rx dropped frames",
77f27c75b3SHimanshu Madhani "rx errors",
78f27c75b3SHimanshu Madhani "rx local frames",
79f27c75b3SHimanshu Madhani "rx numbytes",
80aa43c215SJeff Kirsher };
81aa43c215SJeff Kirsher
827e38d04bSSony Chacko static const char qlcnic_83xx_tx_stats_strings[][ETH_GSTRING_LEN] = {
837e38d04bSSony Chacko "ctx_tx_bytes",
847e38d04bSSony Chacko "ctx_tx_pkts",
857e38d04bSSony Chacko "ctx_tx_errors",
867e38d04bSSony Chacko "ctx_tx_dropped_pkts",
877e38d04bSSony Chacko "ctx_tx_num_buffers",
887e38d04bSSony Chacko };
897e38d04bSSony Chacko
907e38d04bSSony Chacko static const char qlcnic_83xx_mac_stats_strings[][ETH_GSTRING_LEN] = {
9154a8997cSJitendra Kalsaria "mac_tx_frames",
9254a8997cSJitendra Kalsaria "mac_tx_bytes",
9354a8997cSJitendra Kalsaria "mac_tx_mcast_pkts",
9454a8997cSJitendra Kalsaria "mac_tx_bcast_pkts",
9554a8997cSJitendra Kalsaria "mac_tx_pause_cnt",
9654a8997cSJitendra Kalsaria "mac_tx_ctrl_pkt",
9754a8997cSJitendra Kalsaria "mac_tx_lt_64b_pkts",
9854a8997cSJitendra Kalsaria "mac_tx_lt_127b_pkts",
9954a8997cSJitendra Kalsaria "mac_tx_lt_255b_pkts",
10054a8997cSJitendra Kalsaria "mac_tx_lt_511b_pkts",
10154a8997cSJitendra Kalsaria "mac_tx_lt_1023b_pkts",
10254a8997cSJitendra Kalsaria "mac_tx_lt_1518b_pkts",
10354a8997cSJitendra Kalsaria "mac_tx_gt_1518b_pkts",
10454a8997cSJitendra Kalsaria "mac_rx_frames",
10554a8997cSJitendra Kalsaria "mac_rx_bytes",
10654a8997cSJitendra Kalsaria "mac_rx_mcast_pkts",
10754a8997cSJitendra Kalsaria "mac_rx_bcast_pkts",
10854a8997cSJitendra Kalsaria "mac_rx_pause_cnt",
10954a8997cSJitendra Kalsaria "mac_rx_ctrl_pkt",
11054a8997cSJitendra Kalsaria "mac_rx_lt_64b_pkts",
11154a8997cSJitendra Kalsaria "mac_rx_lt_127b_pkts",
11254a8997cSJitendra Kalsaria "mac_rx_lt_255b_pkts",
11354a8997cSJitendra Kalsaria "mac_rx_lt_511b_pkts",
11454a8997cSJitendra Kalsaria "mac_rx_lt_1023b_pkts",
11554a8997cSJitendra Kalsaria "mac_rx_lt_1518b_pkts",
11654a8997cSJitendra Kalsaria "mac_rx_gt_1518b_pkts",
11754a8997cSJitendra Kalsaria "mac_rx_length_error",
11854a8997cSJitendra Kalsaria "mac_rx_length_small",
11954a8997cSJitendra Kalsaria "mac_rx_length_large",
12054a8997cSJitendra Kalsaria "mac_rx_jabber",
12154a8997cSJitendra Kalsaria "mac_rx_dropped",
1227e38d04bSSony Chacko "mac_crc_error",
12354a8997cSJitendra Kalsaria "mac_align_error",
12452290740SShahed Shaikh "eswitch_frames",
12552290740SShahed Shaikh "eswitch_bytes",
12652290740SShahed Shaikh "eswitch_multicast_frames",
12752290740SShahed Shaikh "eswitch_broadcast_frames",
12852290740SShahed Shaikh "eswitch_unicast_frames",
12952290740SShahed Shaikh "eswitch_error_free_frames",
13052290740SShahed Shaikh "eswitch_error_free_bytes",
13154a8997cSJitendra Kalsaria };
13254a8997cSJitendra Kalsaria
133aa43c215SJeff Kirsher #define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats)
134aa4a1f7dSHimanshu Madhani
135f27c75b3SHimanshu Madhani static const char qlcnic_tx_queue_stats_strings[][ETH_GSTRING_LEN] = {
136aa4a1f7dSHimanshu Madhani "xmit_on",
137aa4a1f7dSHimanshu Madhani "xmit_off",
138aa4a1f7dSHimanshu Madhani "xmit_called",
139aa4a1f7dSHimanshu Madhani "xmit_finished",
140f27c75b3SHimanshu Madhani "tx_bytes",
141aa4a1f7dSHimanshu Madhani };
142aa4a1f7dSHimanshu Madhani
143f27c75b3SHimanshu Madhani #define QLCNIC_TX_STATS_LEN ARRAY_SIZE(qlcnic_tx_queue_stats_strings)
144f27c75b3SHimanshu Madhani
1457e38d04bSSony Chacko static const char qlcnic_83xx_rx_stats_strings[][ETH_GSTRING_LEN] = {
1467e38d04bSSony Chacko "ctx_rx_bytes",
1477e38d04bSSony Chacko "ctx_rx_pkts",
1487e38d04bSSony Chacko "ctx_lro_pkt_cnt",
1497e38d04bSSony Chacko "ctx_ip_csum_error",
1507e38d04bSSony Chacko "ctx_rx_pkts_wo_ctx",
1518c046410SShahed Shaikh "ctx_rx_pkts_drop_wo_sds_on_card",
1528c046410SShahed Shaikh "ctx_rx_pkts_drop_wo_sds_on_host",
1537e38d04bSSony Chacko "ctx_rx_osized_pkts",
1547e38d04bSSony Chacko "ctx_rx_pkts_dropped_wo_rds",
1557e38d04bSSony Chacko "ctx_rx_unexpected_mcast_pkts",
1567e38d04bSSony Chacko "ctx_invalid_mac_address",
1578c046410SShahed Shaikh "ctx_rx_rds_ring_prim_attempted",
1587e38d04bSSony Chacko "ctx_rx_rds_ring_prim_success",
1597e38d04bSSony Chacko "ctx_num_lro_flows_added",
1607e38d04bSSony Chacko "ctx_num_lro_flows_removed",
1617e38d04bSSony Chacko "ctx_num_lro_flows_active",
1627e38d04bSSony Chacko "ctx_pkts_dropped_unknown",
1637e38d04bSSony Chacko };
164aa43c215SJeff Kirsher
165aa43c215SJeff Kirsher static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
166aa43c215SJeff Kirsher "Register_Test_on_offline",
167aa43c215SJeff Kirsher "Link_Test_on_offline",
168aa43c215SJeff Kirsher "Interrupt_Test_offline",
169aa43c215SJeff Kirsher "Internal_Loopback_offline",
1702e3ea7e7SShahed Shaikh "External_Loopback_offline",
1717e38d04bSSony Chacko "EEPROM_Test_offline"
172aa43c215SJeff Kirsher };
173aa43c215SJeff Kirsher
174aa43c215SJeff Kirsher #define QLCNIC_TEST_LEN ARRAY_SIZE(qlcnic_gstrings_test)
175aa43c215SJeff Kirsher
qlcnic_82xx_statistics(struct qlcnic_adapter * adapter)176d6e9c89aSShahed Shaikh static inline int qlcnic_82xx_statistics(struct qlcnic_adapter *adapter)
1777e38d04bSSony Chacko {
178d6e9c89aSShahed Shaikh return ARRAY_SIZE(qlcnic_gstrings_stats) +
179d6e9c89aSShahed Shaikh ARRAY_SIZE(qlcnic_83xx_mac_stats_strings) +
180d6e9c89aSShahed Shaikh QLCNIC_TX_STATS_LEN * adapter->drv_tx_rings;
1817e38d04bSSony Chacko }
1827e38d04bSSony Chacko
qlcnic_83xx_statistics(struct qlcnic_adapter * adapter)183d6e9c89aSShahed Shaikh static inline int qlcnic_83xx_statistics(struct qlcnic_adapter *adapter)
1847e38d04bSSony Chacko {
185d6e9c89aSShahed Shaikh return ARRAY_SIZE(qlcnic_gstrings_stats) +
186d6e9c89aSShahed Shaikh ARRAY_SIZE(qlcnic_83xx_tx_stats_strings) +
1877e38d04bSSony Chacko ARRAY_SIZE(qlcnic_83xx_mac_stats_strings) +
188d6e9c89aSShahed Shaikh ARRAY_SIZE(qlcnic_83xx_rx_stats_strings) +
189d6e9c89aSShahed Shaikh QLCNIC_TX_STATS_LEN * adapter->drv_tx_rings;
1907e38d04bSSony Chacko }
1917e38d04bSSony Chacko
qlcnic_dev_statistics_len(struct qlcnic_adapter * adapter)1927e38d04bSSony Chacko static int qlcnic_dev_statistics_len(struct qlcnic_adapter *adapter)
1937e38d04bSSony Chacko {
194d6e9c89aSShahed Shaikh int len = -1;
195d6e9c89aSShahed Shaikh
196d6e9c89aSShahed Shaikh if (qlcnic_82xx_check(adapter)) {
197d6e9c89aSShahed Shaikh len = qlcnic_82xx_statistics(adapter);
198d6e9c89aSShahed Shaikh if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
199d6e9c89aSShahed Shaikh len += ARRAY_SIZE(qlcnic_device_gstrings_stats);
200d6e9c89aSShahed Shaikh } else if (qlcnic_83xx_check(adapter)) {
201d6e9c89aSShahed Shaikh len = qlcnic_83xx_statistics(adapter);
202d6e9c89aSShahed Shaikh }
203d6e9c89aSShahed Shaikh
204d6e9c89aSShahed Shaikh return len;
2057e38d04bSSony Chacko }
2067e38d04bSSony Chacko
207710a1a49SPratik Pujar #define QLCNIC_TX_INTR_NOT_CONFIGURED 0X78563412
208710a1a49SPratik Pujar
209aa43c215SJeff Kirsher #define QLCNIC_MAX_EEPROM_LEN 1024
210aa43c215SJeff Kirsher
211aa43c215SJeff Kirsher static const u32 diag_registers[] = {
2122c6196d2SShahed Shaikh QLCNIC_CMDPEG_STATE,
2132c6196d2SShahed Shaikh QLCNIC_RCVPEG_STATE,
2142c6196d2SShahed Shaikh QLCNIC_FW_CAPABILITIES,
215aa43c215SJeff Kirsher QLCNIC_CRB_DRV_ACTIVE,
216aa43c215SJeff Kirsher QLCNIC_CRB_DEV_STATE,
217aa43c215SJeff Kirsher QLCNIC_CRB_DRV_STATE,
218aa43c215SJeff Kirsher QLCNIC_CRB_DRV_SCRATCH,
219aa43c215SJeff Kirsher QLCNIC_CRB_DEV_PARTITION_INFO,
220aa43c215SJeff Kirsher QLCNIC_CRB_DRV_IDC_VER,
221aa43c215SJeff Kirsher QLCNIC_PEG_ALIVE_COUNTER,
222aa43c215SJeff Kirsher QLCNIC_PEG_HALT_STATUS1,
223aa43c215SJeff Kirsher QLCNIC_PEG_HALT_STATUS2,
2247e38d04bSSony Chacko -1
2257e38d04bSSony Chacko };
2267e38d04bSSony Chacko
2272c6196d2SShahed Shaikh
2287e38d04bSSony Chacko static const u32 ext_diag_registers[] = {
2297e38d04bSSony Chacko CRB_XG_STATE_P3P,
2307e38d04bSSony Chacko ISR_INT_STATE_REG,
231aa43c215SJeff Kirsher QLCNIC_CRB_PEG_NET_0+0x3c,
232aa43c215SJeff Kirsher QLCNIC_CRB_PEG_NET_1+0x3c,
233aa43c215SJeff Kirsher QLCNIC_CRB_PEG_NET_2+0x3c,
234aa43c215SJeff Kirsher QLCNIC_CRB_PEG_NET_4+0x3c,
235aa43c215SJeff Kirsher -1
236aa43c215SJeff Kirsher };
237aa43c215SJeff Kirsher
2382f514c52SJitendra Kalsaria #define QLCNIC_MGMT_API_VERSION 3
239710a1a49SPratik Pujar #define QLCNIC_ETHTOOL_REGS_VER 4
240710a1a49SPratik Pujar
qlcnic_get_ring_regs_len(struct qlcnic_adapter * adapter)241710a1a49SPratik Pujar static inline int qlcnic_get_ring_regs_len(struct qlcnic_adapter *adapter)
242710a1a49SPratik Pujar {
24334e8c406SHimanshu Madhani int ring_regs_cnt = (adapter->drv_tx_rings * 5) +
244710a1a49SPratik Pujar (adapter->max_rds_rings * 2) +
24534e8c406SHimanshu Madhani (adapter->drv_sds_rings * 3) + 5;
246710a1a49SPratik Pujar return ring_regs_cnt * sizeof(u32);
247710a1a49SPratik Pujar }
2487e38d04bSSony Chacko
qlcnic_get_regs_len(struct net_device * dev)249aa43c215SJeff Kirsher static int qlcnic_get_regs_len(struct net_device *dev)
250aa43c215SJeff Kirsher {
2517e38d04bSSony Chacko struct qlcnic_adapter *adapter = netdev_priv(dev);
2527e38d04bSSony Chacko u32 len;
2537e38d04bSSony Chacko
2547e38d04bSSony Chacko if (qlcnic_83xx_check(adapter))
2557e38d04bSSony Chacko len = qlcnic_83xx_get_regs_len(adapter);
2567e38d04bSSony Chacko else
2577e38d04bSSony Chacko len = sizeof(ext_diag_registers) + sizeof(diag_registers);
2587e38d04bSSony Chacko
259710a1a49SPratik Pujar len += ((QLCNIC_DEV_INFO_SIZE + 2) * sizeof(u32));
260710a1a49SPratik Pujar len += qlcnic_get_ring_regs_len(adapter);
261710a1a49SPratik Pujar return len;
262aa43c215SJeff Kirsher }
263aa43c215SJeff Kirsher
qlcnic_get_eeprom_len(struct net_device * dev)264aa43c215SJeff Kirsher static int qlcnic_get_eeprom_len(struct net_device *dev)
265aa43c215SJeff Kirsher {
266aa43c215SJeff Kirsher return QLCNIC_FLASH_TOTAL_SIZE;
267aa43c215SJeff Kirsher }
268aa43c215SJeff Kirsher
269aa43c215SJeff Kirsher static void
qlcnic_get_drvinfo(struct net_device * dev,struct ethtool_drvinfo * drvinfo)270aa43c215SJeff Kirsher qlcnic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
271aa43c215SJeff Kirsher {
272aa43c215SJeff Kirsher struct qlcnic_adapter *adapter = netdev_priv(dev);
273aa43c215SJeff Kirsher u32 fw_major, fw_minor, fw_build;
2747e38d04bSSony Chacko fw_major = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MAJOR);
2757e38d04bSSony Chacko fw_minor = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MINOR);
2767e38d04bSSony Chacko fw_build = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_SUB);
27768aad78cSRick Jones snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
27868aad78cSRick Jones "%d.%d.%d", fw_major, fw_minor, fw_build);
279aa43c215SJeff Kirsher
280*f029c781SWolfram Sang strscpy(drvinfo->bus_info, pci_name(adapter->pdev),
28168aad78cSRick Jones sizeof(drvinfo->bus_info));
282*f029c781SWolfram Sang strscpy(drvinfo->driver, qlcnic_driver_name, sizeof(drvinfo->driver));
283*f029c781SWolfram Sang strscpy(drvinfo->version, QLCNIC_LINUX_VERSIONID,
28468aad78cSRick Jones sizeof(drvinfo->version));
285aa43c215SJeff Kirsher }
286aa43c215SJeff Kirsher
qlcnic_82xx_get_link_ksettings(struct qlcnic_adapter * adapter,struct ethtool_link_ksettings * ecmd)28749cef10fSPhilippe Reynes static int qlcnic_82xx_get_link_ksettings(struct qlcnic_adapter *adapter,
28849cef10fSPhilippe Reynes struct ethtool_link_ksettings *ecmd)
289b938662dSHimanshu Madhani {
2907e38d04bSSony Chacko struct qlcnic_hardware_context *ahw = adapter->ahw;
2917e38d04bSSony Chacko u32 speed, reg;
2924bd8e738SHimanshu Madhani int check_sfp_module = 0, err = 0;
2937e38d04bSSony Chacko u16 pcifn = ahw->pci_func;
29449cef10fSPhilippe Reynes u32 supported, advertising;
295aa43c215SJeff Kirsher
296aa43c215SJeff Kirsher /* read which mode */
297aa43c215SJeff Kirsher if (adapter->ahw->port_type == QLCNIC_GBE) {
29849cef10fSPhilippe Reynes supported = (SUPPORTED_10baseT_Half |
299aa43c215SJeff Kirsher SUPPORTED_10baseT_Full |
300aa43c215SJeff Kirsher SUPPORTED_100baseT_Half |
301aa43c215SJeff Kirsher SUPPORTED_100baseT_Full |
302aa43c215SJeff Kirsher SUPPORTED_1000baseT_Half |
303aa43c215SJeff Kirsher SUPPORTED_1000baseT_Full);
304aa43c215SJeff Kirsher
30549cef10fSPhilippe Reynes advertising = (ADVERTISED_100baseT_Half |
306aa43c215SJeff Kirsher ADVERTISED_100baseT_Full |
307aa43c215SJeff Kirsher ADVERTISED_1000baseT_Half |
308aa43c215SJeff Kirsher ADVERTISED_1000baseT_Full);
309aa43c215SJeff Kirsher
31049cef10fSPhilippe Reynes ecmd->base.speed = adapter->ahw->link_speed;
31149cef10fSPhilippe Reynes ecmd->base.duplex = adapter->ahw->link_duplex;
31249cef10fSPhilippe Reynes ecmd->base.autoneg = adapter->ahw->link_autoneg;
313aa43c215SJeff Kirsher
314aa43c215SJeff Kirsher } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
3157e38d04bSSony Chacko u32 val = 0;
3164bd8e738SHimanshu Madhani val = QLCRD32(adapter, QLCNIC_PORT_MODE_ADDR, &err);
3177e38d04bSSony Chacko
318aa43c215SJeff Kirsher if (val == QLCNIC_PORT_MODE_802_3_AP) {
31949cef10fSPhilippe Reynes supported = SUPPORTED_1000baseT_Full;
32049cef10fSPhilippe Reynes advertising = ADVERTISED_1000baseT_Full;
321aa43c215SJeff Kirsher } else {
32249cef10fSPhilippe Reynes supported = SUPPORTED_10000baseT_Full;
32349cef10fSPhilippe Reynes advertising = ADVERTISED_10000baseT_Full;
324aa43c215SJeff Kirsher }
325aa43c215SJeff Kirsher
326b938662dSHimanshu Madhani if (netif_running(adapter->netdev) && ahw->has_link_events) {
327beb3d3a4SRajesh Borundia if (ahw->linkup) {
328beb3d3a4SRajesh Borundia reg = QLCRD32(adapter,
3294bd8e738SHimanshu Madhani P3P_LINK_SPEED_REG(pcifn), &err);
3307e38d04bSSony Chacko speed = P3P_LINK_SPEED_VAL(pcifn, reg);
3317e38d04bSSony Chacko ahw->link_speed = speed * P3P_LINK_SPEED_MHZ;
332beb3d3a4SRajesh Borundia }
333beb3d3a4SRajesh Borundia
33449cef10fSPhilippe Reynes ecmd->base.speed = ahw->link_speed;
33549cef10fSPhilippe Reynes ecmd->base.autoneg = ahw->link_autoneg;
33649cef10fSPhilippe Reynes ecmd->base.duplex = ahw->link_duplex;
337aa43c215SJeff Kirsher goto skip;
338aa43c215SJeff Kirsher }
339aa43c215SJeff Kirsher
34049cef10fSPhilippe Reynes ecmd->base.speed = SPEED_UNKNOWN;
34149cef10fSPhilippe Reynes ecmd->base.duplex = DUPLEX_UNKNOWN;
34249cef10fSPhilippe Reynes ecmd->base.autoneg = AUTONEG_DISABLE;
343aa43c215SJeff Kirsher } else
344aa43c215SJeff Kirsher return -EIO;
345aa43c215SJeff Kirsher
346aa43c215SJeff Kirsher skip:
34749cef10fSPhilippe Reynes ecmd->base.phy_address = adapter->ahw->physical_port;
348aa43c215SJeff Kirsher
349aa43c215SJeff Kirsher switch (adapter->ahw->board_type) {
350aa43c215SJeff Kirsher case QLCNIC_BRDTYPE_P3P_REF_QG:
351aa43c215SJeff Kirsher case QLCNIC_BRDTYPE_P3P_4_GB:
352aa43c215SJeff Kirsher case QLCNIC_BRDTYPE_P3P_4_GB_MM:
35349cef10fSPhilippe Reynes supported |= SUPPORTED_Autoneg;
35449cef10fSPhilippe Reynes advertising |= ADVERTISED_Autoneg;
355df561f66SGustavo A. R. Silva fallthrough;
356aa43c215SJeff Kirsher case QLCNIC_BRDTYPE_P3P_10G_CX4:
357aa43c215SJeff Kirsher case QLCNIC_BRDTYPE_P3P_10G_CX4_LP:
358aa43c215SJeff Kirsher case QLCNIC_BRDTYPE_P3P_10000_BASE_T:
35949cef10fSPhilippe Reynes supported |= SUPPORTED_TP;
36049cef10fSPhilippe Reynes advertising |= ADVERTISED_TP;
36149cef10fSPhilippe Reynes ecmd->base.port = PORT_TP;
36249cef10fSPhilippe Reynes ecmd->base.autoneg = adapter->ahw->link_autoneg;
363aa43c215SJeff Kirsher break;
364aa43c215SJeff Kirsher case QLCNIC_BRDTYPE_P3P_IMEZ:
365aa43c215SJeff Kirsher case QLCNIC_BRDTYPE_P3P_XG_LOM:
366aa43c215SJeff Kirsher case QLCNIC_BRDTYPE_P3P_HMEZ:
36749cef10fSPhilippe Reynes supported |= SUPPORTED_MII;
36849cef10fSPhilippe Reynes advertising |= ADVERTISED_MII;
36949cef10fSPhilippe Reynes ecmd->base.port = PORT_MII;
37049cef10fSPhilippe Reynes ecmd->base.autoneg = AUTONEG_DISABLE;
371aa43c215SJeff Kirsher break;
372aa43c215SJeff Kirsher case QLCNIC_BRDTYPE_P3P_10G_SFP_PLUS:
373aa43c215SJeff Kirsher case QLCNIC_BRDTYPE_P3P_10G_SFP_CT:
374aa43c215SJeff Kirsher case QLCNIC_BRDTYPE_P3P_10G_SFP_QT:
37549cef10fSPhilippe Reynes advertising |= ADVERTISED_TP;
37649cef10fSPhilippe Reynes supported |= SUPPORTED_TP;
377b938662dSHimanshu Madhani check_sfp_module = netif_running(adapter->netdev) &&
378b938662dSHimanshu Madhani ahw->has_link_events;
379df561f66SGustavo A. R. Silva fallthrough;
380aa43c215SJeff Kirsher case QLCNIC_BRDTYPE_P3P_10G_XFP:
38149cef10fSPhilippe Reynes supported |= SUPPORTED_FIBRE;
38249cef10fSPhilippe Reynes advertising |= ADVERTISED_FIBRE;
38349cef10fSPhilippe Reynes ecmd->base.port = PORT_FIBRE;
38449cef10fSPhilippe Reynes ecmd->base.autoneg = AUTONEG_DISABLE;
385aa43c215SJeff Kirsher break;
386aa43c215SJeff Kirsher case QLCNIC_BRDTYPE_P3P_10G_TP:
387aa43c215SJeff Kirsher if (adapter->ahw->port_type == QLCNIC_XGBE) {
38849cef10fSPhilippe Reynes ecmd->base.autoneg = AUTONEG_DISABLE;
38949cef10fSPhilippe Reynes supported |= (SUPPORTED_FIBRE | SUPPORTED_TP);
39049cef10fSPhilippe Reynes advertising |=
391aa43c215SJeff Kirsher (ADVERTISED_FIBRE | ADVERTISED_TP);
39249cef10fSPhilippe Reynes ecmd->base.port = PORT_FIBRE;
393b938662dSHimanshu Madhani check_sfp_module = netif_running(adapter->netdev) &&
394b938662dSHimanshu Madhani ahw->has_link_events;
395aa43c215SJeff Kirsher } else {
39649cef10fSPhilippe Reynes ecmd->base.autoneg = AUTONEG_ENABLE;
39749cef10fSPhilippe Reynes supported |= (SUPPORTED_TP | SUPPORTED_Autoneg);
39849cef10fSPhilippe Reynes advertising |=
399aa43c215SJeff Kirsher (ADVERTISED_TP | ADVERTISED_Autoneg);
40049cef10fSPhilippe Reynes ecmd->base.port = PORT_TP;
401aa43c215SJeff Kirsher }
402aa43c215SJeff Kirsher break;
403aa43c215SJeff Kirsher default:
404aa43c215SJeff Kirsher dev_err(&adapter->pdev->dev, "Unsupported board model %d\n",
405aa43c215SJeff Kirsher adapter->ahw->board_type);
406aa43c215SJeff Kirsher return -EIO;
407aa43c215SJeff Kirsher }
408aa43c215SJeff Kirsher
409aa43c215SJeff Kirsher if (check_sfp_module) {
41079788450SSony Chacko switch (adapter->ahw->module_type) {
411aa43c215SJeff Kirsher case LINKEVENT_MODULE_OPTICAL_UNKNOWN:
412aa43c215SJeff Kirsher case LINKEVENT_MODULE_OPTICAL_SRLR:
413aa43c215SJeff Kirsher case LINKEVENT_MODULE_OPTICAL_LRM:
414aa43c215SJeff Kirsher case LINKEVENT_MODULE_OPTICAL_SFP_1G:
41549cef10fSPhilippe Reynes ecmd->base.port = PORT_FIBRE;
416aa43c215SJeff Kirsher break;
417aa43c215SJeff Kirsher case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE:
418aa43c215SJeff Kirsher case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN:
419aa43c215SJeff Kirsher case LINKEVENT_MODULE_TWINAX:
42049cef10fSPhilippe Reynes ecmd->base.port = PORT_TP;
421aa43c215SJeff Kirsher break;
422aa43c215SJeff Kirsher default:
42349cef10fSPhilippe Reynes ecmd->base.port = PORT_OTHER;
424aa43c215SJeff Kirsher }
425aa43c215SJeff Kirsher }
426aa43c215SJeff Kirsher
42749cef10fSPhilippe Reynes ethtool_convert_legacy_u32_to_link_mode(ecmd->link_modes.supported,
42849cef10fSPhilippe Reynes supported);
42949cef10fSPhilippe Reynes ethtool_convert_legacy_u32_to_link_mode(ecmd->link_modes.advertising,
43049cef10fSPhilippe Reynes advertising);
43149cef10fSPhilippe Reynes
432aa43c215SJeff Kirsher return 0;
433aa43c215SJeff Kirsher }
434aa43c215SJeff Kirsher
qlcnic_get_link_ksettings(struct net_device * dev,struct ethtool_link_ksettings * ecmd)43549cef10fSPhilippe Reynes static int qlcnic_get_link_ksettings(struct net_device *dev,
43649cef10fSPhilippe Reynes struct ethtool_link_ksettings *ecmd)
43721041400Sstephen hemminger {
43821041400Sstephen hemminger struct qlcnic_adapter *adapter = netdev_priv(dev);
43921041400Sstephen hemminger
44021041400Sstephen hemminger if (qlcnic_82xx_check(adapter))
44149cef10fSPhilippe Reynes return qlcnic_82xx_get_link_ksettings(adapter, ecmd);
44221041400Sstephen hemminger else if (qlcnic_83xx_check(adapter))
44349cef10fSPhilippe Reynes return qlcnic_83xx_get_link_ksettings(adapter, ecmd);
44421041400Sstephen hemminger
44521041400Sstephen hemminger return -EIO;
44621041400Sstephen hemminger }
44721041400Sstephen hemminger
44821041400Sstephen hemminger
qlcnic_set_port_config(struct qlcnic_adapter * adapter,const struct ethtool_link_ksettings * ecmd)4497e38d04bSSony Chacko static int qlcnic_set_port_config(struct qlcnic_adapter *adapter,
45049cef10fSPhilippe Reynes const struct ethtool_link_ksettings *ecmd)
451aa43c215SJeff Kirsher {
4527e38d04bSSony Chacko u32 ret = 0, config = 0;
453aa43c215SJeff Kirsher /* read which mode */
45449cef10fSPhilippe Reynes if (ecmd->base.duplex)
455aa43c215SJeff Kirsher config |= 0x1;
456aa43c215SJeff Kirsher
45749cef10fSPhilippe Reynes if (ecmd->base.autoneg)
458aa43c215SJeff Kirsher config |= 0x2;
459aa43c215SJeff Kirsher
46049cef10fSPhilippe Reynes switch (ecmd->base.speed) {
461aa43c215SJeff Kirsher case SPEED_10:
462aa43c215SJeff Kirsher config |= (0 << 8);
463aa43c215SJeff Kirsher break;
464aa43c215SJeff Kirsher case SPEED_100:
465aa43c215SJeff Kirsher config |= (1 << 8);
466aa43c215SJeff Kirsher break;
467aa43c215SJeff Kirsher case SPEED_1000:
468aa43c215SJeff Kirsher config |= (10 << 8);
469aa43c215SJeff Kirsher break;
470aa43c215SJeff Kirsher default:
471aa43c215SJeff Kirsher return -EIO;
472aa43c215SJeff Kirsher }
473aa43c215SJeff Kirsher
474aa43c215SJeff Kirsher ret = qlcnic_fw_cmd_set_port(adapter, config);
475aa43c215SJeff Kirsher
476aa43c215SJeff Kirsher if (ret == QLCNIC_RCODE_NOT_SUPPORTED)
477aa43c215SJeff Kirsher return -EOPNOTSUPP;
478aa43c215SJeff Kirsher else if (ret)
479aa43c215SJeff Kirsher return -EIO;
4807e38d04bSSony Chacko return ret;
4817e38d04bSSony Chacko }
4827e38d04bSSony Chacko
qlcnic_set_link_ksettings(struct net_device * dev,const struct ethtool_link_ksettings * ecmd)48349cef10fSPhilippe Reynes static int qlcnic_set_link_ksettings(struct net_device *dev,
48449cef10fSPhilippe Reynes const struct ethtool_link_ksettings *ecmd)
4857e38d04bSSony Chacko {
4867e38d04bSSony Chacko u32 ret = 0;
4877e38d04bSSony Chacko struct qlcnic_adapter *adapter = netdev_priv(dev);
4887e38d04bSSony Chacko
489f9c3fe2fSChopra, Manish if (qlcnic_83xx_check(adapter))
490f9c3fe2fSChopra, Manish qlcnic_83xx_get_port_type(adapter);
491f9c3fe2fSChopra, Manish
4927e38d04bSSony Chacko if (adapter->ahw->port_type != QLCNIC_GBE)
4937e38d04bSSony Chacko return -EOPNOTSUPP;
4947e38d04bSSony Chacko
4957e38d04bSSony Chacko if (qlcnic_83xx_check(adapter))
49649cef10fSPhilippe Reynes ret = qlcnic_83xx_set_link_ksettings(adapter, ecmd);
4977e38d04bSSony Chacko else
4987e38d04bSSony Chacko ret = qlcnic_set_port_config(adapter, ecmd);
4997e38d04bSSony Chacko
5007e38d04bSSony Chacko if (!ret)
5017e38d04bSSony Chacko return ret;
502aa43c215SJeff Kirsher
50349cef10fSPhilippe Reynes adapter->ahw->link_speed = ecmd->base.speed;
50449cef10fSPhilippe Reynes adapter->ahw->link_duplex = ecmd->base.duplex;
50549cef10fSPhilippe Reynes adapter->ahw->link_autoneg = ecmd->base.autoneg;
506aa43c215SJeff Kirsher
507aa43c215SJeff Kirsher if (!netif_running(dev))
508aa43c215SJeff Kirsher return 0;
509aa43c215SJeff Kirsher
510aa43c215SJeff Kirsher dev->netdev_ops->ndo_stop(dev);
511aa43c215SJeff Kirsher return dev->netdev_ops->ndo_open(dev);
512aa43c215SJeff Kirsher }
513aa43c215SJeff Kirsher
qlcnic_82xx_get_registers(struct qlcnic_adapter * adapter,u32 * regs_buff)5147e38d04bSSony Chacko static int qlcnic_82xx_get_registers(struct qlcnic_adapter *adapter,
5157e38d04bSSony Chacko u32 *regs_buff)
5167e38d04bSSony Chacko {
5174bd8e738SHimanshu Madhani int i, j = 0, err = 0;
5187e38d04bSSony Chacko
5197e38d04bSSony Chacko for (i = QLCNIC_DEV_INFO_SIZE + 1; diag_registers[j] != -1; j++, i++)
5207e38d04bSSony Chacko regs_buff[i] = QLC_SHARED_REG_RD32(adapter, diag_registers[j]);
5217e38d04bSSony Chacko j = 0;
5227e38d04bSSony Chacko while (ext_diag_registers[j] != -1)
5234bd8e738SHimanshu Madhani regs_buff[i++] = QLCRD32(adapter, ext_diag_registers[j++],
5244bd8e738SHimanshu Madhani &err);
5257e38d04bSSony Chacko return i;
5267e38d04bSSony Chacko }
5277e38d04bSSony Chacko
528aa43c215SJeff Kirsher static void
qlcnic_get_regs(struct net_device * dev,struct ethtool_regs * regs,void * p)529aa43c215SJeff Kirsher qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
530aa43c215SJeff Kirsher {
531aa43c215SJeff Kirsher struct qlcnic_adapter *adapter = netdev_priv(dev);
532aa43c215SJeff Kirsher struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
533aa43c215SJeff Kirsher struct qlcnic_host_sds_ring *sds_ring;
534710a1a49SPratik Pujar struct qlcnic_host_rds_ring *rds_rings;
535710a1a49SPratik Pujar struct qlcnic_host_tx_ring *tx_ring;
536aa43c215SJeff Kirsher u32 *regs_buff = p;
5377e38d04bSSony Chacko int ring, i = 0;
538aa43c215SJeff Kirsher
539aa43c215SJeff Kirsher memset(p, 0, qlcnic_get_regs_len(dev));
5407e38d04bSSony Chacko
541aa43c215SJeff Kirsher regs->version = (QLCNIC_ETHTOOL_REGS_VER << 24) |
542aa43c215SJeff Kirsher (adapter->ahw->revision_id << 16) | (adapter->pdev)->device;
543aa43c215SJeff Kirsher
544aa43c215SJeff Kirsher regs_buff[0] = (0xcafe0000 | (QLCNIC_DEV_INFO_SIZE & 0xffff));
545aa43c215SJeff Kirsher regs_buff[1] = QLCNIC_MGMT_API_VERSION;
546aa43c215SJeff Kirsher
5472f514c52SJitendra Kalsaria if (adapter->ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY)
5482f514c52SJitendra Kalsaria regs_buff[2] = adapter->ahw->max_vnic_func;
5492f514c52SJitendra Kalsaria
5507e38d04bSSony Chacko if (qlcnic_82xx_check(adapter))
5517e38d04bSSony Chacko i = qlcnic_82xx_get_registers(adapter, regs_buff);
5527e38d04bSSony Chacko else
5537e38d04bSSony Chacko i = qlcnic_83xx_get_registers(adapter, regs_buff);
554aa43c215SJeff Kirsher
555aa43c215SJeff Kirsher if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
556aa43c215SJeff Kirsher return;
557aa43c215SJeff Kirsher
558710a1a49SPratik Pujar /* Marker btw regs and TX ring count */
559710a1a49SPratik Pujar regs_buff[i++] = 0xFFEFCDAB;
560aa43c215SJeff Kirsher
56134e8c406SHimanshu Madhani regs_buff[i++] = adapter->drv_tx_rings; /* No. of TX ring */
56234e8c406SHimanshu Madhani for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
563710a1a49SPratik Pujar tx_ring = &adapter->tx_ring[ring];
564710a1a49SPratik Pujar regs_buff[i++] = le32_to_cpu(*(tx_ring->hw_consumer));
565710a1a49SPratik Pujar regs_buff[i++] = tx_ring->sw_consumer;
566710a1a49SPratik Pujar regs_buff[i++] = readl(tx_ring->crb_cmd_producer);
567710a1a49SPratik Pujar regs_buff[i++] = tx_ring->producer;
568710a1a49SPratik Pujar if (tx_ring->crb_intr_mask)
569710a1a49SPratik Pujar regs_buff[i++] = readl(tx_ring->crb_intr_mask);
570710a1a49SPratik Pujar else
571710a1a49SPratik Pujar regs_buff[i++] = QLCNIC_TX_INTR_NOT_CONFIGURED;
572710a1a49SPratik Pujar }
573aa43c215SJeff Kirsher
574710a1a49SPratik Pujar regs_buff[i++] = adapter->max_rds_rings; /* No. of RX ring */
575710a1a49SPratik Pujar for (ring = 0; ring < adapter->max_rds_rings; ring++) {
576710a1a49SPratik Pujar rds_rings = &recv_ctx->rds_rings[ring];
577710a1a49SPratik Pujar regs_buff[i++] = readl(rds_rings->crb_rcv_producer);
578710a1a49SPratik Pujar regs_buff[i++] = rds_rings->producer;
579710a1a49SPratik Pujar }
580aa43c215SJeff Kirsher
58134e8c406SHimanshu Madhani regs_buff[i++] = adapter->drv_sds_rings; /* No. of SDS ring */
58234e8c406SHimanshu Madhani for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
583aa43c215SJeff Kirsher sds_ring = &(recv_ctx->sds_rings[ring]);
584aa43c215SJeff Kirsher regs_buff[i++] = readl(sds_ring->crb_sts_consumer);
585710a1a49SPratik Pujar regs_buff[i++] = sds_ring->consumer;
586710a1a49SPratik Pujar regs_buff[i++] = readl(sds_ring->crb_intr_mask);
587aa43c215SJeff Kirsher }
588aa43c215SJeff Kirsher }
589aa43c215SJeff Kirsher
qlcnic_test_link(struct net_device * dev)590aa43c215SJeff Kirsher static u32 qlcnic_test_link(struct net_device *dev)
591aa43c215SJeff Kirsher {
592aa43c215SJeff Kirsher struct qlcnic_adapter *adapter = netdev_priv(dev);
5934bd8e738SHimanshu Madhani int err = 0;
594aa43c215SJeff Kirsher u32 val;
595aa43c215SJeff Kirsher
5967e38d04bSSony Chacko if (qlcnic_83xx_check(adapter)) {
5977e38d04bSSony Chacko val = qlcnic_83xx_test_link(adapter);
5987e38d04bSSony Chacko return (val & 1) ? 0 : 1;
5997e38d04bSSony Chacko }
6004bd8e738SHimanshu Madhani val = QLCRD32(adapter, CRB_XG_STATE_P3P, &err);
6014bd8e738SHimanshu Madhani if (err == -EIO)
6024bd8e738SHimanshu Madhani return err;
603aa43c215SJeff Kirsher val = XG_LINK_STATE_P3P(adapter->ahw->pci_func, val);
604aa43c215SJeff Kirsher return (val == XG_LINK_UP_P3P) ? 0 : 1;
605aa43c215SJeff Kirsher }
606aa43c215SJeff Kirsher
607aa43c215SJeff Kirsher static int
qlcnic_get_eeprom(struct net_device * dev,struct ethtool_eeprom * eeprom,u8 * bytes)608aa43c215SJeff Kirsher qlcnic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
609aa43c215SJeff Kirsher u8 *bytes)
610aa43c215SJeff Kirsher {
611aa43c215SJeff Kirsher struct qlcnic_adapter *adapter = netdev_priv(dev);
612aa43c215SJeff Kirsher int offset;
6137e38d04bSSony Chacko int ret = -1;
614aa43c215SJeff Kirsher
6157e38d04bSSony Chacko if (qlcnic_83xx_check(adapter))
6167e38d04bSSony Chacko return 0;
617aa43c215SJeff Kirsher if (eeprom->len == 0)
618aa43c215SJeff Kirsher return -EINVAL;
619aa43c215SJeff Kirsher
620aa43c215SJeff Kirsher eeprom->magic = (adapter->pdev)->vendor |
621aa43c215SJeff Kirsher ((adapter->pdev)->device << 16);
622aa43c215SJeff Kirsher offset = eeprom->offset;
623aa43c215SJeff Kirsher
6247e38d04bSSony Chacko if (qlcnic_82xx_check(adapter))
625aa43c215SJeff Kirsher ret = qlcnic_rom_fast_read_words(adapter, offset, bytes,
626aa43c215SJeff Kirsher eeprom->len);
627aa43c215SJeff Kirsher if (ret < 0)
628aa43c215SJeff Kirsher return ret;
629aa43c215SJeff Kirsher
630aa43c215SJeff Kirsher return 0;
631aa43c215SJeff Kirsher }
632aa43c215SJeff Kirsher
633aa43c215SJeff Kirsher static void
qlcnic_get_ringparam(struct net_device * dev,struct ethtool_ringparam * ring,struct kernel_ethtool_ringparam * kernel_ring,struct netlink_ext_ack * extack)634aa43c215SJeff Kirsher qlcnic_get_ringparam(struct net_device *dev,
63574624944SHao Chen struct ethtool_ringparam *ring,
63674624944SHao Chen struct kernel_ethtool_ringparam *kernel_ring,
63774624944SHao Chen struct netlink_ext_ack *extack)
638aa43c215SJeff Kirsher {
639aa43c215SJeff Kirsher struct qlcnic_adapter *adapter = netdev_priv(dev);
640aa43c215SJeff Kirsher
641aa43c215SJeff Kirsher ring->rx_pending = adapter->num_rxd;
642aa43c215SJeff Kirsher ring->rx_jumbo_pending = adapter->num_jumbo_rxd;
643aa43c215SJeff Kirsher ring->tx_pending = adapter->num_txd;
644aa43c215SJeff Kirsher
645aa43c215SJeff Kirsher ring->rx_max_pending = adapter->max_rxd;
646aa43c215SJeff Kirsher ring->rx_jumbo_max_pending = adapter->max_jumbo_rxd;
647aa43c215SJeff Kirsher ring->tx_max_pending = MAX_CMD_DESCRIPTORS;
648aa43c215SJeff Kirsher }
649aa43c215SJeff Kirsher
650aa43c215SJeff Kirsher static u32
qlcnic_validate_ringparam(u32 val,u32 min,u32 max,char * r_name)651aa43c215SJeff Kirsher qlcnic_validate_ringparam(u32 val, u32 min, u32 max, char *r_name)
652aa43c215SJeff Kirsher {
653aa43c215SJeff Kirsher u32 num_desc;
654aa43c215SJeff Kirsher num_desc = max(val, min);
655aa43c215SJeff Kirsher num_desc = min(num_desc, max);
656aa43c215SJeff Kirsher num_desc = roundup_pow_of_two(num_desc);
657aa43c215SJeff Kirsher
658aa43c215SJeff Kirsher if (val != num_desc) {
659aa43c215SJeff Kirsher printk(KERN_INFO "%s: setting %s ring size %d instead of %d\n",
660aa43c215SJeff Kirsher qlcnic_driver_name, r_name, num_desc, val);
661aa43c215SJeff Kirsher }
662aa43c215SJeff Kirsher
663aa43c215SJeff Kirsher return num_desc;
664aa43c215SJeff Kirsher }
665aa43c215SJeff Kirsher
666aa43c215SJeff Kirsher static int
qlcnic_set_ringparam(struct net_device * dev,struct ethtool_ringparam * ring,struct kernel_ethtool_ringparam * kernel_ring,struct netlink_ext_ack * extack)667aa43c215SJeff Kirsher qlcnic_set_ringparam(struct net_device *dev,
66874624944SHao Chen struct ethtool_ringparam *ring,
66974624944SHao Chen struct kernel_ethtool_ringparam *kernel_ring,
67074624944SHao Chen struct netlink_ext_ack *extack)
671aa43c215SJeff Kirsher {
672aa43c215SJeff Kirsher struct qlcnic_adapter *adapter = netdev_priv(dev);
673aa43c215SJeff Kirsher u16 num_rxd, num_jumbo_rxd, num_txd;
674aa43c215SJeff Kirsher
675aa43c215SJeff Kirsher if (ring->rx_mini_pending)
676aa43c215SJeff Kirsher return -EOPNOTSUPP;
677aa43c215SJeff Kirsher
678aa43c215SJeff Kirsher num_rxd = qlcnic_validate_ringparam(ring->rx_pending,
679aa43c215SJeff Kirsher MIN_RCV_DESCRIPTORS, adapter->max_rxd, "rx");
680aa43c215SJeff Kirsher
681aa43c215SJeff Kirsher num_jumbo_rxd = qlcnic_validate_ringparam(ring->rx_jumbo_pending,
682aa43c215SJeff Kirsher MIN_JUMBO_DESCRIPTORS, adapter->max_jumbo_rxd,
683aa43c215SJeff Kirsher "rx jumbo");
684aa43c215SJeff Kirsher
685aa43c215SJeff Kirsher num_txd = qlcnic_validate_ringparam(ring->tx_pending,
686aa43c215SJeff Kirsher MIN_CMD_DESCRIPTORS, MAX_CMD_DESCRIPTORS, "tx");
687aa43c215SJeff Kirsher
688aa43c215SJeff Kirsher if (num_rxd == adapter->num_rxd && num_txd == adapter->num_txd &&
689aa43c215SJeff Kirsher num_jumbo_rxd == adapter->num_jumbo_rxd)
690aa43c215SJeff Kirsher return 0;
691aa43c215SJeff Kirsher
692aa43c215SJeff Kirsher adapter->num_rxd = num_rxd;
693aa43c215SJeff Kirsher adapter->num_jumbo_rxd = num_jumbo_rxd;
694aa43c215SJeff Kirsher adapter->num_txd = num_txd;
695aa43c215SJeff Kirsher
696aa43c215SJeff Kirsher return qlcnic_reset_context(adapter);
697aa43c215SJeff Kirsher }
698aa43c215SJeff Kirsher
qlcnic_validate_ring_count(struct qlcnic_adapter * adapter,u8 rx_ring,u8 tx_ring)69934e8c406SHimanshu Madhani static int qlcnic_validate_ring_count(struct qlcnic_adapter *adapter,
70034e8c406SHimanshu Madhani u8 rx_ring, u8 tx_ring)
70134e8c406SHimanshu Madhani {
702f9566265SHimanshu Madhani if (rx_ring == 0 || tx_ring == 0)
703f9566265SHimanshu Madhani return -EINVAL;
704f9566265SHimanshu Madhani
70534e8c406SHimanshu Madhani if (rx_ring != 0) {
70634e8c406SHimanshu Madhani if (rx_ring > adapter->max_sds_rings) {
707f9566265SHimanshu Madhani netdev_err(adapter->netdev,
708f9566265SHimanshu Madhani "Invalid ring count, SDS ring count %d should not be greater than max %d driver sds rings.\n",
70934e8c406SHimanshu Madhani rx_ring, adapter->max_sds_rings);
71034e8c406SHimanshu Madhani return -EINVAL;
71134e8c406SHimanshu Madhani }
71234e8c406SHimanshu Madhani }
71334e8c406SHimanshu Madhani
71434e8c406SHimanshu Madhani if (tx_ring != 0) {
715b17a44d8SHimanshu Madhani if (tx_ring > adapter->max_tx_rings) {
71634e8c406SHimanshu Madhani netdev_err(adapter->netdev,
71734e8c406SHimanshu Madhani "Invalid ring count, Tx ring count %d should not be greater than max %d driver Tx rings.\n",
71834e8c406SHimanshu Madhani tx_ring, adapter->max_tx_rings);
71934e8c406SHimanshu Madhani return -EINVAL;
72034e8c406SHimanshu Madhani }
72134e8c406SHimanshu Madhani }
72234e8c406SHimanshu Madhani
72334e8c406SHimanshu Madhani return 0;
72434e8c406SHimanshu Madhani }
72534e8c406SHimanshu Madhani
qlcnic_get_channels(struct net_device * dev,struct ethtool_channels * channel)726aa43c215SJeff Kirsher static void qlcnic_get_channels(struct net_device *dev,
727aa43c215SJeff Kirsher struct ethtool_channels *channel)
728aa43c215SJeff Kirsher {
729aa43c215SJeff Kirsher struct qlcnic_adapter *adapter = netdev_priv(dev);
730aa43c215SJeff Kirsher
73134e8c406SHimanshu Madhani channel->max_rx = adapter->max_sds_rings;
73234e8c406SHimanshu Madhani channel->max_tx = adapter->max_tx_rings;
73334e8c406SHimanshu Madhani channel->rx_count = adapter->drv_sds_rings;
73434e8c406SHimanshu Madhani channel->tx_count = adapter->drv_tx_rings;
735aa43c215SJeff Kirsher }
736aa43c215SJeff Kirsher
qlcnic_set_channels(struct net_device * dev,struct ethtool_channels * channel)737aa43c215SJeff Kirsher static int qlcnic_set_channels(struct net_device *dev,
738aa43c215SJeff Kirsher struct ethtool_channels *channel)
739aa43c215SJeff Kirsher {
740aa43c215SJeff Kirsher struct qlcnic_adapter *adapter = netdev_priv(dev);
741aa43c215SJeff Kirsher int err;
742aa43c215SJeff Kirsher
74318e0d625SShahed Shaikh if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
74418e0d625SShahed Shaikh netdev_err(dev, "No RSS/TSS support in non MSI-X mode\n");
74518e0d625SShahed Shaikh return -EINVAL;
74618e0d625SShahed Shaikh }
74718e0d625SShahed Shaikh
748aa4a1f7dSHimanshu Madhani if (channel->other_count || channel->combined_count)
749aa43c215SJeff Kirsher return -EINVAL;
750aa43c215SJeff Kirsher
75134e8c406SHimanshu Madhani err = qlcnic_validate_ring_count(adapter, channel->rx_count,
75234e8c406SHimanshu Madhani channel->tx_count);
753aa43c215SJeff Kirsher if (err)
754aa43c215SJeff Kirsher return err;
75534e8c406SHimanshu Madhani
75618e0d625SShahed Shaikh if (adapter->drv_sds_rings != channel->rx_count) {
75734e8c406SHimanshu Madhani err = qlcnic_validate_rings(adapter, channel->rx_count,
75834e8c406SHimanshu Madhani QLCNIC_RX_QUEUE);
75934e8c406SHimanshu Madhani if (err) {
76034e8c406SHimanshu Madhani netdev_err(dev, "Unable to configure %u SDS rings\n",
76134e8c406SHimanshu Madhani channel->rx_count);
76234e8c406SHimanshu Madhani return err;
76334e8c406SHimanshu Madhani }
764cb9327d5SHimanshu Madhani adapter->drv_rss_rings = channel->rx_count;
765aa4a1f7dSHimanshu Madhani }
766aa43c215SJeff Kirsher
76718e0d625SShahed Shaikh if (adapter->drv_tx_rings != channel->tx_count) {
76834e8c406SHimanshu Madhani err = qlcnic_validate_rings(adapter, channel->tx_count,
76934e8c406SHimanshu Madhani QLCNIC_TX_QUEUE);
77034e8c406SHimanshu Madhani if (err) {
77134e8c406SHimanshu Madhani netdev_err(dev, "Unable to configure %u Tx rings\n",
77234e8c406SHimanshu Madhani channel->tx_count);
773aa4a1f7dSHimanshu Madhani return err;
77434e8c406SHimanshu Madhani }
775cb9327d5SHimanshu Madhani adapter->drv_tss_rings = channel->tx_count;
776aa4a1f7dSHimanshu Madhani }
777aa4a1f7dSHimanshu Madhani
778cb9327d5SHimanshu Madhani adapter->flags |= QLCNIC_TSS_RSS;
779cb9327d5SHimanshu Madhani
780cb9327d5SHimanshu Madhani err = qlcnic_setup_rings(adapter);
78134e8c406SHimanshu Madhani netdev_info(dev, "Allocated %d SDS rings and %d Tx rings\n",
78234e8c406SHimanshu Madhani adapter->drv_sds_rings, adapter->drv_tx_rings);
78334e8c406SHimanshu Madhani
784aa43c215SJeff Kirsher return err;
785aa43c215SJeff Kirsher }
786aa43c215SJeff Kirsher
787aa43c215SJeff Kirsher static void
qlcnic_get_pauseparam(struct net_device * netdev,struct ethtool_pauseparam * pause)788aa43c215SJeff Kirsher qlcnic_get_pauseparam(struct net_device *netdev,
789aa43c215SJeff Kirsher struct ethtool_pauseparam *pause)
790aa43c215SJeff Kirsher {
791aa43c215SJeff Kirsher struct qlcnic_adapter *adapter = netdev_priv(netdev);
79279788450SSony Chacko int port = adapter->ahw->physical_port;
7934bd8e738SHimanshu Madhani int err = 0;
794aa43c215SJeff Kirsher __u32 val;
795aa43c215SJeff Kirsher
7967e38d04bSSony Chacko if (qlcnic_83xx_check(adapter)) {
7977e38d04bSSony Chacko qlcnic_83xx_get_pauseparam(adapter, pause);
7987e38d04bSSony Chacko return;
7997e38d04bSSony Chacko }
800aa43c215SJeff Kirsher if (adapter->ahw->port_type == QLCNIC_GBE) {
801aa43c215SJeff Kirsher if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
802aa43c215SJeff Kirsher return;
803aa43c215SJeff Kirsher /* get flow control settings */
8044bd8e738SHimanshu Madhani val = QLCRD32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port), &err);
8054bd8e738SHimanshu Madhani if (err == -EIO)
8064bd8e738SHimanshu Madhani return;
807aa43c215SJeff Kirsher pause->rx_pause = qlcnic_gb_get_rx_flowctl(val);
8084bd8e738SHimanshu Madhani val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, &err);
8094bd8e738SHimanshu Madhani if (err == -EIO)
8104bd8e738SHimanshu Madhani return;
811aa43c215SJeff Kirsher switch (port) {
812aa43c215SJeff Kirsher case 0:
813aa43c215SJeff Kirsher pause->tx_pause = !(qlcnic_gb_get_gb0_mask(val));
814aa43c215SJeff Kirsher break;
815aa43c215SJeff Kirsher case 1:
816aa43c215SJeff Kirsher pause->tx_pause = !(qlcnic_gb_get_gb1_mask(val));
817aa43c215SJeff Kirsher break;
818aa43c215SJeff Kirsher case 2:
819aa43c215SJeff Kirsher pause->tx_pause = !(qlcnic_gb_get_gb2_mask(val));
820aa43c215SJeff Kirsher break;
821aa43c215SJeff Kirsher case 3:
822aa43c215SJeff Kirsher default:
823aa43c215SJeff Kirsher pause->tx_pause = !(qlcnic_gb_get_gb3_mask(val));
824aa43c215SJeff Kirsher break;
825aa43c215SJeff Kirsher }
826aa43c215SJeff Kirsher } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
827aa43c215SJeff Kirsher if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS))
828aa43c215SJeff Kirsher return;
829aa43c215SJeff Kirsher pause->rx_pause = 1;
8304bd8e738SHimanshu Madhani val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL, &err);
8314bd8e738SHimanshu Madhani if (err == -EIO)
8324bd8e738SHimanshu Madhani return;
833aa43c215SJeff Kirsher if (port == 0)
834aa43c215SJeff Kirsher pause->tx_pause = !(qlcnic_xg_get_xg0_mask(val));
835aa43c215SJeff Kirsher else
836aa43c215SJeff Kirsher pause->tx_pause = !(qlcnic_xg_get_xg1_mask(val));
837aa43c215SJeff Kirsher } else {
838aa43c215SJeff Kirsher dev_err(&netdev->dev, "Unknown board type: %x\n",
839aa43c215SJeff Kirsher adapter->ahw->port_type);
840aa43c215SJeff Kirsher }
841aa43c215SJeff Kirsher }
842aa43c215SJeff Kirsher
843aa43c215SJeff Kirsher static int
qlcnic_set_pauseparam(struct net_device * netdev,struct ethtool_pauseparam * pause)844aa43c215SJeff Kirsher qlcnic_set_pauseparam(struct net_device *netdev,
845aa43c215SJeff Kirsher struct ethtool_pauseparam *pause)
846aa43c215SJeff Kirsher {
847aa43c215SJeff Kirsher struct qlcnic_adapter *adapter = netdev_priv(netdev);
84879788450SSony Chacko int port = adapter->ahw->physical_port;
8494bd8e738SHimanshu Madhani int err = 0;
850aa43c215SJeff Kirsher __u32 val;
851aa43c215SJeff Kirsher
8527e38d04bSSony Chacko if (qlcnic_83xx_check(adapter))
8537e38d04bSSony Chacko return qlcnic_83xx_set_pauseparam(adapter, pause);
8547e38d04bSSony Chacko
855aa43c215SJeff Kirsher /* read mode */
856aa43c215SJeff Kirsher if (adapter->ahw->port_type == QLCNIC_GBE) {
857aa43c215SJeff Kirsher if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
858aa43c215SJeff Kirsher return -EIO;
859aa43c215SJeff Kirsher /* set flow control */
8604bd8e738SHimanshu Madhani val = QLCRD32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port), &err);
8614bd8e738SHimanshu Madhani if (err == -EIO)
8624bd8e738SHimanshu Madhani return err;
863aa43c215SJeff Kirsher
864aa43c215SJeff Kirsher if (pause->rx_pause)
865aa43c215SJeff Kirsher qlcnic_gb_rx_flowctl(val);
866aa43c215SJeff Kirsher else
867aa43c215SJeff Kirsher qlcnic_gb_unset_rx_flowctl(val);
868aa43c215SJeff Kirsher
869aa43c215SJeff Kirsher QLCWR32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port),
870aa43c215SJeff Kirsher val);
8717e38d04bSSony Chacko QLCWR32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port), val);
872aa43c215SJeff Kirsher /* set autoneg */
8734bd8e738SHimanshu Madhani val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, &err);
8744bd8e738SHimanshu Madhani if (err == -EIO)
8754bd8e738SHimanshu Madhani return err;
876aa43c215SJeff Kirsher switch (port) {
877aa43c215SJeff Kirsher case 0:
878aa43c215SJeff Kirsher if (pause->tx_pause)
879aa43c215SJeff Kirsher qlcnic_gb_unset_gb0_mask(val);
880aa43c215SJeff Kirsher else
881aa43c215SJeff Kirsher qlcnic_gb_set_gb0_mask(val);
882aa43c215SJeff Kirsher break;
883aa43c215SJeff Kirsher case 1:
884aa43c215SJeff Kirsher if (pause->tx_pause)
885aa43c215SJeff Kirsher qlcnic_gb_unset_gb1_mask(val);
886aa43c215SJeff Kirsher else
887aa43c215SJeff Kirsher qlcnic_gb_set_gb1_mask(val);
888aa43c215SJeff Kirsher break;
889aa43c215SJeff Kirsher case 2:
890aa43c215SJeff Kirsher if (pause->tx_pause)
891aa43c215SJeff Kirsher qlcnic_gb_unset_gb2_mask(val);
892aa43c215SJeff Kirsher else
893aa43c215SJeff Kirsher qlcnic_gb_set_gb2_mask(val);
894aa43c215SJeff Kirsher break;
895aa43c215SJeff Kirsher case 3:
896aa43c215SJeff Kirsher default:
897aa43c215SJeff Kirsher if (pause->tx_pause)
898aa43c215SJeff Kirsher qlcnic_gb_unset_gb3_mask(val);
899aa43c215SJeff Kirsher else
900aa43c215SJeff Kirsher qlcnic_gb_set_gb3_mask(val);
901aa43c215SJeff Kirsher break;
902aa43c215SJeff Kirsher }
903aa43c215SJeff Kirsher QLCWR32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, val);
904aa43c215SJeff Kirsher } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
905aa43c215SJeff Kirsher if (!pause->rx_pause || pause->autoneg)
906aa43c215SJeff Kirsher return -EOPNOTSUPP;
907aa43c215SJeff Kirsher
908aa43c215SJeff Kirsher if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS))
909aa43c215SJeff Kirsher return -EIO;
910aa43c215SJeff Kirsher
9114bd8e738SHimanshu Madhani val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL, &err);
9124bd8e738SHimanshu Madhani if (err == -EIO)
9134bd8e738SHimanshu Madhani return err;
914aa43c215SJeff Kirsher if (port == 0) {
915aa43c215SJeff Kirsher if (pause->tx_pause)
916aa43c215SJeff Kirsher qlcnic_xg_unset_xg0_mask(val);
917aa43c215SJeff Kirsher else
918aa43c215SJeff Kirsher qlcnic_xg_set_xg0_mask(val);
919aa43c215SJeff Kirsher } else {
920aa43c215SJeff Kirsher if (pause->tx_pause)
921aa43c215SJeff Kirsher qlcnic_xg_unset_xg1_mask(val);
922aa43c215SJeff Kirsher else
923aa43c215SJeff Kirsher qlcnic_xg_set_xg1_mask(val);
924aa43c215SJeff Kirsher }
925aa43c215SJeff Kirsher QLCWR32(adapter, QLCNIC_NIU_XG_PAUSE_CTL, val);
926aa43c215SJeff Kirsher } else {
927aa43c215SJeff Kirsher dev_err(&netdev->dev, "Unknown board type: %x\n",
928aa43c215SJeff Kirsher adapter->ahw->port_type);
929aa43c215SJeff Kirsher }
930aa43c215SJeff Kirsher return 0;
931aa43c215SJeff Kirsher }
932aa43c215SJeff Kirsher
qlcnic_reg_test(struct net_device * dev)933aa43c215SJeff Kirsher static int qlcnic_reg_test(struct net_device *dev)
934aa43c215SJeff Kirsher {
935aa43c215SJeff Kirsher struct qlcnic_adapter *adapter = netdev_priv(dev);
936aa43c215SJeff Kirsher u32 data_read;
9374bd8e738SHimanshu Madhani int err = 0;
938aa43c215SJeff Kirsher
9397e38d04bSSony Chacko if (qlcnic_83xx_check(adapter))
9407e38d04bSSony Chacko return qlcnic_83xx_reg_test(adapter);
9417e38d04bSSony Chacko
9424bd8e738SHimanshu Madhani data_read = QLCRD32(adapter, QLCNIC_PCIX_PH_REG(0), &err);
9434bd8e738SHimanshu Madhani if (err == -EIO)
9444bd8e738SHimanshu Madhani return err;
945aa43c215SJeff Kirsher if ((data_read & 0xffff) != adapter->pdev->vendor)
946aa43c215SJeff Kirsher return 1;
947aa43c215SJeff Kirsher
948aa43c215SJeff Kirsher return 0;
949aa43c215SJeff Kirsher }
950aa43c215SJeff Kirsher
qlcnic_eeprom_test(struct net_device * dev)9517e38d04bSSony Chacko static int qlcnic_eeprom_test(struct net_device *dev)
9527e38d04bSSony Chacko {
9537e38d04bSSony Chacko struct qlcnic_adapter *adapter = netdev_priv(dev);
9547e38d04bSSony Chacko
9557e38d04bSSony Chacko if (qlcnic_82xx_check(adapter))
9567e38d04bSSony Chacko return 0;
9577e38d04bSSony Chacko
9587e38d04bSSony Chacko return qlcnic_83xx_flash_test(adapter);
9597e38d04bSSony Chacko }
9607e38d04bSSony Chacko
qlcnic_get_sset_count(struct net_device * dev,int sset)961aa43c215SJeff Kirsher static int qlcnic_get_sset_count(struct net_device *dev, int sset)
962aa43c215SJeff Kirsher {
9637e38d04bSSony Chacko
964aa43c215SJeff Kirsher struct qlcnic_adapter *adapter = netdev_priv(dev);
965aa43c215SJeff Kirsher switch (sset) {
966aa43c215SJeff Kirsher case ETH_SS_TEST:
967aa43c215SJeff Kirsher return QLCNIC_TEST_LEN;
968aa43c215SJeff Kirsher case ETH_SS_STATS:
969d6e9c89aSShahed Shaikh return qlcnic_dev_statistics_len(adapter);
970aa43c215SJeff Kirsher default:
971aa43c215SJeff Kirsher return -EOPNOTSUPP;
972aa43c215SJeff Kirsher }
973aa43c215SJeff Kirsher }
974aa43c215SJeff Kirsher
qlcnic_irq_test(struct net_device * netdev)975aa43c215SJeff Kirsher static int qlcnic_irq_test(struct net_device *netdev)
976aa43c215SJeff Kirsher {
977aa43c215SJeff Kirsher struct qlcnic_adapter *adapter = netdev_priv(netdev);
97858ead415SJitendra Kalsaria struct qlcnic_hardware_context *ahw = adapter->ahw;
9797777de9aSAnirban Chakraborty struct qlcnic_cmd_args cmd;
98034e8c406SHimanshu Madhani int ret, drv_sds_rings = adapter->drv_sds_rings;
9813bf517dfSHimanshu Madhani int drv_tx_rings = adapter->drv_tx_rings;
98258ead415SJitendra Kalsaria
98358ead415SJitendra Kalsaria if (qlcnic_83xx_check(adapter))
98458ead415SJitendra Kalsaria return qlcnic_83xx_interrupt_test(netdev);
985aa43c215SJeff Kirsher
986aa43c215SJeff Kirsher if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
987aa43c215SJeff Kirsher return -EIO;
988aa43c215SJeff Kirsher
989aa43c215SJeff Kirsher ret = qlcnic_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST);
990aa43c215SJeff Kirsher if (ret)
99158ead415SJitendra Kalsaria goto clear_diag_irq;
992aa43c215SJeff Kirsher
99358ead415SJitendra Kalsaria ahw->diag_cnt = 0;
994b6b4316cSShahed Shaikh ret = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INTRPT_TEST);
995b6b4316cSShahed Shaikh if (ret)
996b6b4316cSShahed Shaikh goto free_diag_res;
9977e2cf4feSSony Chacko
99858ead415SJitendra Kalsaria cmd.req.arg[1] = ahw->pci_func;
9997e2cf4feSSony Chacko ret = qlcnic_issue_cmd(adapter, &cmd);
1000aa43c215SJeff Kirsher if (ret)
1001aa43c215SJeff Kirsher goto done;
1002aa43c215SJeff Kirsher
10037e2cf4feSSony Chacko usleep_range(1000, 12000);
100458ead415SJitendra Kalsaria ret = !ahw->diag_cnt;
1005aa43c215SJeff Kirsher
1006aa43c215SJeff Kirsher done:
10077e2cf4feSSony Chacko qlcnic_free_mbx_args(&cmd);
1008b6b4316cSShahed Shaikh
1009b6b4316cSShahed Shaikh free_diag_res:
101034e8c406SHimanshu Madhani qlcnic_diag_free_res(netdev, drv_sds_rings);
1011aa43c215SJeff Kirsher
101258ead415SJitendra Kalsaria clear_diag_irq:
101334e8c406SHimanshu Madhani adapter->drv_sds_rings = drv_sds_rings;
10143bf517dfSHimanshu Madhani adapter->drv_tx_rings = drv_tx_rings;
1015aa43c215SJeff Kirsher clear_bit(__QLCNIC_RESETTING, &adapter->state);
1016aa4a1f7dSHimanshu Madhani
1017aa43c215SJeff Kirsher return ret;
1018aa43c215SJeff Kirsher }
1019aa43c215SJeff Kirsher
1020aa43c215SJeff Kirsher #define QLCNIC_ILB_PKT_SIZE 64
1021aa43c215SJeff Kirsher #define QLCNIC_NUM_ILB_PKT 16
1022aa43c215SJeff Kirsher #define QLCNIC_ILB_MAX_RCV_LOOP 10
1023d1a1105eSRajesh Borundia #define QLCNIC_LB_PKT_POLL_DELAY_MSEC 1
1024d1a1105eSRajesh Borundia #define QLCNIC_LB_PKT_POLL_COUNT 20
1025aa43c215SJeff Kirsher
qlcnic_create_loopback_buff(unsigned char * data,u8 mac[])1026aa43c215SJeff Kirsher static void qlcnic_create_loopback_buff(unsigned char *data, u8 mac[])
1027aa43c215SJeff Kirsher {
1028a6afdb04SColin Ian King static const unsigned char random_data[] = {0xa8, 0x06, 0x45, 0x00};
1029aa43c215SJeff Kirsher
1030aa43c215SJeff Kirsher memset(data, 0x4e, QLCNIC_ILB_PKT_SIZE);
1031aa43c215SJeff Kirsher
1032aa43c215SJeff Kirsher memcpy(data, mac, ETH_ALEN);
1033aa43c215SJeff Kirsher memcpy(data + ETH_ALEN, mac, ETH_ALEN);
1034aa43c215SJeff Kirsher
1035aa43c215SJeff Kirsher memcpy(data + 2 * ETH_ALEN, random_data, sizeof(random_data));
1036aa43c215SJeff Kirsher }
1037aa43c215SJeff Kirsher
qlcnic_check_loopback_buff(unsigned char * data,u8 mac[])1038aa43c215SJeff Kirsher int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[])
1039aa43c215SJeff Kirsher {
1040aa43c215SJeff Kirsher unsigned char buff[QLCNIC_ILB_PKT_SIZE];
1041aa43c215SJeff Kirsher qlcnic_create_loopback_buff(buff, mac);
1042aa43c215SJeff Kirsher return memcmp(data, buff, QLCNIC_ILB_PKT_SIZE);
1043aa43c215SJeff Kirsher }
1044aa43c215SJeff Kirsher
qlcnic_do_lb_test(struct qlcnic_adapter * adapter,u8 mode)1045ba4468dbSJitendra Kalsaria int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode)
1046aa43c215SJeff Kirsher {
1047aa43c215SJeff Kirsher struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
1048aa43c215SJeff Kirsher struct qlcnic_host_sds_ring *sds_ring = &recv_ctx->sds_rings[0];
1049aa43c215SJeff Kirsher struct sk_buff *skb;
1050aa43c215SJeff Kirsher int i, loop, cnt = 0;
1051aa43c215SJeff Kirsher
1052aa43c215SJeff Kirsher for (i = 0; i < QLCNIC_NUM_ILB_PKT; i++) {
1053dae2e9f4SPradeep A. Dalvi skb = netdev_alloc_skb(adapter->netdev, QLCNIC_ILB_PKT_SIZE);
105484460f01STom Seewald if (!skb)
105584460f01STom Seewald goto error;
1056aa43c215SJeff Kirsher qlcnic_create_loopback_buff(skb->data, adapter->mac_addr);
1057aa43c215SJeff Kirsher skb_put(skb, QLCNIC_ILB_PKT_SIZE);
105879788450SSony Chacko adapter->ahw->diag_cnt = 0;
1059aa43c215SJeff Kirsher qlcnic_xmit_frame(skb, adapter->netdev);
1060aa43c215SJeff Kirsher loop = 0;
10617e38d04bSSony Chacko
1062aa43c215SJeff Kirsher do {
1063d1a1105eSRajesh Borundia msleep(QLCNIC_LB_PKT_POLL_DELAY_MSEC);
1064aa43c215SJeff Kirsher qlcnic_process_rcv_ring_diag(sds_ring);
1065d1a1105eSRajesh Borundia if (loop++ > QLCNIC_LB_PKT_POLL_COUNT)
1066aa43c215SJeff Kirsher break;
106779788450SSony Chacko } while (!adapter->ahw->diag_cnt);
1068aa43c215SJeff Kirsher
1069aa43c215SJeff Kirsher dev_kfree_skb_any(skb);
1070aa43c215SJeff Kirsher
107179788450SSony Chacko if (!adapter->ahw->diag_cnt)
10727e38d04bSSony Chacko dev_warn(&adapter->pdev->dev,
10737e38d04bSSony Chacko "LB Test: packet #%d was not received\n",
10747e38d04bSSony Chacko i + 1);
1075aa43c215SJeff Kirsher else
1076aa43c215SJeff Kirsher cnt++;
1077aa43c215SJeff Kirsher }
1078aa43c215SJeff Kirsher if (cnt != i) {
107984460f01STom Seewald error:
10807e38d04bSSony Chacko dev_err(&adapter->pdev->dev,
10817e38d04bSSony Chacko "LB Test: failed, TX[%d], RX[%d]\n", i, cnt);
10827e38d04bSSony Chacko if (mode != QLCNIC_ILB_MODE)
1083df3cfbe3SManish chopra dev_warn(&adapter->pdev->dev,
10847e38d04bSSony Chacko "WARNING: Please check loopback cable\n");
1085aa43c215SJeff Kirsher return -1;
1086aa43c215SJeff Kirsher }
1087aa43c215SJeff Kirsher return 0;
1088aa43c215SJeff Kirsher }
1089aa43c215SJeff Kirsher
qlcnic_loopback_test(struct net_device * netdev,u8 mode)109021041400Sstephen hemminger static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
1091aa43c215SJeff Kirsher {
1092aa43c215SJeff Kirsher struct qlcnic_adapter *adapter = netdev_priv(netdev);
109334e8c406SHimanshu Madhani int drv_tx_rings = adapter->drv_tx_rings;
109434e8c406SHimanshu Madhani int drv_sds_rings = adapter->drv_sds_rings;
1095aa43c215SJeff Kirsher struct qlcnic_host_sds_ring *sds_ring;
10967e38d04bSSony Chacko struct qlcnic_hardware_context *ahw = adapter->ahw;
1097aa43c215SJeff Kirsher int loop = 0;
1098aa43c215SJeff Kirsher int ret;
1099aa43c215SJeff Kirsher
11007e38d04bSSony Chacko if (qlcnic_83xx_check(adapter))
1101ba4468dbSJitendra Kalsaria return qlcnic_83xx_loopback_test(netdev, mode);
1102ba4468dbSJitendra Kalsaria
11037e38d04bSSony Chacko if (!(ahw->capabilities & QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK)) {
11047e38d04bSSony Chacko dev_info(&adapter->pdev->dev,
11057e38d04bSSony Chacko "Firmware do not support loopback test\n");
1106aa43c215SJeff Kirsher return -EOPNOTSUPP;
1107aa43c215SJeff Kirsher }
1108ba4468dbSJitendra Kalsaria
11097e38d04bSSony Chacko dev_warn(&adapter->pdev->dev, "%s loopback test in progress\n",
1110aa43c215SJeff Kirsher mode == QLCNIC_ILB_MODE ? "internal" : "external");
11117e38d04bSSony Chacko if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
11127e38d04bSSony Chacko dev_warn(&adapter->pdev->dev,
11137e38d04bSSony Chacko "Loopback test not supported in nonprivileged mode\n");
1114aa43c215SJeff Kirsher return 0;
1115aa43c215SJeff Kirsher }
1116aa43c215SJeff Kirsher
1117aa43c215SJeff Kirsher if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
1118aa43c215SJeff Kirsher return -EBUSY;
1119aa43c215SJeff Kirsher
1120aa43c215SJeff Kirsher ret = qlcnic_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST);
1121aa43c215SJeff Kirsher if (ret)
1122aa43c215SJeff Kirsher goto clear_it;
1123aa43c215SJeff Kirsher
1124aa43c215SJeff Kirsher sds_ring = &adapter->recv_ctx->sds_rings[0];
1125aa43c215SJeff Kirsher ret = qlcnic_set_lb_mode(adapter, mode);
1126aa43c215SJeff Kirsher if (ret)
1127aa43c215SJeff Kirsher goto free_res;
1128aa43c215SJeff Kirsher
11297e38d04bSSony Chacko ahw->diag_cnt = 0;
1130aa43c215SJeff Kirsher do {
1131aa43c215SJeff Kirsher msleep(500);
1132aa43c215SJeff Kirsher qlcnic_process_rcv_ring_diag(sds_ring);
1133aa43c215SJeff Kirsher if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) {
1134b9c11984SJitendra Kalsaria netdev_info(netdev,
1135b9c11984SJitendra Kalsaria "Firmware didn't sent link up event to loopback request\n");
1136b9c11984SJitendra Kalsaria ret = -ETIMEDOUT;
1137aa43c215SJeff Kirsher goto free_res;
113879788450SSony Chacko } else if (adapter->ahw->diag_cnt) {
113979788450SSony Chacko ret = adapter->ahw->diag_cnt;
1140aa43c215SJeff Kirsher goto free_res;
1141aa43c215SJeff Kirsher }
11427e38d04bSSony Chacko } while (!QLCNIC_IS_LB_CONFIGURED(ahw->loopback_state));
1143ba4468dbSJitendra Kalsaria
1144df3cfbe3SManish chopra ret = qlcnic_do_lb_test(adapter, mode);
1145ba4468dbSJitendra Kalsaria
11467e2cf4feSSony Chacko qlcnic_clear_lb_mode(adapter, mode);
1147aa43c215SJeff Kirsher
1148aa43c215SJeff Kirsher free_res:
114934e8c406SHimanshu Madhani qlcnic_diag_free_res(netdev, drv_sds_rings);
1150aa43c215SJeff Kirsher
1151aa43c215SJeff Kirsher clear_it:
115234e8c406SHimanshu Madhani adapter->drv_sds_rings = drv_sds_rings;
115334e8c406SHimanshu Madhani adapter->drv_tx_rings = drv_tx_rings;
1154aa43c215SJeff Kirsher clear_bit(__QLCNIC_RESETTING, &adapter->state);
1155aa43c215SJeff Kirsher return ret;
1156aa43c215SJeff Kirsher }
1157aa43c215SJeff Kirsher
1158aa43c215SJeff Kirsher static void
qlcnic_diag_test(struct net_device * dev,struct ethtool_test * eth_test,u64 * data)1159aa43c215SJeff Kirsher qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
1160aa43c215SJeff Kirsher u64 *data)
1161aa43c215SJeff Kirsher {
1162aa43c215SJeff Kirsher memset(data, 0, sizeof(u64) * QLCNIC_TEST_LEN);
1163aa43c215SJeff Kirsher
1164aa43c215SJeff Kirsher data[0] = qlcnic_reg_test(dev);
1165aa43c215SJeff Kirsher if (data[0])
1166aa43c215SJeff Kirsher eth_test->flags |= ETH_TEST_FL_FAILED;
1167aa43c215SJeff Kirsher
1168aa43c215SJeff Kirsher data[1] = (u64) qlcnic_test_link(dev);
1169aa43c215SJeff Kirsher if (data[1])
1170aa43c215SJeff Kirsher eth_test->flags |= ETH_TEST_FL_FAILED;
1171aa43c215SJeff Kirsher
1172aa43c215SJeff Kirsher if (eth_test->flags & ETH_TEST_FL_OFFLINE) {
1173aa43c215SJeff Kirsher data[2] = qlcnic_irq_test(dev);
1174aa43c215SJeff Kirsher if (data[2])
1175aa43c215SJeff Kirsher eth_test->flags |= ETH_TEST_FL_FAILED;
1176aa43c215SJeff Kirsher
1177aa43c215SJeff Kirsher data[3] = qlcnic_loopback_test(dev, QLCNIC_ILB_MODE);
1178aa43c215SJeff Kirsher if (data[3])
1179aa43c215SJeff Kirsher eth_test->flags |= ETH_TEST_FL_FAILED;
11807e38d04bSSony Chacko
11812e3ea7e7SShahed Shaikh if (eth_test->flags & ETH_TEST_FL_EXTERNAL_LB) {
11822e3ea7e7SShahed Shaikh data[4] = qlcnic_loopback_test(dev, QLCNIC_ELB_MODE);
1183aa43c215SJeff Kirsher if (data[4])
1184aa43c215SJeff Kirsher eth_test->flags |= ETH_TEST_FL_FAILED;
11852e3ea7e7SShahed Shaikh eth_test->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE;
11862e3ea7e7SShahed Shaikh }
11872e3ea7e7SShahed Shaikh
11882e3ea7e7SShahed Shaikh data[5] = qlcnic_eeprom_test(dev);
11892e3ea7e7SShahed Shaikh if (data[5])
11902e3ea7e7SShahed Shaikh eth_test->flags |= ETH_TEST_FL_FAILED;
1191aa43c215SJeff Kirsher }
1192aa43c215SJeff Kirsher }
1193aa43c215SJeff Kirsher
1194aa43c215SJeff Kirsher static void
qlcnic_get_strings(struct net_device * dev,u32 stringset,u8 * data)1195aa43c215SJeff Kirsher qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
1196aa43c215SJeff Kirsher {
1197aa43c215SJeff Kirsher struct qlcnic_adapter *adapter = netdev_priv(dev);
11987e38d04bSSony Chacko int index, i, num_stats;
1199aa43c215SJeff Kirsher
1200aa43c215SJeff Kirsher switch (stringset) {
1201aa43c215SJeff Kirsher case ETH_SS_TEST:
1202aa43c215SJeff Kirsher memcpy(data, *qlcnic_gstrings_test,
1203aa43c215SJeff Kirsher QLCNIC_TEST_LEN * ETH_GSTRING_LEN);
1204aa43c215SJeff Kirsher break;
1205aa43c215SJeff Kirsher case ETH_SS_STATS:
1206f27c75b3SHimanshu Madhani num_stats = ARRAY_SIZE(qlcnic_tx_queue_stats_strings);
120734e8c406SHimanshu Madhani for (i = 0; i < adapter->drv_tx_rings; i++) {
1208aa4a1f7dSHimanshu Madhani for (index = 0; index < num_stats; index++) {
1209f27c75b3SHimanshu Madhani sprintf(data, "tx_queue_%d %s", i,
1210f27c75b3SHimanshu Madhani qlcnic_tx_queue_stats_strings[index]);
1211aa4a1f7dSHimanshu Madhani data += ETH_GSTRING_LEN;
1212aa4a1f7dSHimanshu Madhani }
1213aa4a1f7dSHimanshu Madhani }
1214aa4a1f7dSHimanshu Madhani
1215aa43c215SJeff Kirsher for (index = 0; index < QLCNIC_STATS_LEN; index++) {
1216aa43c215SJeff Kirsher memcpy(data + index * ETH_GSTRING_LEN,
1217aa43c215SJeff Kirsher qlcnic_gstrings_stats[index].stat_string,
1218aa43c215SJeff Kirsher ETH_GSTRING_LEN);
1219aa43c215SJeff Kirsher }
1220aa4a1f7dSHimanshu Madhani
12217e38d04bSSony Chacko if (qlcnic_83xx_check(adapter)) {
12227e38d04bSSony Chacko num_stats = ARRAY_SIZE(qlcnic_83xx_tx_stats_strings);
12237e38d04bSSony Chacko for (i = 0; i < num_stats; i++, index++)
122454a8997cSJitendra Kalsaria memcpy(data + index * ETH_GSTRING_LEN,
12257e38d04bSSony Chacko qlcnic_83xx_tx_stats_strings[i],
12267e38d04bSSony Chacko ETH_GSTRING_LEN);
12277e38d04bSSony Chacko num_stats = ARRAY_SIZE(qlcnic_83xx_mac_stats_strings);
12287e38d04bSSony Chacko for (i = 0; i < num_stats; i++, index++)
12297e38d04bSSony Chacko memcpy(data + index * ETH_GSTRING_LEN,
12307e38d04bSSony Chacko qlcnic_83xx_mac_stats_strings[i],
12317e38d04bSSony Chacko ETH_GSTRING_LEN);
12327e38d04bSSony Chacko num_stats = ARRAY_SIZE(qlcnic_83xx_rx_stats_strings);
12337e38d04bSSony Chacko for (i = 0; i < num_stats; i++, index++)
12347e38d04bSSony Chacko memcpy(data + index * ETH_GSTRING_LEN,
12357e38d04bSSony Chacko qlcnic_83xx_rx_stats_strings[i],
12367e38d04bSSony Chacko ETH_GSTRING_LEN);
12377e38d04bSSony Chacko return;
12387e38d04bSSony Chacko } else {
12397e38d04bSSony Chacko num_stats = ARRAY_SIZE(qlcnic_83xx_mac_stats_strings);
12407e38d04bSSony Chacko for (i = 0; i < num_stats; i++, index++)
12417e38d04bSSony Chacko memcpy(data + index * ETH_GSTRING_LEN,
12427e38d04bSSony Chacko qlcnic_83xx_mac_stats_strings[i],
124354a8997cSJitendra Kalsaria ETH_GSTRING_LEN);
124454a8997cSJitendra Kalsaria }
1245aa43c215SJeff Kirsher if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
1246aa43c215SJeff Kirsher return;
12477e38d04bSSony Chacko num_stats = ARRAY_SIZE(qlcnic_device_gstrings_stats);
12487e38d04bSSony Chacko for (i = 0; i < num_stats; index++, i++) {
1249aa43c215SJeff Kirsher memcpy(data + index * ETH_GSTRING_LEN,
1250aa43c215SJeff Kirsher qlcnic_device_gstrings_stats[i],
1251aa43c215SJeff Kirsher ETH_GSTRING_LEN);
1252aa43c215SJeff Kirsher }
1253aa43c215SJeff Kirsher }
1254aa43c215SJeff Kirsher }
1255aa43c215SJeff Kirsher
qlcnic_fill_stats(u64 * data,void * stats,int type)12569434dbfeSShahed Shaikh static u64 *qlcnic_fill_stats(u64 *data, void *stats, int type)
1257aa43c215SJeff Kirsher {
125854a8997cSJitendra Kalsaria if (type == QLCNIC_MAC_STATS) {
125954a8997cSJitendra Kalsaria struct qlcnic_mac_statistics *mac_stats =
126054a8997cSJitendra Kalsaria (struct qlcnic_mac_statistics *)stats;
12617e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_frames);
12627e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_bytes);
12637e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_mcast_pkts);
12647e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_bcast_pkts);
12657e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_pause_cnt);
12667e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_ctrl_pkt);
12677e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_64b_pkts);
12687e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_127b_pkts);
12697e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_255b_pkts);
12707e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_511b_pkts);
12717e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_1023b_pkts);
12727e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_1518b_pkts);
12737e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_gt_1518b_pkts);
12747e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_frames);
12757e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_bytes);
12767e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_mcast_pkts);
12777e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_bcast_pkts);
12787e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_pause_cnt);
12797e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_ctrl_pkt);
12807e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_64b_pkts);
12817e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_127b_pkts);
12827e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_255b_pkts);
12837e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_511b_pkts);
12847e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_1023b_pkts);
12857e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_1518b_pkts);
12867e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_gt_1518b_pkts);
12877e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_error);
12887e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_small);
12897e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_large);
12907e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_jabber);
12917e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_dropped);
12927e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_crc_error);
12937e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(mac_stats->mac_align_error);
129454a8997cSJitendra Kalsaria } else if (type == QLCNIC_ESW_STATS) {
129554a8997cSJitendra Kalsaria struct __qlcnic_esw_statistics *esw_stats =
129654a8997cSJitendra Kalsaria (struct __qlcnic_esw_statistics *)stats;
12977e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(esw_stats->unicast_frames);
12987e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(esw_stats->multicast_frames);
12997e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(esw_stats->broadcast_frames);
13007e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(esw_stats->dropped_frames);
13017e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(esw_stats->errors);
13027e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(esw_stats->local_frames);
13037e38d04bSSony Chacko *data++ = QLCNIC_FILL_STATS(esw_stats->numbytes);
13047e38d04bSSony Chacko }
13059434dbfeSShahed Shaikh return data;
130654a8997cSJitendra Kalsaria }
1307aa43c215SJeff Kirsher
qlcnic_update_stats(struct qlcnic_adapter * adapter)13081ac6762aSManish Chopra void qlcnic_update_stats(struct qlcnic_adapter *adapter)
1309f27c75b3SHimanshu Madhani {
1310a0eaf75cSRajesh Borundia struct qlcnic_tx_queue_stats tx_stats;
1311f27c75b3SHimanshu Madhani struct qlcnic_host_tx_ring *tx_ring;
1312f27c75b3SHimanshu Madhani int ring;
1313f27c75b3SHimanshu Madhani
1314a0eaf75cSRajesh Borundia memset(&tx_stats, 0, sizeof(tx_stats));
131534e8c406SHimanshu Madhani for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
1316f27c75b3SHimanshu Madhani tx_ring = &adapter->tx_ring[ring];
1317a0eaf75cSRajesh Borundia tx_stats.xmit_on += tx_ring->tx_stats.xmit_on;
1318a0eaf75cSRajesh Borundia tx_stats.xmit_off += tx_ring->tx_stats.xmit_off;
1319a0eaf75cSRajesh Borundia tx_stats.xmit_called += tx_ring->tx_stats.xmit_called;
1320a0eaf75cSRajesh Borundia tx_stats.xmit_finished += tx_ring->tx_stats.xmit_finished;
1321a0eaf75cSRajesh Borundia tx_stats.tx_bytes += tx_ring->tx_stats.tx_bytes;
1322f27c75b3SHimanshu Madhani }
1323a0eaf75cSRajesh Borundia
1324a0eaf75cSRajesh Borundia adapter->stats.xmit_on = tx_stats.xmit_on;
1325a0eaf75cSRajesh Borundia adapter->stats.xmit_off = tx_stats.xmit_off;
1326a0eaf75cSRajesh Borundia adapter->stats.xmitcalled = tx_stats.xmit_called;
1327a0eaf75cSRajesh Borundia adapter->stats.xmitfinished = tx_stats.xmit_finished;
1328a0eaf75cSRajesh Borundia adapter->stats.txbytes = tx_stats.tx_bytes;
1329f27c75b3SHimanshu Madhani }
1330f27c75b3SHimanshu Madhani
qlcnic_fill_tx_queue_stats(u64 * data,void * stats)1331f27c75b3SHimanshu Madhani static u64 *qlcnic_fill_tx_queue_stats(u64 *data, void *stats)
1332f27c75b3SHimanshu Madhani {
1333f27c75b3SHimanshu Madhani struct qlcnic_host_tx_ring *tx_ring;
1334f27c75b3SHimanshu Madhani
1335f27c75b3SHimanshu Madhani tx_ring = (struct qlcnic_host_tx_ring *)stats;
1336f27c75b3SHimanshu Madhani
1337f27c75b3SHimanshu Madhani *data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.xmit_on);
1338f27c75b3SHimanshu Madhani *data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.xmit_off);
1339f27c75b3SHimanshu Madhani *data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.xmit_called);
1340f27c75b3SHimanshu Madhani *data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.xmit_finished);
1341f27c75b3SHimanshu Madhani *data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.tx_bytes);
1342f27c75b3SHimanshu Madhani
1343f27c75b3SHimanshu Madhani return data;
1344f27c75b3SHimanshu Madhani }
1345f27c75b3SHimanshu Madhani
qlcnic_get_ethtool_stats(struct net_device * dev,struct ethtool_stats * stats,u64 * data)13467e38d04bSSony Chacko static void qlcnic_get_ethtool_stats(struct net_device *dev,
1347aa43c215SJeff Kirsher struct ethtool_stats *stats, u64 *data)
1348aa43c215SJeff Kirsher {
1349aa43c215SJeff Kirsher struct qlcnic_adapter *adapter = netdev_priv(dev);
1350aa4a1f7dSHimanshu Madhani struct qlcnic_host_tx_ring *tx_ring;
1351aa43c215SJeff Kirsher struct qlcnic_esw_statistics port_stats;
135254a8997cSJitendra Kalsaria struct qlcnic_mac_statistics mac_stats;
1353c0230301SManish Chopra int index, ret, length, size, ring;
13547e38d04bSSony Chacko char *p;
1355aa43c215SJeff Kirsher
1356c0230301SManish Chopra memset(data, 0, stats->n_stats * sizeof(u64));
1357f27c75b3SHimanshu Madhani
135879fdce05SColin Ian King for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
13596c0fd0dfSManish Chopra if (adapter->is_up == QLCNIC_ADAPTER_UP_MAGIC) {
1360aa4a1f7dSHimanshu Madhani tx_ring = &adapter->tx_ring[ring];
1361f27c75b3SHimanshu Madhani data = qlcnic_fill_tx_queue_stats(data, tx_ring);
1362f27c75b3SHimanshu Madhani qlcnic_update_stats(adapter);
13633456399bSManish Chopra } else {
13643456399bSManish Chopra data += QLCNIC_TX_STATS_LEN;
1365aa4a1f7dSHimanshu Madhani }
1366aa4a1f7dSHimanshu Madhani }
1367f27c75b3SHimanshu Madhani
13687e38d04bSSony Chacko length = QLCNIC_STATS_LEN;
13697e38d04bSSony Chacko for (index = 0; index < length; index++) {
13707e38d04bSSony Chacko p = (char *)adapter + qlcnic_gstrings_stats[index].stat_offset;
13717e38d04bSSony Chacko size = qlcnic_gstrings_stats[index].sizeof_stat;
13727e38d04bSSony Chacko *data++ = (size == sizeof(u64)) ? (*(u64 *)p) : ((*(u32 *)p));
1373aa43c215SJeff Kirsher }
1374aa43c215SJeff Kirsher
13757e38d04bSSony Chacko if (qlcnic_83xx_check(adapter)) {
13767e38d04bSSony Chacko if (adapter->ahw->linkup)
13777e38d04bSSony Chacko qlcnic_83xx_get_stats(adapter, data);
13787e38d04bSSony Chacko return;
13797e38d04bSSony Chacko } else {
138054a8997cSJitendra Kalsaria /* Retrieve MAC statistics from firmware */
138154a8997cSJitendra Kalsaria memset(&mac_stats, 0, sizeof(struct qlcnic_mac_statistics));
138254a8997cSJitendra Kalsaria qlcnic_get_mac_stats(adapter, &mac_stats);
13839434dbfeSShahed Shaikh data = qlcnic_fill_stats(data, &mac_stats, QLCNIC_MAC_STATS);
13847e38d04bSSony Chacko }
138554a8997cSJitendra Kalsaria
1386aa43c215SJeff Kirsher if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
1387aa43c215SJeff Kirsher return;
1388aa43c215SJeff Kirsher
1389aa43c215SJeff Kirsher memset(&port_stats, 0, sizeof(struct qlcnic_esw_statistics));
1390aa43c215SJeff Kirsher ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
1391aa43c215SJeff Kirsher QLCNIC_QUERY_RX_COUNTER, &port_stats.rx);
1392aa43c215SJeff Kirsher if (ret)
1393aa43c215SJeff Kirsher return;
1394aa43c215SJeff Kirsher
13959434dbfeSShahed Shaikh data = qlcnic_fill_stats(data, &port_stats.rx, QLCNIC_ESW_STATS);
1396aa43c215SJeff Kirsher ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
1397aa43c215SJeff Kirsher QLCNIC_QUERY_TX_COUNTER, &port_stats.tx);
1398aa43c215SJeff Kirsher if (ret)
1399aa43c215SJeff Kirsher return;
1400aa43c215SJeff Kirsher
14017e38d04bSSony Chacko qlcnic_fill_stats(data, &port_stats.tx, QLCNIC_ESW_STATS);
1402aa43c215SJeff Kirsher }
1403aa43c215SJeff Kirsher
qlcnic_set_led(struct net_device * dev,enum ethtool_phys_id_state state)1404aa43c215SJeff Kirsher static int qlcnic_set_led(struct net_device *dev,
1405aa43c215SJeff Kirsher enum ethtool_phys_id_state state)
1406aa43c215SJeff Kirsher {
1407aa43c215SJeff Kirsher struct qlcnic_adapter *adapter = netdev_priv(dev);
140834e8c406SHimanshu Madhani int drv_sds_rings = adapter->drv_sds_rings;
140910ee0faeSSucheta Chakraborty int err = -EIO, active = 1;
141010ee0faeSSucheta Chakraborty
14117e38d04bSSony Chacko if (qlcnic_83xx_check(adapter))
1412d16951d9SHimanshu Madhani return qlcnic_83xx_set_led(dev, state);
1413d16951d9SHimanshu Madhani
141479788450SSony Chacko if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
141510ee0faeSSucheta Chakraborty netdev_warn(dev, "LED test not supported for non "
141610ee0faeSSucheta Chakraborty "privilege function\n");
141710ee0faeSSucheta Chakraborty return -EOPNOTSUPP;
141810ee0faeSSucheta Chakraborty }
1419aa43c215SJeff Kirsher
1420aa43c215SJeff Kirsher switch (state) {
1421aa43c215SJeff Kirsher case ETHTOOL_ID_ACTIVE:
1422728a98b8SSucheta Chakraborty if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state))
1423728a98b8SSucheta Chakraborty return -EBUSY;
1424728a98b8SSucheta Chakraborty
142510ee0faeSSucheta Chakraborty if (test_bit(__QLCNIC_RESETTING, &adapter->state))
142610ee0faeSSucheta Chakraborty break;
1427aa43c215SJeff Kirsher
142810ee0faeSSucheta Chakraborty if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
142910ee0faeSSucheta Chakraborty if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST))
143010ee0faeSSucheta Chakraborty break;
1431aa43c215SJeff Kirsher set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
1432aa43c215SJeff Kirsher }
1433aa43c215SJeff Kirsher
143410ee0faeSSucheta Chakraborty if (adapter->nic_ops->config_led(adapter, 1, 0xf) == 0) {
143510ee0faeSSucheta Chakraborty err = 0;
143610ee0faeSSucheta Chakraborty break;
143710ee0faeSSucheta Chakraborty }
1438aa43c215SJeff Kirsher
1439aa43c215SJeff Kirsher dev_err(&adapter->pdev->dev,
1440aa43c215SJeff Kirsher "Failed to set LED blink state.\n");
1441aa43c215SJeff Kirsher break;
1442aa43c215SJeff Kirsher
1443aa43c215SJeff Kirsher case ETHTOOL_ID_INACTIVE:
144410ee0faeSSucheta Chakraborty active = 0;
144510ee0faeSSucheta Chakraborty
144610ee0faeSSucheta Chakraborty if (test_bit(__QLCNIC_RESETTING, &adapter->state))
144710ee0faeSSucheta Chakraborty break;
144810ee0faeSSucheta Chakraborty
144910ee0faeSSucheta Chakraborty if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
145010ee0faeSSucheta Chakraborty if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST))
145110ee0faeSSucheta Chakraborty break;
145210ee0faeSSucheta Chakraborty set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
145310ee0faeSSucheta Chakraborty }
145410ee0faeSSucheta Chakraborty
1455aa43c215SJeff Kirsher if (adapter->nic_ops->config_led(adapter, 0, 0xf))
1456aa43c215SJeff Kirsher dev_err(&adapter->pdev->dev,
1457aa43c215SJeff Kirsher "Failed to reset LED blink state.\n");
1458aa43c215SJeff Kirsher
1459aa43c215SJeff Kirsher break;
1460aa43c215SJeff Kirsher
1461aa43c215SJeff Kirsher default:
1462aa43c215SJeff Kirsher return -EINVAL;
1463aa43c215SJeff Kirsher }
1464aa43c215SJeff Kirsher
146510ee0faeSSucheta Chakraborty if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
146634e8c406SHimanshu Madhani qlcnic_diag_free_res(dev, drv_sds_rings);
1467aa43c215SJeff Kirsher
146810ee0faeSSucheta Chakraborty if (!active || err)
1469728a98b8SSucheta Chakraborty clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
1470728a98b8SSucheta Chakraborty
147110ee0faeSSucheta Chakraborty return err;
1472aa43c215SJeff Kirsher }
1473aa43c215SJeff Kirsher
1474aa43c215SJeff Kirsher static void
qlcnic_get_wol(struct net_device * dev,struct ethtool_wolinfo * wol)1475aa43c215SJeff Kirsher qlcnic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1476aa43c215SJeff Kirsher {
1477aa43c215SJeff Kirsher struct qlcnic_adapter *adapter = netdev_priv(dev);
1478aa43c215SJeff Kirsher u32 wol_cfg;
14794bd8e738SHimanshu Madhani int err = 0;
1480aa43c215SJeff Kirsher
14817e38d04bSSony Chacko if (qlcnic_83xx_check(adapter))
14827e38d04bSSony Chacko return;
1483aa43c215SJeff Kirsher wol->supported = 0;
1484aa43c215SJeff Kirsher wol->wolopts = 0;
1485aa43c215SJeff Kirsher
14864bd8e738SHimanshu Madhani wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV, &err);
14874bd8e738SHimanshu Madhani if (err == -EIO)
14884bd8e738SHimanshu Madhani return;
1489aa43c215SJeff Kirsher if (wol_cfg & (1UL << adapter->portnum))
1490aa43c215SJeff Kirsher wol->supported |= WAKE_MAGIC;
1491aa43c215SJeff Kirsher
14924bd8e738SHimanshu Madhani wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG, &err);
1493aa43c215SJeff Kirsher if (wol_cfg & (1UL << adapter->portnum))
1494aa43c215SJeff Kirsher wol->wolopts |= WAKE_MAGIC;
1495aa43c215SJeff Kirsher }
1496aa43c215SJeff Kirsher
1497aa43c215SJeff Kirsher static int
qlcnic_set_wol(struct net_device * dev,struct ethtool_wolinfo * wol)1498aa43c215SJeff Kirsher qlcnic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1499aa43c215SJeff Kirsher {
1500aa43c215SJeff Kirsher struct qlcnic_adapter *adapter = netdev_priv(dev);
1501aa43c215SJeff Kirsher u32 wol_cfg;
15024bd8e738SHimanshu Madhani int err = 0;
1503aa43c215SJeff Kirsher
15047e38d04bSSony Chacko if (qlcnic_83xx_check(adapter))
1505aa43c215SJeff Kirsher return -EOPNOTSUPP;
15067e38d04bSSony Chacko if (wol->wolopts & ~WAKE_MAGIC)
15077e38d04bSSony Chacko return -EINVAL;
1508aa43c215SJeff Kirsher
15094bd8e738SHimanshu Madhani wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV, &err);
15104bd8e738SHimanshu Madhani if (err == -EIO)
15114bd8e738SHimanshu Madhani return err;
1512aa43c215SJeff Kirsher if (!(wol_cfg & (1 << adapter->portnum)))
1513aa43c215SJeff Kirsher return -EOPNOTSUPP;
1514aa43c215SJeff Kirsher
15154bd8e738SHimanshu Madhani wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG, &err);
15164bd8e738SHimanshu Madhani if (err == -EIO)
15174bd8e738SHimanshu Madhani return err;
1518aa43c215SJeff Kirsher if (wol->wolopts & WAKE_MAGIC)
1519aa43c215SJeff Kirsher wol_cfg |= 1UL << adapter->portnum;
1520aa43c215SJeff Kirsher else
1521aa43c215SJeff Kirsher wol_cfg &= ~(1UL << adapter->portnum);
1522aa43c215SJeff Kirsher
1523aa43c215SJeff Kirsher QLCWR32(adapter, QLCNIC_WOL_CONFIG, wol_cfg);
1524aa43c215SJeff Kirsher
1525aa43c215SJeff Kirsher return 0;
1526aa43c215SJeff Kirsher }
1527aa43c215SJeff Kirsher
1528aa43c215SJeff Kirsher /*
1529aa43c215SJeff Kirsher * Set the coalescing parameters. Currently only normal is supported.
1530aa43c215SJeff Kirsher * If rx_coalesce_usecs == 0 or rx_max_coalesced_frames == 0 then set the
1531aa43c215SJeff Kirsher * firmware coalescing to default.
1532aa43c215SJeff Kirsher */
qlcnic_set_intr_coalesce(struct net_device * netdev,struct ethtool_coalesce * ethcoal,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)1533aa43c215SJeff Kirsher static int qlcnic_set_intr_coalesce(struct net_device *netdev,
1534f3ccfda1SYufeng Mo struct ethtool_coalesce *ethcoal,
1535f3ccfda1SYufeng Mo struct kernel_ethtool_coalesce *kernel_coal,
1536f3ccfda1SYufeng Mo struct netlink_ext_ack *extack)
1537aa43c215SJeff Kirsher {
1538aa43c215SJeff Kirsher struct qlcnic_adapter *adapter = netdev_priv(netdev);
1539a514722aSHimanshu Madhani int err;
1540aa43c215SJeff Kirsher
1541aa43c215SJeff Kirsher if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
1542aa43c215SJeff Kirsher return -EINVAL;
1543aa43c215SJeff Kirsher
1544aa43c215SJeff Kirsher /*
1545aa43c215SJeff Kirsher * Return Error if unsupported values or
1546aa43c215SJeff Kirsher * unsupported parameters are set.
1547aa43c215SJeff Kirsher */
1548aa43c215SJeff Kirsher if (ethcoal->rx_coalesce_usecs > 0xffff ||
1549aa43c215SJeff Kirsher ethcoal->rx_max_coalesced_frames > 0xffff ||
1550be273dc1SHimanshu Madhani ethcoal->tx_coalesce_usecs > 0xffff ||
15514a988e31SJakub Kicinski ethcoal->tx_max_coalesced_frames > 0xffff)
1552aa43c215SJeff Kirsher return -EINVAL;
1553aa43c215SJeff Kirsher
1554a514722aSHimanshu Madhani err = qlcnic_config_intr_coalesce(adapter, ethcoal);
1555be273dc1SHimanshu Madhani
1556a514722aSHimanshu Madhani return err;
1557aa43c215SJeff Kirsher }
1558aa43c215SJeff Kirsher
qlcnic_get_intr_coalesce(struct net_device * netdev,struct ethtool_coalesce * ethcoal,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)1559aa43c215SJeff Kirsher static int qlcnic_get_intr_coalesce(struct net_device *netdev,
1560f3ccfda1SYufeng Mo struct ethtool_coalesce *ethcoal,
1561f3ccfda1SYufeng Mo struct kernel_ethtool_coalesce *kernel_coal,
1562f3ccfda1SYufeng Mo struct netlink_ext_ack *extack)
1563aa43c215SJeff Kirsher {
1564aa43c215SJeff Kirsher struct qlcnic_adapter *adapter = netdev_priv(netdev);
1565aa43c215SJeff Kirsher
1566aa43c215SJeff Kirsher if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
1567aa43c215SJeff Kirsher return -EINVAL;
1568aa43c215SJeff Kirsher
1569aa43c215SJeff Kirsher ethcoal->rx_coalesce_usecs = adapter->ahw->coal.rx_time_us;
1570aa43c215SJeff Kirsher ethcoal->rx_max_coalesced_frames = adapter->ahw->coal.rx_packets;
1571be273dc1SHimanshu Madhani ethcoal->tx_coalesce_usecs = adapter->ahw->coal.tx_time_us;
1572be273dc1SHimanshu Madhani ethcoal->tx_max_coalesced_frames = adapter->ahw->coal.tx_packets;
1573aa43c215SJeff Kirsher
1574aa43c215SJeff Kirsher return 0;
1575aa43c215SJeff Kirsher }
1576aa43c215SJeff Kirsher
qlcnic_get_msglevel(struct net_device * netdev)1577aa43c215SJeff Kirsher static u32 qlcnic_get_msglevel(struct net_device *netdev)
1578aa43c215SJeff Kirsher {
1579aa43c215SJeff Kirsher struct qlcnic_adapter *adapter = netdev_priv(netdev);
1580aa43c215SJeff Kirsher
158179788450SSony Chacko return adapter->ahw->msg_enable;
1582aa43c215SJeff Kirsher }
1583aa43c215SJeff Kirsher
qlcnic_set_msglevel(struct net_device * netdev,u32 msglvl)1584aa43c215SJeff Kirsher static void qlcnic_set_msglevel(struct net_device *netdev, u32 msglvl)
1585aa43c215SJeff Kirsher {
1586aa43c215SJeff Kirsher struct qlcnic_adapter *adapter = netdev_priv(netdev);
1587aa43c215SJeff Kirsher
158879788450SSony Chacko adapter->ahw->msg_enable = msglvl;
1589aa43c215SJeff Kirsher }
1590aa43c215SJeff Kirsher
qlcnic_enable_fw_dump_state(struct qlcnic_adapter * adapter)1591890b6e02SShahed Shaikh int qlcnic_enable_fw_dump_state(struct qlcnic_adapter *adapter)
1592890b6e02SShahed Shaikh {
1593890b6e02SShahed Shaikh struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1594890b6e02SShahed Shaikh u32 val;
1595890b6e02SShahed Shaikh
1596890b6e02SShahed Shaikh if (qlcnic_84xx_check(adapter)) {
1597890b6e02SShahed Shaikh if (qlcnic_83xx_lock_driver(adapter))
1598890b6e02SShahed Shaikh return -EBUSY;
1599890b6e02SShahed Shaikh
1600890b6e02SShahed Shaikh val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
1601890b6e02SShahed Shaikh val &= ~QLC_83XX_IDC_DISABLE_FW_DUMP;
1602890b6e02SShahed Shaikh QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val);
1603890b6e02SShahed Shaikh
1604890b6e02SShahed Shaikh qlcnic_83xx_unlock_driver(adapter);
1605890b6e02SShahed Shaikh } else {
1606890b6e02SShahed Shaikh fw_dump->enable = true;
1607890b6e02SShahed Shaikh }
1608890b6e02SShahed Shaikh
1609890b6e02SShahed Shaikh dev_info(&adapter->pdev->dev, "FW dump enabled\n");
1610890b6e02SShahed Shaikh
1611890b6e02SShahed Shaikh return 0;
1612890b6e02SShahed Shaikh }
1613890b6e02SShahed Shaikh
qlcnic_disable_fw_dump_state(struct qlcnic_adapter * adapter)1614890b6e02SShahed Shaikh static int qlcnic_disable_fw_dump_state(struct qlcnic_adapter *adapter)
1615890b6e02SShahed Shaikh {
1616890b6e02SShahed Shaikh struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1617890b6e02SShahed Shaikh u32 val;
1618890b6e02SShahed Shaikh
1619890b6e02SShahed Shaikh if (qlcnic_84xx_check(adapter)) {
1620890b6e02SShahed Shaikh if (qlcnic_83xx_lock_driver(adapter))
1621890b6e02SShahed Shaikh return -EBUSY;
1622890b6e02SShahed Shaikh
1623890b6e02SShahed Shaikh val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
1624890b6e02SShahed Shaikh val |= QLC_83XX_IDC_DISABLE_FW_DUMP;
1625890b6e02SShahed Shaikh QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val);
1626890b6e02SShahed Shaikh
1627890b6e02SShahed Shaikh qlcnic_83xx_unlock_driver(adapter);
1628890b6e02SShahed Shaikh } else {
1629890b6e02SShahed Shaikh fw_dump->enable = false;
1630890b6e02SShahed Shaikh }
1631890b6e02SShahed Shaikh
1632890b6e02SShahed Shaikh dev_info(&adapter->pdev->dev, "FW dump disabled\n");
1633890b6e02SShahed Shaikh
1634890b6e02SShahed Shaikh return 0;
1635890b6e02SShahed Shaikh }
1636890b6e02SShahed Shaikh
qlcnic_check_fw_dump_state(struct qlcnic_adapter * adapter)1637890b6e02SShahed Shaikh bool qlcnic_check_fw_dump_state(struct qlcnic_adapter *adapter)
1638890b6e02SShahed Shaikh {
1639890b6e02SShahed Shaikh struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1640890b6e02SShahed Shaikh bool state;
1641890b6e02SShahed Shaikh u32 val;
1642890b6e02SShahed Shaikh
1643890b6e02SShahed Shaikh if (qlcnic_84xx_check(adapter)) {
1644890b6e02SShahed Shaikh val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
1645890b6e02SShahed Shaikh state = (val & QLC_83XX_IDC_DISABLE_FW_DUMP) ? false : true;
1646890b6e02SShahed Shaikh } else {
1647890b6e02SShahed Shaikh state = fw_dump->enable;
1648890b6e02SShahed Shaikh }
1649890b6e02SShahed Shaikh
1650890b6e02SShahed Shaikh return state;
1651890b6e02SShahed Shaikh }
1652890b6e02SShahed Shaikh
1653aa43c215SJeff Kirsher static int
qlcnic_get_dump_flag(struct net_device * netdev,struct ethtool_dump * dump)1654aa43c215SJeff Kirsher qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump)
1655aa43c215SJeff Kirsher {
1656aa43c215SJeff Kirsher struct qlcnic_adapter *adapter = netdev_priv(netdev);
1657aa43c215SJeff Kirsher struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1658aa43c215SJeff Kirsher
1659b43e5ee7SSucheta Chakraborty if (!fw_dump->tmpl_hdr) {
1660b43e5ee7SSucheta Chakraborty netdev_err(adapter->netdev, "FW Dump not supported\n");
1661b43e5ee7SSucheta Chakraborty return -ENOTSUPP;
1662b43e5ee7SSucheta Chakraborty }
1663b43e5ee7SSucheta Chakraborty
1664aa43c215SJeff Kirsher if (fw_dump->clr)
1665225837a0SShahed Shaikh dump->len = fw_dump->tmpl_hdr_size + fw_dump->size;
1666aa43c215SJeff Kirsher else
1667aa43c215SJeff Kirsher dump->len = 0;
1668bcebe559SManish chopra
1669890b6e02SShahed Shaikh if (!qlcnic_check_fw_dump_state(adapter))
1670bcebe559SManish chopra dump->flag = ETH_FW_DUMP_DISABLE;
1671bcebe559SManish chopra else
1672225837a0SShahed Shaikh dump->flag = fw_dump->cap_mask;
1673bcebe559SManish chopra
1674aa43c215SJeff Kirsher dump->version = adapter->fw_version;
1675aa43c215SJeff Kirsher return 0;
1676aa43c215SJeff Kirsher }
1677aa43c215SJeff Kirsher
1678aa43c215SJeff Kirsher static int
qlcnic_get_dump_data(struct net_device * netdev,struct ethtool_dump * dump,void * buffer)1679aa43c215SJeff Kirsher qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
1680aa43c215SJeff Kirsher void *buffer)
1681aa43c215SJeff Kirsher {
1682aa43c215SJeff Kirsher int i, copy_sz;
168363507592SShahed Shaikh u32 *hdr_ptr;
168463507592SShahed Shaikh __le32 *data;
1685aa43c215SJeff Kirsher struct qlcnic_adapter *adapter = netdev_priv(netdev);
1686aa43c215SJeff Kirsher struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1687aa43c215SJeff Kirsher
1688b43e5ee7SSucheta Chakraborty if (!fw_dump->tmpl_hdr) {
1689b43e5ee7SSucheta Chakraborty netdev_err(netdev, "FW Dump not supported\n");
1690b43e5ee7SSucheta Chakraborty return -ENOTSUPP;
1691b43e5ee7SSucheta Chakraborty }
1692b43e5ee7SSucheta Chakraborty
1693aa43c215SJeff Kirsher if (!fw_dump->clr) {
1694aa43c215SJeff Kirsher netdev_info(netdev, "Dump not available\n");
1695aa43c215SJeff Kirsher return -EINVAL;
1696aa43c215SJeff Kirsher }
1697225837a0SShahed Shaikh
1698aa43c215SJeff Kirsher /* Copy template header first */
1699225837a0SShahed Shaikh copy_sz = fw_dump->tmpl_hdr_size;
1700aa43c215SJeff Kirsher hdr_ptr = (u32 *)fw_dump->tmpl_hdr;
1701aa43c215SJeff Kirsher data = buffer;
1702aa43c215SJeff Kirsher for (i = 0; i < copy_sz/sizeof(u32); i++)
1703aa43c215SJeff Kirsher *data++ = cpu_to_le32(*hdr_ptr++);
1704aa43c215SJeff Kirsher
1705aa43c215SJeff Kirsher /* Copy captured dump data */
1706aa43c215SJeff Kirsher memcpy(buffer + copy_sz, fw_dump->data, fw_dump->size);
1707aa43c215SJeff Kirsher dump->len = copy_sz + fw_dump->size;
1708225837a0SShahed Shaikh dump->flag = fw_dump->cap_mask;
1709aa43c215SJeff Kirsher
1710aa43c215SJeff Kirsher /* Free dump area once data has been captured */
1711aa43c215SJeff Kirsher vfree(fw_dump->data);
1712aa43c215SJeff Kirsher fw_dump->data = NULL;
1713aa43c215SJeff Kirsher fw_dump->clr = 0;
1714c47884e4SManish chopra netdev_info(netdev, "extracted the FW dump Successfully\n");
1715aa43c215SJeff Kirsher return 0;
1716aa43c215SJeff Kirsher }
1717aa43c215SJeff Kirsher
qlcnic_set_dump_mask(struct qlcnic_adapter * adapter,u32 mask)1718890b6e02SShahed Shaikh static int qlcnic_set_dump_mask(struct qlcnic_adapter *adapter, u32 mask)
1719890b6e02SShahed Shaikh {
1720890b6e02SShahed Shaikh struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1721890b6e02SShahed Shaikh struct net_device *netdev = adapter->netdev;
1722890b6e02SShahed Shaikh
1723890b6e02SShahed Shaikh if (!qlcnic_check_fw_dump_state(adapter)) {
1724890b6e02SShahed Shaikh netdev_info(netdev,
1725890b6e02SShahed Shaikh "Can not change driver mask to 0x%x. FW dump not enabled\n",
1726890b6e02SShahed Shaikh mask);
1727890b6e02SShahed Shaikh return -EOPNOTSUPP;
1728890b6e02SShahed Shaikh }
1729890b6e02SShahed Shaikh
1730225837a0SShahed Shaikh fw_dump->cap_mask = mask;
1731225837a0SShahed Shaikh
1732225837a0SShahed Shaikh /* Store new capture mask in template header as well*/
1733225837a0SShahed Shaikh qlcnic_store_cap_mask(adapter, fw_dump->tmpl_hdr, mask);
1734225837a0SShahed Shaikh
1735890b6e02SShahed Shaikh netdev_info(netdev, "Driver mask changed to: 0x%x\n", mask);
1736890b6e02SShahed Shaikh return 0;
1737890b6e02SShahed Shaikh }
1738890b6e02SShahed Shaikh
1739aa43c215SJeff Kirsher static int
qlcnic_set_dump(struct net_device * netdev,struct ethtool_dump * val)1740aa43c215SJeff Kirsher qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
1741aa43c215SJeff Kirsher {
1742aa43c215SJeff Kirsher struct qlcnic_adapter *adapter = netdev_priv(netdev);
1743aa43c215SJeff Kirsher struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1744890b6e02SShahed Shaikh bool valid_mask = false;
1745890b6e02SShahed Shaikh int i, ret = 0;
1746aa43c215SJeff Kirsher
1747aa43c215SJeff Kirsher switch (val->flag) {
1748aa43c215SJeff Kirsher case QLCNIC_FORCE_FW_DUMP_KEY:
1749b43e5ee7SSucheta Chakraborty if (!fw_dump->tmpl_hdr) {
1750b43e5ee7SSucheta Chakraborty netdev_err(netdev, "FW dump not supported\n");
1751890b6e02SShahed Shaikh ret = -EOPNOTSUPP;
1752890b6e02SShahed Shaikh break;
1753b43e5ee7SSucheta Chakraborty }
1754890b6e02SShahed Shaikh
1755890b6e02SShahed Shaikh if (!qlcnic_check_fw_dump_state(adapter)) {
1756aa43c215SJeff Kirsher netdev_info(netdev, "FW dump not enabled\n");
1757890b6e02SShahed Shaikh ret = -EOPNOTSUPP;
1758890b6e02SShahed Shaikh break;
1759aa43c215SJeff Kirsher }
1760890b6e02SShahed Shaikh
1761aa43c215SJeff Kirsher if (fw_dump->clr) {
1762c47884e4SManish chopra netdev_info(netdev,
1763aa43c215SJeff Kirsher "Previous dump not cleared, not forcing dump\n");
1764890b6e02SShahed Shaikh break;
1765aa43c215SJeff Kirsher }
1766890b6e02SShahed Shaikh
1767aa43c215SJeff Kirsher netdev_info(netdev, "Forcing a FW dump\n");
17687e38d04bSSony Chacko qlcnic_dev_request_reset(adapter, val->flag);
1769aa43c215SJeff Kirsher break;
1770aa43c215SJeff Kirsher case QLCNIC_DISABLE_FW_DUMP:
1771890b6e02SShahed Shaikh if (!fw_dump->tmpl_hdr) {
1772890b6e02SShahed Shaikh netdev_err(netdev, "FW dump not supported\n");
1773890b6e02SShahed Shaikh ret = -EOPNOTSUPP;
1774890b6e02SShahed Shaikh break;
1775aa43c215SJeff Kirsher }
1776890b6e02SShahed Shaikh
1777890b6e02SShahed Shaikh ret = qlcnic_disable_fw_dump_state(adapter);
1778890b6e02SShahed Shaikh break;
1779890b6e02SShahed Shaikh
1780aa43c215SJeff Kirsher case QLCNIC_ENABLE_FW_DUMP:
1781b43e5ee7SSucheta Chakraborty if (!fw_dump->tmpl_hdr) {
1782b43e5ee7SSucheta Chakraborty netdev_err(netdev, "FW dump not supported\n");
1783890b6e02SShahed Shaikh ret = -EOPNOTSUPP;
1784890b6e02SShahed Shaikh break;
1785b43e5ee7SSucheta Chakraborty }
1786890b6e02SShahed Shaikh
1787890b6e02SShahed Shaikh ret = qlcnic_enable_fw_dump_state(adapter);
1788890b6e02SShahed Shaikh break;
1789890b6e02SShahed Shaikh
1790aa43c215SJeff Kirsher case QLCNIC_FORCE_FW_RESET:
1791aa43c215SJeff Kirsher netdev_info(netdev, "Forcing a FW reset\n");
17927e38d04bSSony Chacko qlcnic_dev_request_reset(adapter, val->flag);
1793aa43c215SJeff Kirsher adapter->flags &= ~QLCNIC_FW_RESET_OWNER;
1794890b6e02SShahed Shaikh break;
17953cc4a678SDan Carpenter
1796b43e5ee7SSucheta Chakraborty case QLCNIC_SET_QUIESCENT:
1797b43e5ee7SSucheta Chakraborty case QLCNIC_RESET_QUIESCENT:
179878ea2d97SSucheta Chakraborty if (test_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state))
179978ea2d97SSucheta Chakraborty netdev_info(netdev, "Device is in non-operational state\n");
1800890b6e02SShahed Shaikh break;
1801890b6e02SShahed Shaikh
1802aa43c215SJeff Kirsher default:
1803b43e5ee7SSucheta Chakraborty if (!fw_dump->tmpl_hdr) {
1804b43e5ee7SSucheta Chakraborty netdev_err(netdev, "FW dump not supported\n");
1805890b6e02SShahed Shaikh ret = -EOPNOTSUPP;
1806890b6e02SShahed Shaikh break;
1807b43e5ee7SSucheta Chakraborty }
1808890b6e02SShahed Shaikh
18097e38d04bSSony Chacko for (i = 0; i < ARRAY_SIZE(qlcnic_fw_dump_level); i++) {
18107e38d04bSSony Chacko if (val->flag == qlcnic_fw_dump_level[i]) {
1811890b6e02SShahed Shaikh valid_mask = true;
1812890b6e02SShahed Shaikh break;
1813aa43c215SJeff Kirsher }
18144fbec4d8SManish Chopra }
1815890b6e02SShahed Shaikh
1816890b6e02SShahed Shaikh if (valid_mask) {
1817890b6e02SShahed Shaikh ret = qlcnic_set_dump_mask(adapter, val->flag);
1818890b6e02SShahed Shaikh } else {
1819890b6e02SShahed Shaikh netdev_info(netdev, "Invalid dump level: 0x%x\n",
1820890b6e02SShahed Shaikh val->flag);
1821890b6e02SShahed Shaikh ret = -EINVAL;
18224fbec4d8SManish Chopra }
1823890b6e02SShahed Shaikh }
1824890b6e02SShahed Shaikh return ret;
1825aa43c215SJeff Kirsher }
1826aa43c215SJeff Kirsher
1827aa43c215SJeff Kirsher const struct ethtool_ops qlcnic_ethtool_ops = {
18284a988e31SJakub Kicinski .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
18294a988e31SJakub Kicinski ETHTOOL_COALESCE_MAX_FRAMES,
1830aa43c215SJeff Kirsher .get_drvinfo = qlcnic_get_drvinfo,
1831aa43c215SJeff Kirsher .get_regs_len = qlcnic_get_regs_len,
1832aa43c215SJeff Kirsher .get_regs = qlcnic_get_regs,
1833aa43c215SJeff Kirsher .get_link = ethtool_op_get_link,
1834aa43c215SJeff Kirsher .get_eeprom_len = qlcnic_get_eeprom_len,
1835aa43c215SJeff Kirsher .get_eeprom = qlcnic_get_eeprom,
1836aa43c215SJeff Kirsher .get_ringparam = qlcnic_get_ringparam,
1837aa43c215SJeff Kirsher .set_ringparam = qlcnic_set_ringparam,
1838aa43c215SJeff Kirsher .get_channels = qlcnic_get_channels,
1839aa43c215SJeff Kirsher .set_channels = qlcnic_set_channels,
1840aa43c215SJeff Kirsher .get_pauseparam = qlcnic_get_pauseparam,
1841aa43c215SJeff Kirsher .set_pauseparam = qlcnic_set_pauseparam,
1842aa43c215SJeff Kirsher .get_wol = qlcnic_get_wol,
1843aa43c215SJeff Kirsher .set_wol = qlcnic_set_wol,
1844aa43c215SJeff Kirsher .self_test = qlcnic_diag_test,
1845aa43c215SJeff Kirsher .get_strings = qlcnic_get_strings,
1846aa43c215SJeff Kirsher .get_ethtool_stats = qlcnic_get_ethtool_stats,
1847aa43c215SJeff Kirsher .get_sset_count = qlcnic_get_sset_count,
1848aa43c215SJeff Kirsher .get_coalesce = qlcnic_get_intr_coalesce,
1849aa43c215SJeff Kirsher .set_coalesce = qlcnic_set_intr_coalesce,
1850aa43c215SJeff Kirsher .set_phys_id = qlcnic_set_led,
1851aa43c215SJeff Kirsher .set_msglevel = qlcnic_set_msglevel,
1852aa43c215SJeff Kirsher .get_msglevel = qlcnic_get_msglevel,
1853aa43c215SJeff Kirsher .get_dump_flag = qlcnic_get_dump_flag,
1854aa43c215SJeff Kirsher .get_dump_data = qlcnic_get_dump_data,
1855aa43c215SJeff Kirsher .set_dump = qlcnic_set_dump,
185649cef10fSPhilippe Reynes .get_link_ksettings = qlcnic_get_link_ksettings,
185749cef10fSPhilippe Reynes .set_link_ksettings = qlcnic_set_link_ksettings,
1858aa43c215SJeff Kirsher };
1859d1a1105eSRajesh Borundia
1860d1a1105eSRajesh Borundia const struct ethtool_ops qlcnic_sriov_vf_ethtool_ops = {
18614a988e31SJakub Kicinski .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
18624a988e31SJakub Kicinski ETHTOOL_COALESCE_MAX_FRAMES,
1863d1a1105eSRajesh Borundia .get_drvinfo = qlcnic_get_drvinfo,
1864d1a1105eSRajesh Borundia .get_regs_len = qlcnic_get_regs_len,
1865d1a1105eSRajesh Borundia .get_regs = qlcnic_get_regs,
1866d1a1105eSRajesh Borundia .get_link = ethtool_op_get_link,
1867d1a1105eSRajesh Borundia .get_eeprom_len = qlcnic_get_eeprom_len,
1868d1a1105eSRajesh Borundia .get_eeprom = qlcnic_get_eeprom,
1869d1a1105eSRajesh Borundia .get_ringparam = qlcnic_get_ringparam,
1870d1a1105eSRajesh Borundia .set_ringparam = qlcnic_set_ringparam,
1871d1a1105eSRajesh Borundia .get_channels = qlcnic_get_channels,
1872d1a1105eSRajesh Borundia .get_pauseparam = qlcnic_get_pauseparam,
1873d1a1105eSRajesh Borundia .get_wol = qlcnic_get_wol,
1874d1a1105eSRajesh Borundia .get_strings = qlcnic_get_strings,
1875d1a1105eSRajesh Borundia .get_ethtool_stats = qlcnic_get_ethtool_stats,
1876d1a1105eSRajesh Borundia .get_sset_count = qlcnic_get_sset_count,
1877d1a1105eSRajesh Borundia .get_coalesce = qlcnic_get_intr_coalesce,
1878d1a1105eSRajesh Borundia .set_coalesce = qlcnic_set_intr_coalesce,
1879d1a1105eSRajesh Borundia .set_msglevel = qlcnic_set_msglevel,
1880d1a1105eSRajesh Borundia .get_msglevel = qlcnic_get_msglevel,
188149cef10fSPhilippe Reynes .get_link_ksettings = qlcnic_get_link_ksettings,
1882d1a1105eSRajesh Borundia };
188366451615SSucheta Chakraborty
188466451615SSucheta Chakraborty const struct ethtool_ops qlcnic_ethtool_failed_ops = {
188566451615SSucheta Chakraborty .get_drvinfo = qlcnic_get_drvinfo,
188666451615SSucheta Chakraborty .set_msglevel = qlcnic_set_msglevel,
188766451615SSucheta Chakraborty .get_msglevel = qlcnic_get_msglevel,
188866451615SSucheta Chakraborty .set_dump = qlcnic_set_dump,
188949cef10fSPhilippe Reynes .get_link_ksettings = qlcnic_get_link_ksettings,
189066451615SSucheta Chakraborty };
1891