| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  * Linux driver for VMware's vmxnet3 ethernet NIC. | 
 | 3 |  * | 
 | 4 |  * Copyright (C) 2008-2009, VMware, Inc. All Rights Reserved. | 
 | 5 |  * | 
 | 6 |  * This program is free software; you can redistribute it and/or modify it | 
 | 7 |  * under the terms of the GNU General Public License as published by the | 
 | 8 |  * Free Software Foundation; version 2 of the License and no later version. | 
 | 9 |  * | 
 | 10 |  * This program is distributed in the hope that it will be useful, but | 
 | 11 |  * WITHOUT ANY WARRANTY; without even the implied warranty of | 
 | 12 |  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | 
 | 13 |  * NON INFRINGEMENT.  See the GNU General Public License for more | 
 | 14 |  * details. | 
 | 15 |  * | 
 | 16 |  * You should have received a copy of the GNU General Public License | 
 | 17 |  * along with this program; if not, write to the Free Software | 
 | 18 |  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | 
 | 19 |  * | 
 | 20 |  * The full GNU General Public License is included in this distribution in | 
 | 21 |  * the file called "COPYING". | 
 | 22 |  * | 
 | 23 |  * Maintained by: Shreyas Bhatewara <pv-drivers@vmware.com> | 
 | 24 |  * | 
 | 25 |  */ | 
 | 26 |  | 
 | 27 |  | 
 | 28 | #include "vmxnet3_int.h" | 
 | 29 |  | 
 | 30 | struct vmxnet3_stat_desc { | 
 | 31 | 	char desc[ETH_GSTRING_LEN]; | 
 | 32 | 	int  offset; | 
 | 33 | }; | 
 | 34 |  | 
 | 35 |  | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 36 | /* per tq stats maintained by the device */ | 
 | 37 | static const struct vmxnet3_stat_desc | 
 | 38 | vmxnet3_tq_dev_stats[] = { | 
 | 39 | 	/* description,         offset */ | 
| Shreyas Bhatewara | 76d39da | 2011-01-14 14:59:47 +0000 | [diff] [blame] | 40 | 	{ "Tx Queue#",        0 }, | 
 | 41 | 	{ "  TSO pkts tx",	offsetof(struct UPT1_TxStats, TSOPktsTxOK) }, | 
 | 42 | 	{ "  TSO bytes tx",	offsetof(struct UPT1_TxStats, TSOBytesTxOK) }, | 
 | 43 | 	{ "  ucast pkts tx",	offsetof(struct UPT1_TxStats, ucastPktsTxOK) }, | 
 | 44 | 	{ "  ucast bytes tx",	offsetof(struct UPT1_TxStats, ucastBytesTxOK) }, | 
 | 45 | 	{ "  mcast pkts tx",	offsetof(struct UPT1_TxStats, mcastPktsTxOK) }, | 
 | 46 | 	{ "  mcast bytes tx",	offsetof(struct UPT1_TxStats, mcastBytesTxOK) }, | 
 | 47 | 	{ "  bcast pkts tx",	offsetof(struct UPT1_TxStats, bcastPktsTxOK) }, | 
 | 48 | 	{ "  bcast bytes tx",	offsetof(struct UPT1_TxStats, bcastBytesTxOK) }, | 
 | 49 | 	{ "  pkts tx err",	offsetof(struct UPT1_TxStats, pktsTxError) }, | 
 | 50 | 	{ "  pkts tx discard",	offsetof(struct UPT1_TxStats, pktsTxDiscard) }, | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 51 | }; | 
 | 52 |  | 
 | 53 | /* per tq stats maintained by the driver */ | 
 | 54 | static const struct vmxnet3_stat_desc | 
 | 55 | vmxnet3_tq_driver_stats[] = { | 
 | 56 | 	/* description,         offset */ | 
| Shreyas Bhatewara | 76d39da | 2011-01-14 14:59:47 +0000 | [diff] [blame] | 57 | 	{"  drv dropped tx total",	offsetof(struct vmxnet3_tq_driver_stats, | 
 | 58 | 						 drop_total) }, | 
 | 59 | 	{ "     too many frags", offsetof(struct vmxnet3_tq_driver_stats, | 
 | 60 | 					  drop_too_many_frags) }, | 
 | 61 | 	{ "     giant hdr",	offsetof(struct vmxnet3_tq_driver_stats, | 
 | 62 | 					 drop_oversized_hdr) }, | 
 | 63 | 	{ "     hdr err",	offsetof(struct vmxnet3_tq_driver_stats, | 
 | 64 | 					 drop_hdr_inspect_err) }, | 
 | 65 | 	{ "     tso",		offsetof(struct vmxnet3_tq_driver_stats, | 
 | 66 | 					 drop_tso) }, | 
 | 67 | 	{ "  ring full",	offsetof(struct vmxnet3_tq_driver_stats, | 
 | 68 | 					 tx_ring_full) }, | 
 | 69 | 	{ "  pkts linearized",	offsetof(struct vmxnet3_tq_driver_stats, | 
 | 70 | 					 linearized) }, | 
 | 71 | 	{ "  hdr cloned",	offsetof(struct vmxnet3_tq_driver_stats, | 
 | 72 | 					 copy_skb_header) }, | 
 | 73 | 	{ "  giant hdr",	offsetof(struct vmxnet3_tq_driver_stats, | 
 | 74 | 					 oversized_hdr) }, | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 75 | }; | 
 | 76 |  | 
 | 77 | /* per rq stats maintained by the device */ | 
 | 78 | static const struct vmxnet3_stat_desc | 
 | 79 | vmxnet3_rq_dev_stats[] = { | 
| Shreyas Bhatewara | 76d39da | 2011-01-14 14:59:47 +0000 | [diff] [blame] | 80 | 	{ "Rx Queue#",        0 }, | 
 | 81 | 	{ "  LRO pkts rx",	offsetof(struct UPT1_RxStats, LROPktsRxOK) }, | 
 | 82 | 	{ "  LRO byte rx",	offsetof(struct UPT1_RxStats, LROBytesRxOK) }, | 
 | 83 | 	{ "  ucast pkts rx",	offsetof(struct UPT1_RxStats, ucastPktsRxOK) }, | 
 | 84 | 	{ "  ucast bytes rx",	offsetof(struct UPT1_RxStats, ucastBytesRxOK) }, | 
 | 85 | 	{ "  mcast pkts rx",	offsetof(struct UPT1_RxStats, mcastPktsRxOK) }, | 
 | 86 | 	{ "  mcast bytes rx",	offsetof(struct UPT1_RxStats, mcastBytesRxOK) }, | 
 | 87 | 	{ "  bcast pkts rx",	offsetof(struct UPT1_RxStats, bcastPktsRxOK) }, | 
 | 88 | 	{ "  bcast bytes rx",	offsetof(struct UPT1_RxStats, bcastBytesRxOK) }, | 
 | 89 | 	{ "  pkts rx OOB",	offsetof(struct UPT1_RxStats, pktsRxOutOfBuf) }, | 
 | 90 | 	{ "  pkts rx err",	offsetof(struct UPT1_RxStats, pktsRxError) }, | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 91 | }; | 
 | 92 |  | 
 | 93 | /* per rq stats maintained by the driver */ | 
 | 94 | static const struct vmxnet3_stat_desc | 
 | 95 | vmxnet3_rq_driver_stats[] = { | 
 | 96 | 	/* description,         offset */ | 
| Shreyas Bhatewara | 76d39da | 2011-01-14 14:59:47 +0000 | [diff] [blame] | 97 | 	{ "  drv dropped rx total", offsetof(struct vmxnet3_rq_driver_stats, | 
 | 98 | 					     drop_total) }, | 
 | 99 | 	{ "     err",		offsetof(struct vmxnet3_rq_driver_stats, | 
 | 100 | 					 drop_err) }, | 
 | 101 | 	{ "     fcs",		offsetof(struct vmxnet3_rq_driver_stats, | 
 | 102 | 					 drop_fcs) }, | 
 | 103 | 	{ "  rx buf alloc fail", offsetof(struct vmxnet3_rq_driver_stats, | 
 | 104 | 					  rx_buf_alloc_failure) }, | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 105 | }; | 
 | 106 |  | 
 | 107 | /* gloabl stats maintained by the driver */ | 
 | 108 | static const struct vmxnet3_stat_desc | 
 | 109 | vmxnet3_global_stats[] = { | 
 | 110 | 	/* description,         offset */ | 
| Shreyas Bhatewara | 76d39da | 2011-01-14 14:59:47 +0000 | [diff] [blame] | 111 | 	{ "tx timeout count",	offsetof(struct vmxnet3_adapter, | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 112 | 					 tx_timeout_count) } | 
 | 113 | }; | 
 | 114 |  | 
 | 115 |  | 
