18b230ed8SRasesh Mody /* 28b230ed8SRasesh Mody * Linux network driver for Brocade Converged Network Adapter. 38b230ed8SRasesh Mody * 48b230ed8SRasesh Mody * This program is free software; you can redistribute it and/or modify it 58b230ed8SRasesh Mody * under the terms of the GNU General Public License (GPL) Version 2 as 68b230ed8SRasesh Mody * published by the Free Software Foundation 78b230ed8SRasesh Mody * 88b230ed8SRasesh Mody * This program is distributed in the hope that it will be useful, but 98b230ed8SRasesh Mody * WITHOUT ANY WARRANTY; without even the implied warranty of 108b230ed8SRasesh Mody * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 118b230ed8SRasesh Mody * General Public License for more details. 128b230ed8SRasesh Mody */ 138b230ed8SRasesh Mody /* 148b230ed8SRasesh Mody * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. 158b230ed8SRasesh Mody * All rights reserved 168b230ed8SRasesh Mody * www.brocade.com 178b230ed8SRasesh Mody */ 188b230ed8SRasesh Mody 198b230ed8SRasesh Mody #include "cna.h" 208b230ed8SRasesh Mody 218b230ed8SRasesh Mody #include <linux/netdevice.h> 228b230ed8SRasesh Mody #include <linux/skbuff.h> 238b230ed8SRasesh Mody #include <linux/ethtool.h> 248b230ed8SRasesh Mody #include <linux/rtnetlink.h> 258b230ed8SRasesh Mody 268b230ed8SRasesh Mody #include "bna.h" 278b230ed8SRasesh Mody 288b230ed8SRasesh Mody #include "bnad.h" 298b230ed8SRasesh Mody 308b230ed8SRasesh Mody #define BNAD_NUM_TXF_COUNTERS 12 318b230ed8SRasesh Mody #define BNAD_NUM_RXF_COUNTERS 10 32078086f3SRasesh Mody #define BNAD_NUM_CQ_COUNTERS (3 + 5) 338b230ed8SRasesh Mody #define BNAD_NUM_RXQ_COUNTERS 6 348b230ed8SRasesh Mody #define BNAD_NUM_TXQ_COUNTERS 5 358b230ed8SRasesh Mody 368b230ed8SRasesh Mody #define BNAD_ETHTOOL_STATS_NUM \ 37250e061eSEric Dumazet (sizeof(struct rtnl_link_stats64) / sizeof(u64) + \ 388b230ed8SRasesh Mody sizeof(struct bnad_drv_stats) / sizeof(u64) + \ 39078086f3SRasesh Mody offsetof(struct bfi_enet_stats, rxf_stats[0]) / sizeof(u64)) 408b230ed8SRasesh Mody 41975419cfSstephen hemminger static const char *bnad_net_stats_strings[BNAD_ETHTOOL_STATS_NUM] = { 428b230ed8SRasesh Mody "rx_packets", 438b230ed8SRasesh Mody "tx_packets", 448b230ed8SRasesh Mody "rx_bytes", 458b230ed8SRasesh Mody "tx_bytes", 468b230ed8SRasesh Mody "rx_errors", 478b230ed8SRasesh Mody "tx_errors", 488b230ed8SRasesh Mody "rx_dropped", 498b230ed8SRasesh Mody "tx_dropped", 508b230ed8SRasesh Mody "multicast", 518b230ed8SRasesh Mody "collisions", 528b230ed8SRasesh Mody 538b230ed8SRasesh Mody "rx_length_errors", 548b230ed8SRasesh Mody "rx_over_errors", 558b230ed8SRasesh Mody "rx_crc_errors", 568b230ed8SRasesh Mody "rx_frame_errors", 578b230ed8SRasesh Mody "rx_fifo_errors", 588b230ed8SRasesh Mody "rx_missed_errors", 598b230ed8SRasesh Mody 608b230ed8SRasesh Mody "tx_aborted_errors", 618b230ed8SRasesh Mody "tx_carrier_errors", 628b230ed8SRasesh Mody "tx_fifo_errors", 638b230ed8SRasesh Mody "tx_heartbeat_errors", 648b230ed8SRasesh Mody "tx_window_errors", 658b230ed8SRasesh Mody 668b230ed8SRasesh Mody "rx_compressed", 678b230ed8SRasesh Mody "tx_compressed", 688b230ed8SRasesh Mody 698b230ed8SRasesh Mody "netif_queue_stop", 708b230ed8SRasesh Mody "netif_queue_wakeup", 71f7c0fa4cSRasesh Mody "netif_queue_stopped", 728b230ed8SRasesh Mody "tso4", 738b230ed8SRasesh Mody "tso6", 748b230ed8SRasesh Mody "tso_err", 758b230ed8SRasesh Mody "tcpcsum_offload", 768b230ed8SRasesh Mody "udpcsum_offload", 778b230ed8SRasesh Mody "csum_help", 78a2122d95SRasesh Mody "tx_skb_too_short", 79a2122d95SRasesh Mody "tx_skb_stopping", 80a2122d95SRasesh Mody "tx_skb_max_vectors", 81a2122d95SRasesh Mody "tx_skb_mss_too_long", 82a2122d95SRasesh Mody "tx_skb_tso_too_short", 83a2122d95SRasesh Mody "tx_skb_tso_prepare", 84a2122d95SRasesh Mody "tx_skb_non_tso_too_long", 85a2122d95SRasesh Mody "tx_skb_tcp_hdr", 86a2122d95SRasesh Mody "tx_skb_udp_hdr", 87a2122d95SRasesh Mody "tx_skb_csum_err", 88a2122d95SRasesh Mody "tx_skb_headlen_too_long", 89a2122d95SRasesh Mody "tx_skb_headlen_zero", 90a2122d95SRasesh Mody "tx_skb_frag_zero", 91a2122d95SRasesh Mody "tx_skb_len_mismatch", 928b230ed8SRasesh Mody "hw_stats_updates", 938b230ed8SRasesh Mody "netif_rx_dropped", 948b230ed8SRasesh Mody 958b230ed8SRasesh Mody "link_toggle", 96a2122d95SRasesh Mody "cee_toggle", 978b230ed8SRasesh Mody 988b230ed8SRasesh Mody "rxp_info_alloc_failed", 998b230ed8SRasesh Mody "mbox_intr_disabled", 1008b230ed8SRasesh Mody "mbox_intr_enabled", 1018b230ed8SRasesh Mody "tx_unmap_q_alloc_failed", 1028b230ed8SRasesh Mody "rx_unmap_q_alloc_failed", 1038b230ed8SRasesh Mody "rxbuf_alloc_failed", 1048b230ed8SRasesh Mody 105478ab8c9SRasesh Mody "mac_stats_clr_cnt", 1068b230ed8SRasesh Mody "mac_frame_64", 1078b230ed8SRasesh Mody "mac_frame_65_127", 1088b230ed8SRasesh Mody "mac_frame_128_255", 1098b230ed8SRasesh Mody "mac_frame_256_511", 1108b230ed8SRasesh Mody "mac_frame_512_1023", 1118b230ed8SRasesh Mody "mac_frame_1024_1518", 1128b230ed8SRasesh Mody "mac_frame_1518_1522", 1138b230ed8SRasesh Mody "mac_rx_bytes", 1148b230ed8SRasesh Mody "mac_rx_packets", 1158b230ed8SRasesh Mody "mac_rx_fcs_error", 1168b230ed8SRasesh Mody "mac_rx_multicast", 1178b230ed8SRasesh Mody "mac_rx_broadcast", 1188b230ed8SRasesh Mody "mac_rx_control_frames", 1198b230ed8SRasesh Mody "mac_rx_pause", 1208b230ed8SRasesh Mody "mac_rx_unknown_opcode", 1218b230ed8SRasesh Mody "mac_rx_alignment_error", 1228b230ed8SRasesh Mody "mac_rx_frame_length_error", 1238b230ed8SRasesh Mody "mac_rx_code_error", 1248b230ed8SRasesh Mody "mac_rx_carrier_sense_error", 1258b230ed8SRasesh Mody "mac_rx_undersize", 1268b230ed8SRasesh Mody "mac_rx_oversize", 1278b230ed8SRasesh Mody "mac_rx_fragments", 1288b230ed8SRasesh Mody "mac_rx_jabber", 1298b230ed8SRasesh Mody "mac_rx_drop", 1308b230ed8SRasesh Mody 1318b230ed8SRasesh Mody "mac_tx_bytes", 1328b230ed8SRasesh Mody "mac_tx_packets", 1338b230ed8SRasesh Mody "mac_tx_multicast", 1348b230ed8SRasesh Mody "mac_tx_broadcast", 1358b230ed8SRasesh Mody "mac_tx_pause", 1368b230ed8SRasesh Mody "mac_tx_deferral", 1378b230ed8SRasesh Mody "mac_tx_excessive_deferral", 1388b230ed8SRasesh Mody "mac_tx_single_collision", 1398b230ed8SRasesh Mody "mac_tx_muliple_collision", 1408b230ed8SRasesh Mody "mac_tx_late_collision", 1418b230ed8SRasesh Mody "mac_tx_excessive_collision", 1428b230ed8SRasesh Mody "mac_tx_total_collision", 1438b230ed8SRasesh Mody "mac_tx_pause_honored", 1448b230ed8SRasesh Mody "mac_tx_drop", 1458b230ed8SRasesh Mody "mac_tx_jabber", 1468b230ed8SRasesh Mody "mac_tx_fcs_error", 1478b230ed8SRasesh Mody "mac_tx_control_frame", 1488b230ed8SRasesh Mody "mac_tx_oversize", 1498b230ed8SRasesh Mody "mac_tx_undersize", 1508b230ed8SRasesh Mody "mac_tx_fragments", 1518b230ed8SRasesh Mody 1528b230ed8SRasesh Mody "bpc_tx_pause_0", 1538b230ed8SRasesh Mody "bpc_tx_pause_1", 1548b230ed8SRasesh Mody "bpc_tx_pause_2", 1558b230ed8SRasesh Mody "bpc_tx_pause_3", 1568b230ed8SRasesh Mody "bpc_tx_pause_4", 1578b230ed8SRasesh Mody "bpc_tx_pause_5", 1588b230ed8SRasesh Mody "bpc_tx_pause_6", 1598b230ed8SRasesh Mody "bpc_tx_pause_7", 1608b230ed8SRasesh Mody "bpc_tx_zero_pause_0", 1618b230ed8SRasesh Mody "bpc_tx_zero_pause_1", 1628b230ed8SRasesh Mody "bpc_tx_zero_pause_2", 1638b230ed8SRasesh Mody "bpc_tx_zero_pause_3", 1648b230ed8SRasesh Mody "bpc_tx_zero_pause_4", 1658b230ed8SRasesh Mody "bpc_tx_zero_pause_5", 1668b230ed8SRasesh Mody "bpc_tx_zero_pause_6", 1678b230ed8SRasesh Mody "bpc_tx_zero_pause_7", 1688b230ed8SRasesh Mody "bpc_tx_first_pause_0", 1698b230ed8SRasesh Mody "bpc_tx_first_pause_1", 1708b230ed8SRasesh Mody "bpc_tx_first_pause_2", 1718b230ed8SRasesh Mody "bpc_tx_first_pause_3", 1728b230ed8SRasesh Mody "bpc_tx_first_pause_4", 1738b230ed8SRasesh Mody "bpc_tx_first_pause_5", 1748b230ed8SRasesh Mody "bpc_tx_first_pause_6", 1758b230ed8SRasesh Mody "bpc_tx_first_pause_7", 1768b230ed8SRasesh Mody 1778b230ed8SRasesh Mody "bpc_rx_pause_0", 1788b230ed8SRasesh Mody "bpc_rx_pause_1", 1798b230ed8SRasesh Mody "bpc_rx_pause_2", 1808b230ed8SRasesh Mody "bpc_rx_pause_3", 1818b230ed8SRasesh Mody "bpc_rx_pause_4", 1828b230ed8SRasesh Mody "bpc_rx_pause_5", 1838b230ed8SRasesh Mody "bpc_rx_pause_6", 1848b230ed8SRasesh Mody "bpc_rx_pause_7", 1858b230ed8SRasesh Mody "bpc_rx_zero_pause_0", 1868b230ed8SRasesh Mody "bpc_rx_zero_pause_1", 1878b230ed8SRasesh Mody "bpc_rx_zero_pause_2", 1888b230ed8SRasesh Mody "bpc_rx_zero_pause_3", 1898b230ed8SRasesh Mody "bpc_rx_zero_pause_4", 1908b230ed8SRasesh Mody "bpc_rx_zero_pause_5", 1918b230ed8SRasesh Mody "bpc_rx_zero_pause_6", 1928b230ed8SRasesh Mody "bpc_rx_zero_pause_7", 1938b230ed8SRasesh Mody "bpc_rx_first_pause_0", 1948b230ed8SRasesh Mody "bpc_rx_first_pause_1", 1958b230ed8SRasesh Mody "bpc_rx_first_pause_2", 1968b230ed8SRasesh Mody "bpc_rx_first_pause_3", 1978b230ed8SRasesh Mody "bpc_rx_first_pause_4", 1988b230ed8SRasesh Mody "bpc_rx_first_pause_5", 1998b230ed8SRasesh Mody "bpc_rx_first_pause_6", 2008b230ed8SRasesh Mody "bpc_rx_first_pause_7", 2018b230ed8SRasesh Mody 2028b230ed8SRasesh Mody "rad_rx_frames", 2038b230ed8SRasesh Mody "rad_rx_octets", 2048b230ed8SRasesh Mody "rad_rx_vlan_frames", 2058b230ed8SRasesh Mody "rad_rx_ucast", 2068b230ed8SRasesh Mody "rad_rx_ucast_octets", 2078b230ed8SRasesh Mody "rad_rx_ucast_vlan", 2088b230ed8SRasesh Mody "rad_rx_mcast", 2098b230ed8SRasesh Mody "rad_rx_mcast_octets", 2108b230ed8SRasesh Mody "rad_rx_mcast_vlan", 2118b230ed8SRasesh Mody "rad_rx_bcast", 2128b230ed8SRasesh Mody "rad_rx_bcast_octets", 2138b230ed8SRasesh Mody "rad_rx_bcast_vlan", 2148b230ed8SRasesh Mody "rad_rx_drops", 2158b230ed8SRasesh Mody 216a2122d95SRasesh Mody "rlb_rad_rx_frames", 217a2122d95SRasesh Mody "rlb_rad_rx_octets", 218a2122d95SRasesh Mody "rlb_rad_rx_vlan_frames", 219a2122d95SRasesh Mody "rlb_rad_rx_ucast", 220a2122d95SRasesh Mody "rlb_rad_rx_ucast_octets", 221a2122d95SRasesh Mody "rlb_rad_rx_ucast_vlan", 222a2122d95SRasesh Mody "rlb_rad_rx_mcast", 223a2122d95SRasesh Mody "rlb_rad_rx_mcast_octets", 224a2122d95SRasesh Mody "rlb_rad_rx_mcast_vlan", 225a2122d95SRasesh Mody "rlb_rad_rx_bcast", 226a2122d95SRasesh Mody "rlb_rad_rx_bcast_octets", 227a2122d95SRasesh Mody "rlb_rad_rx_bcast_vlan", 228a2122d95SRasesh Mody "rlb_rad_rx_drops", 229a2122d95SRasesh Mody 2308b230ed8SRasesh Mody "fc_rx_ucast_octets", 2318b230ed8SRasesh Mody "fc_rx_ucast", 2328b230ed8SRasesh Mody "fc_rx_ucast_vlan", 2338b230ed8SRasesh Mody "fc_rx_mcast_octets", 2348b230ed8SRasesh Mody "fc_rx_mcast", 2358b230ed8SRasesh Mody "fc_rx_mcast_vlan", 2368b230ed8SRasesh Mody "fc_rx_bcast_octets", 2378b230ed8SRasesh Mody "fc_rx_bcast", 2388b230ed8SRasesh Mody "fc_rx_bcast_vlan", 2398b230ed8SRasesh Mody 2408b230ed8SRasesh Mody "fc_tx_ucast_octets", 2418b230ed8SRasesh Mody "fc_tx_ucast", 2428b230ed8SRasesh Mody "fc_tx_ucast_vlan", 2438b230ed8SRasesh Mody "fc_tx_mcast_octets", 2448b230ed8SRasesh Mody "fc_tx_mcast", 2458b230ed8SRasesh Mody "fc_tx_mcast_vlan", 2468b230ed8SRasesh Mody "fc_tx_bcast_octets", 2478b230ed8SRasesh Mody "fc_tx_bcast", 2488b230ed8SRasesh Mody "fc_tx_bcast_vlan", 2498b230ed8SRasesh Mody "fc_tx_parity_errors", 2508b230ed8SRasesh Mody "fc_tx_timeout", 2518b230ed8SRasesh Mody "fc_tx_fid_parity_errors", 2528b230ed8SRasesh Mody }; 2538b230ed8SRasesh Mody 2548b230ed8SRasesh Mody static int 2558b230ed8SRasesh Mody bnad_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) 2568b230ed8SRasesh Mody { 2578b230ed8SRasesh Mody cmd->supported = SUPPORTED_10000baseT_Full; 2588b230ed8SRasesh Mody cmd->advertising = ADVERTISED_10000baseT_Full; 2598b230ed8SRasesh Mody cmd->autoneg = AUTONEG_DISABLE; 2608b230ed8SRasesh Mody cmd->supported |= SUPPORTED_FIBRE; 2618b230ed8SRasesh Mody cmd->advertising |= ADVERTISED_FIBRE; 2628b230ed8SRasesh Mody cmd->port = PORT_FIBRE; 2638b230ed8SRasesh Mody cmd->phy_address = 0; 2648b230ed8SRasesh Mody 2658b230ed8SRasesh Mody if (netif_carrier_ok(netdev)) { 26670739497SDavid Decotigny ethtool_cmd_speed_set(cmd, SPEED_10000); 2678b230ed8SRasesh Mody cmd->duplex = DUPLEX_FULL; 2688b230ed8SRasesh Mody } else { 26970739497SDavid Decotigny ethtool_cmd_speed_set(cmd, -1); 2708b230ed8SRasesh Mody cmd->duplex = -1; 2718b230ed8SRasesh Mody } 2728b230ed8SRasesh Mody cmd->transceiver = XCVR_EXTERNAL; 2738b230ed8SRasesh Mody cmd->maxtxpkt = 0; 2748b230ed8SRasesh Mody cmd->maxrxpkt = 0; 2758b230ed8SRasesh Mody 2768b230ed8SRasesh Mody return 0; 2778b230ed8SRasesh Mody } 2788b230ed8SRasesh Mody 2798b230ed8SRasesh Mody static int 2808b230ed8SRasesh Mody bnad_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd) 2818b230ed8SRasesh Mody { 2828b230ed8SRasesh Mody /* 10G full duplex setting supported only */ 2838b230ed8SRasesh Mody if (cmd->autoneg == AUTONEG_ENABLE) 2848b230ed8SRasesh Mody return -EOPNOTSUPP; else { 28525db0338SDavid Decotigny if ((ethtool_cmd_speed(cmd) == SPEED_10000) 28625db0338SDavid Decotigny && (cmd->duplex == DUPLEX_FULL)) 2878b230ed8SRasesh Mody return 0; 2888b230ed8SRasesh Mody } 2898b230ed8SRasesh Mody 2908b230ed8SRasesh Mody return -EOPNOTSUPP; 2918b230ed8SRasesh Mody } 2928b230ed8SRasesh Mody 2938b230ed8SRasesh Mody static void 2948b230ed8SRasesh Mody bnad_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) 2958b230ed8SRasesh Mody { 2968b230ed8SRasesh Mody struct bnad *bnad = netdev_priv(netdev); 2978b230ed8SRasesh Mody struct bfa_ioc_attr *ioc_attr; 2988b230ed8SRasesh Mody unsigned long flags; 2998b230ed8SRasesh Mody 30068aad78cSRick Jones strlcpy(drvinfo->driver, BNAD_NAME, sizeof(drvinfo->driver)); 30168aad78cSRick Jones strlcpy(drvinfo->version, BNAD_VERSION, sizeof(drvinfo->version)); 3028b230ed8SRasesh Mody 3038b230ed8SRasesh Mody ioc_attr = kzalloc(sizeof(*ioc_attr), GFP_KERNEL); 3048b230ed8SRasesh Mody if (ioc_attr) { 3058b230ed8SRasesh Mody spin_lock_irqsave(&bnad->bna_lock, flags); 306078086f3SRasesh Mody bfa_nw_ioc_get_attr(&bnad->bna.ioceth.ioc, ioc_attr); 3078b230ed8SRasesh Mody spin_unlock_irqrestore(&bnad->bna_lock, flags); 3088b230ed8SRasesh Mody 30968aad78cSRick Jones strlcpy(drvinfo->fw_version, ioc_attr->adapter_attr.fw_ver, 31068aad78cSRick Jones sizeof(drvinfo->fw_version)); 3118b230ed8SRasesh Mody kfree(ioc_attr); 3128b230ed8SRasesh Mody } 3138b230ed8SRasesh Mody 31468aad78cSRick Jones strlcpy(drvinfo->bus_info, pci_name(bnad->pcidev), 31568aad78cSRick Jones sizeof(drvinfo->bus_info)); 3168b230ed8SRasesh Mody } 3178b230ed8SRasesh Mody 3188b230ed8SRasesh Mody static void 3198b230ed8SRasesh Mody bnad_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wolinfo) 3208b230ed8SRasesh Mody { 3218b230ed8SRasesh Mody wolinfo->supported = 0; 3228b230ed8SRasesh Mody wolinfo->wolopts = 0; 3238b230ed8SRasesh Mody } 3248b230ed8SRasesh Mody 3258b230ed8SRasesh Mody static int 3268b230ed8SRasesh Mody bnad_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) 3278b230ed8SRasesh Mody { 3288b230ed8SRasesh Mody struct bnad *bnad = netdev_priv(netdev); 3298b230ed8SRasesh Mody unsigned long flags; 3308b230ed8SRasesh Mody 3318b230ed8SRasesh Mody /* Lock rqd. to access bnad->bna_lock */ 3328b230ed8SRasesh Mody spin_lock_irqsave(&bnad->bna_lock, flags); 3338b230ed8SRasesh Mody coalesce->use_adaptive_rx_coalesce = 3348b230ed8SRasesh Mody (bnad->cfg_flags & BNAD_CF_DIM_ENABLED) ? true : false; 3358b230ed8SRasesh Mody spin_unlock_irqrestore(&bnad->bna_lock, flags); 3368b230ed8SRasesh Mody 3378b230ed8SRasesh Mody coalesce->rx_coalesce_usecs = bnad->rx_coalescing_timeo * 3388b230ed8SRasesh Mody BFI_COALESCING_TIMER_UNIT; 3398b230ed8SRasesh Mody coalesce->tx_coalesce_usecs = bnad->tx_coalescing_timeo * 3408b230ed8SRasesh Mody BFI_COALESCING_TIMER_UNIT; 3418b230ed8SRasesh Mody coalesce->tx_max_coalesced_frames = BFI_TX_INTERPKT_COUNT; 3428b230ed8SRasesh Mody 3438b230ed8SRasesh Mody return 0; 3448b230ed8SRasesh Mody } 3458b230ed8SRasesh Mody 3468b230ed8SRasesh Mody static int 3478b230ed8SRasesh Mody bnad_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) 3488b230ed8SRasesh Mody { 3498b230ed8SRasesh Mody struct bnad *bnad = netdev_priv(netdev); 3508b230ed8SRasesh Mody unsigned long flags; 351a2122d95SRasesh Mody int to_del = 0; 3528b230ed8SRasesh Mody 3538b230ed8SRasesh Mody if (coalesce->rx_coalesce_usecs == 0 || 3548b230ed8SRasesh Mody coalesce->rx_coalesce_usecs > 3558b230ed8SRasesh Mody BFI_MAX_COALESCING_TIMEO * BFI_COALESCING_TIMER_UNIT) 3568b230ed8SRasesh Mody return -EINVAL; 3578b230ed8SRasesh Mody 3588b230ed8SRasesh Mody if (coalesce->tx_coalesce_usecs == 0 || 3598b230ed8SRasesh Mody coalesce->tx_coalesce_usecs > 3608b230ed8SRasesh Mody BFI_MAX_COALESCING_TIMEO * BFI_COALESCING_TIMER_UNIT) 3618b230ed8SRasesh Mody return -EINVAL; 3628b230ed8SRasesh Mody 3638b230ed8SRasesh Mody mutex_lock(&bnad->conf_mutex); 3648b230ed8SRasesh Mody /* 3658b230ed8SRasesh Mody * Do not need to store rx_coalesce_usecs here 3668b230ed8SRasesh Mody * Every time DIM is disabled, we can get it from the 3678b230ed8SRasesh Mody * stack. 3688b230ed8SRasesh Mody */ 3698b230ed8SRasesh Mody spin_lock_irqsave(&bnad->bna_lock, flags); 3708b230ed8SRasesh Mody if (coalesce->use_adaptive_rx_coalesce) { 3718b230ed8SRasesh Mody if (!(bnad->cfg_flags & BNAD_CF_DIM_ENABLED)) { 3728b230ed8SRasesh Mody bnad->cfg_flags |= BNAD_CF_DIM_ENABLED; 3738b230ed8SRasesh Mody bnad_dim_timer_start(bnad); 3748b230ed8SRasesh Mody } 3758b230ed8SRasesh Mody } else { 3768b230ed8SRasesh Mody if (bnad->cfg_flags & BNAD_CF_DIM_ENABLED) { 3778b230ed8SRasesh Mody bnad->cfg_flags &= ~BNAD_CF_DIM_ENABLED; 378a2122d95SRasesh Mody if (bnad->cfg_flags & BNAD_CF_DIM_ENABLED && 379a2122d95SRasesh Mody test_bit(BNAD_RF_DIM_TIMER_RUNNING, 380a2122d95SRasesh Mody &bnad->run_flags)) { 3818b230ed8SRasesh Mody clear_bit(BNAD_RF_DIM_TIMER_RUNNING, 3828b230ed8SRasesh Mody &bnad->run_flags); 383a2122d95SRasesh Mody to_del = 1; 384a2122d95SRasesh Mody } 3858b230ed8SRasesh Mody spin_unlock_irqrestore(&bnad->bna_lock, flags); 386a2122d95SRasesh Mody if (to_del) 3878b230ed8SRasesh Mody del_timer_sync(&bnad->dim_timer); 3888b230ed8SRasesh Mody spin_lock_irqsave(&bnad->bna_lock, flags); 3898b230ed8SRasesh Mody bnad_rx_coalescing_timeo_set(bnad); 3908b230ed8SRasesh Mody } 3918b230ed8SRasesh Mody } 3928b230ed8SRasesh Mody if (bnad->tx_coalescing_timeo != coalesce->tx_coalesce_usecs / 3938b230ed8SRasesh Mody BFI_COALESCING_TIMER_UNIT) { 3948b230ed8SRasesh Mody bnad->tx_coalescing_timeo = coalesce->tx_coalesce_usecs / 3958b230ed8SRasesh Mody BFI_COALESCING_TIMER_UNIT; 3968b230ed8SRasesh Mody bnad_tx_coalescing_timeo_set(bnad); 3978b230ed8SRasesh Mody } 3988b230ed8SRasesh Mody 3998b230ed8SRasesh Mody if (bnad->rx_coalescing_timeo != coalesce->rx_coalesce_usecs / 4008b230ed8SRasesh Mody BFI_COALESCING_TIMER_UNIT) { 4018b230ed8SRasesh Mody bnad->rx_coalescing_timeo = coalesce->rx_coalesce_usecs / 4028b230ed8SRasesh Mody BFI_COALESCING_TIMER_UNIT; 4038b230ed8SRasesh Mody 4048b230ed8SRasesh Mody if (!(bnad->cfg_flags & BNAD_CF_DIM_ENABLED)) 4058b230ed8SRasesh Mody bnad_rx_coalescing_timeo_set(bnad); 4068b230ed8SRasesh Mody 4078b230ed8SRasesh Mody } 4088b230ed8SRasesh Mody 4098b230ed8SRasesh Mody /* Add Tx Inter-pkt DMA count? */ 4108b230ed8SRasesh Mody 4118b230ed8SRasesh Mody spin_unlock_irqrestore(&bnad->bna_lock, flags); 4128b230ed8SRasesh Mody 4138b230ed8SRasesh Mody mutex_unlock(&bnad->conf_mutex); 4148b230ed8SRasesh Mody return 0; 4158b230ed8SRasesh Mody } 4168b230ed8SRasesh Mody 4178b230ed8SRasesh Mody static void 4188b230ed8SRasesh Mody bnad_get_ringparam(struct net_device *netdev, 4198b230ed8SRasesh Mody struct ethtool_ringparam *ringparam) 4208b230ed8SRasesh Mody { 4218b230ed8SRasesh Mody struct bnad *bnad = netdev_priv(netdev); 4228b230ed8SRasesh Mody 42341eb5ba4SRasesh Mody ringparam->rx_max_pending = BNAD_MAX_RXQ_DEPTH; 42441eb5ba4SRasesh Mody ringparam->tx_max_pending = BNAD_MAX_TXQ_DEPTH; 4258b230ed8SRasesh Mody 4268b230ed8SRasesh Mody ringparam->rx_pending = bnad->rxq_depth; 4278b230ed8SRasesh Mody ringparam->tx_pending = bnad->txq_depth; 4288b230ed8SRasesh Mody } 4298b230ed8SRasesh Mody 4308b230ed8SRasesh Mody static int 4318b230ed8SRasesh Mody bnad_set_ringparam(struct net_device *netdev, 4328b230ed8SRasesh Mody struct ethtool_ringparam *ringparam) 4338b230ed8SRasesh Mody { 4348b230ed8SRasesh Mody int i, current_err, err = 0; 4358b230ed8SRasesh Mody struct bnad *bnad = netdev_priv(netdev); 436a2122d95SRasesh Mody unsigned long flags; 4378b230ed8SRasesh Mody 4388b230ed8SRasesh Mody mutex_lock(&bnad->conf_mutex); 4398b230ed8SRasesh Mody if (ringparam->rx_pending == bnad->rxq_depth && 4408b230ed8SRasesh Mody ringparam->tx_pending == bnad->txq_depth) { 4418b230ed8SRasesh Mody mutex_unlock(&bnad->conf_mutex); 4428b230ed8SRasesh Mody return 0; 4438b230ed8SRasesh Mody } 4448b230ed8SRasesh Mody 4458b230ed8SRasesh Mody if (ringparam->rx_pending < BNAD_MIN_Q_DEPTH || 44641eb5ba4SRasesh Mody ringparam->rx_pending > BNAD_MAX_RXQ_DEPTH || 4478b230ed8SRasesh Mody !BNA_POWER_OF_2(ringparam->rx_pending)) { 4488b230ed8SRasesh Mody mutex_unlock(&bnad->conf_mutex); 4498b230ed8SRasesh Mody return -EINVAL; 4508b230ed8SRasesh Mody } 4518b230ed8SRasesh Mody if (ringparam->tx_pending < BNAD_MIN_Q_DEPTH || 45241eb5ba4SRasesh Mody ringparam->tx_pending > BNAD_MAX_TXQ_DEPTH || 4538b230ed8SRasesh Mody !BNA_POWER_OF_2(ringparam->tx_pending)) { 4548b230ed8SRasesh Mody mutex_unlock(&bnad->conf_mutex); 4558b230ed8SRasesh Mody return -EINVAL; 4568b230ed8SRasesh Mody } 4578b230ed8SRasesh Mody 4588b230ed8SRasesh Mody if (ringparam->rx_pending != bnad->rxq_depth) { 4598b230ed8SRasesh Mody bnad->rxq_depth = ringparam->rx_pending; 460a2122d95SRasesh Mody if (!netif_running(netdev)) { 461a2122d95SRasesh Mody mutex_unlock(&bnad->conf_mutex); 462a2122d95SRasesh Mody return 0; 463a2122d95SRasesh Mody } 464a2122d95SRasesh Mody 4658b230ed8SRasesh Mody for (i = 0; i < bnad->num_rx; i++) { 4668b230ed8SRasesh Mody if (!bnad->rx_info[i].rx) 4678b230ed8SRasesh Mody continue; 468b3cc6e88SJing Huang bnad_destroy_rx(bnad, i); 4698b230ed8SRasesh Mody current_err = bnad_setup_rx(bnad, i); 4708b230ed8SRasesh Mody if (current_err && !err) 4718b230ed8SRasesh Mody err = current_err; 472a2122d95SRasesh Mody } 473a2122d95SRasesh Mody 474a2122d95SRasesh Mody if (!err && bnad->rx_info[0].rx) { 475a2122d95SRasesh Mody /* restore rx configuration */ 4763fb9852fSRasesh Mody bnad_restore_vlans(bnad, 0); 477a2122d95SRasesh Mody bnad_enable_default_bcast(bnad); 478a2122d95SRasesh Mody spin_lock_irqsave(&bnad->bna_lock, flags); 479a2122d95SRasesh Mody bnad_mac_addr_set_locked(bnad, netdev->dev_addr); 480a2122d95SRasesh Mody spin_unlock_irqrestore(&bnad->bna_lock, flags); 4813fb9852fSRasesh Mody bnad->cfg_flags &= ~(BNAD_CF_ALLMULTI | 4823fb9852fSRasesh Mody BNAD_CF_PROMISC); 483a2122d95SRasesh Mody bnad_set_rx_mode(netdev); 4848b230ed8SRasesh Mody } 4858b230ed8SRasesh Mody } 4868b230ed8SRasesh Mody if (ringparam->tx_pending != bnad->txq_depth) { 4878b230ed8SRasesh Mody bnad->txq_depth = ringparam->tx_pending; 488a2122d95SRasesh Mody if (!netif_running(netdev)) { 489a2122d95SRasesh Mody mutex_unlock(&bnad->conf_mutex); 490a2122d95SRasesh Mody return 0; 491a2122d95SRasesh Mody } 492a2122d95SRasesh Mody 4938b230ed8SRasesh Mody for (i = 0; i < bnad->num_tx; i++) { 4948b230ed8SRasesh Mody if (!bnad->tx_info[i].tx) 4958b230ed8SRasesh Mody continue; 496b3cc6e88SJing Huang bnad_destroy_tx(bnad, i); 4978b230ed8SRasesh Mody current_err = bnad_setup_tx(bnad, i); 4988b230ed8SRasesh Mody if (current_err && !err) 4998b230ed8SRasesh Mody err = current_err; 5008b230ed8SRasesh Mody } 5018b230ed8SRasesh Mody } 5028b230ed8SRasesh Mody 5038b230ed8SRasesh Mody mutex_unlock(&bnad->conf_mutex); 5048b230ed8SRasesh Mody return err; 5058b230ed8SRasesh Mody } 5068b230ed8SRasesh Mody 5078b230ed8SRasesh Mody static void 5088b230ed8SRasesh Mody bnad_get_pauseparam(struct net_device *netdev, 5098b230ed8SRasesh Mody struct ethtool_pauseparam *pauseparam) 5108b230ed8SRasesh Mody { 5118b230ed8SRasesh Mody struct bnad *bnad = netdev_priv(netdev); 5128b230ed8SRasesh Mody 5138b230ed8SRasesh Mody pauseparam->autoneg = 0; 514078086f3SRasesh Mody pauseparam->rx_pause = bnad->bna.enet.pause_config.rx_pause; 515078086f3SRasesh Mody pauseparam->tx_pause = bnad->bna.enet.pause_config.tx_pause; 5168b230ed8SRasesh Mody } 5178b230ed8SRasesh Mody 5188b230ed8SRasesh Mody static int 5198b230ed8SRasesh Mody bnad_set_pauseparam(struct net_device *netdev, 5208b230ed8SRasesh Mody struct ethtool_pauseparam *pauseparam) 5218b230ed8SRasesh Mody { 5228b230ed8SRasesh Mody struct bnad *bnad = netdev_priv(netdev); 5238b230ed8SRasesh Mody struct bna_pause_config pause_config; 5248b230ed8SRasesh Mody unsigned long flags; 5258b230ed8SRasesh Mody 5268b230ed8SRasesh Mody if (pauseparam->autoneg == AUTONEG_ENABLE) 5278b230ed8SRasesh Mody return -EINVAL; 5288b230ed8SRasesh Mody 5298b230ed8SRasesh Mody mutex_lock(&bnad->conf_mutex); 530078086f3SRasesh Mody if (pauseparam->rx_pause != bnad->bna.enet.pause_config.rx_pause || 531078086f3SRasesh Mody pauseparam->tx_pause != bnad->bna.enet.pause_config.tx_pause) { 5328b230ed8SRasesh Mody pause_config.rx_pause = pauseparam->rx_pause; 5338b230ed8SRasesh Mody pause_config.tx_pause = pauseparam->tx_pause; 5348b230ed8SRasesh Mody spin_lock_irqsave(&bnad->bna_lock, flags); 535078086f3SRasesh Mody bna_enet_pause_config(&bnad->bna.enet, &pause_config, NULL); 5368b230ed8SRasesh Mody spin_unlock_irqrestore(&bnad->bna_lock, flags); 5378b230ed8SRasesh Mody } 5388b230ed8SRasesh Mody mutex_unlock(&bnad->conf_mutex); 5398b230ed8SRasesh Mody return 0; 5408b230ed8SRasesh Mody } 5418b230ed8SRasesh Mody 5428b230ed8SRasesh Mody static void 5438b230ed8SRasesh Mody bnad_get_strings(struct net_device *netdev, u32 stringset, u8 *string) 5448b230ed8SRasesh Mody { 5458b230ed8SRasesh Mody struct bnad *bnad = netdev_priv(netdev); 5468b230ed8SRasesh Mody int i, j, q_num; 547078086f3SRasesh Mody u32 bmap; 5488b230ed8SRasesh Mody 5498b230ed8SRasesh Mody mutex_lock(&bnad->conf_mutex); 5508b230ed8SRasesh Mody 5518b230ed8SRasesh Mody switch (stringset) { 5528b230ed8SRasesh Mody case ETH_SS_STATS: 5538b230ed8SRasesh Mody for (i = 0; i < BNAD_ETHTOOL_STATS_NUM; i++) { 5548b230ed8SRasesh Mody BUG_ON(!(strlen(bnad_net_stats_strings[i]) < 5558b230ed8SRasesh Mody ETH_GSTRING_LEN)); 5568b230ed8SRasesh Mody memcpy(string, bnad_net_stats_strings[i], 5578b230ed8SRasesh Mody ETH_GSTRING_LEN); 5588b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5598b230ed8SRasesh Mody } 560078086f3SRasesh Mody bmap = bna_tx_rid_mask(&bnad->bna); 561078086f3SRasesh Mody for (i = 0; bmap; i++) { 5628b230ed8SRasesh Mody if (bmap & 1) { 5638b230ed8SRasesh Mody sprintf(string, "txf%d_ucast_octets", i); 5648b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5658b230ed8SRasesh Mody sprintf(string, "txf%d_ucast", i); 5668b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5678b230ed8SRasesh Mody sprintf(string, "txf%d_ucast_vlan", i); 5688b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5698b230ed8SRasesh Mody sprintf(string, "txf%d_mcast_octets", i); 5708b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5718b230ed8SRasesh Mody sprintf(string, "txf%d_mcast", i); 5728b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5738b230ed8SRasesh Mody sprintf(string, "txf%d_mcast_vlan", i); 5748b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5758b230ed8SRasesh Mody sprintf(string, "txf%d_bcast_octets", i); 5768b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5778b230ed8SRasesh Mody sprintf(string, "txf%d_bcast", i); 5788b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5798b230ed8SRasesh Mody sprintf(string, "txf%d_bcast_vlan", i); 5808b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5818b230ed8SRasesh Mody sprintf(string, "txf%d_errors", i); 5828b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5838b230ed8SRasesh Mody sprintf(string, "txf%d_filter_vlan", i); 5848b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5858b230ed8SRasesh Mody sprintf(string, "txf%d_filter_mac_sa", i); 5868b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5878b230ed8SRasesh Mody } 5888b230ed8SRasesh Mody bmap >>= 1; 5898b230ed8SRasesh Mody } 5908b230ed8SRasesh Mody 591078086f3SRasesh Mody bmap = bna_rx_rid_mask(&bnad->bna); 592078086f3SRasesh Mody for (i = 0; bmap; i++) { 5938b230ed8SRasesh Mody if (bmap & 1) { 5948b230ed8SRasesh Mody sprintf(string, "rxf%d_ucast_octets", i); 5958b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5968b230ed8SRasesh Mody sprintf(string, "rxf%d_ucast", i); 5978b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5988b230ed8SRasesh Mody sprintf(string, "rxf%d_ucast_vlan", i); 5998b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6008b230ed8SRasesh Mody sprintf(string, "rxf%d_mcast_octets", i); 6018b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6028b230ed8SRasesh Mody sprintf(string, "rxf%d_mcast", i); 6038b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6048b230ed8SRasesh Mody sprintf(string, "rxf%d_mcast_vlan", i); 6058b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6068b230ed8SRasesh Mody sprintf(string, "rxf%d_bcast_octets", i); 6078b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6088b230ed8SRasesh Mody sprintf(string, "rxf%d_bcast", i); 6098b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6108b230ed8SRasesh Mody sprintf(string, "rxf%d_bcast_vlan", i); 6118b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6128b230ed8SRasesh Mody sprintf(string, "rxf%d_frame_drops", i); 6138b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6148b230ed8SRasesh Mody } 6158b230ed8SRasesh Mody bmap >>= 1; 6168b230ed8SRasesh Mody } 6178b230ed8SRasesh Mody 6188b230ed8SRasesh Mody q_num = 0; 6198b230ed8SRasesh Mody for (i = 0; i < bnad->num_rx; i++) { 6208b230ed8SRasesh Mody if (!bnad->rx_info[i].rx) 6218b230ed8SRasesh Mody continue; 6228b230ed8SRasesh Mody for (j = 0; j < bnad->num_rxp_per_rx; j++) { 6238b230ed8SRasesh Mody sprintf(string, "cq%d_producer_index", q_num); 6248b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6258b230ed8SRasesh Mody sprintf(string, "cq%d_consumer_index", q_num); 6268b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6278b230ed8SRasesh Mody sprintf(string, "cq%d_hw_producer_index", 6288b230ed8SRasesh Mody q_num); 6298b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 630a2122d95SRasesh Mody sprintf(string, "cq%d_intr", q_num); 631a2122d95SRasesh Mody string += ETH_GSTRING_LEN; 632a2122d95SRasesh Mody sprintf(string, "cq%d_poll", q_num); 633a2122d95SRasesh Mody string += ETH_GSTRING_LEN; 634a2122d95SRasesh Mody sprintf(string, "cq%d_schedule", q_num); 635a2122d95SRasesh Mody string += ETH_GSTRING_LEN; 636a2122d95SRasesh Mody sprintf(string, "cq%d_keep_poll", q_num); 637a2122d95SRasesh Mody string += ETH_GSTRING_LEN; 638a2122d95SRasesh Mody sprintf(string, "cq%d_complete", q_num); 639a2122d95SRasesh Mody string += ETH_GSTRING_LEN; 6408b230ed8SRasesh Mody q_num++; 6418b230ed8SRasesh Mody } 6428b230ed8SRasesh Mody } 6438b230ed8SRasesh Mody 6448b230ed8SRasesh Mody q_num = 0; 6458b230ed8SRasesh Mody for (i = 0; i < bnad->num_rx; i++) { 6468b230ed8SRasesh Mody if (!bnad->rx_info[i].rx) 6478b230ed8SRasesh Mody continue; 6488b230ed8SRasesh Mody for (j = 0; j < bnad->num_rxp_per_rx; j++) { 6498b230ed8SRasesh Mody sprintf(string, "rxq%d_packets", q_num); 6508b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6518b230ed8SRasesh Mody sprintf(string, "rxq%d_bytes", q_num); 6528b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6538b230ed8SRasesh Mody sprintf(string, "rxq%d_packets_with_error", 6548b230ed8SRasesh Mody q_num); 6558b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6568b230ed8SRasesh Mody sprintf(string, "rxq%d_allocbuf_failed", q_num); 6578b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6588b230ed8SRasesh Mody sprintf(string, "rxq%d_producer_index", q_num); 6598b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6608b230ed8SRasesh Mody sprintf(string, "rxq%d_consumer_index", q_num); 6618b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6628b230ed8SRasesh Mody q_num++; 6638b230ed8SRasesh Mody if (bnad->rx_info[i].rx_ctrl[j].ccb && 6648b230ed8SRasesh Mody bnad->rx_info[i].rx_ctrl[j].ccb-> 6658b230ed8SRasesh Mody rcb[1] && 6668b230ed8SRasesh Mody bnad->rx_info[i].rx_ctrl[j].ccb-> 6678b230ed8SRasesh Mody rcb[1]->rxq) { 6688b230ed8SRasesh Mody sprintf(string, "rxq%d_packets", q_num); 6698b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6708b230ed8SRasesh Mody sprintf(string, "rxq%d_bytes", q_num); 6718b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6728b230ed8SRasesh Mody sprintf(string, 6738b230ed8SRasesh Mody "rxq%d_packets_with_error", q_num); 6748b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6758b230ed8SRasesh Mody sprintf(string, "rxq%d_allocbuf_failed", 6768b230ed8SRasesh Mody q_num); 6778b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6788b230ed8SRasesh Mody sprintf(string, "rxq%d_producer_index", 6798b230ed8SRasesh Mody q_num); 6808b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6818b230ed8SRasesh Mody sprintf(string, "rxq%d_consumer_index", 6828b230ed8SRasesh Mody q_num); 6838b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6848b230ed8SRasesh Mody q_num++; 6858b230ed8SRasesh Mody } 6868b230ed8SRasesh Mody } 6878b230ed8SRasesh Mody } 6888b230ed8SRasesh Mody 6898b230ed8SRasesh Mody q_num = 0; 6908b230ed8SRasesh Mody for (i = 0; i < bnad->num_tx; i++) { 6918b230ed8SRasesh Mody if (!bnad->tx_info[i].tx) 6928b230ed8SRasesh Mody continue; 6938b230ed8SRasesh Mody for (j = 0; j < bnad->num_txq_per_tx; j++) { 6948b230ed8SRasesh Mody sprintf(string, "txq%d_packets", q_num); 6958b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6968b230ed8SRasesh Mody sprintf(string, "txq%d_bytes", q_num); 6978b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6988b230ed8SRasesh Mody sprintf(string, "txq%d_producer_index", q_num); 6998b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 7008b230ed8SRasesh Mody sprintf(string, "txq%d_consumer_index", q_num); 7018b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 7028b230ed8SRasesh Mody sprintf(string, "txq%d_hw_consumer_index", 7038b230ed8SRasesh Mody q_num); 7048b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 7058b230ed8SRasesh Mody q_num++; 7068b230ed8SRasesh Mody } 7078b230ed8SRasesh Mody } 7088b230ed8SRasesh Mody 7098b230ed8SRasesh Mody break; 7108b230ed8SRasesh Mody 7118b230ed8SRasesh Mody default: 7128b230ed8SRasesh Mody break; 7138b230ed8SRasesh Mody } 7148b230ed8SRasesh Mody 7158b230ed8SRasesh Mody mutex_unlock(&bnad->conf_mutex); 7168b230ed8SRasesh Mody } 7178b230ed8SRasesh Mody 7188b230ed8SRasesh Mody static int 7198b230ed8SRasesh Mody bnad_get_stats_count_locked(struct net_device *netdev) 7208b230ed8SRasesh Mody { 7218b230ed8SRasesh Mody struct bnad *bnad = netdev_priv(netdev); 722a2122d95SRasesh Mody int i, j, count = 0, rxf_active_num = 0, txf_active_num = 0; 723078086f3SRasesh Mody u32 bmap; 7248b230ed8SRasesh Mody 725078086f3SRasesh Mody bmap = bna_tx_rid_mask(&bnad->bna); 726078086f3SRasesh Mody for (i = 0; bmap; i++) { 7278b230ed8SRasesh Mody if (bmap & 1) 7288b230ed8SRasesh Mody txf_active_num++; 7298b230ed8SRasesh Mody bmap >>= 1; 7308b230ed8SRasesh Mody } 731078086f3SRasesh Mody bmap = bna_rx_rid_mask(&bnad->bna); 732078086f3SRasesh Mody for (i = 0; bmap; i++) { 7338b230ed8SRasesh Mody if (bmap & 1) 7348b230ed8SRasesh Mody rxf_active_num++; 7358b230ed8SRasesh Mody bmap >>= 1; 7368b230ed8SRasesh Mody } 7378b230ed8SRasesh Mody count = BNAD_ETHTOOL_STATS_NUM + 7388b230ed8SRasesh Mody txf_active_num * BNAD_NUM_TXF_COUNTERS + 7398b230ed8SRasesh Mody rxf_active_num * BNAD_NUM_RXF_COUNTERS; 7408b230ed8SRasesh Mody 7418b230ed8SRasesh Mody for (i = 0; i < bnad->num_rx; i++) { 7428b230ed8SRasesh Mody if (!bnad->rx_info[i].rx) 7438b230ed8SRasesh Mody continue; 7448b230ed8SRasesh Mody count += bnad->num_rxp_per_rx * BNAD_NUM_CQ_COUNTERS; 7458b230ed8SRasesh Mody count += bnad->num_rxp_per_rx * BNAD_NUM_RXQ_COUNTERS; 7468b230ed8SRasesh Mody for (j = 0; j < bnad->num_rxp_per_rx; j++) 7478b230ed8SRasesh Mody if (bnad->rx_info[i].rx_ctrl[j].ccb && 7488b230ed8SRasesh Mody bnad->rx_info[i].rx_ctrl[j].ccb->rcb[1] && 7498b230ed8SRasesh Mody bnad->rx_info[i].rx_ctrl[j].ccb->rcb[1]->rxq) 7508b230ed8SRasesh Mody count += BNAD_NUM_RXQ_COUNTERS; 7518b230ed8SRasesh Mody } 7528b230ed8SRasesh Mody 7538b230ed8SRasesh Mody for (i = 0; i < bnad->num_tx; i++) { 7548b230ed8SRasesh Mody if (!bnad->tx_info[i].tx) 7558b230ed8SRasesh Mody continue; 7568b230ed8SRasesh Mody count += bnad->num_txq_per_tx * BNAD_NUM_TXQ_COUNTERS; 7578b230ed8SRasesh Mody } 7588b230ed8SRasesh Mody return count; 7598b230ed8SRasesh Mody } 7608b230ed8SRasesh Mody 7618b230ed8SRasesh Mody static int 7628b230ed8SRasesh Mody bnad_per_q_stats_fill(struct bnad *bnad, u64 *buf, int bi) 7638b230ed8SRasesh Mody { 7648b230ed8SRasesh Mody int i, j; 7658b230ed8SRasesh Mody struct bna_rcb *rcb = NULL; 7668b230ed8SRasesh Mody struct bna_tcb *tcb = NULL; 7678b230ed8SRasesh Mody 7688b230ed8SRasesh Mody for (i = 0; i < bnad->num_rx; i++) { 7698b230ed8SRasesh Mody if (!bnad->rx_info[i].rx) 7708b230ed8SRasesh Mody continue; 7718b230ed8SRasesh Mody for (j = 0; j < bnad->num_rxp_per_rx; j++) 7728b230ed8SRasesh Mody if (bnad->rx_info[i].rx_ctrl[j].ccb && 7738b230ed8SRasesh Mody bnad->rx_info[i].rx_ctrl[j].ccb->rcb[0] && 7748b230ed8SRasesh Mody bnad->rx_info[i].rx_ctrl[j].ccb->rcb[0]->rxq) { 7758b230ed8SRasesh Mody buf[bi++] = bnad->rx_info[i].rx_ctrl[j]. 7768b230ed8SRasesh Mody ccb->producer_index; 7778b230ed8SRasesh Mody buf[bi++] = 0; /* ccb->consumer_index */ 7788b230ed8SRasesh Mody buf[bi++] = *(bnad->rx_info[i].rx_ctrl[j]. 7798b230ed8SRasesh Mody ccb->hw_producer_index); 780a2122d95SRasesh Mody 781a2122d95SRasesh Mody buf[bi++] = bnad->rx_info[i]. 782a2122d95SRasesh Mody rx_ctrl[j].rx_intr_ctr; 783a2122d95SRasesh Mody buf[bi++] = bnad->rx_info[i]. 784a2122d95SRasesh Mody rx_ctrl[j].rx_poll_ctr; 785a2122d95SRasesh Mody buf[bi++] = bnad->rx_info[i]. 786a2122d95SRasesh Mody rx_ctrl[j].rx_schedule; 787a2122d95SRasesh Mody buf[bi++] = bnad->rx_info[i]. 788a2122d95SRasesh Mody rx_ctrl[j].rx_keep_poll; 789a2122d95SRasesh Mody buf[bi++] = bnad->rx_info[i]. 790a2122d95SRasesh Mody rx_ctrl[j].rx_complete; 7918b230ed8SRasesh Mody } 7928b230ed8SRasesh Mody } 7938b230ed8SRasesh Mody for (i = 0; i < bnad->num_rx; i++) { 7948b230ed8SRasesh Mody if (!bnad->rx_info[i].rx) 7958b230ed8SRasesh Mody continue; 7968b230ed8SRasesh Mody for (j = 0; j < bnad->num_rxp_per_rx; j++) 7978b230ed8SRasesh Mody if (bnad->rx_info[i].rx_ctrl[j].ccb) { 7988b230ed8SRasesh Mody if (bnad->rx_info[i].rx_ctrl[j].ccb->rcb[0] && 7998b230ed8SRasesh Mody bnad->rx_info[i].rx_ctrl[j].ccb-> 8008b230ed8SRasesh Mody rcb[0]->rxq) { 8018b230ed8SRasesh Mody rcb = bnad->rx_info[i].rx_ctrl[j]. 8028b230ed8SRasesh Mody ccb->rcb[0]; 8038b230ed8SRasesh Mody buf[bi++] = rcb->rxq->rx_packets; 8048b230ed8SRasesh Mody buf[bi++] = rcb->rxq->rx_bytes; 8058b230ed8SRasesh Mody buf[bi++] = rcb->rxq-> 8068b230ed8SRasesh Mody rx_packets_with_error; 8078b230ed8SRasesh Mody buf[bi++] = rcb->rxq-> 8088b230ed8SRasesh Mody rxbuf_alloc_failed; 8098b230ed8SRasesh Mody buf[bi++] = rcb->producer_index; 8108b230ed8SRasesh Mody buf[bi++] = rcb->consumer_index; 8118b230ed8SRasesh Mody } 8128b230ed8SRasesh Mody if (bnad->rx_info[i].rx_ctrl[j].ccb->rcb[1] && 8138b230ed8SRasesh Mody bnad->rx_info[i].rx_ctrl[j].ccb-> 8148b230ed8SRasesh Mody rcb[1]->rxq) { 8158b230ed8SRasesh Mody rcb = bnad->rx_info[i].rx_ctrl[j]. 8168b230ed8SRasesh Mody ccb->rcb[1]; 8178b230ed8SRasesh Mody buf[bi++] = rcb->rxq->rx_packets; 8188b230ed8SRasesh Mody buf[bi++] = rcb->rxq->rx_bytes; 8198b230ed8SRasesh Mody buf[bi++] = rcb->rxq-> 8208b230ed8SRasesh Mody rx_packets_with_error; 8218b230ed8SRasesh Mody buf[bi++] = rcb->rxq-> 8228b230ed8SRasesh Mody rxbuf_alloc_failed; 8238b230ed8SRasesh Mody buf[bi++] = rcb->producer_index; 8248b230ed8SRasesh Mody buf[bi++] = rcb->consumer_index; 8258b230ed8SRasesh Mody } 8268b230ed8SRasesh Mody } 8278b230ed8SRasesh Mody } 8288b230ed8SRasesh Mody 8298b230ed8SRasesh Mody for (i = 0; i < bnad->num_tx; i++) { 8308b230ed8SRasesh Mody if (!bnad->tx_info[i].tx) 8318b230ed8SRasesh Mody continue; 8328b230ed8SRasesh Mody for (j = 0; j < bnad->num_txq_per_tx; j++) 8338b230ed8SRasesh Mody if (bnad->tx_info[i].tcb[j] && 8348b230ed8SRasesh Mody bnad->tx_info[i].tcb[j]->txq) { 8358b230ed8SRasesh Mody tcb = bnad->tx_info[i].tcb[j]; 8368b230ed8SRasesh Mody buf[bi++] = tcb->txq->tx_packets; 8378b230ed8SRasesh Mody buf[bi++] = tcb->txq->tx_bytes; 8388b230ed8SRasesh Mody buf[bi++] = tcb->producer_index; 8398b230ed8SRasesh Mody buf[bi++] = tcb->consumer_index; 8408b230ed8SRasesh Mody buf[bi++] = *(tcb->hw_consumer_index); 8418b230ed8SRasesh Mody } 8428b230ed8SRasesh Mody } 8438b230ed8SRasesh Mody 8448b230ed8SRasesh Mody return bi; 8458b230ed8SRasesh Mody } 8468b230ed8SRasesh Mody 8478b230ed8SRasesh Mody static void 8488b230ed8SRasesh Mody bnad_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, 8498b230ed8SRasesh Mody u64 *buf) 8508b230ed8SRasesh Mody { 8518b230ed8SRasesh Mody struct bnad *bnad = netdev_priv(netdev); 8528b230ed8SRasesh Mody int i, j, bi; 853250e061eSEric Dumazet unsigned long flags; 854250e061eSEric Dumazet struct rtnl_link_stats64 *net_stats64; 8558b230ed8SRasesh Mody u64 *stats64; 856078086f3SRasesh Mody u32 bmap; 8578b230ed8SRasesh Mody 8588b230ed8SRasesh Mody mutex_lock(&bnad->conf_mutex); 8598b230ed8SRasesh Mody if (bnad_get_stats_count_locked(netdev) != stats->n_stats) { 8608b230ed8SRasesh Mody mutex_unlock(&bnad->conf_mutex); 8618b230ed8SRasesh Mody return; 8628b230ed8SRasesh Mody } 8638b230ed8SRasesh Mody 8648b230ed8SRasesh Mody /* 8658b230ed8SRasesh Mody * Used bna_lock to sync reads from bna_stats, which is written 8668b230ed8SRasesh Mody * under the same lock 8678b230ed8SRasesh Mody */ 8688b230ed8SRasesh Mody spin_lock_irqsave(&bnad->bna_lock, flags); 8698b230ed8SRasesh Mody bi = 0; 8708b230ed8SRasesh Mody memset(buf, 0, stats->n_stats * sizeof(u64)); 8718b230ed8SRasesh Mody 872250e061eSEric Dumazet net_stats64 = (struct rtnl_link_stats64 *)buf; 873250e061eSEric Dumazet bnad_netdev_qstats_fill(bnad, net_stats64); 874250e061eSEric Dumazet bnad_netdev_hwstats_fill(bnad, net_stats64); 8758b230ed8SRasesh Mody 876250e061eSEric Dumazet bi = sizeof(*net_stats64) / sizeof(u64); 8778b230ed8SRasesh Mody 878f7c0fa4cSRasesh Mody /* Get netif_queue_stopped from stack */ 879f7c0fa4cSRasesh Mody bnad->stats.drv_stats.netif_queue_stopped = netif_queue_stopped(netdev); 880f7c0fa4cSRasesh Mody 8818b230ed8SRasesh Mody /* Fill driver stats into ethtool buffers */ 8828b230ed8SRasesh Mody stats64 = (u64 *)&bnad->stats.drv_stats; 8838b230ed8SRasesh Mody for (i = 0; i < sizeof(struct bnad_drv_stats) / sizeof(u64); i++) 8848b230ed8SRasesh Mody buf[bi++] = stats64[i]; 8858b230ed8SRasesh Mody 8868b230ed8SRasesh Mody /* Fill hardware stats excluding the rxf/txf into ethtool bufs */ 887078086f3SRasesh Mody stats64 = (u64 *) &bnad->stats.bna_stats->hw_stats; 8888b230ed8SRasesh Mody for (i = 0; 889078086f3SRasesh Mody i < offsetof(struct bfi_enet_stats, rxf_stats[0]) / 890078086f3SRasesh Mody sizeof(u64); 8918b230ed8SRasesh Mody i++) 8928b230ed8SRasesh Mody buf[bi++] = stats64[i]; 8938b230ed8SRasesh Mody 8948b230ed8SRasesh Mody /* Fill txf stats into ethtool buffers */ 895078086f3SRasesh Mody bmap = bna_tx_rid_mask(&bnad->bna); 896078086f3SRasesh Mody for (i = 0; bmap; i++) { 8978b230ed8SRasesh Mody if (bmap & 1) { 8988b230ed8SRasesh Mody stats64 = (u64 *)&bnad->stats.bna_stats-> 899078086f3SRasesh Mody hw_stats.txf_stats[i]; 900078086f3SRasesh Mody for (j = 0; j < sizeof(struct bfi_enet_stats_txf) / 9018b230ed8SRasesh Mody sizeof(u64); j++) 9028b230ed8SRasesh Mody buf[bi++] = stats64[j]; 9038b230ed8SRasesh Mody } 9048b230ed8SRasesh Mody bmap >>= 1; 9058b230ed8SRasesh Mody } 9068b230ed8SRasesh Mody 9078b230ed8SRasesh Mody /* Fill rxf stats into ethtool buffers */ 908078086f3SRasesh Mody bmap = bna_rx_rid_mask(&bnad->bna); 909078086f3SRasesh Mody for (i = 0; bmap; i++) { 9108b230ed8SRasesh Mody if (bmap & 1) { 9118b230ed8SRasesh Mody stats64 = (u64 *)&bnad->stats.bna_stats-> 912078086f3SRasesh Mody hw_stats.rxf_stats[i]; 913078086f3SRasesh Mody for (j = 0; j < sizeof(struct bfi_enet_stats_rxf) / 9148b230ed8SRasesh Mody sizeof(u64); j++) 9158b230ed8SRasesh Mody buf[bi++] = stats64[j]; 9168b230ed8SRasesh Mody } 9178b230ed8SRasesh Mody bmap >>= 1; 9188b230ed8SRasesh Mody } 9198b230ed8SRasesh Mody 9208b230ed8SRasesh Mody /* Fill per Q stats into ethtool buffers */ 9218b230ed8SRasesh Mody bi = bnad_per_q_stats_fill(bnad, buf, bi); 9228b230ed8SRasesh Mody 9238b230ed8SRasesh Mody spin_unlock_irqrestore(&bnad->bna_lock, flags); 9248b230ed8SRasesh Mody 9258b230ed8SRasesh Mody mutex_unlock(&bnad->conf_mutex); 9268b230ed8SRasesh Mody } 9278b230ed8SRasesh Mody 9288b230ed8SRasesh Mody static int 9298b230ed8SRasesh Mody bnad_get_sset_count(struct net_device *netdev, int sset) 9308b230ed8SRasesh Mody { 9318b230ed8SRasesh Mody switch (sset) { 9328b230ed8SRasesh Mody case ETH_SS_STATS: 9338b230ed8SRasesh Mody return bnad_get_stats_count_locked(netdev); 9348b230ed8SRasesh Mody default: 9358b230ed8SRasesh Mody return -EOPNOTSUPP; 9368b230ed8SRasesh Mody } 9378b230ed8SRasesh Mody } 9388b230ed8SRasesh Mody 93972a9730bSKrishna Gudipati static u32 94072a9730bSKrishna Gudipati bnad_get_flash_partition_by_offset(struct bnad *bnad, u32 offset, 94172a9730bSKrishna Gudipati u32 *base_offset) 94272a9730bSKrishna Gudipati { 94372a9730bSKrishna Gudipati struct bfa_flash_attr *flash_attr; 94472a9730bSKrishna Gudipati struct bnad_iocmd_comp fcomp; 94572a9730bSKrishna Gudipati u32 i, flash_part = 0, ret; 94672a9730bSKrishna Gudipati unsigned long flags = 0; 94772a9730bSKrishna Gudipati 94872a9730bSKrishna Gudipati flash_attr = kzalloc(sizeof(struct bfa_flash_attr), GFP_KERNEL); 94972a9730bSKrishna Gudipati if (!flash_attr) 950027a3b61SDan Carpenter return 0; 95172a9730bSKrishna Gudipati 95272a9730bSKrishna Gudipati fcomp.bnad = bnad; 95372a9730bSKrishna Gudipati fcomp.comp_status = 0; 95472a9730bSKrishna Gudipati 95572a9730bSKrishna Gudipati init_completion(&fcomp.comp); 95672a9730bSKrishna Gudipati spin_lock_irqsave(&bnad->bna_lock, flags); 95772a9730bSKrishna Gudipati ret = bfa_nw_flash_get_attr(&bnad->bna.flash, flash_attr, 95872a9730bSKrishna Gudipati bnad_cb_completion, &fcomp); 95972a9730bSKrishna Gudipati if (ret != BFA_STATUS_OK) { 96072a9730bSKrishna Gudipati spin_unlock_irqrestore(&bnad->bna_lock, flags); 96172a9730bSKrishna Gudipati kfree(flash_attr); 962027a3b61SDan Carpenter return 0; 96372a9730bSKrishna Gudipati } 96472a9730bSKrishna Gudipati spin_unlock_irqrestore(&bnad->bna_lock, flags); 96572a9730bSKrishna Gudipati wait_for_completion(&fcomp.comp); 96672a9730bSKrishna Gudipati ret = fcomp.comp_status; 96772a9730bSKrishna Gudipati 96872a9730bSKrishna Gudipati /* Check for the flash type & base offset value */ 96972a9730bSKrishna Gudipati if (ret == BFA_STATUS_OK) { 97072a9730bSKrishna Gudipati for (i = 0; i < flash_attr->npart; i++) { 97172a9730bSKrishna Gudipati if (offset >= flash_attr->part[i].part_off && 97272a9730bSKrishna Gudipati offset < (flash_attr->part[i].part_off + 97372a9730bSKrishna Gudipati flash_attr->part[i].part_size)) { 97472a9730bSKrishna Gudipati flash_part = flash_attr->part[i].part_type; 97572a9730bSKrishna Gudipati *base_offset = flash_attr->part[i].part_off; 97672a9730bSKrishna Gudipati break; 97772a9730bSKrishna Gudipati } 97872a9730bSKrishna Gudipati } 97972a9730bSKrishna Gudipati } 98072a9730bSKrishna Gudipati kfree(flash_attr); 98172a9730bSKrishna Gudipati return flash_part; 98272a9730bSKrishna Gudipati } 98372a9730bSKrishna Gudipati 98472a9730bSKrishna Gudipati static int 98572a9730bSKrishna Gudipati bnad_get_eeprom_len(struct net_device *netdev) 98672a9730bSKrishna Gudipati { 98772a9730bSKrishna Gudipati return BFA_TOTAL_FLASH_SIZE; 98872a9730bSKrishna Gudipati } 98972a9730bSKrishna Gudipati 99072a9730bSKrishna Gudipati static int 99172a9730bSKrishna Gudipati bnad_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, 99272a9730bSKrishna Gudipati u8 *bytes) 99372a9730bSKrishna Gudipati { 99472a9730bSKrishna Gudipati struct bnad *bnad = netdev_priv(netdev); 99572a9730bSKrishna Gudipati struct bnad_iocmd_comp fcomp; 99672a9730bSKrishna Gudipati u32 flash_part = 0, base_offset = 0; 99772a9730bSKrishna Gudipati unsigned long flags = 0; 99872a9730bSKrishna Gudipati int ret = 0; 99972a9730bSKrishna Gudipati 100072a9730bSKrishna Gudipati /* Check if the flash read request is valid */ 100172a9730bSKrishna Gudipati if (eeprom->magic != (bnad->pcidev->vendor | 100272a9730bSKrishna Gudipati (bnad->pcidev->device << 16))) 100372a9730bSKrishna Gudipati return -EFAULT; 100472a9730bSKrishna Gudipati 100572a9730bSKrishna Gudipati /* Query the flash partition based on the offset */ 100672a9730bSKrishna Gudipati flash_part = bnad_get_flash_partition_by_offset(bnad, 100772a9730bSKrishna Gudipati eeprom->offset, &base_offset); 1008027a3b61SDan Carpenter if (flash_part == 0) 100972a9730bSKrishna Gudipati return -EFAULT; 101072a9730bSKrishna Gudipati 101172a9730bSKrishna Gudipati fcomp.bnad = bnad; 101272a9730bSKrishna Gudipati fcomp.comp_status = 0; 101372a9730bSKrishna Gudipati 101472a9730bSKrishna Gudipati init_completion(&fcomp.comp); 101572a9730bSKrishna Gudipati spin_lock_irqsave(&bnad->bna_lock, flags); 101672a9730bSKrishna Gudipati ret = bfa_nw_flash_read_part(&bnad->bna.flash, flash_part, 101772a9730bSKrishna Gudipati bnad->id, bytes, eeprom->len, 101872a9730bSKrishna Gudipati eeprom->offset - base_offset, 101972a9730bSKrishna Gudipati bnad_cb_completion, &fcomp); 102072a9730bSKrishna Gudipati if (ret != BFA_STATUS_OK) { 102172a9730bSKrishna Gudipati spin_unlock_irqrestore(&bnad->bna_lock, flags); 102272a9730bSKrishna Gudipati goto done; 102372a9730bSKrishna Gudipati } 102472a9730bSKrishna Gudipati 102572a9730bSKrishna Gudipati spin_unlock_irqrestore(&bnad->bna_lock, flags); 102672a9730bSKrishna Gudipati wait_for_completion(&fcomp.comp); 102772a9730bSKrishna Gudipati ret = fcomp.comp_status; 102872a9730bSKrishna Gudipati done: 102972a9730bSKrishna Gudipati return ret; 103072a9730bSKrishna Gudipati } 103172a9730bSKrishna Gudipati 103272a9730bSKrishna Gudipati static int 103372a9730bSKrishna Gudipati bnad_set_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, 103472a9730bSKrishna Gudipati u8 *bytes) 103572a9730bSKrishna Gudipati { 103672a9730bSKrishna Gudipati struct bnad *bnad = netdev_priv(netdev); 103772a9730bSKrishna Gudipati struct bnad_iocmd_comp fcomp; 103872a9730bSKrishna Gudipati u32 flash_part = 0, base_offset = 0; 103972a9730bSKrishna Gudipati unsigned long flags = 0; 104072a9730bSKrishna Gudipati int ret = 0; 104172a9730bSKrishna Gudipati 104272a9730bSKrishna Gudipati /* Check if the flash update request is valid */ 104372a9730bSKrishna Gudipati if (eeprom->magic != (bnad->pcidev->vendor | 104472a9730bSKrishna Gudipati (bnad->pcidev->device << 16))) 104572a9730bSKrishna Gudipati return -EINVAL; 104672a9730bSKrishna Gudipati 104772a9730bSKrishna Gudipati /* Query the flash partition based on the offset */ 104872a9730bSKrishna Gudipati flash_part = bnad_get_flash_partition_by_offset(bnad, 104972a9730bSKrishna Gudipati eeprom->offset, &base_offset); 1050027a3b61SDan Carpenter if (flash_part == 0) 105172a9730bSKrishna Gudipati return -EFAULT; 105272a9730bSKrishna Gudipati 105372a9730bSKrishna Gudipati fcomp.bnad = bnad; 105472a9730bSKrishna Gudipati fcomp.comp_status = 0; 105572a9730bSKrishna Gudipati 105672a9730bSKrishna Gudipati init_completion(&fcomp.comp); 105772a9730bSKrishna Gudipati spin_lock_irqsave(&bnad->bna_lock, flags); 105872a9730bSKrishna Gudipati ret = bfa_nw_flash_update_part(&bnad->bna.flash, flash_part, 105972a9730bSKrishna Gudipati bnad->id, bytes, eeprom->len, 106072a9730bSKrishna Gudipati eeprom->offset - base_offset, 106172a9730bSKrishna Gudipati bnad_cb_completion, &fcomp); 106272a9730bSKrishna Gudipati if (ret != BFA_STATUS_OK) { 106372a9730bSKrishna Gudipati spin_unlock_irqrestore(&bnad->bna_lock, flags); 106472a9730bSKrishna Gudipati goto done; 106572a9730bSKrishna Gudipati } 106672a9730bSKrishna Gudipati 106772a9730bSKrishna Gudipati spin_unlock_irqrestore(&bnad->bna_lock, flags); 106872a9730bSKrishna Gudipati wait_for_completion(&fcomp.comp); 106972a9730bSKrishna Gudipati ret = fcomp.comp_status; 107072a9730bSKrishna Gudipati done: 107172a9730bSKrishna Gudipati return ret; 107272a9730bSKrishna Gudipati } 107372a9730bSKrishna Gudipati 107457b9bef0SKrishna Gudipati static int 107557b9bef0SKrishna Gudipati bnad_flash_device(struct net_device *netdev, struct ethtool_flash *eflash) 107657b9bef0SKrishna Gudipati { 107757b9bef0SKrishna Gudipati struct bnad *bnad = netdev_priv(netdev); 107857b9bef0SKrishna Gudipati struct bnad_iocmd_comp fcomp; 107957b9bef0SKrishna Gudipati const struct firmware *fw; 108057b9bef0SKrishna Gudipati int ret = 0; 108157b9bef0SKrishna Gudipati 108257b9bef0SKrishna Gudipati ret = request_firmware(&fw, eflash->data, &bnad->pcidev->dev); 108357b9bef0SKrishna Gudipati if (ret) { 108457b9bef0SKrishna Gudipati pr_err("BNA: Can't locate firmware %s\n", eflash->data); 108557b9bef0SKrishna Gudipati goto out; 108657b9bef0SKrishna Gudipati } 108757b9bef0SKrishna Gudipati 108857b9bef0SKrishna Gudipati fcomp.bnad = bnad; 108957b9bef0SKrishna Gudipati fcomp.comp_status = 0; 109057b9bef0SKrishna Gudipati 109157b9bef0SKrishna Gudipati init_completion(&fcomp.comp); 109257b9bef0SKrishna Gudipati spin_lock_irq(&bnad->bna_lock); 109357b9bef0SKrishna Gudipati ret = bfa_nw_flash_update_part(&bnad->bna.flash, BFA_FLASH_PART_FWIMG, 109457b9bef0SKrishna Gudipati bnad->id, (u8 *)fw->data, fw->size, 0, 109557b9bef0SKrishna Gudipati bnad_cb_completion, &fcomp); 109657b9bef0SKrishna Gudipati if (ret != BFA_STATUS_OK) { 109757b9bef0SKrishna Gudipati pr_warn("BNA: Flash update failed with err: %d\n", ret); 109857b9bef0SKrishna Gudipati ret = -EIO; 109957b9bef0SKrishna Gudipati spin_unlock_irq(&bnad->bna_lock); 110057b9bef0SKrishna Gudipati goto out; 110157b9bef0SKrishna Gudipati } 110257b9bef0SKrishna Gudipati 110357b9bef0SKrishna Gudipati spin_unlock_irq(&bnad->bna_lock); 110457b9bef0SKrishna Gudipati wait_for_completion(&fcomp.comp); 110557b9bef0SKrishna Gudipati if (fcomp.comp_status != BFA_STATUS_OK) { 110657b9bef0SKrishna Gudipati ret = -EIO; 110757b9bef0SKrishna Gudipati pr_warn("BNA: Firmware image update to flash failed with: %d\n", 110857b9bef0SKrishna Gudipati fcomp.comp_status); 110957b9bef0SKrishna Gudipati } 111057b9bef0SKrishna Gudipati out: 111157b9bef0SKrishna Gudipati release_firmware(fw); 111257b9bef0SKrishna Gudipati return ret; 111357b9bef0SKrishna Gudipati } 111457b9bef0SKrishna Gudipati 1115975419cfSstephen hemminger static const struct ethtool_ops bnad_ethtool_ops = { 11168b230ed8SRasesh Mody .get_settings = bnad_get_settings, 11178b230ed8SRasesh Mody .set_settings = bnad_set_settings, 11188b230ed8SRasesh Mody .get_drvinfo = bnad_get_drvinfo, 11198b230ed8SRasesh Mody .get_wol = bnad_get_wol, 11208b230ed8SRasesh Mody .get_link = ethtool_op_get_link, 11218b230ed8SRasesh Mody .get_coalesce = bnad_get_coalesce, 11228b230ed8SRasesh Mody .set_coalesce = bnad_set_coalesce, 11238b230ed8SRasesh Mody .get_ringparam = bnad_get_ringparam, 11248b230ed8SRasesh Mody .set_ringparam = bnad_set_ringparam, 11258b230ed8SRasesh Mody .get_pauseparam = bnad_get_pauseparam, 11268b230ed8SRasesh Mody .set_pauseparam = bnad_set_pauseparam, 11278b230ed8SRasesh Mody .get_strings = bnad_get_strings, 11288b230ed8SRasesh Mody .get_ethtool_stats = bnad_get_ethtool_stats, 112972a9730bSKrishna Gudipati .get_sset_count = bnad_get_sset_count, 113072a9730bSKrishna Gudipati .get_eeprom_len = bnad_get_eeprom_len, 113172a9730bSKrishna Gudipati .get_eeprom = bnad_get_eeprom, 113272a9730bSKrishna Gudipati .set_eeprom = bnad_set_eeprom, 113357b9bef0SKrishna Gudipati .flash_device = bnad_flash_device, 1134*fee1253eSRasesh Mody .get_ts_info = ethtool_op_get_ts_info, 11358b230ed8SRasesh Mody }; 11368b230ed8SRasesh Mody 11378b230ed8SRasesh Mody void 11388b230ed8SRasesh Mody bnad_set_ethtool_ops(struct net_device *netdev) 11398b230ed8SRasesh Mody { 11408b230ed8SRasesh Mody SET_ETHTOOL_OPS(netdev, &bnad_ethtool_ops); 11418b230ed8SRasesh Mody } 1142