1/*
2 * Copyright (C) 1999 - 2010 Intel Corporation.
3 * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
4 *
5 * This code was derived from the Intel e1000e Linux driver.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
19 */
20#include "pch_gbe.h"
21#include "pch_gbe_api.h"
22
23/**
24 * pch_gbe_stats - Stats item information
25 */
26struct pch_gbe_stats {
27	char string[ETH_GSTRING_LEN];
28	size_t size;
29	size_t offset;
30};
31
32#define PCH_GBE_STAT(m)						\
33{								\
34	.string = #m,						\
35	.size = FIELD_SIZEOF(struct pch_gbe_hw_stats, m),	\
36	.offset = offsetof(struct pch_gbe_hw_stats, m),		\
37}
38
39/**
40 * pch_gbe_gstrings_stats - ethtool information status name list
41 */
42static const struct pch_gbe_stats pch_gbe_gstrings_stats[] = {
43	PCH_GBE_STAT(rx_packets),
44	PCH_GBE_STAT(tx_packets),
45	PCH_GBE_STAT(rx_bytes),
46	PCH_GBE_STAT(tx_bytes),
47	PCH_GBE_STAT(rx_errors),
48	PCH_GBE_STAT(tx_errors),
49	PCH_GBE_STAT(rx_dropped),
50	PCH_GBE_STAT(tx_dropped),
51	PCH_GBE_STAT(multicast),
52	PCH_GBE_STAT(collisions),
53	PCH_GBE_STAT(rx_crc_errors),
54	PCH_GBE_STAT(rx_frame_errors),
55	PCH_GBE_STAT(rx_alloc_buff_failed),
56	PCH_GBE_STAT(tx_length_errors),
57	PCH_GBE_STAT(tx_aborted_errors),
58	PCH_GBE_STAT(tx_carrier_errors),
59	PCH_GBE_STAT(tx_timeout_count),
60	PCH_GBE_STAT(tx_restart_count),
61	PCH_GBE_STAT(intr_rx_dsc_empty_count),
62	PCH_GBE_STAT(intr_rx_frame_err_count),
63	PCH_GBE_STAT(intr_rx_fifo_err_count),
64	PCH_GBE_STAT(intr_rx_dma_err_count),
65	PCH_GBE_STAT(intr_tx_fifo_err_count),
66	PCH_GBE_STAT(intr_tx_dma_err_count),
67	PCH_GBE_STAT(intr_tcpip_err_count)
68};
69
70#define PCH_GBE_QUEUE_STATS_LEN 0
71#define PCH_GBE_GLOBAL_STATS_LEN	ARRAY_SIZE(pch_gbe_gstrings_stats)
72#define PCH_GBE_STATS_LEN (PCH_GBE_GLOBAL_STATS_LEN + PCH_GBE_QUEUE_STATS_LEN)
73
74#define PCH_GBE_MAC_REGS_LEN    (sizeof(struct pch_gbe_regs) / 4)
75#define PCH_GBE_REGS_LEN        (PCH_GBE_MAC_REGS_LEN + PCH_GBE_PHY_REGS_LEN)
76/**
77 * pch_gbe_get_settings - Get device-specific settings
78 * @netdev: Network interface device structure
79 * @ecmd:   Ethtool command
80 * Returns
81 *	0:			Successful.
82 *	Negative value:		Failed.
83 */
84static int pch_gbe_get_settings(struct net_device *netdev,
85				 struct ethtool_cmd *ecmd)
86{
87	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
88	int ret;
89
90	ret = mii_ethtool_gset(&adapter->mii, ecmd);
91	ecmd->supported &= ~(SUPPORTED_TP | SUPPORTED_1000baseT_Half);
92	ecmd->advertising &= ~(ADVERTISED_TP | ADVERTISED_1000baseT_Half);
93
94	if (!netif_carrier_ok(adapter->netdev))
95		ethtool_cmd_speed_set(ecmd, -1);
96	return ret;
97}
98
99/**
100 * pch_gbe_set_settings - Set device-specific settings
101 * @netdev: Network interface device structure
102 * @ecmd:   Ethtool command
103 * Returns
104 *	0:			Successful.
105 *	Negative value:		Failed.
106 */
107static int pch_gbe_set_settings(struct net_device *netdev,
108				 struct ethtool_cmd *ecmd)
109{
110	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
111	struct pch_gbe_hw *hw = &adapter->hw;
112	u32 speed = ethtool_cmd_speed(ecmd);
113	int ret;
114
115	pch_gbe_hal_write_phy_reg(hw, MII_BMCR, BMCR_RESET);
116
117	/* when set_settings() is called with a ethtool_cmd previously
118	 * filled by get_settings() on a down link, speed is -1: */
119	if (speed == UINT_MAX) {
120		speed = SPEED_1000;
121		ecmd->duplex = DUPLEX_FULL;
122	}
123	ret = mii_ethtool_sset(&adapter->mii, ecmd);
124	if (ret) {
125		pr_err("Error: mii_ethtool_sset\n");
126		return ret;
127	}
128	hw->mac.link_speed = speed;
129	hw->mac.link_duplex = ecmd->duplex;
130	hw->phy.autoneg_advertised = ecmd->advertising;
131	hw->mac.autoneg = ecmd->autoneg;
132	pch_gbe_hal_phy_sw_reset(hw);
133
134	/* reset the link */
135	if (netif_running(adapter->netdev)) {
136		pch_gbe_down(adapter);
137		ret = pch_gbe_up(adapter);
138	} else {
139		pch_gbe_reset(adapter);
140	}
141	return ret;
142}
143
144/**
145 * pch_gbe_get_regs_len - Report the size of device registers
146 * @netdev: Network interface device structure
147 * Returns: the size of device registers.
148 */
149static int pch_gbe_get_regs_len(struct net_device *netdev)
150{
151	return PCH_GBE_REGS_LEN * (int)sizeof(u32);
152}
153
154/**
155 * pch_gbe_get_drvinfo - Report driver information
156 * @netdev:  Network interface device structure
157 * @drvinfo: Driver information structure
158 */
159static void pch_gbe_get_drvinfo(struct net_device *netdev,
160				 struct ethtool_drvinfo *drvinfo)
161{
162	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
163
164	strlcpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
165	strlcpy(drvinfo->version, pch_driver_version, sizeof(drvinfo->version));
166	strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
167		sizeof(drvinfo->bus_info));
168	drvinfo->regdump_len = pch_gbe_get_regs_len(netdev);
169}
170
171/**
172 * pch_gbe_get_regs - Get device registers
173 * @netdev: Network interface device structure
174 * @regs:   Ethtool register structure
175 * @p:      Buffer pointer of read device register date
176 */
177static void pch_gbe_get_regs(struct net_device *netdev,
178				struct ethtool_regs *regs, void *p)
179{
180	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
181	struct pch_gbe_hw *hw = &adapter->hw;
182	struct pci_dev *pdev = adapter->pdev;
183	u32 *regs_buff = p;
184	u16 i, tmp;
185
186	regs->version = 0x1000000 | (__u32)pdev->revision << 16 | pdev->device;
187	for (i = 0; i < PCH_GBE_MAC_REGS_LEN; i++)
188		*regs_buff++ = ioread32(&hw->reg->INT_ST + i);
189	/* PHY register */
190	for (i = 0; i < PCH_GBE_PHY_REGS_LEN; i++) {
191		pch_gbe_hal_read_phy_reg(&adapter->hw, i, &tmp);
192		*regs_buff++ = tmp;
193	}
194}
195
196/**
197 * pch_gbe_get_wol - Report whether Wake-on-Lan is enabled
198 * @netdev: Network interface device structure
199 * @wol:    Wake-on-Lan information
200 */
201static void pch_gbe_get_wol(struct net_device *netdev,
202				struct ethtool_wolinfo *wol)
203{
204	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
205
206	wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
207	wol->wolopts = 0;
208
209	if ((adapter->wake_up_evt & PCH_GBE_WLC_IND))
210		wol->wolopts |= WAKE_UCAST;
211	if ((adapter->wake_up_evt & PCH_GBE_WLC_MLT))
212		wol->wolopts |= WAKE_MCAST;
213	if ((adapter->wake_up_evt & PCH_GBE_WLC_BR))
214		wol->wolopts |= WAKE_BCAST;
215	if ((adapter->wake_up_evt & PCH_GBE_WLC_MP))
216		wol->wolopts |= WAKE_MAGIC;
217}
218
219/**
220 * pch_gbe_set_wol - Turn Wake-on-Lan on or off
221 * @netdev: Network interface device structure
222 * @wol:    Pointer of wake-on-Lan information straucture
223 * Returns
224 *	0:			Successful.
225 *	Negative value:		Failed.
226 */
227static int pch_gbe_set_wol(struct net_device *netdev,
228				struct ethtool_wolinfo *wol)
229{
230	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
231
232	if ((wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)))
233		return -EOPNOTSUPP;
234	/* these settings will always override what we currently have */
235	adapter->wake_up_evt = 0;
236
237	if ((wol->wolopts & WAKE_UCAST))
238		adapter->wake_up_evt |= PCH_GBE_WLC_IND;
239	if ((wol->wolopts & WAKE_MCAST))
240		adapter->wake_up_evt |= PCH_GBE_WLC_MLT;
241	if ((wol->wolopts & WAKE_BCAST))
242		adapter->wake_up_evt |= PCH_GBE_WLC_BR;
243	if ((wol->wolopts & WAKE_MAGIC))
244		adapter->wake_up_evt |= PCH_GBE_WLC_MP;
245	return 0;
246}
247
248/**
249 * pch_gbe_nway_reset - Restart autonegotiation
250 * @netdev: Network interface device structure
251 * Returns
252 *	0:			Successful.
253 *	Negative value:		Failed.
254 */
255static int pch_gbe_nway_reset(struct net_device *netdev)
256{
257	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
258
259	return mii_nway_restart(&adapter->mii);
260}
261
262/**
263 * pch_gbe_get_ringparam - Report ring sizes
264 * @netdev:  Network interface device structure
265 * @ring:    Ring param structure
266 */
267static void pch_gbe_get_ringparam(struct net_device *netdev,
268					struct ethtool_ringparam *ring)
269{
270	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
271	struct pch_gbe_tx_ring *txdr = adapter->tx_ring;
272	struct pch_gbe_rx_ring *rxdr = adapter->rx_ring;
273
274	ring->rx_max_pending = PCH_GBE_MAX_RXD;
275	ring->tx_max_pending = PCH_GBE_MAX_TXD;
276	ring->rx_pending = rxdr->count;
277	ring->tx_pending = txdr->count;
278}
279
280/**
281 * pch_gbe_set_ringparam - Set ring sizes
282 * @netdev:  Network interface device structure
283 * @ring:    Ring param structure
284 * Returns
285 *	0:			Successful.
286 *	Negative value:		Failed.
287 */
288static int pch_gbe_set_ringparam(struct net_device *netdev,
289					struct ethtool_ringparam *ring)
290{
291	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
292	struct pch_gbe_tx_ring *txdr, *tx_old;
293	struct pch_gbe_rx_ring *rxdr, *rx_old;
294	int tx_ring_size, rx_ring_size;
295	int err = 0;
296
297	if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
298		return -EINVAL;
299	tx_ring_size = (int)sizeof(struct pch_gbe_tx_ring);
300	rx_ring_size = (int)sizeof(struct pch_gbe_rx_ring);
301
302	if ((netif_running(adapter->netdev)))
303		pch_gbe_down(adapter);
304	tx_old = adapter->tx_ring;
305	rx_old = adapter->rx_ring;
306
307	txdr = kzalloc(tx_ring_size, GFP_KERNEL);
308	if (!txdr) {
309		err = -ENOMEM;
310		goto err_alloc_tx;
311	}
312	rxdr = kzalloc(rx_ring_size, GFP_KERNEL);
313	if (!rxdr) {
314		err = -ENOMEM;
315		goto err_alloc_rx;
316	}
317	adapter->tx_ring = txdr;
318	adapter->rx_ring = rxdr;
319
320	rxdr->count =
321		clamp_val(ring->rx_pending, PCH_GBE_MIN_RXD, PCH_GBE_MAX_RXD);
322	rxdr->count = roundup(rxdr->count, PCH_GBE_RX_DESC_MULTIPLE);
323
324	txdr->count =
325		clamp_val(ring->tx_pending, PCH_GBE_MIN_RXD, PCH_GBE_MAX_RXD);
326	txdr->count = roundup(txdr->count, PCH_GBE_TX_DESC_MULTIPLE);
327
328	if ((netif_running(adapter->netdev))) {
329		/* Try to get new resources before deleting old */
330		err = pch_gbe_setup_rx_resources(adapter, adapter->rx_ring);
331		if (err)
332			goto err_setup_rx;
333		err = pch_gbe_setup_tx_resources(adapter, adapter->tx_ring);
334		if (err)
335			goto err_setup_tx;
336		/* save the new, restore the old in order to free it,
337		 * then restore the new back again */
338#ifdef RINGFREE
339		adapter->rx_ring = rx_old;
340		adapter->tx_ring = tx_old;
341		pch_gbe_free_rx_resources(adapter, adapter->rx_ring);
342		pch_gbe_free_tx_resources(adapter, adapter->tx_ring);
343		kfree(tx_old);
344		kfree(rx_old);
345		adapter->rx_ring = rxdr;
346		adapter->tx_ring = txdr;
347#else
348		pch_gbe_free_rx_resources(adapter, rx_old);
349		pch_gbe_free_tx_resources(adapter, tx_old);
350		kfree(tx_old);
351		kfree(rx_old);
352		adapter->rx_ring = rxdr;
353		adapter->tx_ring = txdr;
354#endif
355		err = pch_gbe_up(adapter);
356	}
357	return err;
358
359err_setup_tx:
360	pch_gbe_free_rx_resources(adapter, adapter->rx_ring);
361err_setup_rx:
362	adapter->rx_ring = rx_old;
363	adapter->tx_ring = tx_old;
364	kfree(rxdr);
365err_alloc_rx:
366	kfree(txdr);
367err_alloc_tx:
368	if (netif_running(adapter->netdev))
369		pch_gbe_up(adapter);
370	return err;
371}
372
373/**
374 * pch_gbe_get_pauseparam - Report pause parameters
375 * @netdev:  Network interface device structure
376 * @pause:   Pause parameters structure
377 */
378static void pch_gbe_get_pauseparam(struct net_device *netdev,
379				       struct ethtool_pauseparam *pause)
380{
381	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
382	struct pch_gbe_hw *hw = &adapter->hw;
383
384	pause->autoneg =
385	    ((hw->mac.fc_autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE);
386
387	if (hw->mac.fc == PCH_GBE_FC_RX_PAUSE) {
388		pause->rx_pause = 1;
389	} else if (hw->mac.fc == PCH_GBE_FC_TX_PAUSE) {
390		pause->tx_pause = 1;
391	} else if (hw->mac.fc == PCH_GBE_FC_FULL) {
392		pause->rx_pause = 1;
393		pause->tx_pause = 1;
394	}
395}
396
397/**
398 * pch_gbe_set_pauseparam - Set pause paramters
399 * @netdev:  Network interface device structure
400 * @pause:   Pause parameters structure
401 * Returns
402 *	0:			Successful.
403 *	Negative value:		Failed.
404 */
405static int pch_gbe_set_pauseparam(struct net_device *netdev,
406				       struct ethtool_pauseparam *pause)
407{
408	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
409	struct pch_gbe_hw *hw = &adapter->hw;
410	int ret = 0;
411
412	hw->mac.fc_autoneg = pause->autoneg;
413	if ((pause->rx_pause) && (pause->tx_pause))
414		hw->mac.fc = PCH_GBE_FC_FULL;
415	else if ((pause->rx_pause) && (!pause->tx_pause))
416		hw->mac.fc = PCH_GBE_FC_RX_PAUSE;
417	else if ((!pause->rx_pause) && (pause->tx_pause))
418		hw->mac.fc = PCH_GBE_FC_TX_PAUSE;
419	else if ((!pause->rx_pause) && (!pause->tx_pause))
420		hw->mac.fc = PCH_GBE_FC_NONE;
421
422	if (hw->mac.fc_autoneg == AUTONEG_ENABLE) {
423		if ((netif_running(adapter->netdev))) {
424			pch_gbe_down(adapter);
425			ret = pch_gbe_up(adapter);
426		} else {
427			pch_gbe_reset(adapter);
428		}
429	} else {
430		ret = pch_gbe_mac_force_mac_fc(hw);
431	}
432	return ret;
433}
434
435/**
436 * pch_gbe_get_strings - Return a set of strings that describe the requested
437 *			 objects
438 * @netdev:    Network interface device structure
439 * @stringset: Select the stringset. [ETH_SS_TEST] [ETH_SS_STATS]
440 * @data:      Pointer of read string data.
441 */
442static void pch_gbe_get_strings(struct net_device *netdev, u32 stringset,
443					u8 *data)
444{
445	u8 *p = data;
446	int i;
447
448	switch (stringset) {
449	case (u32) ETH_SS_STATS:
450		for (i = 0; i < PCH_GBE_GLOBAL_STATS_LEN; i++) {
451			memcpy(p, pch_gbe_gstrings_stats[i].string,
452			       ETH_GSTRING_LEN);
453			p += ETH_GSTRING_LEN;
454		}
455		break;
456	}
457}
458
459/**
460 * pch_gbe_get_ethtool_stats - Return statistics about the device
461 * @netdev: Network interface device structure
462 * @stats:  Ethtool statue structure
463 * @data:   Pointer of read status area
464 */
465static void pch_gbe_get_ethtool_stats(struct net_device *netdev,
466				  struct ethtool_stats *stats, u64 *data)
467{
468	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
469	int i;
470	const struct pch_gbe_stats *gstats = pch_gbe_gstrings_stats;
471	char *hw_stats = (char *)&adapter->stats;
472
473	pch_gbe_update_stats(adapter);
474	for (i = 0; i < PCH_GBE_GLOBAL_STATS_LEN; i++) {
475		char *p = hw_stats + gstats->offset;
476		data[i] = gstats->size == sizeof(u64) ? *(u64 *)p:(*(u32 *)p);
477		gstats++;
478	}
479}
480
481static int pch_gbe_get_sset_count(struct net_device *netdev, int sset)
482{
483	switch (sset) {
484	case ETH_SS_STATS:
485		return PCH_GBE_STATS_LEN;
486	default:
487		return -EOPNOTSUPP;
488	}
489}
490
491static const struct ethtool_ops pch_gbe_ethtool_ops = {
492	.get_settings = pch_gbe_get_settings,
493	.set_settings = pch_gbe_set_settings,
494	.get_drvinfo = pch_gbe_get_drvinfo,
495	.get_regs_len = pch_gbe_get_regs_len,
496	.get_regs = pch_gbe_get_regs,
497	.get_wol = pch_gbe_get_wol,
498	.set_wol = pch_gbe_set_wol,
499	.nway_reset = pch_gbe_nway_reset,
500	.get_link = ethtool_op_get_link,
501	.get_ringparam = pch_gbe_get_ringparam,
502	.set_ringparam = pch_gbe_set_ringparam,
503	.get_pauseparam = pch_gbe_get_pauseparam,
504	.set_pauseparam = pch_gbe_set_pauseparam,
505	.get_strings = pch_gbe_get_strings,
506	.get_ethtool_stats = pch_gbe_get_ethtool_stats,
507	.get_sset_count = pch_gbe_get_sset_count,
508};
509
510void pch_gbe_set_ethtool_ops(struct net_device *netdev)
511{
512	SET_ETHTOOL_OPS(netdev, &pch_gbe_ethtool_ops);
513}
514