| stephen hemminger | 95305f6 | 2011-06-08 14:53:57 +0000 | [diff] [blame] | 116 | struct rtnl_link_stats64 * | 
 | 117 | vmxnet3_get_stats64(struct net_device *netdev, | 
 | 118 | 		   struct rtnl_link_stats64 *stats) | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 119 | { | 
 | 120 | 	struct vmxnet3_adapter *adapter; | 
 | 121 | 	struct vmxnet3_tq_driver_stats *drvTxStats; | 
 | 122 | 	struct vmxnet3_rq_driver_stats *drvRxStats; | 
 | 123 | 	struct UPT1_TxStats *devTxStats; | 
 | 124 | 	struct UPT1_RxStats *devRxStats; | 
| Shreyas Bhatewara | 83d0fef | 2011-01-14 14:59:57 +0000 | [diff] [blame] | 125 | 	unsigned long flags; | 
| Shreyas Bhatewara | 09c5088 | 2010-11-19 10:55:24 +0000 | [diff] [blame] | 126 | 	int i; | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 127 |  | 
 | 128 | 	adapter = netdev_priv(netdev); | 
 | 129 |  | 
 | 130 | 	/* Collect the dev stats into the shared area */ | 
| Shreyas Bhatewara | 83d0fef | 2011-01-14 14:59:57 +0000 | [diff] [blame] | 131 | 	spin_lock_irqsave(&adapter->cmd_lock, flags); | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 132 | 	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_GET_STATS); | 
| Shreyas Bhatewara | 83d0fef | 2011-01-14 14:59:57 +0000 | [diff] [blame] | 133 | 	spin_unlock_irqrestore(&adapter->cmd_lock, flags); | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 134 |  | 
| Shreyas Bhatewara | 09c5088 | 2010-11-19 10:55:24 +0000 | [diff] [blame] | 135 | 	for (i = 0; i < adapter->num_tx_queues; i++) { | 
 | 136 | 		devTxStats = &adapter->tqd_start[i].stats; | 
 | 137 | 		drvTxStats = &adapter->tx_queue[i].stats; | 
| stephen hemminger | 95305f6 | 2011-06-08 14:53:57 +0000 | [diff] [blame] | 138 | 		stats->tx_packets += devTxStats->ucastPktsTxOK + | 
 | 139 | 				     devTxStats->mcastPktsTxOK + | 
 | 140 | 				     devTxStats->bcastPktsTxOK; | 
 | 141 | 		stats->tx_bytes += devTxStats->ucastBytesTxOK + | 
 | 142 | 				   devTxStats->mcastBytesTxOK + | 
 | 143 | 				   devTxStats->bcastBytesTxOK; | 
 | 144 | 		stats->tx_errors += devTxStats->pktsTxError; | 
 | 145 | 		stats->tx_dropped += drvTxStats->drop_total; | 
| Shreyas Bhatewara | 09c5088 | 2010-11-19 10:55:24 +0000 | [diff] [blame] | 146 | 	} | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 147 |  | 
| Shreyas Bhatewara | 09c5088 | 2010-11-19 10:55:24 +0000 | [diff] [blame] | 148 | 	for (i = 0; i < adapter->num_rx_queues; i++) { | 
 | 149 | 		devRxStats = &adapter->rqd_start[i].stats; | 
 | 150 | 		drvRxStats = &adapter->rx_queue[i].stats; | 
| stephen hemminger | 95305f6 | 2011-06-08 14:53:57 +0000 | [diff] [blame] | 151 | 		stats->rx_packets += devRxStats->ucastPktsRxOK + | 
 | 152 | 				     devRxStats->mcastPktsRxOK + | 
 | 153 | 				     devRxStats->bcastPktsRxOK; | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 154 |  | 
| stephen hemminger | 95305f6 | 2011-06-08 14:53:57 +0000 | [diff] [blame] | 155 | 		stats->rx_bytes += devRxStats->ucastBytesRxOK + | 
 | 156 | 				   devRxStats->mcastBytesRxOK + | 
 | 157 | 				   devRxStats->bcastBytesRxOK; | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 158 |  | 
| stephen hemminger | 95305f6 | 2011-06-08 14:53:57 +0000 | [diff] [blame] | 159 | 		stats->rx_errors += devRxStats->pktsRxError; | 
 | 160 | 		stats->rx_dropped += drvRxStats->drop_total; | 
 | 161 | 		stats->multicast +=  devRxStats->mcastPktsRxOK; | 
| Shreyas Bhatewara | 09c5088 | 2010-11-19 10:55:24 +0000 | [diff] [blame] | 162 | 	} | 
| stephen hemminger | 95305f6 | 2011-06-08 14:53:57 +0000 | [diff] [blame] | 163 |  | 
 | 164 | 	return stats; | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 165 | } | 
 | 166 |  | 
 | 167 | static int | 
 | 168 | vmxnet3_get_sset_count(struct net_device *netdev, int sset) | 
 | 169 | { | 
| Shreyas Bhatewara | 76d39da | 2011-01-14 14:59:47 +0000 | [diff] [blame] | 170 | 	struct vmxnet3_adapter *adapter = netdev_priv(netdev); | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 171 | 	switch (sset) { | 
 | 172 | 	case ETH_SS_STATS: | 
| Shreyas Bhatewara | 76d39da | 2011-01-14 14:59:47 +0000 | [diff] [blame] | 173 | 		return (ARRAY_SIZE(vmxnet3_tq_dev_stats) + | 
 | 174 | 			ARRAY_SIZE(vmxnet3_tq_driver_stats)) * | 
 | 175 | 		       adapter->num_tx_queues + | 
 | 176 | 		       (ARRAY_SIZE(vmxnet3_rq_dev_stats) + | 
 | 177 | 			ARRAY_SIZE(vmxnet3_rq_driver_stats)) * | 
 | 178 | 		       adapter->num_rx_queues + | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 179 | 			ARRAY_SIZE(vmxnet3_global_stats); | 
 | 180 | 	default: | 
 | 181 | 		return -EOPNOTSUPP; | 
 | 182 | 	} | 
 | 183 | } | 
 | 184 |  | 
 | 185 |  | 
