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 1058b230ed8SRasesh Mody "mac_frame_64", 1068b230ed8SRasesh Mody "mac_frame_65_127", 1078b230ed8SRasesh Mody "mac_frame_128_255", 1088b230ed8SRasesh Mody "mac_frame_256_511", 1098b230ed8SRasesh Mody "mac_frame_512_1023", 1108b230ed8SRasesh Mody "mac_frame_1024_1518", 1118b230ed8SRasesh Mody "mac_frame_1518_1522", 1128b230ed8SRasesh Mody "mac_rx_bytes", 1138b230ed8SRasesh Mody "mac_rx_packets", 1148b230ed8SRasesh Mody "mac_rx_fcs_error", 1158b230ed8SRasesh Mody "mac_rx_multicast", 1168b230ed8SRasesh Mody "mac_rx_broadcast", 1178b230ed8SRasesh Mody "mac_rx_control_frames", 1188b230ed8SRasesh Mody "mac_rx_pause", 1198b230ed8SRasesh Mody "mac_rx_unknown_opcode", 1208b230ed8SRasesh Mody "mac_rx_alignment_error", 1218b230ed8SRasesh Mody "mac_rx_frame_length_error", 1228b230ed8SRasesh Mody "mac_rx_code_error", 1238b230ed8SRasesh Mody "mac_rx_carrier_sense_error", 1248b230ed8SRasesh Mody "mac_rx_undersize", 1258b230ed8SRasesh Mody "mac_rx_oversize", 1268b230ed8SRasesh Mody "mac_rx_fragments", 1278b230ed8SRasesh Mody "mac_rx_jabber", 1288b230ed8SRasesh Mody "mac_rx_drop", 1298b230ed8SRasesh Mody 1308b230ed8SRasesh Mody "mac_tx_bytes", 1318b230ed8SRasesh Mody "mac_tx_packets", 1328b230ed8SRasesh Mody "mac_tx_multicast", 1338b230ed8SRasesh Mody "mac_tx_broadcast", 1348b230ed8SRasesh Mody "mac_tx_pause", 1358b230ed8SRasesh Mody "mac_tx_deferral", 1368b230ed8SRasesh Mody "mac_tx_excessive_deferral", 1378b230ed8SRasesh Mody "mac_tx_single_collision", 1388b230ed8SRasesh Mody "mac_tx_muliple_collision", 1398b230ed8SRasesh Mody "mac_tx_late_collision", 1408b230ed8SRasesh Mody "mac_tx_excessive_collision", 1418b230ed8SRasesh Mody "mac_tx_total_collision", 1428b230ed8SRasesh Mody "mac_tx_pause_honored", 1438b230ed8SRasesh Mody "mac_tx_drop", 1448b230ed8SRasesh Mody "mac_tx_jabber", 1458b230ed8SRasesh Mody "mac_tx_fcs_error", 1468b230ed8SRasesh Mody "mac_tx_control_frame", 1478b230ed8SRasesh Mody "mac_tx_oversize", 1488b230ed8SRasesh Mody "mac_tx_undersize", 1498b230ed8SRasesh Mody "mac_tx_fragments", 1508b230ed8SRasesh Mody 1518b230ed8SRasesh Mody "bpc_tx_pause_0", 1528b230ed8SRasesh Mody "bpc_tx_pause_1", 1538b230ed8SRasesh Mody "bpc_tx_pause_2", 1548b230ed8SRasesh Mody "bpc_tx_pause_3", 1558b230ed8SRasesh Mody "bpc_tx_pause_4", 1568b230ed8SRasesh Mody "bpc_tx_pause_5", 1578b230ed8SRasesh Mody "bpc_tx_pause_6", 1588b230ed8SRasesh Mody "bpc_tx_pause_7", 1598b230ed8SRasesh Mody "bpc_tx_zero_pause_0", 1608b230ed8SRasesh Mody "bpc_tx_zero_pause_1", 1618b230ed8SRasesh Mody "bpc_tx_zero_pause_2", 1628b230ed8SRasesh Mody "bpc_tx_zero_pause_3", 1638b230ed8SRasesh Mody "bpc_tx_zero_pause_4", 1648b230ed8SRasesh Mody "bpc_tx_zero_pause_5", 1658b230ed8SRasesh Mody "bpc_tx_zero_pause_6", 1668b230ed8SRasesh Mody "bpc_tx_zero_pause_7", 1678b230ed8SRasesh Mody "bpc_tx_first_pause_0", 1688b230ed8SRasesh Mody "bpc_tx_first_pause_1", 1698b230ed8SRasesh Mody "bpc_tx_first_pause_2", 1708b230ed8SRasesh Mody "bpc_tx_first_pause_3", 1718b230ed8SRasesh Mody "bpc_tx_first_pause_4", 1728b230ed8SRasesh Mody "bpc_tx_first_pause_5", 1738b230ed8SRasesh Mody "bpc_tx_first_pause_6", 1748b230ed8SRasesh Mody "bpc_tx_first_pause_7", 1758b230ed8SRasesh Mody 1768b230ed8SRasesh Mody "bpc_rx_pause_0", 1778b230ed8SRasesh Mody "bpc_rx_pause_1", 1788b230ed8SRasesh Mody "bpc_rx_pause_2", 1798b230ed8SRasesh Mody "bpc_rx_pause_3", 1808b230ed8SRasesh Mody "bpc_rx_pause_4", 1818b230ed8SRasesh Mody "bpc_rx_pause_5", 1828b230ed8SRasesh Mody "bpc_rx_pause_6", 1838b230ed8SRasesh Mody "bpc_rx_pause_7", 1848b230ed8SRasesh Mody "bpc_rx_zero_pause_0", 1858b230ed8SRasesh Mody "bpc_rx_zero_pause_1", 1868b230ed8SRasesh Mody "bpc_rx_zero_pause_2", 1878b230ed8SRasesh Mody "bpc_rx_zero_pause_3", 1888b230ed8SRasesh Mody "bpc_rx_zero_pause_4", 1898b230ed8SRasesh Mody "bpc_rx_zero_pause_5", 1908b230ed8SRasesh Mody "bpc_rx_zero_pause_6", 1918b230ed8SRasesh Mody "bpc_rx_zero_pause_7", 1928b230ed8SRasesh Mody "bpc_rx_first_pause_0", 1938b230ed8SRasesh Mody "bpc_rx_first_pause_1", 1948b230ed8SRasesh Mody "bpc_rx_first_pause_2", 1958b230ed8SRasesh Mody "bpc_rx_first_pause_3", 1968b230ed8SRasesh Mody "bpc_rx_first_pause_4", 1978b230ed8SRasesh Mody "bpc_rx_first_pause_5", 1988b230ed8SRasesh Mody "bpc_rx_first_pause_6", 1998b230ed8SRasesh Mody "bpc_rx_first_pause_7", 2008b230ed8SRasesh Mody 2018b230ed8SRasesh Mody "rad_rx_frames", 2028b230ed8SRasesh Mody "rad_rx_octets", 2038b230ed8SRasesh Mody "rad_rx_vlan_frames", 2048b230ed8SRasesh Mody "rad_rx_ucast", 2058b230ed8SRasesh Mody "rad_rx_ucast_octets", 2068b230ed8SRasesh Mody "rad_rx_ucast_vlan", 2078b230ed8SRasesh Mody "rad_rx_mcast", 2088b230ed8SRasesh Mody "rad_rx_mcast_octets", 2098b230ed8SRasesh Mody "rad_rx_mcast_vlan", 2108b230ed8SRasesh Mody "rad_rx_bcast", 2118b230ed8SRasesh Mody "rad_rx_bcast_octets", 2128b230ed8SRasesh Mody "rad_rx_bcast_vlan", 2138b230ed8SRasesh Mody "rad_rx_drops", 2148b230ed8SRasesh Mody 215a2122d95SRasesh Mody "rlb_rad_rx_frames", 216a2122d95SRasesh Mody "rlb_rad_rx_octets", 217a2122d95SRasesh Mody "rlb_rad_rx_vlan_frames", 218a2122d95SRasesh Mody "rlb_rad_rx_ucast", 219a2122d95SRasesh Mody "rlb_rad_rx_ucast_octets", 220a2122d95SRasesh Mody "rlb_rad_rx_ucast_vlan", 221a2122d95SRasesh Mody "rlb_rad_rx_mcast", 222a2122d95SRasesh Mody "rlb_rad_rx_mcast_octets", 223a2122d95SRasesh Mody "rlb_rad_rx_mcast_vlan", 224a2122d95SRasesh Mody "rlb_rad_rx_bcast", 225a2122d95SRasesh Mody "rlb_rad_rx_bcast_octets", 226a2122d95SRasesh Mody "rlb_rad_rx_bcast_vlan", 227a2122d95SRasesh Mody "rlb_rad_rx_drops", 228a2122d95SRasesh Mody 2298b230ed8SRasesh Mody "fc_rx_ucast_octets", 2308b230ed8SRasesh Mody "fc_rx_ucast", 2318b230ed8SRasesh Mody "fc_rx_ucast_vlan", 2328b230ed8SRasesh Mody "fc_rx_mcast_octets", 2338b230ed8SRasesh Mody "fc_rx_mcast", 2348b230ed8SRasesh Mody "fc_rx_mcast_vlan", 2358b230ed8SRasesh Mody "fc_rx_bcast_octets", 2368b230ed8SRasesh Mody "fc_rx_bcast", 2378b230ed8SRasesh Mody "fc_rx_bcast_vlan", 2388b230ed8SRasesh Mody 2398b230ed8SRasesh Mody "fc_tx_ucast_octets", 2408b230ed8SRasesh Mody "fc_tx_ucast", 2418b230ed8SRasesh Mody "fc_tx_ucast_vlan", 2428b230ed8SRasesh Mody "fc_tx_mcast_octets", 2438b230ed8SRasesh Mody "fc_tx_mcast", 2448b230ed8SRasesh Mody "fc_tx_mcast_vlan", 2458b230ed8SRasesh Mody "fc_tx_bcast_octets", 2468b230ed8SRasesh Mody "fc_tx_bcast", 2478b230ed8SRasesh Mody "fc_tx_bcast_vlan", 2488b230ed8SRasesh Mody "fc_tx_parity_errors", 2498b230ed8SRasesh Mody "fc_tx_timeout", 2508b230ed8SRasesh Mody "fc_tx_fid_parity_errors", 2518b230ed8SRasesh Mody }; 2528b230ed8SRasesh Mody 2538b230ed8SRasesh Mody static int 2548b230ed8SRasesh Mody bnad_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) 2558b230ed8SRasesh Mody { 2568b230ed8SRasesh Mody cmd->supported = SUPPORTED_10000baseT_Full; 2578b230ed8SRasesh Mody cmd->advertising = ADVERTISED_10000baseT_Full; 2588b230ed8SRasesh Mody cmd->autoneg = AUTONEG_DISABLE; 2598b230ed8SRasesh Mody cmd->supported |= SUPPORTED_FIBRE; 2608b230ed8SRasesh Mody cmd->advertising |= ADVERTISED_FIBRE; 2618b230ed8SRasesh Mody cmd->port = PORT_FIBRE; 2628b230ed8SRasesh Mody cmd->phy_address = 0; 2638b230ed8SRasesh Mody 2648b230ed8SRasesh Mody if (netif_carrier_ok(netdev)) { 26570739497SDavid Decotigny ethtool_cmd_speed_set(cmd, SPEED_10000); 2668b230ed8SRasesh Mody cmd->duplex = DUPLEX_FULL; 2678b230ed8SRasesh Mody } else { 26870739497SDavid Decotigny ethtool_cmd_speed_set(cmd, -1); 2698b230ed8SRasesh Mody cmd->duplex = -1; 2708b230ed8SRasesh Mody } 2718b230ed8SRasesh Mody cmd->transceiver = XCVR_EXTERNAL; 2728b230ed8SRasesh Mody cmd->maxtxpkt = 0; 2738b230ed8SRasesh Mody cmd->maxrxpkt = 0; 2748b230ed8SRasesh Mody 2758b230ed8SRasesh Mody return 0; 2768b230ed8SRasesh Mody } 2778b230ed8SRasesh Mody 2788b230ed8SRasesh Mody static int 2798b230ed8SRasesh Mody bnad_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd) 2808b230ed8SRasesh Mody { 2818b230ed8SRasesh Mody /* 10G full duplex setting supported only */ 2828b230ed8SRasesh Mody if (cmd->autoneg == AUTONEG_ENABLE) 2838b230ed8SRasesh Mody return -EOPNOTSUPP; else { 28425db0338SDavid Decotigny if ((ethtool_cmd_speed(cmd) == SPEED_10000) 28525db0338SDavid Decotigny && (cmd->duplex == DUPLEX_FULL)) 2868b230ed8SRasesh Mody return 0; 2878b230ed8SRasesh Mody } 2888b230ed8SRasesh Mody 2898b230ed8SRasesh Mody return -EOPNOTSUPP; 2908b230ed8SRasesh Mody } 2918b230ed8SRasesh Mody 2928b230ed8SRasesh Mody static void 2938b230ed8SRasesh Mody bnad_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) 2948b230ed8SRasesh Mody { 2958b230ed8SRasesh Mody struct bnad *bnad = netdev_priv(netdev); 2968b230ed8SRasesh Mody struct bfa_ioc_attr *ioc_attr; 2978b230ed8SRasesh Mody unsigned long flags; 2988b230ed8SRasesh Mody 29968aad78cSRick Jones strlcpy(drvinfo->driver, BNAD_NAME, sizeof(drvinfo->driver)); 30068aad78cSRick Jones strlcpy(drvinfo->version, BNAD_VERSION, sizeof(drvinfo->version)); 3018b230ed8SRasesh Mody 3028b230ed8SRasesh Mody ioc_attr = kzalloc(sizeof(*ioc_attr), GFP_KERNEL); 3038b230ed8SRasesh Mody if (ioc_attr) { 3048b230ed8SRasesh Mody spin_lock_irqsave(&bnad->bna_lock, flags); 305078086f3SRasesh Mody bfa_nw_ioc_get_attr(&bnad->bna.ioceth.ioc, ioc_attr); 3068b230ed8SRasesh Mody spin_unlock_irqrestore(&bnad->bna_lock, flags); 3078b230ed8SRasesh Mody 30868aad78cSRick Jones strlcpy(drvinfo->fw_version, ioc_attr->adapter_attr.fw_ver, 30968aad78cSRick Jones sizeof(drvinfo->fw_version)); 3108b230ed8SRasesh Mody kfree(ioc_attr); 3118b230ed8SRasesh Mody } 3128b230ed8SRasesh Mody 31368aad78cSRick Jones strlcpy(drvinfo->bus_info, pci_name(bnad->pcidev), 31468aad78cSRick Jones sizeof(drvinfo->bus_info)); 3158b230ed8SRasesh Mody } 3168b230ed8SRasesh Mody 3178b230ed8SRasesh Mody static void 3188b230ed8SRasesh Mody bnad_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wolinfo) 3198b230ed8SRasesh Mody { 3208b230ed8SRasesh Mody wolinfo->supported = 0; 3218b230ed8SRasesh Mody wolinfo->wolopts = 0; 3228b230ed8SRasesh Mody } 3238b230ed8SRasesh Mody 3248b230ed8SRasesh Mody static int 3258b230ed8SRasesh Mody bnad_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) 3268b230ed8SRasesh Mody { 3278b230ed8SRasesh Mody struct bnad *bnad = netdev_priv(netdev); 3288b230ed8SRasesh Mody unsigned long flags; 3298b230ed8SRasesh Mody 3308b230ed8SRasesh Mody /* Lock rqd. to access bnad->bna_lock */ 3318b230ed8SRasesh Mody spin_lock_irqsave(&bnad->bna_lock, flags); 3328b230ed8SRasesh Mody coalesce->use_adaptive_rx_coalesce = 3338b230ed8SRasesh Mody (bnad->cfg_flags & BNAD_CF_DIM_ENABLED) ? true : false; 3348b230ed8SRasesh Mody spin_unlock_irqrestore(&bnad->bna_lock, flags); 3358b230ed8SRasesh Mody 3368b230ed8SRasesh Mody coalesce->rx_coalesce_usecs = bnad->rx_coalescing_timeo * 3378b230ed8SRasesh Mody BFI_COALESCING_TIMER_UNIT; 3388b230ed8SRasesh Mody coalesce->tx_coalesce_usecs = bnad->tx_coalescing_timeo * 3398b230ed8SRasesh Mody BFI_COALESCING_TIMER_UNIT; 3408b230ed8SRasesh Mody coalesce->tx_max_coalesced_frames = BFI_TX_INTERPKT_COUNT; 3418b230ed8SRasesh Mody 3428b230ed8SRasesh Mody return 0; 3438b230ed8SRasesh Mody } 3448b230ed8SRasesh Mody 3458b230ed8SRasesh Mody static int 3468b230ed8SRasesh Mody bnad_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) 3478b230ed8SRasesh Mody { 3488b230ed8SRasesh Mody struct bnad *bnad = netdev_priv(netdev); 3498b230ed8SRasesh Mody unsigned long flags; 350a2122d95SRasesh Mody int to_del = 0; 3518b230ed8SRasesh Mody 3528b230ed8SRasesh Mody if (coalesce->rx_coalesce_usecs == 0 || 3538b230ed8SRasesh Mody coalesce->rx_coalesce_usecs > 3548b230ed8SRasesh Mody BFI_MAX_COALESCING_TIMEO * BFI_COALESCING_TIMER_UNIT) 3558b230ed8SRasesh Mody return -EINVAL; 3568b230ed8SRasesh Mody 3578b230ed8SRasesh Mody if (coalesce->tx_coalesce_usecs == 0 || 3588b230ed8SRasesh Mody coalesce->tx_coalesce_usecs > 3598b230ed8SRasesh Mody BFI_MAX_COALESCING_TIMEO * BFI_COALESCING_TIMER_UNIT) 3608b230ed8SRasesh Mody return -EINVAL; 3618b230ed8SRasesh Mody 3628b230ed8SRasesh Mody mutex_lock(&bnad->conf_mutex); 3638b230ed8SRasesh Mody /* 3648b230ed8SRasesh Mody * Do not need to store rx_coalesce_usecs here 3658b230ed8SRasesh Mody * Every time DIM is disabled, we can get it from the 3668b230ed8SRasesh Mody * stack. 3678b230ed8SRasesh Mody */ 3688b230ed8SRasesh Mody spin_lock_irqsave(&bnad->bna_lock, flags); 3698b230ed8SRasesh Mody if (coalesce->use_adaptive_rx_coalesce) { 3708b230ed8SRasesh Mody if (!(bnad->cfg_flags & BNAD_CF_DIM_ENABLED)) { 3718b230ed8SRasesh Mody bnad->cfg_flags |= BNAD_CF_DIM_ENABLED; 3728b230ed8SRasesh Mody bnad_dim_timer_start(bnad); 3738b230ed8SRasesh Mody } 3748b230ed8SRasesh Mody } else { 3758b230ed8SRasesh Mody if (bnad->cfg_flags & BNAD_CF_DIM_ENABLED) { 3768b230ed8SRasesh Mody bnad->cfg_flags &= ~BNAD_CF_DIM_ENABLED; 377a2122d95SRasesh Mody if (bnad->cfg_flags & BNAD_CF_DIM_ENABLED && 378a2122d95SRasesh Mody test_bit(BNAD_RF_DIM_TIMER_RUNNING, 379a2122d95SRasesh Mody &bnad->run_flags)) { 3808b230ed8SRasesh Mody clear_bit(BNAD_RF_DIM_TIMER_RUNNING, 3818b230ed8SRasesh Mody &bnad->run_flags); 382a2122d95SRasesh Mody to_del = 1; 383a2122d95SRasesh Mody } 3848b230ed8SRasesh Mody spin_unlock_irqrestore(&bnad->bna_lock, flags); 385a2122d95SRasesh Mody if (to_del) 3868b230ed8SRasesh Mody del_timer_sync(&bnad->dim_timer); 3878b230ed8SRasesh Mody spin_lock_irqsave(&bnad->bna_lock, flags); 3888b230ed8SRasesh Mody bnad_rx_coalescing_timeo_set(bnad); 3898b230ed8SRasesh Mody } 3908b230ed8SRasesh Mody } 3918b230ed8SRasesh Mody if (bnad->tx_coalescing_timeo != coalesce->tx_coalesce_usecs / 3928b230ed8SRasesh Mody BFI_COALESCING_TIMER_UNIT) { 3938b230ed8SRasesh Mody bnad->tx_coalescing_timeo = coalesce->tx_coalesce_usecs / 3948b230ed8SRasesh Mody BFI_COALESCING_TIMER_UNIT; 3958b230ed8SRasesh Mody bnad_tx_coalescing_timeo_set(bnad); 3968b230ed8SRasesh Mody } 3978b230ed8SRasesh Mody 3988b230ed8SRasesh Mody if (bnad->rx_coalescing_timeo != coalesce->rx_coalesce_usecs / 3998b230ed8SRasesh Mody BFI_COALESCING_TIMER_UNIT) { 4008b230ed8SRasesh Mody bnad->rx_coalescing_timeo = coalesce->rx_coalesce_usecs / 4018b230ed8SRasesh Mody BFI_COALESCING_TIMER_UNIT; 4028b230ed8SRasesh Mody 4038b230ed8SRasesh Mody if (!(bnad->cfg_flags & BNAD_CF_DIM_ENABLED)) 4048b230ed8SRasesh Mody bnad_rx_coalescing_timeo_set(bnad); 4058b230ed8SRasesh Mody 4068b230ed8SRasesh Mody } 4078b230ed8SRasesh Mody 4088b230ed8SRasesh Mody /* Add Tx Inter-pkt DMA count? */ 4098b230ed8SRasesh Mody 4108b230ed8SRasesh Mody spin_unlock_irqrestore(&bnad->bna_lock, flags); 4118b230ed8SRasesh Mody 4128b230ed8SRasesh Mody mutex_unlock(&bnad->conf_mutex); 4138b230ed8SRasesh Mody return 0; 4148b230ed8SRasesh Mody } 4158b230ed8SRasesh Mody 4168b230ed8SRasesh Mody static void 4178b230ed8SRasesh Mody bnad_get_ringparam(struct net_device *netdev, 4188b230ed8SRasesh Mody struct ethtool_ringparam *ringparam) 4198b230ed8SRasesh Mody { 4208b230ed8SRasesh Mody struct bnad *bnad = netdev_priv(netdev); 4218b230ed8SRasesh Mody 42241eb5ba4SRasesh Mody ringparam->rx_max_pending = BNAD_MAX_RXQ_DEPTH; 42341eb5ba4SRasesh Mody ringparam->tx_max_pending = BNAD_MAX_TXQ_DEPTH; 4248b230ed8SRasesh Mody 4258b230ed8SRasesh Mody ringparam->rx_pending = bnad->rxq_depth; 4268b230ed8SRasesh Mody ringparam->tx_pending = bnad->txq_depth; 4278b230ed8SRasesh Mody } 4288b230ed8SRasesh Mody 4298b230ed8SRasesh Mody static int 4308b230ed8SRasesh Mody bnad_set_ringparam(struct net_device *netdev, 4318b230ed8SRasesh Mody struct ethtool_ringparam *ringparam) 4328b230ed8SRasesh Mody { 4338b230ed8SRasesh Mody int i, current_err, err = 0; 4348b230ed8SRasesh Mody struct bnad *bnad = netdev_priv(netdev); 435a2122d95SRasesh Mody unsigned long flags; 4368b230ed8SRasesh Mody 4378b230ed8SRasesh Mody mutex_lock(&bnad->conf_mutex); 4388b230ed8SRasesh Mody if (ringparam->rx_pending == bnad->rxq_depth && 4398b230ed8SRasesh Mody ringparam->tx_pending == bnad->txq_depth) { 4408b230ed8SRasesh Mody mutex_unlock(&bnad->conf_mutex); 4418b230ed8SRasesh Mody return 0; 4428b230ed8SRasesh Mody } 4438b230ed8SRasesh Mody 4448b230ed8SRasesh Mody if (ringparam->rx_pending < BNAD_MIN_Q_DEPTH || 44541eb5ba4SRasesh Mody ringparam->rx_pending > BNAD_MAX_RXQ_DEPTH || 4468b230ed8SRasesh Mody !BNA_POWER_OF_2(ringparam->rx_pending)) { 4478b230ed8SRasesh Mody mutex_unlock(&bnad->conf_mutex); 4488b230ed8SRasesh Mody return -EINVAL; 4498b230ed8SRasesh Mody } 4508b230ed8SRasesh Mody if (ringparam->tx_pending < BNAD_MIN_Q_DEPTH || 45141eb5ba4SRasesh Mody ringparam->tx_pending > BNAD_MAX_TXQ_DEPTH || 4528b230ed8SRasesh Mody !BNA_POWER_OF_2(ringparam->tx_pending)) { 4538b230ed8SRasesh Mody mutex_unlock(&bnad->conf_mutex); 4548b230ed8SRasesh Mody return -EINVAL; 4558b230ed8SRasesh Mody } 4568b230ed8SRasesh Mody 4578b230ed8SRasesh Mody if (ringparam->rx_pending != bnad->rxq_depth) { 4588b230ed8SRasesh Mody bnad->rxq_depth = ringparam->rx_pending; 459a2122d95SRasesh Mody if (!netif_running(netdev)) { 460a2122d95SRasesh Mody mutex_unlock(&bnad->conf_mutex); 461a2122d95SRasesh Mody return 0; 462a2122d95SRasesh Mody } 463a2122d95SRasesh Mody 4648b230ed8SRasesh Mody for (i = 0; i < bnad->num_rx; i++) { 4658b230ed8SRasesh Mody if (!bnad->rx_info[i].rx) 4668b230ed8SRasesh Mody continue; 467*b3cc6e88SJing Huang bnad_destroy_rx(bnad, i); 4688b230ed8SRasesh Mody current_err = bnad_setup_rx(bnad, i); 4698b230ed8SRasesh Mody if (current_err && !err) 4708b230ed8SRasesh Mody err = current_err; 471a2122d95SRasesh Mody } 472a2122d95SRasesh Mody 473a2122d95SRasesh Mody if (!err && bnad->rx_info[0].rx) { 474a2122d95SRasesh Mody /* restore rx configuration */ 4753fb9852fSRasesh Mody bnad_restore_vlans(bnad, 0); 476a2122d95SRasesh Mody bnad_enable_default_bcast(bnad); 477a2122d95SRasesh Mody spin_lock_irqsave(&bnad->bna_lock, flags); 478a2122d95SRasesh Mody bnad_mac_addr_set_locked(bnad, netdev->dev_addr); 479a2122d95SRasesh Mody spin_unlock_irqrestore(&bnad->bna_lock, flags); 4803fb9852fSRasesh Mody bnad->cfg_flags &= ~(BNAD_CF_ALLMULTI | 4813fb9852fSRasesh Mody BNAD_CF_PROMISC); 482a2122d95SRasesh Mody bnad_set_rx_mode(netdev); 4838b230ed8SRasesh Mody } 4848b230ed8SRasesh Mody } 4858b230ed8SRasesh Mody if (ringparam->tx_pending != bnad->txq_depth) { 4868b230ed8SRasesh Mody bnad->txq_depth = ringparam->tx_pending; 487a2122d95SRasesh Mody if (!netif_running(netdev)) { 488a2122d95SRasesh Mody mutex_unlock(&bnad->conf_mutex); 489a2122d95SRasesh Mody return 0; 490a2122d95SRasesh Mody } 491a2122d95SRasesh Mody 4928b230ed8SRasesh Mody for (i = 0; i < bnad->num_tx; i++) { 4938b230ed8SRasesh Mody if (!bnad->tx_info[i].tx) 4948b230ed8SRasesh Mody continue; 495*b3cc6e88SJing Huang bnad_destroy_tx(bnad, i); 4968b230ed8SRasesh Mody current_err = bnad_setup_tx(bnad, i); 4978b230ed8SRasesh Mody if (current_err && !err) 4988b230ed8SRasesh Mody err = current_err; 4998b230ed8SRasesh Mody } 5008b230ed8SRasesh Mody } 5018b230ed8SRasesh Mody 5028b230ed8SRasesh Mody mutex_unlock(&bnad->conf_mutex); 5038b230ed8SRasesh Mody return err; 5048b230ed8SRasesh Mody } 5058b230ed8SRasesh Mody 5068b230ed8SRasesh Mody static void 5078b230ed8SRasesh Mody bnad_get_pauseparam(struct net_device *netdev, 5088b230ed8SRasesh Mody struct ethtool_pauseparam *pauseparam) 5098b230ed8SRasesh Mody { 5108b230ed8SRasesh Mody struct bnad *bnad = netdev_priv(netdev); 5118b230ed8SRasesh Mody 5128b230ed8SRasesh Mody pauseparam->autoneg = 0; 513078086f3SRasesh Mody pauseparam->rx_pause = bnad->bna.enet.pause_config.rx_pause; 514078086f3SRasesh Mody pauseparam->tx_pause = bnad->bna.enet.pause_config.tx_pause; 5158b230ed8SRasesh Mody } 5168b230ed8SRasesh Mody 5178b230ed8SRasesh Mody static int 5188b230ed8SRasesh Mody bnad_set_pauseparam(struct net_device *netdev, 5198b230ed8SRasesh Mody struct ethtool_pauseparam *pauseparam) 5208b230ed8SRasesh Mody { 5218b230ed8SRasesh Mody struct bnad *bnad = netdev_priv(netdev); 5228b230ed8SRasesh Mody struct bna_pause_config pause_config; 5238b230ed8SRasesh Mody unsigned long flags; 5248b230ed8SRasesh Mody 5258b230ed8SRasesh Mody if (pauseparam->autoneg == AUTONEG_ENABLE) 5268b230ed8SRasesh Mody return -EINVAL; 5278b230ed8SRasesh Mody 5288b230ed8SRasesh Mody mutex_lock(&bnad->conf_mutex); 529078086f3SRasesh Mody if (pauseparam->rx_pause != bnad->bna.enet.pause_config.rx_pause || 530078086f3SRasesh Mody pauseparam->tx_pause != bnad->bna.enet.pause_config.tx_pause) { 5318b230ed8SRasesh Mody pause_config.rx_pause = pauseparam->rx_pause; 5328b230ed8SRasesh Mody pause_config.tx_pause = pauseparam->tx_pause; 5338b230ed8SRasesh Mody spin_lock_irqsave(&bnad->bna_lock, flags); 534078086f3SRasesh Mody bna_enet_pause_config(&bnad->bna.enet, &pause_config, NULL); 5358b230ed8SRasesh Mody spin_unlock_irqrestore(&bnad->bna_lock, flags); 5368b230ed8SRasesh Mody } 5378b230ed8SRasesh Mody mutex_unlock(&bnad->conf_mutex); 5388b230ed8SRasesh Mody return 0; 5398b230ed8SRasesh Mody } 5408b230ed8SRasesh Mody 5418b230ed8SRasesh Mody static void 5428b230ed8SRasesh Mody bnad_get_strings(struct net_device *netdev, u32 stringset, u8 *string) 5438b230ed8SRasesh Mody { 5448b230ed8SRasesh Mody struct bnad *bnad = netdev_priv(netdev); 5458b230ed8SRasesh Mody int i, j, q_num; 546078086f3SRasesh Mody u32 bmap; 5478b230ed8SRasesh Mody 5488b230ed8SRasesh Mody mutex_lock(&bnad->conf_mutex); 5498b230ed8SRasesh Mody 5508b230ed8SRasesh Mody switch (stringset) { 5518b230ed8SRasesh Mody case ETH_SS_STATS: 5528b230ed8SRasesh Mody for (i = 0; i < BNAD_ETHTOOL_STATS_NUM; i++) { 5538b230ed8SRasesh Mody BUG_ON(!(strlen(bnad_net_stats_strings[i]) < 5548b230ed8SRasesh Mody ETH_GSTRING_LEN)); 5558b230ed8SRasesh Mody memcpy(string, bnad_net_stats_strings[i], 5568b230ed8SRasesh Mody ETH_GSTRING_LEN); 5578b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5588b230ed8SRasesh Mody } 559078086f3SRasesh Mody bmap = bna_tx_rid_mask(&bnad->bna); 560078086f3SRasesh Mody for (i = 0; bmap; i++) { 5618b230ed8SRasesh Mody if (bmap & 1) { 5628b230ed8SRasesh Mody sprintf(string, "txf%d_ucast_octets", i); 5638b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5648b230ed8SRasesh Mody sprintf(string, "txf%d_ucast", i); 5658b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5668b230ed8SRasesh Mody sprintf(string, "txf%d_ucast_vlan", i); 5678b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5688b230ed8SRasesh Mody sprintf(string, "txf%d_mcast_octets", i); 5698b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5708b230ed8SRasesh Mody sprintf(string, "txf%d_mcast", i); 5718b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5728b230ed8SRasesh Mody sprintf(string, "txf%d_mcast_vlan", i); 5738b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5748b230ed8SRasesh Mody sprintf(string, "txf%d_bcast_octets", i); 5758b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5768b230ed8SRasesh Mody sprintf(string, "txf%d_bcast", i); 5778b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5788b230ed8SRasesh Mody sprintf(string, "txf%d_bcast_vlan", i); 5798b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5808b230ed8SRasesh Mody sprintf(string, "txf%d_errors", i); 5818b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5828b230ed8SRasesh Mody sprintf(string, "txf%d_filter_vlan", i); 5838b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5848b230ed8SRasesh Mody sprintf(string, "txf%d_filter_mac_sa", i); 5858b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5868b230ed8SRasesh Mody } 5878b230ed8SRasesh Mody bmap >>= 1; 5888b230ed8SRasesh Mody } 5898b230ed8SRasesh Mody 590078086f3SRasesh Mody bmap = bna_rx_rid_mask(&bnad->bna); 591078086f3SRasesh Mody for (i = 0; bmap; i++) { 5928b230ed8SRasesh Mody if (bmap & 1) { 5938b230ed8SRasesh Mody sprintf(string, "rxf%d_ucast_octets", i); 5948b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5958b230ed8SRasesh Mody sprintf(string, "rxf%d_ucast", i); 5968b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5978b230ed8SRasesh Mody sprintf(string, "rxf%d_ucast_vlan", i); 5988b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 5998b230ed8SRasesh Mody sprintf(string, "rxf%d_mcast_octets", i); 6008b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6018b230ed8SRasesh Mody sprintf(string, "rxf%d_mcast", i); 6028b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6038b230ed8SRasesh Mody sprintf(string, "rxf%d_mcast_vlan", i); 6048b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6058b230ed8SRasesh Mody sprintf(string, "rxf%d_bcast_octets", i); 6068b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6078b230ed8SRasesh Mody sprintf(string, "rxf%d_bcast", i); 6088b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6098b230ed8SRasesh Mody sprintf(string, "rxf%d_bcast_vlan", i); 6108b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6118b230ed8SRasesh Mody sprintf(string, "rxf%d_frame_drops", i); 6128b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6138b230ed8SRasesh Mody } 6148b230ed8SRasesh Mody bmap >>= 1; 6158b230ed8SRasesh Mody } 6168b230ed8SRasesh Mody 6178b230ed8SRasesh Mody q_num = 0; 6188b230ed8SRasesh Mody for (i = 0; i < bnad->num_rx; i++) { 6198b230ed8SRasesh Mody if (!bnad->rx_info[i].rx) 6208b230ed8SRasesh Mody continue; 6218b230ed8SRasesh Mody for (j = 0; j < bnad->num_rxp_per_rx; j++) { 6228b230ed8SRasesh Mody sprintf(string, "cq%d_producer_index", q_num); 6238b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6248b230ed8SRasesh Mody sprintf(string, "cq%d_consumer_index", q_num); 6258b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6268b230ed8SRasesh Mody sprintf(string, "cq%d_hw_producer_index", 6278b230ed8SRasesh Mody q_num); 6288b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 629a2122d95SRasesh Mody sprintf(string, "cq%d_intr", q_num); 630a2122d95SRasesh Mody string += ETH_GSTRING_LEN; 631a2122d95SRasesh Mody sprintf(string, "cq%d_poll", q_num); 632a2122d95SRasesh Mody string += ETH_GSTRING_LEN; 633a2122d95SRasesh Mody sprintf(string, "cq%d_schedule", q_num); 634a2122d95SRasesh Mody string += ETH_GSTRING_LEN; 635a2122d95SRasesh Mody sprintf(string, "cq%d_keep_poll", q_num); 636a2122d95SRasesh Mody string += ETH_GSTRING_LEN; 637a2122d95SRasesh Mody sprintf(string, "cq%d_complete", q_num); 638a2122d95SRasesh Mody string += ETH_GSTRING_LEN; 6398b230ed8SRasesh Mody q_num++; 6408b230ed8SRasesh Mody } 6418b230ed8SRasesh Mody } 6428b230ed8SRasesh Mody 6438b230ed8SRasesh Mody q_num = 0; 6448b230ed8SRasesh Mody for (i = 0; i < bnad->num_rx; i++) { 6458b230ed8SRasesh Mody if (!bnad->rx_info[i].rx) 6468b230ed8SRasesh Mody continue; 6478b230ed8SRasesh Mody for (j = 0; j < bnad->num_rxp_per_rx; j++) { 6488b230ed8SRasesh Mody sprintf(string, "rxq%d_packets", q_num); 6498b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6508b230ed8SRasesh Mody sprintf(string, "rxq%d_bytes", q_num); 6518b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6528b230ed8SRasesh Mody sprintf(string, "rxq%d_packets_with_error", 6538b230ed8SRasesh Mody q_num); 6548b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6558b230ed8SRasesh Mody sprintf(string, "rxq%d_allocbuf_failed", q_num); 6568b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6578b230ed8SRasesh Mody sprintf(string, "rxq%d_producer_index", q_num); 6588b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6598b230ed8SRasesh Mody sprintf(string, "rxq%d_consumer_index", q_num); 6608b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6618b230ed8SRasesh Mody q_num++; 6628b230ed8SRasesh Mody if (bnad->rx_info[i].rx_ctrl[j].ccb && 6638b230ed8SRasesh Mody bnad->rx_info[i].rx_ctrl[j].ccb-> 6648b230ed8SRasesh Mody rcb[1] && 6658b230ed8SRasesh Mody bnad->rx_info[i].rx_ctrl[j].ccb-> 6668b230ed8SRasesh Mody rcb[1]->rxq) { 6678b230ed8SRasesh Mody sprintf(string, "rxq%d_packets", q_num); 6688b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6698b230ed8SRasesh Mody sprintf(string, "rxq%d_bytes", q_num); 6708b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6718b230ed8SRasesh Mody sprintf(string, 6728b230ed8SRasesh Mody "rxq%d_packets_with_error", q_num); 6738b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6748b230ed8SRasesh Mody sprintf(string, "rxq%d_allocbuf_failed", 6758b230ed8SRasesh Mody q_num); 6768b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6778b230ed8SRasesh Mody sprintf(string, "rxq%d_producer_index", 6788b230ed8SRasesh Mody q_num); 6798b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6808b230ed8SRasesh Mody sprintf(string, "rxq%d_consumer_index", 6818b230ed8SRasesh Mody q_num); 6828b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6838b230ed8SRasesh Mody q_num++; 6848b230ed8SRasesh Mody } 6858b230ed8SRasesh Mody } 6868b230ed8SRasesh Mody } 6878b230ed8SRasesh Mody 6888b230ed8SRasesh Mody q_num = 0; 6898b230ed8SRasesh Mody for (i = 0; i < bnad->num_tx; i++) { 6908b230ed8SRasesh Mody if (!bnad->tx_info[i].tx) 6918b230ed8SRasesh Mody continue; 6928b230ed8SRasesh Mody for (j = 0; j < bnad->num_txq_per_tx; j++) { 6938b230ed8SRasesh Mody sprintf(string, "txq%d_packets", q_num); 6948b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6958b230ed8SRasesh Mody sprintf(string, "txq%d_bytes", q_num); 6968b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6978b230ed8SRasesh Mody sprintf(string, "txq%d_producer_index", q_num); 6988b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 6998b230ed8SRasesh Mody sprintf(string, "txq%d_consumer_index", q_num); 7008b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 7018b230ed8SRasesh Mody sprintf(string, "txq%d_hw_consumer_index", 7028b230ed8SRasesh Mody q_num); 7038b230ed8SRasesh Mody string += ETH_GSTRING_LEN; 7048b230ed8SRasesh Mody q_num++; 7058b230ed8SRasesh Mody } 7068b230ed8SRasesh Mody } 7078b230ed8SRasesh Mody 7088b230ed8SRasesh Mody break; 7098b230ed8SRasesh Mody 7108b230ed8SRasesh Mody default: 7118b230ed8SRasesh Mody break; 7128b230ed8SRasesh Mody } 7138b230ed8SRasesh Mody 7148b230ed8SRasesh Mody mutex_unlock(&bnad->conf_mutex); 7158b230ed8SRasesh Mody } 7168b230ed8SRasesh Mody 7178b230ed8SRasesh Mody static int 7188b230ed8SRasesh Mody bnad_get_stats_count_locked(struct net_device *netdev) 7198b230ed8SRasesh Mody { 7208b230ed8SRasesh Mody struct bnad *bnad = netdev_priv(netdev); 721a2122d95SRasesh Mody int i, j, count = 0, rxf_active_num = 0, txf_active_num = 0; 722078086f3SRasesh Mody u32 bmap; 7238b230ed8SRasesh Mody 724078086f3SRasesh Mody bmap = bna_tx_rid_mask(&bnad->bna); 725078086f3SRasesh Mody for (i = 0; bmap; i++) { 7268b230ed8SRasesh Mody if (bmap & 1) 7278b230ed8SRasesh Mody txf_active_num++; 7288b230ed8SRasesh Mody bmap >>= 1; 7298b230ed8SRasesh Mody } 730078086f3SRasesh Mody bmap = bna_rx_rid_mask(&bnad->bna); 731078086f3SRasesh Mody for (i = 0; bmap; i++) { 7328b230ed8SRasesh Mody if (bmap & 1) 7338b230ed8SRasesh Mody rxf_active_num++; 7348b230ed8SRasesh Mody bmap >>= 1; 7358b230ed8SRasesh Mody } 7368b230ed8SRasesh Mody count = BNAD_ETHTOOL_STATS_NUM + 7378b230ed8SRasesh Mody txf_active_num * BNAD_NUM_TXF_COUNTERS + 7388b230ed8SRasesh Mody rxf_active_num * BNAD_NUM_RXF_COUNTERS; 7398b230ed8SRasesh Mody 7408b230ed8SRasesh Mody for (i = 0; i < bnad->num_rx; i++) { 7418b230ed8SRasesh Mody if (!bnad->rx_info[i].rx) 7428b230ed8SRasesh Mody continue; 7438b230ed8SRasesh Mody count += bnad->num_rxp_per_rx * BNAD_NUM_CQ_COUNTERS; 7448b230ed8SRasesh Mody count += bnad->num_rxp_per_rx * BNAD_NUM_RXQ_COUNTERS; 7458b230ed8SRasesh Mody for (j = 0; j < bnad->num_rxp_per_rx; j++) 7468b230ed8SRasesh Mody if (bnad->rx_info[i].rx_ctrl[j].ccb && 7478b230ed8SRasesh Mody bnad->rx_info[i].rx_ctrl[j].ccb->rcb[1] && 7488b230ed8SRasesh Mody bnad->rx_info[i].rx_ctrl[j].ccb->rcb[1]->rxq) 7498b230ed8SRasesh Mody count += BNAD_NUM_RXQ_COUNTERS; 7508b230ed8SRasesh Mody } 7518b230ed8SRasesh Mody 7528b230ed8SRasesh Mody for (i = 0; i < bnad->num_tx; i++) { 7538b230ed8SRasesh Mody if (!bnad->tx_info[i].tx) 7548b230ed8SRasesh Mody continue; 7558b230ed8SRasesh Mody count += bnad->num_txq_per_tx * BNAD_NUM_TXQ_COUNTERS; 7568b230ed8SRasesh Mody } 7578b230ed8SRasesh Mody return count; 7588b230ed8SRasesh Mody } 7598b230ed8SRasesh Mody 7608b230ed8SRasesh Mody static int 7618b230ed8SRasesh Mody bnad_per_q_stats_fill(struct bnad *bnad, u64 *buf, int bi) 7628b230ed8SRasesh Mody { 7638b230ed8SRasesh Mody int i, j; 7648b230ed8SRasesh Mody struct bna_rcb *rcb = NULL; 7658b230ed8SRasesh Mody struct bna_tcb *tcb = NULL; 7668b230ed8SRasesh Mody 7678b230ed8SRasesh Mody for (i = 0; i < bnad->num_rx; i++) { 7688b230ed8SRasesh Mody if (!bnad->rx_info[i].rx) 7698b230ed8SRasesh Mody continue; 7708b230ed8SRasesh Mody for (j = 0; j < bnad->num_rxp_per_rx; j++) 7718b230ed8SRasesh Mody if (bnad->rx_info[i].rx_ctrl[j].ccb && 7728b230ed8SRasesh Mody bnad->rx_info[i].rx_ctrl[j].ccb->rcb[0] && 7738b230ed8SRasesh Mody bnad->rx_info[i].rx_ctrl[j].ccb->rcb[0]->rxq) { 7748b230ed8SRasesh Mody buf[bi++] = bnad->rx_info[i].rx_ctrl[j]. 7758b230ed8SRasesh Mody ccb->producer_index; 7768b230ed8SRasesh Mody buf[bi++] = 0; /* ccb->consumer_index */ 7778b230ed8SRasesh Mody buf[bi++] = *(bnad->rx_info[i].rx_ctrl[j]. 7788b230ed8SRasesh Mody ccb->hw_producer_index); 779a2122d95SRasesh Mody 780a2122d95SRasesh Mody buf[bi++] = bnad->rx_info[i]. 781a2122d95SRasesh Mody rx_ctrl[j].rx_intr_ctr; 782a2122d95SRasesh Mody buf[bi++] = bnad->rx_info[i]. 783a2122d95SRasesh Mody rx_ctrl[j].rx_poll_ctr; 784a2122d95SRasesh Mody buf[bi++] = bnad->rx_info[i]. 785a2122d95SRasesh Mody rx_ctrl[j].rx_schedule; 786a2122d95SRasesh Mody buf[bi++] = bnad->rx_info[i]. 787a2122d95SRasesh Mody rx_ctrl[j].rx_keep_poll; 788a2122d95SRasesh Mody buf[bi++] = bnad->rx_info[i]. 789a2122d95SRasesh Mody rx_ctrl[j].rx_complete; 7908b230ed8SRasesh Mody } 7918b230ed8SRasesh Mody } 7928b230ed8SRasesh Mody for (i = 0; i < bnad->num_rx; i++) { 7938b230ed8SRasesh Mody if (!bnad->rx_info[i].rx) 7948b230ed8SRasesh Mody continue; 7958b230ed8SRasesh Mody for (j = 0; j < bnad->num_rxp_per_rx; j++) 7968b230ed8SRasesh Mody if (bnad->rx_info[i].rx_ctrl[j].ccb) { 7978b230ed8SRasesh Mody if (bnad->rx_info[i].rx_ctrl[j].ccb->rcb[0] && 7988b230ed8SRasesh Mody bnad->rx_info[i].rx_ctrl[j].ccb-> 7998b230ed8SRasesh Mody rcb[0]->rxq) { 8008b230ed8SRasesh Mody rcb = bnad->rx_info[i].rx_ctrl[j]. 8018b230ed8SRasesh Mody ccb->rcb[0]; 8028b230ed8SRasesh Mody buf[bi++] = rcb->rxq->rx_packets; 8038b230ed8SRasesh Mody buf[bi++] = rcb->rxq->rx_bytes; 8048b230ed8SRasesh Mody buf[bi++] = rcb->rxq-> 8058b230ed8SRasesh Mody rx_packets_with_error; 8068b230ed8SRasesh Mody buf[bi++] = rcb->rxq-> 8078b230ed8SRasesh Mody rxbuf_alloc_failed; 8088b230ed8SRasesh Mody buf[bi++] = rcb->producer_index; 8098b230ed8SRasesh Mody buf[bi++] = rcb->consumer_index; 8108b230ed8SRasesh Mody } 8118b230ed8SRasesh Mody if (bnad->rx_info[i].rx_ctrl[j].ccb->rcb[1] && 8128b230ed8SRasesh Mody bnad->rx_info[i].rx_ctrl[j].ccb-> 8138b230ed8SRasesh Mody rcb[1]->rxq) { 8148b230ed8SRasesh Mody rcb = bnad->rx_info[i].rx_ctrl[j]. 8158b230ed8SRasesh Mody ccb->rcb[1]; 8168b230ed8SRasesh Mody buf[bi++] = rcb->rxq->rx_packets; 8178b230ed8SRasesh Mody buf[bi++] = rcb->rxq->rx_bytes; 8188b230ed8SRasesh Mody buf[bi++] = rcb->rxq-> 8198b230ed8SRasesh Mody rx_packets_with_error; 8208b230ed8SRasesh Mody buf[bi++] = rcb->rxq-> 8218b230ed8SRasesh Mody rxbuf_alloc_failed; 8228b230ed8SRasesh Mody buf[bi++] = rcb->producer_index; 8238b230ed8SRasesh Mody buf[bi++] = rcb->consumer_index; 8248b230ed8SRasesh Mody } 8258b230ed8SRasesh Mody } 8268b230ed8SRasesh Mody } 8278b230ed8SRasesh Mody 8288b230ed8SRasesh Mody for (i = 0; i < bnad->num_tx; i++) { 8298b230ed8SRasesh Mody if (!bnad->tx_info[i].tx) 8308b230ed8SRasesh Mody continue; 8318b230ed8SRasesh Mody for (j = 0; j < bnad->num_txq_per_tx; j++) 8328b230ed8SRasesh Mody if (bnad->tx_info[i].tcb[j] && 8338b230ed8SRasesh Mody bnad->tx_info[i].tcb[j]->txq) { 8348b230ed8SRasesh Mody tcb = bnad->tx_info[i].tcb[j]; 8358b230ed8SRasesh Mody buf[bi++] = tcb->txq->tx_packets; 8368b230ed8SRasesh Mody buf[bi++] = tcb->txq->tx_bytes; 8378b230ed8SRasesh Mody buf[bi++] = tcb->producer_index; 8388b230ed8SRasesh Mody buf[bi++] = tcb->consumer_index; 8398b230ed8SRasesh Mody buf[bi++] = *(tcb->hw_consumer_index); 8408b230ed8SRasesh Mody } 8418b230ed8SRasesh Mody } 8428b230ed8SRasesh Mody 8438b230ed8SRasesh Mody return bi; 8448b230ed8SRasesh Mody } 8458b230ed8SRasesh Mody 8468b230ed8SRasesh Mody static void 8478b230ed8SRasesh Mody bnad_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, 8488b230ed8SRasesh Mody u64 *buf) 8498b230ed8SRasesh Mody { 8508b230ed8SRasesh Mody struct bnad *bnad = netdev_priv(netdev); 8518b230ed8SRasesh Mody int i, j, bi; 852250e061eSEric Dumazet unsigned long flags; 853250e061eSEric Dumazet struct rtnl_link_stats64 *net_stats64; 8548b230ed8SRasesh Mody u64 *stats64; 855078086f3SRasesh Mody u32 bmap; 8568b230ed8SRasesh Mody 8578b230ed8SRasesh Mody mutex_lock(&bnad->conf_mutex); 8588b230ed8SRasesh Mody if (bnad_get_stats_count_locked(netdev) != stats->n_stats) { 8598b230ed8SRasesh Mody mutex_unlock(&bnad->conf_mutex); 8608b230ed8SRasesh Mody return; 8618b230ed8SRasesh Mody } 8628b230ed8SRasesh Mody 8638b230ed8SRasesh Mody /* 8648b230ed8SRasesh Mody * Used bna_lock to sync reads from bna_stats, which is written 8658b230ed8SRasesh Mody * under the same lock 8668b230ed8SRasesh Mody */ 8678b230ed8SRasesh Mody spin_lock_irqsave(&bnad->bna_lock, flags); 8688b230ed8SRasesh Mody bi = 0; 8698b230ed8SRasesh Mody memset(buf, 0, stats->n_stats * sizeof(u64)); 8708b230ed8SRasesh Mody 871250e061eSEric Dumazet net_stats64 = (struct rtnl_link_stats64 *)buf; 872250e061eSEric Dumazet bnad_netdev_qstats_fill(bnad, net_stats64); 873250e061eSEric Dumazet bnad_netdev_hwstats_fill(bnad, net_stats64); 8748b230ed8SRasesh Mody 875250e061eSEric Dumazet bi = sizeof(*net_stats64) / sizeof(u64); 8768b230ed8SRasesh Mody 877f7c0fa4cSRasesh Mody /* Get netif_queue_stopped from stack */ 878f7c0fa4cSRasesh Mody bnad->stats.drv_stats.netif_queue_stopped = netif_queue_stopped(netdev); 879f7c0fa4cSRasesh Mody 8808b230ed8SRasesh Mody /* Fill driver stats into ethtool buffers */ 8818b230ed8SRasesh Mody stats64 = (u64 *)&bnad->stats.drv_stats; 8828b230ed8SRasesh Mody for (i = 0; i < sizeof(struct bnad_drv_stats) / sizeof(u64); i++) 8838b230ed8SRasesh Mody buf[bi++] = stats64[i]; 8848b230ed8SRasesh Mody 8858b230ed8SRasesh Mody /* Fill hardware stats excluding the rxf/txf into ethtool bufs */ 886078086f3SRasesh Mody stats64 = (u64 *) &bnad->stats.bna_stats->hw_stats; 8878b230ed8SRasesh Mody for (i = 0; 888078086f3SRasesh Mody i < offsetof(struct bfi_enet_stats, rxf_stats[0]) / 889078086f3SRasesh Mody sizeof(u64); 8908b230ed8SRasesh Mody i++) 8918b230ed8SRasesh Mody buf[bi++] = stats64[i]; 8928b230ed8SRasesh Mody 8938b230ed8SRasesh Mody /* Fill txf stats into ethtool buffers */ 894078086f3SRasesh Mody bmap = bna_tx_rid_mask(&bnad->bna); 895078086f3SRasesh Mody for (i = 0; bmap; i++) { 8968b230ed8SRasesh Mody if (bmap & 1) { 8978b230ed8SRasesh Mody stats64 = (u64 *)&bnad->stats.bna_stats-> 898078086f3SRasesh Mody hw_stats.txf_stats[i]; 899078086f3SRasesh Mody for (j = 0; j < sizeof(struct bfi_enet_stats_txf) / 9008b230ed8SRasesh Mody sizeof(u64); j++) 9018b230ed8SRasesh Mody buf[bi++] = stats64[j]; 9028b230ed8SRasesh Mody } 9038b230ed8SRasesh Mody bmap >>= 1; 9048b230ed8SRasesh Mody } 9058b230ed8SRasesh Mody 9068b230ed8SRasesh Mody /* Fill rxf stats into ethtool buffers */ 907078086f3SRasesh Mody bmap = bna_rx_rid_mask(&bnad->bna); 908078086f3SRasesh Mody for (i = 0; bmap; i++) { 9098b230ed8SRasesh Mody if (bmap & 1) { 9108b230ed8SRasesh Mody stats64 = (u64 *)&bnad->stats.bna_stats-> 911078086f3SRasesh Mody hw_stats.rxf_stats[i]; 912078086f3SRasesh Mody for (j = 0; j < sizeof(struct bfi_enet_stats_rxf) / 9138b230ed8SRasesh Mody sizeof(u64); j++) 9148b230ed8SRasesh Mody buf[bi++] = stats64[j]; 9158b230ed8SRasesh Mody } 9168b230ed8SRasesh Mody bmap >>= 1; 9178b230ed8SRasesh Mody } 9188b230ed8SRasesh Mody 9198b230ed8SRasesh Mody /* Fill per Q stats into ethtool buffers */ 9208b230ed8SRasesh Mody bi = bnad_per_q_stats_fill(bnad, buf, bi); 9218b230ed8SRasesh Mody 9228b230ed8SRasesh Mody spin_unlock_irqrestore(&bnad->bna_lock, flags); 9238b230ed8SRasesh Mody 9248b230ed8SRasesh Mody mutex_unlock(&bnad->conf_mutex); 9258b230ed8SRasesh Mody } 9268b230ed8SRasesh Mody 9278b230ed8SRasesh Mody static int 9288b230ed8SRasesh Mody bnad_get_sset_count(struct net_device *netdev, int sset) 9298b230ed8SRasesh Mody { 9308b230ed8SRasesh Mody switch (sset) { 9318b230ed8SRasesh Mody case ETH_SS_STATS: 9328b230ed8SRasesh Mody return bnad_get_stats_count_locked(netdev); 9338b230ed8SRasesh Mody default: 9348b230ed8SRasesh Mody return -EOPNOTSUPP; 9358b230ed8SRasesh Mody } 9368b230ed8SRasesh Mody } 9378b230ed8SRasesh Mody 93872a9730bSKrishna Gudipati static u32 93972a9730bSKrishna Gudipati bnad_get_flash_partition_by_offset(struct bnad *bnad, u32 offset, 94072a9730bSKrishna Gudipati u32 *base_offset) 94172a9730bSKrishna Gudipati { 94272a9730bSKrishna Gudipati struct bfa_flash_attr *flash_attr; 94372a9730bSKrishna Gudipati struct bnad_iocmd_comp fcomp; 94472a9730bSKrishna Gudipati u32 i, flash_part = 0, ret; 94572a9730bSKrishna Gudipati unsigned long flags = 0; 94672a9730bSKrishna Gudipati 94772a9730bSKrishna Gudipati flash_attr = kzalloc(sizeof(struct bfa_flash_attr), GFP_KERNEL); 94872a9730bSKrishna Gudipati if (!flash_attr) 949027a3b61SDan Carpenter return 0; 95072a9730bSKrishna Gudipati 95172a9730bSKrishna Gudipati fcomp.bnad = bnad; 95272a9730bSKrishna Gudipati fcomp.comp_status = 0; 95372a9730bSKrishna Gudipati 95472a9730bSKrishna Gudipati init_completion(&fcomp.comp); 95572a9730bSKrishna Gudipati spin_lock_irqsave(&bnad->bna_lock, flags); 95672a9730bSKrishna Gudipati ret = bfa_nw_flash_get_attr(&bnad->bna.flash, flash_attr, 95772a9730bSKrishna Gudipati bnad_cb_completion, &fcomp); 95872a9730bSKrishna Gudipati if (ret != BFA_STATUS_OK) { 95972a9730bSKrishna Gudipati spin_unlock_irqrestore(&bnad->bna_lock, flags); 96072a9730bSKrishna Gudipati kfree(flash_attr); 961027a3b61SDan Carpenter return 0; 96272a9730bSKrishna Gudipati } 96372a9730bSKrishna Gudipati spin_unlock_irqrestore(&bnad->bna_lock, flags); 96472a9730bSKrishna Gudipati wait_for_completion(&fcomp.comp); 96572a9730bSKrishna Gudipati ret = fcomp.comp_status; 96672a9730bSKrishna Gudipati 96772a9730bSKrishna Gudipati /* Check for the flash type & base offset value */ 96872a9730bSKrishna Gudipati if (ret == BFA_STATUS_OK) { 96972a9730bSKrishna Gudipati for (i = 0; i < flash_attr->npart; i++) { 97072a9730bSKrishna Gudipati if (offset >= flash_attr->part[i].part_off && 97172a9730bSKrishna Gudipati offset < (flash_attr->part[i].part_off + 97272a9730bSKrishna Gudipati flash_attr->part[i].part_size)) { 97372a9730bSKrishna Gudipati flash_part = flash_attr->part[i].part_type; 97472a9730bSKrishna Gudipati *base_offset = flash_attr->part[i].part_off; 97572a9730bSKrishna Gudipati break; 97672a9730bSKrishna Gudipati } 97772a9730bSKrishna Gudipati } 97872a9730bSKrishna Gudipati } 97972a9730bSKrishna Gudipati kfree(flash_attr); 98072a9730bSKrishna Gudipati return flash_part; 98172a9730bSKrishna Gudipati } 98272a9730bSKrishna Gudipati 98372a9730bSKrishna Gudipati static int 98472a9730bSKrishna Gudipati bnad_get_eeprom_len(struct net_device *netdev) 98572a9730bSKrishna Gudipati { 98672a9730bSKrishna Gudipati return BFA_TOTAL_FLASH_SIZE; 98772a9730bSKrishna Gudipati } 98872a9730bSKrishna Gudipati 98972a9730bSKrishna Gudipati static int 99072a9730bSKrishna Gudipati bnad_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, 99172a9730bSKrishna Gudipati u8 *bytes) 99272a9730bSKrishna Gudipati { 99372a9730bSKrishna Gudipati struct bnad *bnad = netdev_priv(netdev); 99472a9730bSKrishna Gudipati struct bnad_iocmd_comp fcomp; 99572a9730bSKrishna Gudipati u32 flash_part = 0, base_offset = 0; 99672a9730bSKrishna Gudipati unsigned long flags = 0; 99772a9730bSKrishna Gudipati int ret = 0; 99872a9730bSKrishna Gudipati 99972a9730bSKrishna Gudipati /* Check if the flash read request is valid */ 100072a9730bSKrishna Gudipati if (eeprom->magic != (bnad->pcidev->vendor | 100172a9730bSKrishna Gudipati (bnad->pcidev->device << 16))) 100272a9730bSKrishna Gudipati return -EFAULT; 100372a9730bSKrishna Gudipati 100472a9730bSKrishna Gudipati /* Query the flash partition based on the offset */ 100572a9730bSKrishna Gudipati flash_part = bnad_get_flash_partition_by_offset(bnad, 100672a9730bSKrishna Gudipati eeprom->offset, &base_offset); 1007027a3b61SDan Carpenter if (flash_part == 0) 100872a9730bSKrishna Gudipati return -EFAULT; 100972a9730bSKrishna Gudipati 101072a9730bSKrishna Gudipati fcomp.bnad = bnad; 101172a9730bSKrishna Gudipati fcomp.comp_status = 0; 101272a9730bSKrishna Gudipati 101372a9730bSKrishna Gudipati init_completion(&fcomp.comp); 101472a9730bSKrishna Gudipati spin_lock_irqsave(&bnad->bna_lock, flags); 101572a9730bSKrishna Gudipati ret = bfa_nw_flash_read_part(&bnad->bna.flash, flash_part, 101672a9730bSKrishna Gudipati bnad->id, bytes, eeprom->len, 101772a9730bSKrishna Gudipati eeprom->offset - base_offset, 101872a9730bSKrishna Gudipati bnad_cb_completion, &fcomp); 101972a9730bSKrishna Gudipati if (ret != BFA_STATUS_OK) { 102072a9730bSKrishna Gudipati spin_unlock_irqrestore(&bnad->bna_lock, flags); 102172a9730bSKrishna Gudipati goto done; 102272a9730bSKrishna Gudipati } 102372a9730bSKrishna Gudipati 102472a9730bSKrishna Gudipati spin_unlock_irqrestore(&bnad->bna_lock, flags); 102572a9730bSKrishna Gudipati wait_for_completion(&fcomp.comp); 102672a9730bSKrishna Gudipati ret = fcomp.comp_status; 102772a9730bSKrishna Gudipati done: 102872a9730bSKrishna Gudipati return ret; 102972a9730bSKrishna Gudipati } 103072a9730bSKrishna Gudipati 103172a9730bSKrishna Gudipati static int 103272a9730bSKrishna Gudipati bnad_set_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, 103372a9730bSKrishna Gudipati u8 *bytes) 103472a9730bSKrishna Gudipati { 103572a9730bSKrishna Gudipati struct bnad *bnad = netdev_priv(netdev); 103672a9730bSKrishna Gudipati struct bnad_iocmd_comp fcomp; 103772a9730bSKrishna Gudipati u32 flash_part = 0, base_offset = 0; 103872a9730bSKrishna Gudipati unsigned long flags = 0; 103972a9730bSKrishna Gudipati int ret = 0; 104072a9730bSKrishna Gudipati 104172a9730bSKrishna Gudipati /* Check if the flash update request is valid */ 104272a9730bSKrishna Gudipati if (eeprom->magic != (bnad->pcidev->vendor | 104372a9730bSKrishna Gudipati (bnad->pcidev->device << 16))) 104472a9730bSKrishna Gudipati return -EINVAL; 104572a9730bSKrishna Gudipati 104672a9730bSKrishna Gudipati /* Query the flash partition based on the offset */ 104772a9730bSKrishna Gudipati flash_part = bnad_get_flash_partition_by_offset(bnad, 104872a9730bSKrishna Gudipati eeprom->offset, &base_offset); 1049027a3b61SDan Carpenter if (flash_part == 0) 105072a9730bSKrishna Gudipati return -EFAULT; 105172a9730bSKrishna Gudipati 105272a9730bSKrishna Gudipati fcomp.bnad = bnad; 105372a9730bSKrishna Gudipati fcomp.comp_status = 0; 105472a9730bSKrishna Gudipati 105572a9730bSKrishna Gudipati init_completion(&fcomp.comp); 105672a9730bSKrishna Gudipati spin_lock_irqsave(&bnad->bna_lock, flags); 105772a9730bSKrishna Gudipati ret = bfa_nw_flash_update_part(&bnad->bna.flash, flash_part, 105872a9730bSKrishna Gudipati bnad->id, bytes, eeprom->len, 105972a9730bSKrishna Gudipati eeprom->offset - base_offset, 106072a9730bSKrishna Gudipati bnad_cb_completion, &fcomp); 106172a9730bSKrishna Gudipati if (ret != BFA_STATUS_OK) { 106272a9730bSKrishna Gudipati spin_unlock_irqrestore(&bnad->bna_lock, flags); 106372a9730bSKrishna Gudipati goto done; 106472a9730bSKrishna Gudipati } 106572a9730bSKrishna Gudipati 106672a9730bSKrishna Gudipati spin_unlock_irqrestore(&bnad->bna_lock, flags); 106772a9730bSKrishna Gudipati wait_for_completion(&fcomp.comp); 106872a9730bSKrishna Gudipati ret = fcomp.comp_status; 106972a9730bSKrishna Gudipati done: 107072a9730bSKrishna Gudipati return ret; 107172a9730bSKrishna Gudipati } 107272a9730bSKrishna Gudipati 107357b9bef0SKrishna Gudipati static int 107457b9bef0SKrishna Gudipati bnad_flash_device(struct net_device *netdev, struct ethtool_flash *eflash) 107557b9bef0SKrishna Gudipati { 107657b9bef0SKrishna Gudipati struct bnad *bnad = netdev_priv(netdev); 107757b9bef0SKrishna Gudipati struct bnad_iocmd_comp fcomp; 107857b9bef0SKrishna Gudipati const struct firmware *fw; 107957b9bef0SKrishna Gudipati int ret = 0; 108057b9bef0SKrishna Gudipati 108157b9bef0SKrishna Gudipati ret = request_firmware(&fw, eflash->data, &bnad->pcidev->dev); 108257b9bef0SKrishna Gudipati if (ret) { 108357b9bef0SKrishna Gudipati pr_err("BNA: Can't locate firmware %s\n", eflash->data); 108457b9bef0SKrishna Gudipati goto out; 108557b9bef0SKrishna Gudipati } 108657b9bef0SKrishna Gudipati 108757b9bef0SKrishna Gudipati fcomp.bnad = bnad; 108857b9bef0SKrishna Gudipati fcomp.comp_status = 0; 108957b9bef0SKrishna Gudipati 109057b9bef0SKrishna Gudipati init_completion(&fcomp.comp); 109157b9bef0SKrishna Gudipati spin_lock_irq(&bnad->bna_lock); 109257b9bef0SKrishna Gudipati ret = bfa_nw_flash_update_part(&bnad->bna.flash, BFA_FLASH_PART_FWIMG, 109357b9bef0SKrishna Gudipati bnad->id, (u8 *)fw->data, fw->size, 0, 109457b9bef0SKrishna Gudipati bnad_cb_completion, &fcomp); 109557b9bef0SKrishna Gudipati if (ret != BFA_STATUS_OK) { 109657b9bef0SKrishna Gudipati pr_warn("BNA: Flash update failed with err: %d\n", ret); 109757b9bef0SKrishna Gudipati ret = -EIO; 109857b9bef0SKrishna Gudipati spin_unlock_irq(&bnad->bna_lock); 109957b9bef0SKrishna Gudipati goto out; 110057b9bef0SKrishna Gudipati } 110157b9bef0SKrishna Gudipati 110257b9bef0SKrishna Gudipati spin_unlock_irq(&bnad->bna_lock); 110357b9bef0SKrishna Gudipati wait_for_completion(&fcomp.comp); 110457b9bef0SKrishna Gudipati if (fcomp.comp_status != BFA_STATUS_OK) { 110557b9bef0SKrishna Gudipati ret = -EIO; 110657b9bef0SKrishna Gudipati pr_warn("BNA: Firmware image update to flash failed with: %d\n", 110757b9bef0SKrishna Gudipati fcomp.comp_status); 110857b9bef0SKrishna Gudipati } 110957b9bef0SKrishna Gudipati out: 111057b9bef0SKrishna Gudipati release_firmware(fw); 111157b9bef0SKrishna Gudipati return ret; 111257b9bef0SKrishna Gudipati } 111357b9bef0SKrishna Gudipati 1114975419cfSstephen hemminger static const struct ethtool_ops bnad_ethtool_ops = { 11158b230ed8SRasesh Mody .get_settings = bnad_get_settings, 11168b230ed8SRasesh Mody .set_settings = bnad_set_settings, 11178b230ed8SRasesh Mody .get_drvinfo = bnad_get_drvinfo, 11188b230ed8SRasesh Mody .get_wol = bnad_get_wol, 11198b230ed8SRasesh Mody .get_link = ethtool_op_get_link, 11208b230ed8SRasesh Mody .get_coalesce = bnad_get_coalesce, 11218b230ed8SRasesh Mody .set_coalesce = bnad_set_coalesce, 11228b230ed8SRasesh Mody .get_ringparam = bnad_get_ringparam, 11238b230ed8SRasesh Mody .set_ringparam = bnad_set_ringparam, 11248b230ed8SRasesh Mody .get_pauseparam = bnad_get_pauseparam, 11258b230ed8SRasesh Mody .set_pauseparam = bnad_set_pauseparam, 11268b230ed8SRasesh Mody .get_strings = bnad_get_strings, 11278b230ed8SRasesh Mody .get_ethtool_stats = bnad_get_ethtool_stats, 112872a9730bSKrishna Gudipati .get_sset_count = bnad_get_sset_count, 112972a9730bSKrishna Gudipati .get_eeprom_len = bnad_get_eeprom_len, 113072a9730bSKrishna Gudipati .get_eeprom = bnad_get_eeprom, 113172a9730bSKrishna Gudipati .set_eeprom = bnad_set_eeprom, 113257b9bef0SKrishna Gudipati .flash_device = bnad_flash_device, 11338b230ed8SRasesh Mody }; 11348b230ed8SRasesh Mody 11358b230ed8SRasesh Mody void 11368b230ed8SRasesh Mody bnad_set_ethtool_ops(struct net_device *netdev) 11378b230ed8SRasesh Mody { 11388b230ed8SRasesh Mody SET_ETHTOOL_OPS(netdev, &bnad_ethtool_ops); 11398b230ed8SRasesh Mody } 1140