brintos

brintos / linux-shallow public Read only

0
0
Text · 28.7 KiB · d1ad6c9 Raw
1099 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Linux network driver for QLogic BR-series Converged Network Adapter.4 */5/*6 * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.7 * Copyright (c) 2014-2015 QLogic Corporation8 * All rights reserved9 * www.qlogic.com10 */11 12#include "cna.h"13 14#include <linux/netdevice.h>15#include <linux/skbuff.h>16#include <linux/ethtool.h>17#include <linux/rtnetlink.h>18 19#include "bna.h"20 21#include "bnad.h"22 23#define BNAD_NUM_TXF_COUNTERS 1224#define BNAD_NUM_RXF_COUNTERS 1025#define BNAD_NUM_CQ_COUNTERS (3 + 5)26#define BNAD_NUM_RXQ_COUNTERS 727#define BNAD_NUM_TXQ_COUNTERS 528 29static const char *bnad_net_stats_strings[] = {30	"rx_packets",31	"tx_packets",32	"rx_bytes",33	"tx_bytes",34	"rx_errors",35	"tx_errors",36	"rx_dropped",37	"tx_dropped",38	"multicast",39	"collisions",40	"rx_length_errors",41	"rx_crc_errors",42	"rx_frame_errors",43	"tx_fifo_errors",44 45	"netif_queue_stop",46	"netif_queue_wakeup",47	"netif_queue_stopped",48	"tso4",49	"tso6",50	"tso_err",51	"tcpcsum_offload",52	"udpcsum_offload",53	"csum_help",54	"tx_skb_too_short",55	"tx_skb_stopping",56	"tx_skb_max_vectors",57	"tx_skb_mss_too_long",58	"tx_skb_tso_too_short",59	"tx_skb_tso_prepare",60	"tx_skb_non_tso_too_long",61	"tx_skb_tcp_hdr",62	"tx_skb_udp_hdr",63	"tx_skb_csum_err",64	"tx_skb_headlen_too_long",65	"tx_skb_headlen_zero",66	"tx_skb_frag_zero",67	"tx_skb_len_mismatch",68	"tx_skb_map_failed",69	"hw_stats_updates",70	"netif_rx_dropped",71 72	"link_toggle",73	"cee_toggle",74 75	"rxp_info_alloc_failed",76	"mbox_intr_disabled",77	"mbox_intr_enabled",78	"tx_unmap_q_alloc_failed",79	"rx_unmap_q_alloc_failed",80	"rxbuf_alloc_failed",81	"rxbuf_map_failed",82 83	"mac_stats_clr_cnt",84	"mac_frame_64",85	"mac_frame_65_127",86	"mac_frame_128_255",87	"mac_frame_256_511",88	"mac_frame_512_1023",89	"mac_frame_1024_1518",90	"mac_frame_1518_1522",91	"mac_rx_bytes",92	"mac_rx_packets",93	"mac_rx_fcs_error",94	"mac_rx_multicast",95	"mac_rx_broadcast",96	"mac_rx_control_frames",97	"mac_rx_pause",98	"mac_rx_unknown_opcode",99	"mac_rx_alignment_error",100	"mac_rx_frame_length_error",101	"mac_rx_code_error",102	"mac_rx_carrier_sense_error",103	"mac_rx_undersize",104	"mac_rx_oversize",105	"mac_rx_fragments",106	"mac_rx_jabber",107	"mac_rx_drop",108 109	"mac_tx_bytes",110	"mac_tx_packets",111	"mac_tx_multicast",112	"mac_tx_broadcast",113	"mac_tx_pause",114	"mac_tx_deferral",115	"mac_tx_excessive_deferral",116	"mac_tx_single_collision",117	"mac_tx_multiple_collision",118	"mac_tx_late_collision",119	"mac_tx_excessive_collision",120	"mac_tx_total_collision",121	"mac_tx_pause_honored",122	"mac_tx_drop",123	"mac_tx_jabber",124	"mac_tx_fcs_error",125	"mac_tx_control_frame",126	"mac_tx_oversize",127	"mac_tx_undersize",128	"mac_tx_fragments",129 130	"bpc_tx_pause_0",131	"bpc_tx_pause_1",132	"bpc_tx_pause_2",133	"bpc_tx_pause_3",134	"bpc_tx_pause_4",135	"bpc_tx_pause_5",136	"bpc_tx_pause_6",137	"bpc_tx_pause_7",138	"bpc_tx_zero_pause_0",139	"bpc_tx_zero_pause_1",140	"bpc_tx_zero_pause_2",141	"bpc_tx_zero_pause_3",142	"bpc_tx_zero_pause_4",143	"bpc_tx_zero_pause_5",144	"bpc_tx_zero_pause_6",145	"bpc_tx_zero_pause_7",146	"bpc_tx_first_pause_0",147	"bpc_tx_first_pause_1",148	"bpc_tx_first_pause_2",149	"bpc_tx_first_pause_3",150	"bpc_tx_first_pause_4",151	"bpc_tx_first_pause_5",152	"bpc_tx_first_pause_6",153	"bpc_tx_first_pause_7",154 155	"bpc_rx_pause_0",156	"bpc_rx_pause_1",157	"bpc_rx_pause_2",158	"bpc_rx_pause_3",159	"bpc_rx_pause_4",160	"bpc_rx_pause_5",161	"bpc_rx_pause_6",162	"bpc_rx_pause_7",163	"bpc_rx_zero_pause_0",164	"bpc_rx_zero_pause_1",165	"bpc_rx_zero_pause_2",166	"bpc_rx_zero_pause_3",167	"bpc_rx_zero_pause_4",168	"bpc_rx_zero_pause_5",169	"bpc_rx_zero_pause_6",170	"bpc_rx_zero_pause_7",171	"bpc_rx_first_pause_0",172	"bpc_rx_first_pause_1",173	"bpc_rx_first_pause_2",174	"bpc_rx_first_pause_3",175	"bpc_rx_first_pause_4",176	"bpc_rx_first_pause_5",177	"bpc_rx_first_pause_6",178	"bpc_rx_first_pause_7",179 180	"rad_rx_frames",181	"rad_rx_octets",182	"rad_rx_vlan_frames",183	"rad_rx_ucast",184	"rad_rx_ucast_octets",185	"rad_rx_ucast_vlan",186	"rad_rx_mcast",187	"rad_rx_mcast_octets",188	"rad_rx_mcast_vlan",189	"rad_rx_bcast",190	"rad_rx_bcast_octets",191	"rad_rx_bcast_vlan",192	"rad_rx_drops",193 194	"rlb_rad_rx_frames",195	"rlb_rad_rx_octets",196	"rlb_rad_rx_vlan_frames",197	"rlb_rad_rx_ucast",198	"rlb_rad_rx_ucast_octets",199	"rlb_rad_rx_ucast_vlan",200	"rlb_rad_rx_mcast",201	"rlb_rad_rx_mcast_octets",202	"rlb_rad_rx_mcast_vlan",203	"rlb_rad_rx_bcast",204	"rlb_rad_rx_bcast_octets",205	"rlb_rad_rx_bcast_vlan",206	"rlb_rad_rx_drops",207 208	"fc_rx_ucast_octets",209	"fc_rx_ucast",210	"fc_rx_ucast_vlan",211	"fc_rx_mcast_octets",212	"fc_rx_mcast",213	"fc_rx_mcast_vlan",214	"fc_rx_bcast_octets",215	"fc_rx_bcast",216	"fc_rx_bcast_vlan",217 218	"fc_tx_ucast_octets",219	"fc_tx_ucast",220	"fc_tx_ucast_vlan",221	"fc_tx_mcast_octets",222	"fc_tx_mcast",223	"fc_tx_mcast_vlan",224	"fc_tx_bcast_octets",225	"fc_tx_bcast",226	"fc_tx_bcast_vlan",227	"fc_tx_parity_errors",228	"fc_tx_timeout",229	"fc_tx_fid_parity_errors",230};231 232#define BNAD_ETHTOOL_STATS_NUM	ARRAY_SIZE(bnad_net_stats_strings)233 234static int235bnad_get_link_ksettings(struct net_device *netdev,236			struct ethtool_link_ksettings *cmd)237{238	ethtool_link_ksettings_zero_link_mode(cmd, supported);239	ethtool_link_ksettings_zero_link_mode(cmd, advertising);240 241	ethtool_link_ksettings_add_link_mode(cmd, supported, 10000baseCR_Full);242	ethtool_link_ksettings_add_link_mode(cmd, supported, 10000baseSR_Full);243	ethtool_link_ksettings_add_link_mode(cmd, supported, 10000baseLR_Full);244	ethtool_link_ksettings_add_link_mode(cmd, advertising, 10000baseCR_Full);245	ethtool_link_ksettings_add_link_mode(cmd, advertising, 10000baseSR_Full);246	ethtool_link_ksettings_add_link_mode(cmd, advertising, 10000baseLR_Full);247	cmd->base.autoneg = AUTONEG_DISABLE;248	ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);249	ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE);250	cmd->base.port = PORT_FIBRE;251	cmd->base.phy_address = 0;252 253	if (netif_carrier_ok(netdev)) {254		cmd->base.speed = SPEED_10000;255		cmd->base.duplex = DUPLEX_FULL;256	} else {257		cmd->base.speed = SPEED_UNKNOWN;258		cmd->base.duplex = DUPLEX_UNKNOWN;259	}260 261	return 0;262}263 264static int265bnad_set_link_ksettings(struct net_device *netdev,266			const struct ethtool_link_ksettings *cmd)267{268	/* 10G full duplex setting supported only */269	if (cmd->base.autoneg == AUTONEG_ENABLE)270		return -EOPNOTSUPP;271 272	if ((cmd->base.speed == SPEED_10000) &&273	    (cmd->base.duplex == DUPLEX_FULL))274		return 0;275 276	return -EOPNOTSUPP;277}278 279static void280bnad_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)281{282	struct bnad *bnad = netdev_priv(netdev);283	struct bfa_ioc_attr *ioc_attr;284	unsigned long flags;285 286	strscpy(drvinfo->driver, BNAD_NAME, sizeof(drvinfo->driver));287 288	ioc_attr = kzalloc(sizeof(*ioc_attr), GFP_KERNEL);289	if (ioc_attr) {290		spin_lock_irqsave(&bnad->bna_lock, flags);291		bfa_nw_ioc_get_attr(&bnad->bna.ioceth.ioc, ioc_attr);292		spin_unlock_irqrestore(&bnad->bna_lock, flags);293 294		strscpy(drvinfo->fw_version, ioc_attr->adapter_attr.fw_ver,295			sizeof(drvinfo->fw_version));296		kfree(ioc_attr);297	}298 299	strscpy(drvinfo->bus_info, pci_name(bnad->pcidev),300		sizeof(drvinfo->bus_info));301}302 303static void304bnad_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wolinfo)305{306	wolinfo->supported = 0;307	wolinfo->wolopts = 0;308}309 310static int bnad_get_coalesce(struct net_device *netdev,311			     struct ethtool_coalesce *coalesce,312			     struct kernel_ethtool_coalesce *kernel_coal,313			     struct netlink_ext_ack *extack)314{315	struct bnad *bnad = netdev_priv(netdev);316	unsigned long flags;317 318	/* Lock rqd. to access bnad->bna_lock */319	spin_lock_irqsave(&bnad->bna_lock, flags);320	coalesce->use_adaptive_rx_coalesce =321		(bnad->cfg_flags & BNAD_CF_DIM_ENABLED) ? true : false;322	spin_unlock_irqrestore(&bnad->bna_lock, flags);323 324	coalesce->rx_coalesce_usecs = bnad->rx_coalescing_timeo *325					BFI_COALESCING_TIMER_UNIT;326	coalesce->tx_coalesce_usecs = bnad->tx_coalescing_timeo *327					BFI_COALESCING_TIMER_UNIT;328	coalesce->tx_max_coalesced_frames = BFI_TX_INTERPKT_COUNT;329 330	return 0;331}332 333static int bnad_set_coalesce(struct net_device *netdev,334			     struct ethtool_coalesce *coalesce,335			     struct kernel_ethtool_coalesce *kernel_coal,336			     struct netlink_ext_ack *extack)337{338	struct bnad *bnad = netdev_priv(netdev);339	unsigned long flags;340	int to_del = 0;341 342	if (coalesce->rx_coalesce_usecs == 0 ||343	    coalesce->rx_coalesce_usecs >344	    BFI_MAX_COALESCING_TIMEO * BFI_COALESCING_TIMER_UNIT)345		return -EINVAL;346 347	if (coalesce->tx_coalesce_usecs == 0 ||348	    coalesce->tx_coalesce_usecs >349	    BFI_MAX_COALESCING_TIMEO * BFI_COALESCING_TIMER_UNIT)350		return -EINVAL;351 352	mutex_lock(&bnad->conf_mutex);353	/*354	 * Do not need to store rx_coalesce_usecs here355	 * Every time DIM is disabled, we can get it from the356	 * stack.357	 */358	spin_lock_irqsave(&bnad->bna_lock, flags);359	if (coalesce->use_adaptive_rx_coalesce) {360		if (!(bnad->cfg_flags & BNAD_CF_DIM_ENABLED)) {361			bnad->cfg_flags |= BNAD_CF_DIM_ENABLED;362			bnad_dim_timer_start(bnad);363		}364	} else {365		if (bnad->cfg_flags & BNAD_CF_DIM_ENABLED) {366			bnad->cfg_flags &= ~BNAD_CF_DIM_ENABLED;367			if (bnad->cfg_flags & BNAD_CF_DIM_ENABLED &&368			    test_bit(BNAD_RF_DIM_TIMER_RUNNING,369			    &bnad->run_flags)) {370				clear_bit(BNAD_RF_DIM_TIMER_RUNNING,371							&bnad->run_flags);372				to_del = 1;373			}374			spin_unlock_irqrestore(&bnad->bna_lock, flags);375			if (to_del)376				del_timer_sync(&bnad->dim_timer);377			spin_lock_irqsave(&bnad->bna_lock, flags);378			bnad_rx_coalescing_timeo_set(bnad);379		}380	}381	if (bnad->tx_coalescing_timeo != coalesce->tx_coalesce_usecs /382					BFI_COALESCING_TIMER_UNIT) {383		bnad->tx_coalescing_timeo = coalesce->tx_coalesce_usecs /384						BFI_COALESCING_TIMER_UNIT;385		bnad_tx_coalescing_timeo_set(bnad);386	}387 388	if (bnad->rx_coalescing_timeo != coalesce->rx_coalesce_usecs /389					BFI_COALESCING_TIMER_UNIT) {390		bnad->rx_coalescing_timeo = coalesce->rx_coalesce_usecs /391						BFI_COALESCING_TIMER_UNIT;392 393		if (!(bnad->cfg_flags & BNAD_CF_DIM_ENABLED))394			bnad_rx_coalescing_timeo_set(bnad);395 396	}397 398	/* Add Tx Inter-pkt DMA count?  */399 400	spin_unlock_irqrestore(&bnad->bna_lock, flags);401 402	mutex_unlock(&bnad->conf_mutex);403	return 0;404}405 406static void407bnad_get_ringparam(struct net_device *netdev,408		   struct ethtool_ringparam *ringparam,409		   struct kernel_ethtool_ringparam *kernel_ringparam,410		   struct netlink_ext_ack *extack)411{412	struct bnad *bnad = netdev_priv(netdev);413 414	ringparam->rx_max_pending = BNAD_MAX_RXQ_DEPTH;415	ringparam->tx_max_pending = BNAD_MAX_TXQ_DEPTH;416 417	ringparam->rx_pending = bnad->rxq_depth;418	ringparam->tx_pending = bnad->txq_depth;419}420 421static int422bnad_set_ringparam(struct net_device *netdev,423		   struct ethtool_ringparam *ringparam,424		   struct kernel_ethtool_ringparam *kernel_ringparam,425		   struct netlink_ext_ack *extack)426{427	int i, current_err, err = 0;428	struct bnad *bnad = netdev_priv(netdev);429	unsigned long flags;430 431	mutex_lock(&bnad->conf_mutex);432	if (ringparam->rx_pending == bnad->rxq_depth &&433	    ringparam->tx_pending == bnad->txq_depth) {434		mutex_unlock(&bnad->conf_mutex);435		return 0;436	}437 438	if (ringparam->rx_pending < BNAD_MIN_Q_DEPTH ||439	    ringparam->rx_pending > BNAD_MAX_RXQ_DEPTH ||440	    !is_power_of_2(ringparam->rx_pending)) {441		mutex_unlock(&bnad->conf_mutex);442		return -EINVAL;443	}444	if (ringparam->tx_pending < BNAD_MIN_Q_DEPTH ||445	    ringparam->tx_pending > BNAD_MAX_TXQ_DEPTH ||446	    !is_power_of_2(ringparam->tx_pending)) {447		mutex_unlock(&bnad->conf_mutex);448		return -EINVAL;449	}450 451	if (ringparam->rx_pending != bnad->rxq_depth) {452		bnad->rxq_depth = ringparam->rx_pending;453		if (!netif_running(netdev)) {454			mutex_unlock(&bnad->conf_mutex);455			return 0;456		}457 458		for (i = 0; i < bnad->num_rx; i++) {459			if (!bnad->rx_info[i].rx)460				continue;461			bnad_destroy_rx(bnad, i);462			current_err = bnad_setup_rx(bnad, i);463			if (current_err && !err)464				err = current_err;465		}466 467		if (!err && bnad->rx_info[0].rx) {468			/* restore rx configuration */469			bnad_restore_vlans(bnad, 0);470			bnad_enable_default_bcast(bnad);471			spin_lock_irqsave(&bnad->bna_lock, flags);472			bnad_mac_addr_set_locked(bnad, netdev->dev_addr);473			spin_unlock_irqrestore(&bnad->bna_lock, flags);474			bnad->cfg_flags &= ~(BNAD_CF_ALLMULTI |475					     BNAD_CF_PROMISC);476			bnad_set_rx_mode(netdev);477		}478	}479	if (ringparam->tx_pending != bnad->txq_depth) {480		bnad->txq_depth = ringparam->tx_pending;481		if (!netif_running(netdev)) {482			mutex_unlock(&bnad->conf_mutex);483			return 0;484		}485 486		for (i = 0; i < bnad->num_tx; i++) {487			if (!bnad->tx_info[i].tx)488				continue;489			bnad_destroy_tx(bnad, i);490			current_err = bnad_setup_tx(bnad, i);491			if (current_err && !err)492				err = current_err;493		}494	}495 496	mutex_unlock(&bnad->conf_mutex);497	return err;498}499 500static void501bnad_get_pauseparam(struct net_device *netdev,502		    struct ethtool_pauseparam *pauseparam)503{504	struct bnad *bnad = netdev_priv(netdev);505 506	pauseparam->autoneg = 0;507	pauseparam->rx_pause = bnad->bna.enet.pause_config.rx_pause;508	pauseparam->tx_pause = bnad->bna.enet.pause_config.tx_pause;509}510 511static int512bnad_set_pauseparam(struct net_device *netdev,513		    struct ethtool_pauseparam *pauseparam)514{515	struct bnad *bnad = netdev_priv(netdev);516	struct bna_pause_config pause_config;517	unsigned long flags;518 519	if (pauseparam->autoneg == AUTONEG_ENABLE)520		return -EINVAL;521 522	mutex_lock(&bnad->conf_mutex);523	if (pauseparam->rx_pause != bnad->bna.enet.pause_config.rx_pause ||524	    pauseparam->tx_pause != bnad->bna.enet.pause_config.tx_pause) {525		pause_config.rx_pause = pauseparam->rx_pause;526		pause_config.tx_pause = pauseparam->tx_pause;527		spin_lock_irqsave(&bnad->bna_lock, flags);528		bna_enet_pause_config(&bnad->bna.enet, &pause_config);529		spin_unlock_irqrestore(&bnad->bna_lock, flags);530	}531	mutex_unlock(&bnad->conf_mutex);532	return 0;533}534 535static void bnad_get_txf_strings(u8 **string, int f_num)536{537	ethtool_sprintf(string, "txf%d_ucast_octets", f_num);538	ethtool_sprintf(string, "txf%d_ucast", f_num);539	ethtool_sprintf(string, "txf%d_ucast_vlan", f_num);540	ethtool_sprintf(string, "txf%d_mcast_octets", f_num);541	ethtool_sprintf(string, "txf%d_mcast", f_num);542	ethtool_sprintf(string, "txf%d_mcast_vlan", f_num);543	ethtool_sprintf(string, "txf%d_bcast_octets", f_num);544	ethtool_sprintf(string, "txf%d_bcast", f_num);545	ethtool_sprintf(string, "txf%d_bcast_vlan", f_num);546	ethtool_sprintf(string, "txf%d_errors", f_num);547	ethtool_sprintf(string, "txf%d_filter_vlan", f_num);548	ethtool_sprintf(string, "txf%d_filter_mac_sa", f_num);549}550 551static void bnad_get_rxf_strings(u8 **string, int f_num)552{553	ethtool_sprintf(string, "rxf%d_ucast_octets", f_num);554	ethtool_sprintf(string, "rxf%d_ucast", f_num);555	ethtool_sprintf(string, "rxf%d_ucast_vlan", f_num);556	ethtool_sprintf(string, "rxf%d_mcast_octets", f_num);557	ethtool_sprintf(string, "rxf%d_mcast", f_num);558	ethtool_sprintf(string, "rxf%d_mcast_vlan", f_num);559	ethtool_sprintf(string, "rxf%d_bcast_octets", f_num);560	ethtool_sprintf(string, "rxf%d_bcast", f_num);561	ethtool_sprintf(string, "rxf%d_bcast_vlan", f_num);562	ethtool_sprintf(string, "rxf%d_frame_drops", f_num);563}564 565static void bnad_get_cq_strings(u8 **string, int q_num)566{567	ethtool_sprintf(string, "cq%d_producer_index", q_num);568	ethtool_sprintf(string, "cq%d_consumer_index", q_num);569	ethtool_sprintf(string, "cq%d_hw_producer_index", q_num);570	ethtool_sprintf(string, "cq%d_intr", q_num);571	ethtool_sprintf(string, "cq%d_poll", q_num);572	ethtool_sprintf(string, "cq%d_schedule", q_num);573	ethtool_sprintf(string, "cq%d_keep_poll", q_num);574	ethtool_sprintf(string, "cq%d_complete", q_num);575}576 577static void bnad_get_rxq_strings(u8 **string, int q_num)578{579	ethtool_sprintf(string, "rxq%d_packets", q_num);580	ethtool_sprintf(string, "rxq%d_bytes", q_num);581	ethtool_sprintf(string, "rxq%d_packets_with_error", q_num);582	ethtool_sprintf(string, "rxq%d_allocbuf_failed", q_num);583	ethtool_sprintf(string, "rxq%d_mapbuf_failed", q_num);584	ethtool_sprintf(string, "rxq%d_producer_index", q_num);585	ethtool_sprintf(string, "rxq%d_consumer_index", q_num);586}587 588static void bnad_get_txq_strings(u8 **string, int q_num)589{590	ethtool_sprintf(string, "txq%d_packets", q_num);591	ethtool_sprintf(string, "txq%d_bytes", q_num);592	ethtool_sprintf(string, "txq%d_producer_index", q_num);593	ethtool_sprintf(string, "txq%d_consumer_index", q_num);594	ethtool_sprintf(string, "txq%d_hw_consumer_index", q_num);595}596 597static void598bnad_get_strings(struct net_device *netdev, u32 stringset, u8 *string)599{600	struct bnad *bnad = netdev_priv(netdev);601	int i, j, q_num;602	u32 bmap;603 604	if (stringset != ETH_SS_STATS)605		return;606 607	mutex_lock(&bnad->conf_mutex);608 609	for (i = 0; i < BNAD_ETHTOOL_STATS_NUM; i++) {610		BUG_ON(!(strlen(bnad_net_stats_strings[i]) < ETH_GSTRING_LEN));611		ethtool_puts(&string, bnad_net_stats_strings[i]);612	}613 614	bmap = bna_tx_rid_mask(&bnad->bna);615	for (i = 0; bmap; i++) {616		if (bmap & 1)617			bnad_get_txf_strings(&string, i);618		bmap >>= 1;619	}620 621	bmap = bna_rx_rid_mask(&bnad->bna);622	for (i = 0; bmap; i++, bmap >>= 1) {623		if (bmap & 1)624			bnad_get_rxf_strings(&string, i);625		bmap >>= 1;626	}627 628	q_num = 0;629	for (i = 0; i < bnad->num_rx; i++) {630		if (!bnad->rx_info[i].rx)631			continue;632		for (j = 0; j < bnad->num_rxp_per_rx; j++)633			bnad_get_cq_strings(&string, q_num++);634	}635 636	q_num = 0;637	for (i = 0; i < bnad->num_rx; i++) {638		if (!bnad->rx_info[i].rx)639			continue;640		for (j = 0; j < bnad->num_rxp_per_rx; j++) {641			bnad_get_rxq_strings(&string, q_num++);642			if (bnad->rx_info[i].rx_ctrl[j].ccb &&643			    bnad->rx_info[i].rx_ctrl[j].ccb->rcb[1] &&644			    bnad->rx_info[i].rx_ctrl[j].ccb->rcb[1]->rxq)645				bnad_get_rxq_strings(&string, q_num++);646		}647	}648 649	q_num = 0;650	for (i = 0; i < bnad->num_tx; i++) {651		if (!bnad->tx_info[i].tx)652			continue;653		for (j = 0; j < bnad->num_txq_per_tx; j++)654			bnad_get_txq_strings(&string, q_num++);655	}656 657	mutex_unlock(&bnad->conf_mutex);658}659 660static int661bnad_get_stats_count_locked(struct net_device *netdev)662{663	struct bnad *bnad = netdev_priv(netdev);664	int i, j, count = 0, rxf_active_num = 0, txf_active_num = 0;665	u32 bmap;666 667	bmap = bna_tx_rid_mask(&bnad->bna);668	for (i = 0; bmap; i++) {669		if (bmap & 1)670			txf_active_num++;671		bmap >>= 1;672	}673	bmap = bna_rx_rid_mask(&bnad->bna);674	for (i = 0; bmap; i++) {675		if (bmap & 1)676			rxf_active_num++;677		bmap >>= 1;678	}679	count = BNAD_ETHTOOL_STATS_NUM +680		txf_active_num * BNAD_NUM_TXF_COUNTERS +681		rxf_active_num * BNAD_NUM_RXF_COUNTERS;682 683	for (i = 0; i < bnad->num_rx; i++) {684		if (!bnad->rx_info[i].rx)685			continue;686		count += bnad->num_rxp_per_rx * BNAD_NUM_CQ_COUNTERS;687		count += bnad->num_rxp_per_rx * BNAD_NUM_RXQ_COUNTERS;688		for (j = 0; j < bnad->num_rxp_per_rx; j++)689			if (bnad->rx_info[i].rx_ctrl[j].ccb &&690				bnad->rx_info[i].rx_ctrl[j].ccb->rcb[1] &&691				bnad->rx_info[i].rx_ctrl[j].ccb->rcb[1]->rxq)692				count +=  BNAD_NUM_RXQ_COUNTERS;693	}694 695	for (i = 0; i < bnad->num_tx; i++) {696		if (!bnad->tx_info[i].tx)697			continue;698		count += bnad->num_txq_per_tx * BNAD_NUM_TXQ_COUNTERS;699	}700	return count;701}702 703static int704bnad_per_q_stats_fill(struct bnad *bnad, u64 *buf, int bi)705{706	int i, j;707	struct bna_rcb *rcb = NULL;708	struct bna_tcb *tcb = NULL;709 710	for (i = 0; i < bnad->num_rx; i++) {711		if (!bnad->rx_info[i].rx)712			continue;713		for (j = 0; j < bnad->num_rxp_per_rx; j++)714			if (bnad->rx_info[i].rx_ctrl[j].ccb &&715				bnad->rx_info[i].rx_ctrl[j].ccb->rcb[0] &&716				bnad->rx_info[i].rx_ctrl[j].ccb->rcb[0]->rxq) {717				buf[bi++] = bnad->rx_info[i].rx_ctrl[j].718						ccb->producer_index;719				buf[bi++] = 0; /* ccb->consumer_index */720				buf[bi++] = *(bnad->rx_info[i].rx_ctrl[j].721						ccb->hw_producer_index);722 723				buf[bi++] = bnad->rx_info[i].724						rx_ctrl[j].rx_intr_ctr;725				buf[bi++] = bnad->rx_info[i].726						rx_ctrl[j].rx_poll_ctr;727				buf[bi++] = bnad->rx_info[i].728						rx_ctrl[j].rx_schedule;729				buf[bi++] = bnad->rx_info[i].730						rx_ctrl[j].rx_keep_poll;731				buf[bi++] = bnad->rx_info[i].732						rx_ctrl[j].rx_complete;733			}734	}735	for (i = 0; i < bnad->num_rx; i++) {736		if (!bnad->rx_info[i].rx)737			continue;738		for (j = 0; j < bnad->num_rxp_per_rx; j++)739			if (bnad->rx_info[i].rx_ctrl[j].ccb) {740				if (bnad->rx_info[i].rx_ctrl[j].ccb->rcb[0] &&741					bnad->rx_info[i].rx_ctrl[j].ccb->742					rcb[0]->rxq) {743					rcb = bnad->rx_info[i].rx_ctrl[j].744							ccb->rcb[0];745					buf[bi++] = rcb->rxq->rx_packets;746					buf[bi++] = rcb->rxq->rx_bytes;747					buf[bi++] = rcb->rxq->748							rx_packets_with_error;749					buf[bi++] = rcb->rxq->750							rxbuf_alloc_failed;751					buf[bi++] = rcb->rxq->rxbuf_map_failed;752					buf[bi++] = rcb->producer_index;753					buf[bi++] = rcb->consumer_index;754				}755				if (bnad->rx_info[i].rx_ctrl[j].ccb->rcb[1] &&756					bnad->rx_info[i].rx_ctrl[j].ccb->757					rcb[1]->rxq) {758					rcb = bnad->rx_info[i].rx_ctrl[j].759								ccb->rcb[1];760					buf[bi++] = rcb->rxq->rx_packets;761					buf[bi++] = rcb->rxq->rx_bytes;762					buf[bi++] = rcb->rxq->763							rx_packets_with_error;764					buf[bi++] = rcb->rxq->765							rxbuf_alloc_failed;766					buf[bi++] = rcb->rxq->rxbuf_map_failed;767					buf[bi++] = rcb->producer_index;768					buf[bi++] = rcb->consumer_index;769				}770			}771	}772 773	for (i = 0; i < bnad->num_tx; i++) {774		if (!bnad->tx_info[i].tx)775			continue;776		for (j = 0; j < bnad->num_txq_per_tx; j++)777			if (bnad->tx_info[i].tcb[j] &&778				bnad->tx_info[i].tcb[j]->txq) {779				tcb = bnad->tx_info[i].tcb[j];780				buf[bi++] = tcb->txq->tx_packets;781				buf[bi++] = tcb->txq->tx_bytes;782				buf[bi++] = tcb->producer_index;783				buf[bi++] = tcb->consumer_index;784				buf[bi++] = *(tcb->hw_consumer_index);785			}786	}787 788	return bi;789}790 791static void792bnad_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats,793		       u64 *buf)794{795	struct bnad *bnad = netdev_priv(netdev);796	int i, j, bi = 0;797	unsigned long flags;798	struct rtnl_link_stats64 net_stats64;799	u64 *stats64;800	u32 bmap;801 802	mutex_lock(&bnad->conf_mutex);803	if (bnad_get_stats_count_locked(netdev) != stats->n_stats) {804		mutex_unlock(&bnad->conf_mutex);805		return;806	}807 808	/*809	 * Used bna_lock to sync reads from bna_stats, which is written810	 * under the same lock811	 */812	spin_lock_irqsave(&bnad->bna_lock, flags);813 814	memset(&net_stats64, 0, sizeof(net_stats64));815	bnad_netdev_qstats_fill(bnad, &net_stats64);816	bnad_netdev_hwstats_fill(bnad, &net_stats64);817 818	buf[bi++] = net_stats64.rx_packets;819	buf[bi++] = net_stats64.tx_packets;820	buf[bi++] = net_stats64.rx_bytes;821	buf[bi++] = net_stats64.tx_bytes;822	buf[bi++] = net_stats64.rx_errors;823	buf[bi++] = net_stats64.tx_errors;824	buf[bi++] = net_stats64.rx_dropped;825	buf[bi++] = net_stats64.tx_dropped;826	buf[bi++] = net_stats64.multicast;827	buf[bi++] = net_stats64.collisions;828	buf[bi++] = net_stats64.rx_length_errors;829	buf[bi++] = net_stats64.rx_crc_errors;830	buf[bi++] = net_stats64.rx_frame_errors;831	buf[bi++] = net_stats64.tx_fifo_errors;832 833	/* Get netif_queue_stopped from stack */834	bnad->stats.drv_stats.netif_queue_stopped = netif_queue_stopped(netdev);835 836	/* Fill driver stats into ethtool buffers */837	stats64 = (u64 *)&bnad->stats.drv_stats;838	for (i = 0; i < sizeof(struct bnad_drv_stats) / sizeof(u64); i++)839		buf[bi++] = stats64[i];840 841	/* Fill hardware stats excluding the rxf/txf into ethtool bufs */842	stats64 = (u64 *) &bnad->stats.bna_stats->hw_stats;843	for (i = 0;844	     i < offsetof(struct bfi_enet_stats, rxf_stats[0]) /845		sizeof(u64);846	     i++)847		buf[bi++] = stats64[i];848 849	/* Fill txf stats into ethtool buffers */850	bmap = bna_tx_rid_mask(&bnad->bna);851	for (i = 0; bmap; i++) {852		if (bmap & 1) {853			stats64 = (u64 *)&bnad->stats.bna_stats->854						hw_stats.txf_stats[i];855			for (j = 0; j < sizeof(struct bfi_enet_stats_txf) /856					sizeof(u64); j++)857				buf[bi++] = stats64[j];858		}859		bmap >>= 1;860	}861 862	/*  Fill rxf stats into ethtool buffers */863	bmap = bna_rx_rid_mask(&bnad->bna);864	for (i = 0; bmap; i++) {865		if (bmap & 1) {866			stats64 = (u64 *)&bnad->stats.bna_stats->867						hw_stats.rxf_stats[i];868			for (j = 0; j < sizeof(struct bfi_enet_stats_rxf) /869					sizeof(u64); j++)870				buf[bi++] = stats64[j];871		}872		bmap >>= 1;873	}874 875	/* Fill per Q stats into ethtool buffers */876	bi = bnad_per_q_stats_fill(bnad, buf, bi);877 878	spin_unlock_irqrestore(&bnad->bna_lock, flags);879 880	mutex_unlock(&bnad->conf_mutex);881}882 883static int884bnad_get_sset_count(struct net_device *netdev, int sset)885{886	switch (sset) {887	case ETH_SS_STATS:888		return bnad_get_stats_count_locked(netdev);889	default:890		return -EOPNOTSUPP;891	}892}893 894static u32895bnad_get_flash_partition_by_offset(struct bnad *bnad, u32 offset,896				u32 *base_offset)897{898	struct bfa_flash_attr *flash_attr;899	struct bnad_iocmd_comp fcomp;900	u32 i, flash_part = 0, ret;901	unsigned long flags = 0;902 903	flash_attr = kzalloc(sizeof(struct bfa_flash_attr), GFP_KERNEL);904	if (!flash_attr)905		return 0;906 907	fcomp.bnad = bnad;908	fcomp.comp_status = 0;909 910	init_completion(&fcomp.comp);911	spin_lock_irqsave(&bnad->bna_lock, flags);912	ret = bfa_nw_flash_get_attr(&bnad->bna.flash, flash_attr,913				bnad_cb_completion, &fcomp);914	if (ret != BFA_STATUS_OK) {915		spin_unlock_irqrestore(&bnad->bna_lock, flags);916		kfree(flash_attr);917		return 0;918	}919	spin_unlock_irqrestore(&bnad->bna_lock, flags);920	wait_for_completion(&fcomp.comp);921	ret = fcomp.comp_status;922 923	/* Check for the flash type & base offset value */924	if (ret == BFA_STATUS_OK) {925		for (i = 0; i < flash_attr->npart; i++) {926			if (offset >= flash_attr->part[i].part_off &&927			    offset < (flash_attr->part[i].part_off +928				      flash_attr->part[i].part_size)) {929				flash_part = flash_attr->part[i].part_type;930				*base_offset = flash_attr->part[i].part_off;931				break;932			}933		}934	}935	kfree(flash_attr);936	return flash_part;937}938 939static int940bnad_get_eeprom_len(struct net_device *netdev)941{942	return BFA_TOTAL_FLASH_SIZE;943}944 945static int946bnad_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,947		u8 *bytes)948{949	struct bnad *bnad = netdev_priv(netdev);950	struct bnad_iocmd_comp fcomp;951	u32 flash_part = 0, base_offset = 0;952	unsigned long flags = 0;953	int ret = 0;954 955	/* Fill the magic value */956	eeprom->magic = bnad->pcidev->vendor | (bnad->pcidev->device << 16);957 958	/* Query the flash partition based on the offset */959	flash_part = bnad_get_flash_partition_by_offset(bnad,960				eeprom->offset, &base_offset);961	if (flash_part == 0)962		return -EFAULT;963 964	fcomp.bnad = bnad;965	fcomp.comp_status = 0;966 967	init_completion(&fcomp.comp);968	spin_lock_irqsave(&bnad->bna_lock, flags);969	ret = bfa_nw_flash_read_part(&bnad->bna.flash, flash_part,970				bnad->id, bytes, eeprom->len,971				eeprom->offset - base_offset,972				bnad_cb_completion, &fcomp);973	if (ret != BFA_STATUS_OK) {974		spin_unlock_irqrestore(&bnad->bna_lock, flags);975		goto done;976	}977 978	spin_unlock_irqrestore(&bnad->bna_lock, flags);979	wait_for_completion(&fcomp.comp);980	ret = fcomp.comp_status;981done:982	return ret;983}984 985static int986bnad_set_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,987		u8 *bytes)988{989	struct bnad *bnad = netdev_priv(netdev);990	struct bnad_iocmd_comp fcomp;991	u32 flash_part = 0, base_offset = 0;992	unsigned long flags = 0;993	int ret = 0;994 995	/* Check if the flash update request is valid */996	if (eeprom->magic != (bnad->pcidev->vendor |997			     (bnad->pcidev->device << 16)))998		return -EINVAL;999 1000	/* Query the flash partition based on the offset */1001	flash_part = bnad_get_flash_partition_by_offset(bnad,1002				eeprom->offset, &base_offset);1003	if (flash_part == 0)1004		return -EFAULT;1005 1006	fcomp.bnad = bnad;1007	fcomp.comp_status = 0;1008 1009	init_completion(&fcomp.comp);1010	spin_lock_irqsave(&bnad->bna_lock, flags);1011	ret = bfa_nw_flash_update_part(&bnad->bna.flash, flash_part,1012				bnad->id, bytes, eeprom->len,1013				eeprom->offset - base_offset,1014				bnad_cb_completion, &fcomp);1015	if (ret != BFA_STATUS_OK) {1016		spin_unlock_irqrestore(&bnad->bna_lock, flags);1017		goto done;1018	}1019 1020	spin_unlock_irqrestore(&bnad->bna_lock, flags);1021	wait_for_completion(&fcomp.comp);1022	ret = fcomp.comp_status;1023done:1024	return ret;1025}1026 1027static int1028bnad_flash_device(struct net_device *netdev, struct ethtool_flash *eflash)1029{1030	struct bnad *bnad = netdev_priv(netdev);1031	struct bnad_iocmd_comp fcomp;1032	const struct firmware *fw;1033	int ret = 0;1034 1035	ret = request_firmware(&fw, eflash->data, &bnad->pcidev->dev);1036	if (ret) {1037		netdev_err(netdev, "can't load firmware %s\n", eflash->data);1038		goto out;1039	}1040 1041	fcomp.bnad = bnad;1042	fcomp.comp_status = 0;1043 1044	init_completion(&fcomp.comp);1045	spin_lock_irq(&bnad->bna_lock);1046	ret = bfa_nw_flash_update_part(&bnad->bna.flash, BFA_FLASH_PART_FWIMG,1047				bnad->id, (u8 *)fw->data, fw->size, 0,1048				bnad_cb_completion, &fcomp);1049	if (ret != BFA_STATUS_OK) {1050		netdev_warn(netdev, "flash update failed with err=%d\n", ret);1051		ret = -EIO;1052		spin_unlock_irq(&bnad->bna_lock);1053		goto out;1054	}1055 1056	spin_unlock_irq(&bnad->bna_lock);1057	wait_for_completion(&fcomp.comp);1058	if (fcomp.comp_status != BFA_STATUS_OK) {1059		ret = -EIO;1060		netdev_warn(netdev,1061			    "firmware image update failed with err=%d\n",1062			    fcomp.comp_status);1063	}1064out:1065	release_firmware(fw);1066	return ret;1067}1068 1069static const struct ethtool_ops bnad_ethtool_ops = {1070	.supported_coalesce_params = ETHTOOL_COALESCE_USECS |1071				     ETHTOOL_COALESCE_TX_MAX_FRAMES |1072				     ETHTOOL_COALESCE_USE_ADAPTIVE_RX,1073	.get_drvinfo = bnad_get_drvinfo,1074	.get_wol = bnad_get_wol,1075	.get_link = ethtool_op_get_link,1076	.get_coalesce = bnad_get_coalesce,1077	.set_coalesce = bnad_set_coalesce,1078	.get_ringparam = bnad_get_ringparam,1079	.set_ringparam = bnad_set_ringparam,1080	.get_pauseparam = bnad_get_pauseparam,1081	.set_pauseparam = bnad_set_pauseparam,1082	.get_strings = bnad_get_strings,1083	.get_ethtool_stats = bnad_get_ethtool_stats,1084	.get_sset_count = bnad_get_sset_count,1085	.get_eeprom_len = bnad_get_eeprom_len,1086	.get_eeprom = bnad_get_eeprom,1087	.set_eeprom = bnad_set_eeprom,1088	.flash_device = bnad_flash_device,1089	.get_ts_info = ethtool_op_get_ts_info,1090	.get_link_ksettings = bnad_get_link_ksettings,1091	.set_link_ksettings = bnad_set_link_ksettings,1092};1093 1094void1095bnad_set_ethtool_ops(struct net_device *netdev)1096{1097	netdev->ethtool_ops = &bnad_ethtool_ops;1098}1099