| Shreyas Bhatewara | 76d39da | 2011-01-14 14:59:47 +0000 | [diff] [blame] | 186 | /* Should be multiple of 4 */ | 
 | 187 | #define NUM_TX_REGS	8 | 
 | 188 | #define NUM_RX_REGS	12 | 
 | 189 |  | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 190 | static int | 
 | 191 | vmxnet3_get_regs_len(struct net_device *netdev) | 
 | 192 | { | 
| Shreyas Bhatewara | 76d39da | 2011-01-14 14:59:47 +0000 | [diff] [blame] | 193 | 	struct vmxnet3_adapter *adapter = netdev_priv(netdev); | 
 | 194 | 	return (adapter->num_tx_queues * NUM_TX_REGS * sizeof(u32) + | 
 | 195 | 		adapter->num_rx_queues * NUM_RX_REGS * sizeof(u32)); | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 196 | } | 
 | 197 |  | 
 | 198 |  | 
 | 199 | static void | 
 | 200 | vmxnet3_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) | 
 | 201 | { | 
 | 202 | 	struct vmxnet3_adapter *adapter = netdev_priv(netdev); | 
 | 203 |  | 
 | 204 | 	strlcpy(drvinfo->driver, vmxnet3_driver_name, sizeof(drvinfo->driver)); | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 205 |  | 
 | 206 | 	strlcpy(drvinfo->version, VMXNET3_DRIVER_VERSION_REPORT, | 
 | 207 | 		sizeof(drvinfo->version)); | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 208 |  | 
 | 209 | 	strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), | 
 | 210 | 		ETHTOOL_BUSINFO_LEN); | 
 | 211 | 	drvinfo->n_stats = vmxnet3_get_sset_count(netdev, ETH_SS_STATS); | 
 | 212 | 	drvinfo->testinfo_len = 0; | 
 | 213 | 	drvinfo->eedump_len   = 0; | 
 | 214 | 	drvinfo->regdump_len  = vmxnet3_get_regs_len(netdev); | 
 | 215 | } | 
 | 216 |  | 
 | 217 |  | 
 | 218 | static void | 
 | 219 | vmxnet3_get_strings(struct net_device *netdev, u32 stringset, u8 *buf) | 
 | 220 | { | 
| Shreyas Bhatewara | 76d39da | 2011-01-14 14:59:47 +0000 | [diff] [blame] | 221 | 	 struct vmxnet3_adapter *adapter = netdev_priv(netdev); | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 222 | 	if (stringset == ETH_SS_STATS) { | 
| Shreyas Bhatewara | 76d39da | 2011-01-14 14:59:47 +0000 | [diff] [blame] | 223 | 		int i, j; | 
 | 224 | 		for (j = 0; j < adapter->num_tx_queues; j++) { | 
 | 225 | 			for (i = 0; i < ARRAY_SIZE(vmxnet3_tq_dev_stats); i++) { | 
 | 226 | 				memcpy(buf, vmxnet3_tq_dev_stats[i].desc, | 
 | 227 | 				       ETH_GSTRING_LEN); | 
 | 228 | 				buf += ETH_GSTRING_LEN; | 
 | 229 | 			} | 
 | 230 | 			for (i = 0; i < ARRAY_SIZE(vmxnet3_tq_driver_stats); | 
 | 231 | 			     i++) { | 
 | 232 | 				memcpy(buf, vmxnet3_tq_driver_stats[i].desc, | 
 | 233 | 				       ETH_GSTRING_LEN); | 
 | 234 | 				buf += ETH_GSTRING_LEN; | 
 | 235 | 			} | 
 | 236 | 		} | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 237 |  | 
| Shreyas Bhatewara | 76d39da | 2011-01-14 14:59:47 +0000 | [diff] [blame] | 238 | 		for (j = 0; j < adapter->num_rx_queues; j++) { | 
 | 239 | 			for (i = 0; i < ARRAY_SIZE(vmxnet3_rq_dev_stats); i++) { | 
 | 240 | 				memcpy(buf, vmxnet3_rq_dev_stats[i].desc, | 
 | 241 | 				       ETH_GSTRING_LEN); | 
 | 242 | 				buf += ETH_GSTRING_LEN; | 
 | 243 | 			} | 
 | 244 | 			for (i = 0; i < ARRAY_SIZE(vmxnet3_rq_driver_stats); | 
 | 245 | 			     i++) { | 
 | 246 | 				memcpy(buf, vmxnet3_rq_driver_stats[i].desc, | 
 | 247 | 				       ETH_GSTRING_LEN); | 
 | 248 | 				buf += ETH_GSTRING_LEN; | 
 | 249 | 			} | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 250 | 		} | 
| Shreyas Bhatewara | 76d39da | 2011-01-14 14:59:47 +0000 | [diff] [blame] | 251 |  | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 252 | 		for (i = 0; i < ARRAY_SIZE(vmxnet3_global_stats); i++) { | 
 | 253 | 			memcpy(buf, vmxnet3_global_stats[i].desc, | 
 | 254 | 				ETH_GSTRING_LEN); | 
 | 255 | 			buf += ETH_GSTRING_LEN; | 
 | 256 | 		} | 
 | 257 | 	} | 
 | 258 | } | 
 | 259 |  | 
| Michał Mirosław | c8f44af | 2011-11-15 15:29:55 +0000 | [diff] [blame] | 260 | int vmxnet3_set_features(struct net_device *netdev, netdev_features_t features) | 
| Stanislaw Gruszka | d92be4b | 2010-06-27 23:29:42 +0000 | [diff] [blame] | 261 | { | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 262 | 	struct vmxnet3_adapter *adapter = netdev_priv(netdev); | 
| Shreyas Bhatewara | 83d0fef | 2011-01-14 14:59:57 +0000 | [diff] [blame] | 263 | 	unsigned long flags; | 
| Michał Mirosław | c8f44af | 2011-11-15 15:29:55 +0000 | [diff] [blame] | 264 | 	netdev_features_t changed = features ^ netdev->features; | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 265 |  | 
| Jesse Gross | 72e85c4 | 2011-06-23 13:04:39 +0000 | [diff] [blame] | 266 | 	if (changed & (NETIF_F_RXCSUM | NETIF_F_LRO | NETIF_F_HW_VLAN_RX)) { | 
| Michał Mirosław | a0d2730 | 2011-04-18 13:31:21 +0000 | [diff] [blame] | 267 | 		if (features & NETIF_F_RXCSUM) | 
 | 268 | 			adapter->shared->devRead.misc.uptFeatures |= | 
 | 269 | 			UPT1_F_RXCSUM; | 
 | 270 | 		else | 
 | 271 | 			adapter->shared->devRead.misc.uptFeatures &= | 
 | 272 | 			~UPT1_F_RXCSUM; | 
| Stanislaw Gruszka | d92be4b | 2010-06-27 23:29:42 +0000 | [diff] [blame] | 273 |  | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 274 | 		/* update harware LRO capability accordingly */ | 
| Michał Mirosław | a0d2730 | 2011-04-18 13:31:21 +0000 | [diff] [blame] | 275 | 		if (features & NETIF_F_LRO) | 
| Shreyas Bhatewara | ca80244 | 2010-07-15 22:17:29 -0700 | [diff] [blame] | 276 | 			adapter->shared->devRead.misc.uptFeatures |= | 
| Harvey Harrison | 3843e51 | 2010-10-21 18:05:32 +0000 | [diff] [blame] | 277 | 							UPT1_F_LRO; | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 278 | 		else | 
 | 279 | 			adapter->shared->devRead.misc.uptFeatures &= | 
| Harvey Harrison | 3843e51 | 2010-10-21 18:05:32 +0000 | [diff] [blame] | 280 | 							~UPT1_F_LRO; | 
| Michał Mirosław | a0d2730 | 2011-04-18 13:31:21 +0000 | [diff] [blame] | 281 |  | 
| Jesse Gross | 72e85c4 | 2011-06-23 13:04:39 +0000 | [diff] [blame] | 282 | 		if (features & NETIF_F_HW_VLAN_RX) | 
 | 283 | 			adapter->shared->devRead.misc.uptFeatures |= | 
 | 284 | 			UPT1_F_RXVLAN; | 
 | 285 | 		else | 
 | 286 | 			adapter->shared->devRead.misc.uptFeatures &= | 
 | 287 | 			~UPT1_F_RXVLAN; | 
 | 288 |  | 
| Shreyas Bhatewara | 83d0fef | 2011-01-14 14:59:57 +0000 | [diff] [blame] | 289 | 		spin_lock_irqsave(&adapter->cmd_lock, flags); | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 290 | 		VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, | 
 | 291 | 				       VMXNET3_CMD_UPDATE_FEATURE); | 
| Shreyas Bhatewara | 83d0fef | 2011-01-14 14:59:57 +0000 | [diff] [blame] | 292 | 		spin_unlock_irqrestore(&adapter->cmd_lock, flags); | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 293 | 	} | 
 | 294 | 	return 0; | 
 | 295 | } | 
 | 296 |  | 
 | 297 | static void | 
 | 298 | vmxnet3_get_ethtool_stats(struct net_device *netdev, | 
 | 299 | 			  struct ethtool_stats *stats, u64  *buf) | 
 | 300 | { | 
 | 301 | 	struct vmxnet3_adapter *adapter = netdev_priv(netdev); | 
| Shreyas Bhatewara | 83d0fef | 2011-01-14 14:59:57 +0000 | [diff] [blame] | 302 | 	unsigned long flags; | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 303 | 	u8 *base; | 
 | 304 | 	int i; | 
| Shreyas Bhatewara | 09c5088 | 2010-11-19 10:55:24 +0000 | [diff] [blame] | 305 | 	int j = 0; | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 306 |  | 
| Shreyas Bhatewara | 83d0fef | 2011-01-14 14:59:57 +0000 | [diff] [blame] | 307 | 	spin_lock_irqsave(&adapter->cmd_lock, flags); | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 308 | 	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, VMXNET3_CMD_GET_STATS); | 
| Shreyas Bhatewara | 83d0fef | 2011-01-14 14:59:57 +0000 | [diff] [blame] | 309 | 	spin_unlock_irqrestore(&adapter->cmd_lock, flags); | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 310 |  | 
 | 311 | 	/* this does assume each counter is 64-bit wide */ | 
| Shreyas Bhatewara | 76d39da | 2011-01-14 14:59:47 +0000 | [diff] [blame] | 312 | 	for (j = 0; j < adapter->num_tx_queues; j++) { | 
 | 313 | 		base = (u8 *)&adapter->tqd_start[j].stats; | 
 | 314 | 		*buf++ = (u64)j; | 
 | 315 | 		for (i = 1; i < ARRAY_SIZE(vmxnet3_tq_dev_stats); i++) | 
 | 316 | 			*buf++ = *(u64 *)(base + | 
 | 317 | 					  vmxnet3_tq_dev_stats[i].offset); | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 318 |  | 
| Shreyas Bhatewara | 76d39da | 2011-01-14 14:59:47 +0000 | [diff] [blame] | 319 | 		base = (u8 *)&adapter->tx_queue[j].stats; | 
 | 320 | 		for (i = 0; i < ARRAY_SIZE(vmxnet3_tq_driver_stats); i++) | 
 | 321 | 			*buf++ = *(u64 *)(base + | 
 | 322 | 					  vmxnet3_tq_driver_stats[i].offset); | 
 | 323 | 	} | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 324 |  | 
| Shreyas Bhatewara | 76d39da | 2011-01-14 14:59:47 +0000 | [diff] [blame] | 325 | 	for (j = 0; j < adapter->num_tx_queues; j++) { | 
 | 326 | 		base = (u8 *)&adapter->rqd_start[j].stats; | 
 | 327 | 		*buf++ = (u64) j; | 
 | 328 | 		for (i = 1; i < ARRAY_SIZE(vmxnet3_rq_dev_stats); i++) | 
 | 329 | 			*buf++ = *(u64 *)(base + | 
 | 330 | 					  vmxnet3_rq_dev_stats[i].offset); | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 331 |  | 
| Shreyas Bhatewara | 76d39da | 2011-01-14 14:59:47 +0000 | [diff] [blame] | 332 | 		base = (u8 *)&adapter->rx_queue[j].stats; | 
 | 333 | 		for (i = 0; i < ARRAY_SIZE(vmxnet3_rq_driver_stats); i++) | 
 | 334 | 			*buf++ = *(u64 *)(base + | 
 | 335 | 					  vmxnet3_rq_driver_stats[i].offset); | 
 | 336 | 	} | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 337 |  | 
 | 338 | 	base = (u8 *)adapter; | 
 | 339 | 	for (i = 0; i < ARRAY_SIZE(vmxnet3_global_stats); i++) | 
 | 340 | 		*buf++ = *(u64 *)(base + vmxnet3_global_stats[i].offset); | 
 | 341 | } | 
 | 342 |  | 
 | 343 |  | 
 | 344 | static void | 
 | 345 | vmxnet3_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p) | 
 | 346 | { | 
 | 347 | 	struct vmxnet3_adapter *adapter = netdev_priv(netdev); | 
 | 348 | 	u32 *buf = p; | 
| Shreyas Bhatewara | 76d39da | 2011-01-14 14:59:47 +0000 | [diff] [blame] | 349 | 	int i = 0, j = 0; | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 350 |  | 
 | 351 | 	memset(p, 0, vmxnet3_get_regs_len(netdev)); | 
 | 352 |  | 
 | 353 | 	regs->version = 1; | 
 | 354 |  | 
 | 355 | 	/* Update vmxnet3_get_regs_len if we want to dump more registers */ | 
 | 356 |  | 
 | 357 | 	/* make each ring use multiple of 16 bytes */ | 
| Shreyas Bhatewara | 76d39da | 2011-01-14 14:59:47 +0000 | [diff] [blame] | 358 | 	for (i = 0; i < adapter->num_tx_queues; i++) { | 
 | 359 | 		buf[j++] = adapter->tx_queue[i].tx_ring.next2fill; | 
 | 360 | 		buf[j++] = adapter->tx_queue[i].tx_ring.next2comp; | 
 | 361 | 		buf[j++] = adapter->tx_queue[i].tx_ring.gen; | 
 | 362 | 		buf[j++] = 0; | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 363 |  | 
| Shreyas Bhatewara | 76d39da | 2011-01-14 14:59:47 +0000 | [diff] [blame] | 364 | 		buf[j++] = adapter->tx_queue[i].comp_ring.next2proc; | 
 | 365 | 		buf[j++] = adapter->tx_queue[i].comp_ring.gen; | 
 | 366 | 		buf[j++] = adapter->tx_queue[i].stopped; | 
 | 367 | 		buf[j++] = 0; | 
 | 368 | 	} | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 369 |  | 
| Shreyas Bhatewara | 76d39da | 2011-01-14 14:59:47 +0000 | [diff] [blame] | 370 | 	for (i = 0; i < adapter->num_rx_queues; i++) { | 
 | 371 | 		buf[j++] = adapter->rx_queue[i].rx_ring[0].next2fill; | 
 | 372 | 		buf[j++] = adapter->rx_queue[i].rx_ring[0].next2comp; | 
 | 373 | 		buf[j++] = adapter->rx_queue[i].rx_ring[0].gen; | 
 | 374 | 		buf[j++] = 0; | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 375 |  | 
| Shreyas Bhatewara | 76d39da | 2011-01-14 14:59:47 +0000 | [diff] [blame] | 376 | 		buf[j++] = adapter->rx_queue[i].rx_ring[1].next2fill; | 
 | 377 | 		buf[j++] = adapter->rx_queue[i].rx_ring[1].next2comp; | 
 | 378 | 		buf[j++] = adapter->rx_queue[i].rx_ring[1].gen; | 
 | 379 | 		buf[j++] = 0; | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 380 |  | 
| Shreyas Bhatewara | 76d39da | 2011-01-14 14:59:47 +0000 | [diff] [blame] | 381 | 		buf[j++] = adapter->rx_queue[i].comp_ring.next2proc; | 
 | 382 | 		buf[j++] = adapter->rx_queue[i].comp_ring.gen; | 
 | 383 | 		buf[j++] = 0; | 
 | 384 | 		buf[j++] = 0; | 
 | 385 | 	} | 
 | 386 |  | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 387 | } | 
 | 388 |  | 
 | 389 |  | 
 | 390 | static void | 
 | 391 | vmxnet3_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | 
 | 392 | { | 
 | 393 | 	struct vmxnet3_adapter *adapter = netdev_priv(netdev); | 
 | 394 |  | 
 | 395 | 	wol->supported = WAKE_UCAST | WAKE_ARP | WAKE_MAGIC; | 
 | 396 | 	wol->wolopts = adapter->wol; | 
 | 397 | } | 
 | 398 |  | 
 | 399 |  | 
 | 400 | static int | 
 | 401 | vmxnet3_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | 
 | 402 | { | 
 | 403 | 	struct vmxnet3_adapter *adapter = netdev_priv(netdev); | 
 | 404 |  | 
 | 405 | 	if (wol->wolopts & (WAKE_PHY | WAKE_MCAST | WAKE_BCAST | | 
 | 406 | 			    WAKE_MAGICSECURE)) { | 
 | 407 | 		return -EOPNOTSUPP; | 
 | 408 | 	} | 
 | 409 |  | 
 | 410 | 	adapter->wol = wol->wolopts; | 
 | 411 |  | 
 | 412 | 	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); | 
 | 413 |  | 
 | 414 | 	return 0; | 
 | 415 | } | 
 | 416 |  | 
 | 417 |  | 
 | 418 | static int | 
 | 419 | vmxnet3_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) | 
 | 420 | { | 
 | 421 | 	struct vmxnet3_adapter *adapter = netdev_priv(netdev); | 
 | 422 |  | 
 | 423 | 	ecmd->supported = SUPPORTED_10000baseT_Full | SUPPORTED_1000baseT_Full | | 
 | 424 | 			  SUPPORTED_TP; | 
 | 425 | 	ecmd->advertising = ADVERTISED_TP; | 
 | 426 | 	ecmd->port = PORT_TP; | 
 | 427 | 	ecmd->transceiver = XCVR_INTERNAL; | 
 | 428 |  | 
 | 429 | 	if (adapter->link_speed) { | 
| David Decotigny | 7073949 | 2011-04-27 18:32:40 +0000 | [diff] [blame] | 430 | 		ethtool_cmd_speed_set(ecmd, adapter->link_speed); | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 431 | 		ecmd->duplex = DUPLEX_FULL; | 
 | 432 | 	} else { | 
| David Decotigny | 7073949 | 2011-04-27 18:32:40 +0000 | [diff] [blame] | 433 | 		ethtool_cmd_speed_set(ecmd, -1); | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 434 | 		ecmd->duplex = -1; | 
 | 435 | 	} | 
 | 436 | 	return 0; | 
 | 437 | } | 
 | 438 |  | 
 | 439 |  | 
 | 440 | static void | 
 | 441 | vmxnet3_get_ringparam(struct net_device *netdev, | 
 | 442 | 		      struct ethtool_ringparam *param) | 
 | 443 | { | 
 | 444 | 	struct vmxnet3_adapter *adapter = netdev_priv(netdev); | 
 | 445 |  | 
 | 446 | 	param->rx_max_pending = VMXNET3_RX_RING_MAX_SIZE; | 
 | 447 | 	param->tx_max_pending = VMXNET3_TX_RING_MAX_SIZE; | 
 | 448 | 	param->rx_mini_max_pending = 0; | 
 | 449 | 	param->rx_jumbo_max_pending = 0; | 
 | 450 |  | 
| Shreyas Bhatewara | 09c5088 | 2010-11-19 10:55:24 +0000 | [diff] [blame] | 451 | 	param->rx_pending = adapter->rx_queue[0].rx_ring[0].size * | 
 | 452 | 			    adapter->num_rx_queues; | 
 | 453 | 	param->tx_pending = adapter->tx_queue[0].tx_ring.size * | 
 | 454 | 			    adapter->num_tx_queues; | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 455 | 	param->rx_mini_pending = 0; | 
 | 456 | 	param->rx_jumbo_pending = 0; | 
 | 457 | } | 
 | 458 |  | 
 | 459 |  | 
 | 460 | static int | 
 | 461 | vmxnet3_set_ringparam(struct net_device *netdev, | 
 | 462 | 		      struct ethtool_ringparam *param) | 
 | 463 | { | 
 | 464 | 	struct vmxnet3_adapter *adapter = netdev_priv(netdev); | 
 | 465 | 	u32 new_tx_ring_size, new_rx_ring_size; | 
 | 466 | 	u32 sz; | 
 | 467 | 	int err = 0; | 
 | 468 |  | 
 | 469 | 	if (param->tx_pending == 0 || param->tx_pending > | 
 | 470 | 						VMXNET3_TX_RING_MAX_SIZE) | 
 | 471 | 		return -EINVAL; | 
 | 472 |  | 
 | 473 | 	if (param->rx_pending == 0 || param->rx_pending > | 
 | 474 | 						VMXNET3_RX_RING_MAX_SIZE) | 
 | 475 | 		return -EINVAL; | 
 | 476 |  | 
 | 477 |  | 
 | 478 | 	/* round it up to a multiple of VMXNET3_RING_SIZE_ALIGN */ | 
 | 479 | 	new_tx_ring_size = (param->tx_pending + VMXNET3_RING_SIZE_MASK) & | 
 | 480 | 							~VMXNET3_RING_SIZE_MASK; | 
 | 481 | 	new_tx_ring_size = min_t(u32, new_tx_ring_size, | 
 | 482 | 				 VMXNET3_TX_RING_MAX_SIZE); | 
 | 483 | 	if (new_tx_ring_size > VMXNET3_TX_RING_MAX_SIZE || (new_tx_ring_size % | 
 | 484 | 						VMXNET3_RING_SIZE_ALIGN) != 0) | 
 | 485 | 		return -EINVAL; | 
 | 486 |  | 
 | 487 | 	/* ring0 has to be a multiple of | 
 | 488 | 	 * rx_buf_per_pkt * VMXNET3_RING_SIZE_ALIGN | 
 | 489 | 	 */ | 
 | 490 | 	sz = adapter->rx_buf_per_pkt * VMXNET3_RING_SIZE_ALIGN; | 
 | 491 | 	new_rx_ring_size = (param->rx_pending + sz - 1) / sz * sz; | 
 | 492 | 	new_rx_ring_size = min_t(u32, new_rx_ring_size, | 
 | 493 | 				 VMXNET3_RX_RING_MAX_SIZE / sz * sz); | 
 | 494 | 	if (new_rx_ring_size > VMXNET3_RX_RING_MAX_SIZE || (new_rx_ring_size % | 
 | 495 | 							   sz) != 0) | 
 | 496 | 		return -EINVAL; | 
 | 497 |  | 
| Shreyas Bhatewara | 09c5088 | 2010-11-19 10:55:24 +0000 | [diff] [blame] | 498 | 	if (new_tx_ring_size == adapter->tx_queue[0].tx_ring.size && | 
 | 499 | 	    new_rx_ring_size == adapter->rx_queue[0].rx_ring[0].size) { | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 500 | 		return 0; | 
 | 501 | 	} | 
 | 502 |  | 
 | 503 | 	/* | 
 | 504 | 	 * Reset_work may be in the middle of resetting the device, wait for its | 
 | 505 | 	 * completion. | 
 | 506 | 	 */ | 
 | 507 | 	while (test_and_set_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state)) | 
 | 508 | 		msleep(1); | 
 | 509 |  | 
 | 510 | 	if (netif_running(netdev)) { | 
 | 511 | 		vmxnet3_quiesce_dev(adapter); | 
 | 512 | 		vmxnet3_reset_dev(adapter); | 
 | 513 |  | 
 | 514 | 		/* recreate the rx queue and the tx queue based on the | 
 | 515 | 		 * new sizes */ | 
| Shreyas Bhatewara | 09c5088 | 2010-11-19 10:55:24 +0000 | [diff] [blame] | 516 | 		vmxnet3_tq_destroy_all(adapter); | 
 | 517 | 		vmxnet3_rq_destroy_all(adapter); | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 518 |  | 
 | 519 | 		err = vmxnet3_create_queues(adapter, new_tx_ring_size, | 
 | 520 | 			new_rx_ring_size, VMXNET3_DEF_RX_RING_SIZE); | 
| Shreyas Bhatewara | 09c5088 | 2010-11-19 10:55:24 +0000 | [diff] [blame] | 521 |  | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 522 | 		if (err) { | 
 | 523 | 			/* failed, most likely because of OOM, try default | 
 | 524 | 			 * size */ | 
 | 525 | 			printk(KERN_ERR "%s: failed to apply new sizes, try the" | 
 | 526 | 				" default ones\n", netdev->name); | 
 | 527 | 			err = vmxnet3_create_queues(adapter, | 
 | 528 | 						    VMXNET3_DEF_TX_RING_SIZE, | 
 | 529 | 						    VMXNET3_DEF_RX_RING_SIZE, | 
 | 530 | 						    VMXNET3_DEF_RX_RING_SIZE); | 
 | 531 | 			if (err) { | 
 | 532 | 				printk(KERN_ERR "%s: failed to create queues " | 
 | 533 | 					"with default sizes. Closing it\n", | 
 | 534 | 					netdev->name); | 
 | 535 | 				goto out; | 
 | 536 | 			} | 
 | 537 | 		} | 
 | 538 |  | 
 | 539 | 		err = vmxnet3_activate_dev(adapter); | 
 | 540 | 		if (err) | 
 | 541 | 			printk(KERN_ERR "%s: failed to re-activate, error %d." | 
 | 542 | 				" Closing it\n", netdev->name, err); | 
 | 543 | 	} | 
 | 544 |  | 
 | 545 | out: | 
 | 546 | 	clear_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state); | 
 | 547 | 	if (err) | 
 | 548 | 		vmxnet3_force_close(adapter); | 
 | 549 |  | 
 | 550 | 	return err; | 
 | 551 | } | 
 | 552 |  | 
 | 553 |  | 
| Shreyas Bhatewara | 09c5088 | 2010-11-19 10:55:24 +0000 | [diff] [blame] | 554 | static int | 
 | 555 | vmxnet3_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *info, | 
| Ben Hutchings | 815c7db | 2011-09-06 13:49:12 +0000 | [diff] [blame] | 556 | 		  u32 *rules) | 
| Shreyas Bhatewara | 09c5088 | 2010-11-19 10:55:24 +0000 | [diff] [blame] | 557 | { | 
 | 558 | 	struct vmxnet3_adapter *adapter = netdev_priv(netdev); | 
 | 559 | 	switch (info->cmd) { | 
 | 560 | 	case ETHTOOL_GRXRINGS: | 
 | 561 | 		info->data = adapter->num_rx_queues; | 
 | 562 | 		return 0; | 
 | 563 | 	} | 
 | 564 | 	return -EOPNOTSUPP; | 
 | 565 | } | 
 | 566 |  | 
| Scott J. Goldman | e9248fb | 2010-11-27 10:33:55 +0000 | [diff] [blame] | 567 | #ifdef VMXNET3_RSS | 
| Ben Hutchings | 7850f63 | 2011-12-15 13:55:01 +0000 | [diff] [blame] | 568 | static u32 | 
 | 569 | vmxnet3_get_rss_indir_size(struct net_device *netdev) | 
| Shreyas Bhatewara | 09c5088 | 2010-11-19 10:55:24 +0000 | [diff] [blame] | 570 | { | 
 | 571 | 	struct vmxnet3_adapter *adapter = netdev_priv(netdev); | 
 | 572 | 	struct UPT1_RSSConf *rssConf = adapter->rss_conf; | 
| Shreyas Bhatewara | 09c5088 | 2010-11-19 10:55:24 +0000 | [diff] [blame] | 573 |  | 
| Ben Hutchings | 7850f63 | 2011-12-15 13:55:01 +0000 | [diff] [blame] | 574 | 	return rssConf->indTableSize; | 
 | 575 | } | 
 | 576 |  | 
 | 577 | static int | 
 | 578 | vmxnet3_get_rss_indir(struct net_device *netdev, u32 *p) | 
 | 579 | { | 
 | 580 | 	struct vmxnet3_adapter *adapter = netdev_priv(netdev); | 
 | 581 | 	struct UPT1_RSSConf *rssConf = adapter->rss_conf; | 
 | 582 | 	unsigned int n = rssConf->indTableSize; | 
 | 583 |  | 
| Shreyas Bhatewara | 09c5088 | 2010-11-19 10:55:24 +0000 | [diff] [blame] | 584 | 	while (n--) | 
| Ben Hutchings | 7850f63 | 2011-12-15 13:55:01 +0000 | [diff] [blame] | 585 | 		p[n] = rssConf->indTable[n]; | 
| Shreyas Bhatewara | 09c5088 | 2010-11-19 10:55:24 +0000 | [diff] [blame] | 586 | 	return 0; | 
 | 587 |  | 
 | 588 | } | 
 | 589 |  | 
 | 590 | static int | 
| Ben Hutchings | 7850f63 | 2011-12-15 13:55:01 +0000 | [diff] [blame] | 591 | vmxnet3_set_rss_indir(struct net_device *netdev, const u32 *p) | 
| Shreyas Bhatewara | 09c5088 | 2010-11-19 10:55:24 +0000 | [diff] [blame] | 592 | { | 
 | 593 | 	unsigned int i; | 
| Shreyas Bhatewara | 83d0fef | 2011-01-14 14:59:57 +0000 | [diff] [blame] | 594 | 	unsigned long flags; | 
| Shreyas Bhatewara | 09c5088 | 2010-11-19 10:55:24 +0000 | [diff] [blame] | 595 | 	struct vmxnet3_adapter *adapter = netdev_priv(netdev); | 
 | 596 | 	struct UPT1_RSSConf *rssConf = adapter->rss_conf; | 
 | 597 |  | 
| Shreyas Bhatewara | 09c5088 | 2010-11-19 10:55:24 +0000 | [diff] [blame] | 598 | 	for (i = 0; i < rssConf->indTableSize; i++) | 
| Ben Hutchings | 7850f63 | 2011-12-15 13:55:01 +0000 | [diff] [blame] | 599 | 		rssConf->indTable[i] = p[i]; | 
| Shreyas Bhatewara | 09c5088 | 2010-11-19 10:55:24 +0000 | [diff] [blame] | 600 |  | 
| Shreyas Bhatewara | 83d0fef | 2011-01-14 14:59:57 +0000 | [diff] [blame] | 601 | 	spin_lock_irqsave(&adapter->cmd_lock, flags); | 
| Shreyas Bhatewara | 09c5088 | 2010-11-19 10:55:24 +0000 | [diff] [blame] | 602 | 	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, | 
 | 603 | 			       VMXNET3_CMD_UPDATE_RSSIDT); | 
| Shreyas Bhatewara | 83d0fef | 2011-01-14 14:59:57 +0000 | [diff] [blame] | 604 | 	spin_unlock_irqrestore(&adapter->cmd_lock, flags); | 
| Shreyas Bhatewara | 09c5088 | 2010-11-19 10:55:24 +0000 | [diff] [blame] | 605 |  | 
 | 606 | 	return 0; | 
 | 607 |  | 
 | 608 | } | 
| Scott J. Goldman | e9248fb | 2010-11-27 10:33:55 +0000 | [diff] [blame] | 609 | #endif | 
| Shreyas Bhatewara | 09c5088 | 2010-11-19 10:55:24 +0000 | [diff] [blame] | 610 |  | 
| stephen hemminger | c8b88ef | 2012-01-04 11:58:13 +0000 | [diff] [blame] | 611 | static const struct ethtool_ops vmxnet3_ethtool_ops = { | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 612 | 	.get_settings      = vmxnet3_get_settings, | 
 | 613 | 	.get_drvinfo       = vmxnet3_get_drvinfo, | 
 | 614 | 	.get_regs_len      = vmxnet3_get_regs_len, | 
 | 615 | 	.get_regs          = vmxnet3_get_regs, | 
 | 616 | 	.get_wol           = vmxnet3_get_wol, | 
 | 617 | 	.set_wol           = vmxnet3_set_wol, | 
 | 618 | 	.get_link          = ethtool_op_get_link, | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 619 | 	.get_strings       = vmxnet3_get_strings, | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 620 | 	.get_sset_count	   = vmxnet3_get_sset_count, | 
 | 621 | 	.get_ethtool_stats = vmxnet3_get_ethtool_stats, | 
 | 622 | 	.get_ringparam     = vmxnet3_get_ringparam, | 
 | 623 | 	.set_ringparam     = vmxnet3_set_ringparam, | 
| Shreyas Bhatewara | 09c5088 | 2010-11-19 10:55:24 +0000 | [diff] [blame] | 624 | 	.get_rxnfc         = vmxnet3_get_rxnfc, | 
| Scott J. Goldman | e9248fb | 2010-11-27 10:33:55 +0000 | [diff] [blame] | 625 | #ifdef VMXNET3_RSS | 
| Ben Hutchings | 7850f63 | 2011-12-15 13:55:01 +0000 | [diff] [blame] | 626 | 	.get_rxfh_indir_size = vmxnet3_get_rss_indir_size, | 
| Shreyas Bhatewara | 09c5088 | 2010-11-19 10:55:24 +0000 | [diff] [blame] | 627 | 	.get_rxfh_indir    = vmxnet3_get_rss_indir, | 
 | 628 | 	.set_rxfh_indir    = vmxnet3_set_rss_indir, | 
| Scott J. Goldman | e9248fb | 2010-11-27 10:33:55 +0000 | [diff] [blame] | 629 | #endif | 
| Shreyas Bhatewara | d1a890f | 2009-10-13 00:15:51 -0700 | [diff] [blame] | 630 | }; | 
 | 631 |  | 
 | 632 | void vmxnet3_set_ethtool_ops(struct net_device *netdev) | 
 | 633 | { | 
 | 634 | 	SET_ETHTOOL_OPS(netdev, &vmxnet3_ethtool_ops); | 
 | 635 | } |