18199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter/*****************************************************************************
28199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter *                                                                           *
38199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter * File: cxgb2.c                                                             *
4559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone * $Revision: 1.25 $                                                         *
5559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone * $Date: 2005/06/22 00:43:25 $                                              *
68199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter * Description:                                                              *
78199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter *  Chelsio 10Gb Ethernet Driver.                                            *
88199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter *                                                                           *
98199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter * This program is free software; you can redistribute it and/or modify      *
108199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter * it under the terms of the GNU General Public License, version 2, as       *
118199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter * published by the Free Software Foundation.                                *
128199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter *                                                                           *
138199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter * You should have received a copy of the GNU General Public License along   *
148199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter * with this program; if not, write to the Free Software Foundation, Inc.,   *
158199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.                 *
168199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter *                                                                           *
178199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
188199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
198199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.                     *
208199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter *                                                                           *
218199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter * http://www.chelsio.com                                                    *
228199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter *                                                                           *
238199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter * Copyright (c) 2003 - 2005 Chelsio Communications, Inc.                    *
248199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter * All rights reserved.                                                      *
258199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter *                                                                           *
268199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter * Maintainers: maintainers@chelsio.com                                      *
278199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter *                                                                           *
288199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter * Authors: Dimitrios Michailidis   <dm@chelsio.com>                         *
298199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter *          Tina Yang               <tainay@chelsio.com>                     *
308199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter *          Felix Marti             <felix@chelsio.com>                      *
318199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter *          Scott Bardone           <sbardone@chelsio.com>                   *
328199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter *          Kurt Ottaway            <kottaway@chelsio.com>                   *
338199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter *          Frank DiMambro          <frank@chelsio.com>                      *
348199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter *                                                                           *
358199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter * History:                                                                  *
368199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter *                                                                           *
378199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter ****************************************************************************/
388199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
398199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter#include "common.h"
408199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter#include <linux/module.h>
418199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter#include <linux/init.h>
428199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter#include <linux/pci.h>
438199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter#include <linux/netdevice.h>
448199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter#include <linux/etherdevice.h>
458199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter#include <linux/if_vlan.h>
468199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter#include <linux/mii.h>
478199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter#include <linux/sockios.h>
48559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone#include <linux/dma-mapping.h>
498199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter#include <asm/uaccess.h>
508199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
518199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter#include "cpl5_cmd.h"
528199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter#include "regs.h"
538199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter#include "gmac.h"
548199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter#include "cphy.h"
558199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter#include "sge.h"
56f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger#include "tp.h"
578199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter#include "espi.h"
58f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger#include "elmer0.h"
598199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
60559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone#include <linux/workqueue.h>
618199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
62559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardonestatic inline void schedule_mac_stats_update(struct adapter *ap, int secs)
63559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone{
64559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	schedule_delayed_work(&ap->stats_update_task, secs * HZ);
65559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone}
668199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
67559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardonestatic inline void cancel_mac_stats_update(struct adapter *ap)
68559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone{
69559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	cancel_delayed_work(&ap->stats_update_task);
70559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone}
718199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
72356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu#define MAX_CMDQ_ENTRIES	16384
73356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu#define MAX_CMDQ1_ENTRIES	1024
74356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu#define MAX_RX_BUFFERS		16384
75356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu#define MAX_RX_JUMBO_BUFFERS	16384
768199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter#define MAX_TX_BUFFERS_HIGH	16384U
778199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter#define MAX_TX_BUFFERS_LOW	1536U
78f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger#define MAX_TX_BUFFERS		1460U
79356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu#define MIN_FL_ENTRIES		32
808199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
818199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter#define DFLT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | \
828199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			 NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP |\
838199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			 NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
848199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
858199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter/*
868199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter * The EEPROM is actually bigger but only the first few bytes are used so we
878199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter * only report those.
888199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter */
898199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter#define EEPROM_SIZE 32
908199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
91559fb51ba7e66fe298b8355fabde1275b7def35fScott BardoneMODULE_DESCRIPTION(DRV_DESCRIPTION);
928199d3a79c224bbe5943fa08684e1f93a17881b0Christoph LameterMODULE_AUTHOR("Chelsio Communications");
938199d3a79c224bbe5943fa08684e1f93a17881b0Christoph LameterMODULE_LICENSE("GPL");
948199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
958199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic int dflt_msg_enable = DFLT_MSG_ENABLE;
968199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
978d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98Rusty Russellmodule_param(dflt_msg_enable, int, 0);
98f1d3d38af75789f1b82969b83b69cab540609789Stephen HemmingerMODULE_PARM_DESC(dflt_msg_enable, "Chelsio T1 default message enable bitmap");
99f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
100f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger#define HCLOCK 0x0
101f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger#define LCLOCK 0x1
102f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
103f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger/* T1 cards powersave mode */
104f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemmingerstatic int t1_clock(struct adapter *adapter, int mode);
105f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemmingerstatic int t1powersave = 1;	/* HW default is powersave mode. */
1068199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
107f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemmingermodule_param(t1powersave, int, 0);
108f1d3d38af75789f1b82969b83b69cab540609789Stephen HemmingerMODULE_PARM_DESC(t1powersave, "Enable/Disable T1 powersaving mode");
1098199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
110325dde48914e8ec1614d79ffacdbf9c0b8d24f42Stephen Hemmingerstatic int disable_msi = 0;
111325dde48914e8ec1614d79ffacdbf9c0b8d24f42Stephen Hemmingermodule_param(disable_msi, int, 0);
112325dde48914e8ec1614d79ffacdbf9c0b8d24f42Stephen HemmingerMODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
1138199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
1148199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic const char pci_speed[][4] = {
1158199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	"33", "66", "100", "133"
1168199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter};
1178199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
1188199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter/*
1198199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter * Setup MAC to receive the types of packets we want.
1208199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter */
1218199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic void t1_set_rxmode(struct net_device *dev)
1228199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
123c3ccc12339afa2633c72131e2aa97d52d9ca1b8aWang Chen	struct adapter *adapter = dev->ml_priv;
1248199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	struct cmac *mac = adapter->port[dev->if_port].mac;
1258199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	struct t1_rx_mode rm;
1268199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
1278199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	rm.dev = dev;
1288199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	mac->ops->set_rx_mode(mac, &rm);
1298199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
1308199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
1318199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic void link_report(struct port_info *p)
1328199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
1338199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (!netif_carrier_ok(p->dev))
134205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger		printk(KERN_INFO "%s: link down\n", p->dev->name);
1358199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	else {
136559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone		const char *s = "10Mbps";
1378199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
1388199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		switch (p->link_config.speed) {
139559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone			case SPEED_10000: s = "10Gbps"; break;
140559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone			case SPEED_1000:  s = "1000Mbps"; break;
141559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone			case SPEED_100:   s = "100Mbps"; break;
1428199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		}
1438199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
144356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu		printk(KERN_INFO "%s: link up, %s, %s-duplex\n",
1458199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		       p->dev->name, s,
1468199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		       p->link_config.duplex == DUPLEX_FULL ? "full" : "half");
1478199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	}
1488199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
1498199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
150f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemmingervoid t1_link_negotiated(struct adapter *adapter, int port_id, int link_stat,
1518199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			int speed, int duplex, int pause)
1528199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
1538199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	struct port_info *p = &adapter->port[port_id];
1548199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
1558199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (link_stat != netif_carrier_ok(p->dev)) {
1568199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		if (link_stat)
1578199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			netif_carrier_on(p->dev);
1588199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		else
1598199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			netif_carrier_off(p->dev);
1608199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		link_report(p);
1618199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
162f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		/* multi-ports: inform toe */
163f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		if ((speed > 0) && (adapter->params.nports > 1)) {
164f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger			unsigned int sched_speed = 10;
165f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger			switch (speed) {
166f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger			case SPEED_1000:
167f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger				sched_speed = 1000;
168f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger				break;
169f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger			case SPEED_100:
170f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger				sched_speed = 100;
171f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger				break;
172f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger			case SPEED_10:
173f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger				sched_speed = 10;
174f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger				break;
175f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger			}
176f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger			t1_sched_update_parms(adapter->sge, port_id, 0, sched_speed);
177f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		}
1788199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	}
1798199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
1808199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
1818199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic void link_start(struct port_info *p)
1828199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
1838199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	struct cmac *mac = p->mac;
1848199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
1858199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	mac->ops->reset(mac);
1868199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (mac->ops->macaddress_set)
1878199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		mac->ops->macaddress_set(mac, p->dev->dev_addr);
1888199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	t1_set_rxmode(p->dev);
1898199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	t1_link_start(p->phy, mac, &p->link_config);
1908199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	mac->ops->enable(mac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
1918199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
1928199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
1938199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic void enable_hw_csum(struct adapter *adapter)
1948199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
19530f554f925335abad89aaa38eec6828242b27527Michał Mirosław	if (adapter->port[0].dev->hw_features & NETIF_F_TSO)
196f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		t1_tp_set_ip_checksum_offload(adapter->tp, 1);	/* for TSO only */
197f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	t1_tp_set_tcp_checksum_offload(adapter->tp, 1);
1988199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
1998199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
2008199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter/*
2018199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter * Things to do upon first use of a card.
2028199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter * This must run with the rtnl lock held.
2038199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter */
2048199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic int cxgb_up(struct adapter *adapter)
2058199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
2068199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	int err = 0;
2078199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
2088199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (!(adapter->flags & FULL_INIT_DONE)) {
2098199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		err = t1_init_hw_modules(adapter);
2108199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		if (err)
2118199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			goto out_err;
2128199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
2138199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		enable_hw_csum(adapter);
2148199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		adapter->flags |= FULL_INIT_DONE;
2158199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	}
2168199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
2178199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	t1_interrupts_clear(adapter);
218325dde48914e8ec1614d79ffacdbf9c0b8d24f42Stephen Hemminger
2197fe26a60e08f38c797851fb3b444d753af616112Stephen Hemminger	adapter->params.has_msi = !disable_msi && !pci_enable_msi(adapter->pdev);
2207fe26a60e08f38c797851fb3b444d753af616112Stephen Hemminger	err = request_irq(adapter->pdev->irq, t1_interrupt,
221325dde48914e8ec1614d79ffacdbf9c0b8d24f42Stephen Hemminger			  adapter->params.has_msi ? 0 : IRQF_SHARED,
222325dde48914e8ec1614d79ffacdbf9c0b8d24f42Stephen Hemminger			  adapter->name, adapter);
223325dde48914e8ec1614d79ffacdbf9c0b8d24f42Stephen Hemminger	if (err) {
224325dde48914e8ec1614d79ffacdbf9c0b8d24f42Stephen Hemminger		if (adapter->params.has_msi)
225325dde48914e8ec1614d79ffacdbf9c0b8d24f42Stephen Hemminger			pci_disable_msi(adapter->pdev);
226325dde48914e8ec1614d79ffacdbf9c0b8d24f42Stephen Hemminger
2278199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		goto out_err;
228559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	}
229325dde48914e8ec1614d79ffacdbf9c0b8d24f42Stephen Hemminger
2308199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	t1_sge_start(adapter->sge);
2318199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	t1_interrupts_enable(adapter);
232356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieuout_err:
2338199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	return err;
2348199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
2358199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
2368199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter/*
2378199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter * Release resources when all the ports have been stopped.
2388199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter */
2398199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic void cxgb_down(struct adapter *adapter)
2408199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
2418199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	t1_sge_stop(adapter->sge);
2428199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	t1_interrupts_disable(adapter);
2438199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	free_irq(adapter->pdev->irq, adapter);
244325dde48914e8ec1614d79ffacdbf9c0b8d24f42Stephen Hemminger	if (adapter->params.has_msi)
245325dde48914e8ec1614d79ffacdbf9c0b8d24f42Stephen Hemminger		pci_disable_msi(adapter->pdev);
2468199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
2478199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
2488199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic int cxgb_open(struct net_device *dev)
2498199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
2508199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	int err;
251c3ccc12339afa2633c72131e2aa97d52d9ca1b8aWang Chen	struct adapter *adapter = dev->ml_priv;
2528199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	int other_ports = adapter->open_device_map & PORT_MASK;
2538199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
254bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	napi_enable(&adapter->napi);
255bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	if (!adapter->open_device_map && (err = cxgb_up(adapter)) < 0) {
256bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger		napi_disable(&adapter->napi);
2578199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		return err;
258bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	}
2598199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
2608199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	__set_bit(dev->if_port, &adapter->open_device_map);
2618199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	link_start(&adapter->port[dev->if_port]);
2628199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	netif_start_queue(dev);
2638199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (!other_ports && adapter->params.stats_update_period)
2648199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		schedule_mac_stats_update(adapter,
2658199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter					  adapter->params.stats_update_period);
266133b08513a99d44d9ed916bb83e46343f6ad2855Jiri Pirko
267133b08513a99d44d9ed916bb83e46343f6ad2855Jiri Pirko	t1_vlan_mode(adapter, dev->features);
2688199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	return 0;
2698199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
2708199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
2718199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic int cxgb_close(struct net_device *dev)
2728199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
273c3ccc12339afa2633c72131e2aa97d52d9ca1b8aWang Chen	struct adapter *adapter = dev->ml_priv;
2748199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	struct port_info *p = &adapter->port[dev->if_port];
2758199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	struct cmac *mac = p->mac;
2768199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
2778199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	netif_stop_queue(dev);
278bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger	napi_disable(&adapter->napi);
2798199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	mac->ops->disable(mac, MAC_DIRECTION_TX | MAC_DIRECTION_RX);
2808199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	netif_carrier_off(dev);
2818199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
2828199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	clear_bit(dev->if_port, &adapter->open_device_map);
2838199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (adapter->params.stats_update_period &&
2848199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	    !(adapter->open_device_map & PORT_MASK)) {
2858199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		/* Stop statistics accumulation. */
2868199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		smp_mb__after_clear_bit();
2878199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		spin_lock(&adapter->work_lock);   /* sync with update task */
2888199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		spin_unlock(&adapter->work_lock);
2898199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		cancel_mac_stats_update(adapter);
2908199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	}
2918199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
2928199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (!adapter->open_device_map)
2938199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		cxgb_down(adapter);
2948199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	return 0;
2958199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
2968199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
2978199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic struct net_device_stats *t1_get_stats(struct net_device *dev)
2988199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
299c3ccc12339afa2633c72131e2aa97d52d9ca1b8aWang Chen	struct adapter *adapter = dev->ml_priv;
3008199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	struct port_info *p = &adapter->port[dev->if_port];
3018199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	struct net_device_stats *ns = &p->netstats;
3028199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	const struct cmac_statistics *pstats;
3038199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
3048199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	/* Do a full update of the MAC stats */
3058199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	pstats = p->mac->ops->statistics_update(p->mac,
306205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger						MAC_STATS_UPDATE_FULL);
3078199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
3088199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	ns->tx_packets = pstats->TxUnicastFramesOK +
3098199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		pstats->TxMulticastFramesOK + pstats->TxBroadcastFramesOK;
3108199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
3118199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	ns->rx_packets = pstats->RxUnicastFramesOK +
3128199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		pstats->RxMulticastFramesOK + pstats->RxBroadcastFramesOK;
3138199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
3148199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	ns->tx_bytes = pstats->TxOctetsOK;
3158199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	ns->rx_bytes = pstats->RxOctetsOK;
3168199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
3178199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	ns->tx_errors = pstats->TxLateCollisions + pstats->TxLengthErrors +
3188199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		pstats->TxUnderrun + pstats->TxFramesAbortedDueToXSCollisions;
3198199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	ns->rx_errors = pstats->RxDataErrors + pstats->RxJabberErrors +
3208199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		pstats->RxFCSErrors + pstats->RxAlignErrors +
3218199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		pstats->RxSequenceErrors + pstats->RxFrameTooLongErrors +
3228199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		pstats->RxSymbolErrors + pstats->RxRuntErrors;
3238199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
3248199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	ns->multicast  = pstats->RxMulticastFramesOK;
3258199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	ns->collisions = pstats->TxTotalCollisions;
3268199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
3278199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	/* detailed rx_errors */
3288199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	ns->rx_length_errors = pstats->RxFrameTooLongErrors +
3298199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		pstats->RxJabberErrors;
3308199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	ns->rx_over_errors   = 0;
3318199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	ns->rx_crc_errors    = pstats->RxFCSErrors;
3328199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	ns->rx_frame_errors  = pstats->RxAlignErrors;
3338199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	ns->rx_fifo_errors   = 0;
3348199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	ns->rx_missed_errors = 0;
3358199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
3368199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	/* detailed tx_errors */
3378199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	ns->tx_aborted_errors   = pstats->TxFramesAbortedDueToXSCollisions;
3388199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	ns->tx_carrier_errors   = 0;
3398199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	ns->tx_fifo_errors      = pstats->TxUnderrun;
3408199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	ns->tx_heartbeat_errors = 0;
3418199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	ns->tx_window_errors    = pstats->TxLateCollisions;
3428199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	return ns;
3438199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
3448199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
3458199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic u32 get_msglevel(struct net_device *dev)
3468199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
347c3ccc12339afa2633c72131e2aa97d52d9ca1b8aWang Chen	struct adapter *adapter = dev->ml_priv;
3488199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
3498199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	return adapter->msg_enable;
3508199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
3518199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
3528199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic void set_msglevel(struct net_device *dev, u32 val)
3538199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
354c3ccc12339afa2633c72131e2aa97d52d9ca1b8aWang Chen	struct adapter *adapter = dev->ml_priv;
3558199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
3568199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	adapter->msg_enable = val;
3578199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
3588199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
3598199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic char stats_strings[][ETH_GSTRING_LEN] = {
360205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"TxOctetsOK",
361205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"TxOctetsBad",
362205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"TxUnicastFramesOK",
363205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"TxMulticastFramesOK",
364205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"TxBroadcastFramesOK",
365205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"TxPauseFrames",
366205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"TxFramesWithDeferredXmissions",
367205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"TxLateCollisions",
368205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"TxTotalCollisions",
369205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"TxFramesAbortedDueToXSCollisions",
370205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"TxUnderrun",
371205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"TxLengthErrors",
372205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"TxInternalMACXmitError",
373205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"TxFramesWithExcessiveDeferral",
374205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"TxFCSErrors",
375e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	"TxJumboFramesOk",
376e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	"TxJumboOctetsOk",
377e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray
378205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"RxOctetsOK",
379205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"RxOctetsBad",
380205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"RxUnicastFramesOK",
381205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"RxMulticastFramesOK",
382205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"RxBroadcastFramesOK",
383205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"RxPauseFrames",
384205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"RxFCSErrors",
385205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"RxAlignErrors",
386205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"RxSymbolErrors",
387205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"RxDataErrors",
388205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"RxSequenceErrors",
389205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"RxRuntErrors",
390205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"RxJabberErrors",
391205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"RxInternalMACRcvError",
392205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"RxInRangeLengthErrors",
393205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"RxOutOfRangeLengthField",
394205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	"RxFrameTooLongErrors",
395e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	"RxJumboFramesOk",
396e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	"RxJumboOctetsOk",
397559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone
39856f643c28c5df63693d7c66e56f8e4767cfd7a65Stephen Hemminger	/* Port stats */
399559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	"RxCsumGood",
400559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	"TxCsumOffload",
40156f643c28c5df63693d7c66e56f8e4767cfd7a65Stephen Hemminger	"TxTso",
40256f643c28c5df63693d7c66e56f8e4767cfd7a65Stephen Hemminger	"RxVlan",
40356f643c28c5df63693d7c66e56f8e4767cfd7a65Stephen Hemminger	"TxVlan",
4047832ee034b6ef78aab020c9ec1348544cd65ccbdDivy Le Ray	"TxNeedHeadroom",
4057832ee034b6ef78aab020c9ec1348544cd65ccbdDivy Le Ray
40656f643c28c5df63693d7c66e56f8e4767cfd7a65Stephen Hemminger	/* Interrupt stats */
40756f643c28c5df63693d7c66e56f8e4767cfd7a65Stephen Hemminger	"rx drops",
40856f643c28c5df63693d7c66e56f8e4767cfd7a65Stephen Hemminger	"pure_rsps",
40956f643c28c5df63693d7c66e56f8e4767cfd7a65Stephen Hemminger	"unhandled irqs",
410559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	"respQ_empty",
411559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	"respQ_overflow",
412559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	"freelistQ_empty",
413559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	"pkt_too_big",
414559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	"pkt_mismatch",
415559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	"cmdQ_full0",
416559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	"cmdQ_full1",
417205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger
418559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	"espi_DIP2ParityErr",
419559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	"espi_DIP4Err",
420559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	"espi_RxDrops",
421559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	"espi_TxDrops",
422559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	"espi_RxOvfl",
423559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	"espi_ParityErr"
4248199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter};
425205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger
426559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone#define T2_REGMAP_SIZE (3 * 1024)
427559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone
428559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardonestatic int get_regs_len(struct net_device *dev)
429559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone{
430559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	return T2_REGMAP_SIZE;
431559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone}
4328199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
4338199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
4348199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
435c3ccc12339afa2633c72131e2aa97d52d9ca1b8aWang Chen	struct adapter *adapter = dev->ml_priv;
4368199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
43723020ab35364f2c91133b099c2b1f7458e29aa96Rick Jones	strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
43823020ab35364f2c91133b099c2b1f7458e29aa96Rick Jones	strlcpy(info->version, DRV_VERSION, sizeof(info->version));
43923020ab35364f2c91133b099c2b1f7458e29aa96Rick Jones	strlcpy(info->bus_info, pci_name(adapter->pdev),
44023020ab35364f2c91133b099c2b1f7458e29aa96Rick Jones		sizeof(info->bus_info));
4418199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
4428199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
443b9f2c0440d806e01968c3ed4def930a43be248adJeff Garzikstatic int get_sset_count(struct net_device *dev, int sset)
4448199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
445b9f2c0440d806e01968c3ed4def930a43be248adJeff Garzik	switch (sset) {
446b9f2c0440d806e01968c3ed4def930a43be248adJeff Garzik	case ETH_SS_STATS:
447b9f2c0440d806e01968c3ed4def930a43be248adJeff Garzik		return ARRAY_SIZE(stats_strings);
448b9f2c0440d806e01968c3ed4def930a43be248adJeff Garzik	default:
449b9f2c0440d806e01968c3ed4def930a43be248adJeff Garzik		return -EOPNOTSUPP;
450b9f2c0440d806e01968c3ed4def930a43be248adJeff Garzik	}
4518199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
4528199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
4538199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic void get_strings(struct net_device *dev, u32 stringset, u8 *data)
4548199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
4558199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (stringset == ETH_SS_STATS)
4568199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		memcpy(data, stats_strings, sizeof(stats_strings));
4578199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
4588199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
4598199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic void get_stats(struct net_device *dev, struct ethtool_stats *stats,
4608199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		      u64 *data)
4618199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
462c3ccc12339afa2633c72131e2aa97d52d9ca1b8aWang Chen	struct adapter *adapter = dev->ml_priv;
4638199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	struct cmac *mac = adapter->port[dev->if_port].mac;
4648199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	const struct cmac_statistics *s;
465559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	const struct sge_intr_counts *t;
46656f643c28c5df63693d7c66e56f8e4767cfd7a65Stephen Hemminger	struct sge_port_stats ss;
4678199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
4688199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	s = mac->ops->statistics_update(mac, MAC_STATS_UPDATE_FULL);
469e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	t = t1_sge_get_intr_counts(adapter->sge);
47056f643c28c5df63693d7c66e56f8e4767cfd7a65Stephen Hemminger	t1_sge_get_port_stats(adapter->sge, dev->if_port, &ss);
47156f643c28c5df63693d7c66e56f8e4767cfd7a65Stephen Hemminger
472e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->TxOctetsOK;
473e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->TxOctetsBad;
474e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->TxUnicastFramesOK;
475e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->TxMulticastFramesOK;
476e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->TxBroadcastFramesOK;
477e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->TxPauseFrames;
478e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->TxFramesWithDeferredXmissions;
479e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->TxLateCollisions;
480e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->TxTotalCollisions;
481e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->TxFramesAbortedDueToXSCollisions;
482e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->TxUnderrun;
483e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->TxLengthErrors;
484e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->TxInternalMACXmitError;
485e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->TxFramesWithExcessiveDeferral;
486e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->TxFCSErrors;
487e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->TxJumboFramesOK;
488e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->TxJumboOctetsOK;
489e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray
490e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->RxOctetsOK;
491e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->RxOctetsBad;
492e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->RxUnicastFramesOK;
493e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->RxMulticastFramesOK;
494e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->RxBroadcastFramesOK;
495e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->RxPauseFrames;
496e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->RxFCSErrors;
497e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->RxAlignErrors;
498e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->RxSymbolErrors;
499e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->RxDataErrors;
500e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->RxSequenceErrors;
501e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->RxRuntErrors;
502e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->RxJabberErrors;
503e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->RxInternalMACRcvError;
504e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->RxInRangeLengthErrors;
505e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->RxOutOfRangeLengthField;
506e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->RxFrameTooLongErrors;
507e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->RxJumboFramesOK;
508e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = s->RxJumboOctetsOK;
509e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray
510e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = ss.rx_cso_good;
511e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = ss.tx_cso;
512e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = ss.tx_tso;
513e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = ss.vlan_xtract;
514e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = ss.vlan_insert;
515e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray	*data++ = ss.tx_need_hdrroom;
516e0348b9ae5374f9a24424ae680bcd80724415f60Divy Le Ray
51756f643c28c5df63693d7c66e56f8e4767cfd7a65Stephen Hemminger	*data++ = t->rx_drops;
51856f643c28c5df63693d7c66e56f8e4767cfd7a65Stephen Hemminger	*data++ = t->pure_rsps;
51956f643c28c5df63693d7c66e56f8e4767cfd7a65Stephen Hemminger	*data++ = t->unhandled_irqs;
52056f643c28c5df63693d7c66e56f8e4767cfd7a65Stephen Hemminger	*data++ = t->respQ_empty;
52156f643c28c5df63693d7c66e56f8e4767cfd7a65Stephen Hemminger	*data++ = t->respQ_overflow;
52256f643c28c5df63693d7c66e56f8e4767cfd7a65Stephen Hemminger	*data++ = t->freelistQ_empty;
52356f643c28c5df63693d7c66e56f8e4767cfd7a65Stephen Hemminger	*data++ = t->pkt_too_big;
52456f643c28c5df63693d7c66e56f8e4767cfd7a65Stephen Hemminger	*data++ = t->pkt_mismatch;
52556f643c28c5df63693d7c66e56f8e4767cfd7a65Stephen Hemminger	*data++ = t->cmdQ_full[0];
52656f643c28c5df63693d7c66e56f8e4767cfd7a65Stephen Hemminger	*data++ = t->cmdQ_full[1];
527f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
528f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	if (adapter->espi) {
529f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		const struct espi_intr_counts *e;
530f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
531f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		e = t1_espi_get_intr_counts(adapter->espi);
53256f643c28c5df63693d7c66e56f8e4767cfd7a65Stephen Hemminger		*data++ = e->DIP2_parity_err;
53356f643c28c5df63693d7c66e56f8e4767cfd7a65Stephen Hemminger		*data++ = e->DIP4_err;
53456f643c28c5df63693d7c66e56f8e4767cfd7a65Stephen Hemminger		*data++ = e->rx_drops;
53556f643c28c5df63693d7c66e56f8e4767cfd7a65Stephen Hemminger		*data++ = e->tx_drops;
53656f643c28c5df63693d7c66e56f8e4767cfd7a65Stephen Hemminger		*data++ = e->rx_ovflw;
53756f643c28c5df63693d7c66e56f8e4767cfd7a65Stephen Hemminger		*data++ = e->parity_err;
538f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	}
539559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone}
540559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone
541559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardonestatic inline void reg_block_dump(struct adapter *ap, void *buf,
542559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone				  unsigned int start, unsigned int end)
543559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone{
544559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	u32 *p = buf + start;
545559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone
546559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	for ( ; start <= end; start += sizeof(u32))
547559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone		*p++ = readl(ap->regs + start);
548559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone}
5498199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
550559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardonestatic void get_regs(struct net_device *dev, struct ethtool_regs *regs,
551559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone		     void *buf)
552559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone{
553c3ccc12339afa2633c72131e2aa97d52d9ca1b8aWang Chen	struct adapter *ap = dev->ml_priv;
554559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone
555559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	/*
556559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	 * Version scheme: bits 0..9: chip version, bits 10..15: chip revision
557559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	 */
558559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	regs->version = 2;
559559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone
560559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	memset(buf, 0, T2_REGMAP_SIZE);
561559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	reg_block_dump(ap, buf, 0, A_SG_RESPACCUTIMER);
562f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	reg_block_dump(ap, buf, A_MC3_CFG, A_MC4_INT_CAUSE);
563f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	reg_block_dump(ap, buf, A_TPI_ADDR, A_TPI_PAR);
564f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	reg_block_dump(ap, buf, A_TP_IN_CONFIG, A_TP_TX_DROP_COUNT);
565f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	reg_block_dump(ap, buf, A_RAT_ROUTE_CONTROL, A_RAT_INTR_CAUSE);
566f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	reg_block_dump(ap, buf, A_CSPI_RX_AE_WM, A_CSPI_INTR_ENABLE);
567f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	reg_block_dump(ap, buf, A_ESPI_SCH_TOKEN0, A_ESPI_GOSTAT);
568f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	reg_block_dump(ap, buf, A_ULP_ULIMIT, A_ULP_PIO_CTRL);
569f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	reg_block_dump(ap, buf, A_PL_ENABLE, A_PL_CAUSE);
570f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	reg_block_dump(ap, buf, A_MC5_CONFIG, A_MC5_MASK_WRITE_CMD);
5718199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
5728199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
5738199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic int get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
5748199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
575c3ccc12339afa2633c72131e2aa97d52d9ca1b8aWang Chen	struct adapter *adapter = dev->ml_priv;
5768199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	struct port_info *p = &adapter->port[dev->if_port];
5778199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
5788199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	cmd->supported = p->link_config.supported;
5798199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	cmd->advertising = p->link_config.advertising;
5808199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
5818199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (netif_carrier_ok(dev)) {
582707394972093e2056e1e8cc39be19cf9bcb3e7b3David Decotigny		ethtool_cmd_speed_set(cmd, p->link_config.speed);
5838199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		cmd->duplex = p->link_config.duplex;
5848199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	} else {
585707394972093e2056e1e8cc39be19cf9bcb3e7b3David Decotigny		ethtool_cmd_speed_set(cmd, -1);
5868199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		cmd->duplex = -1;
5878199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	}
5888199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
589205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	cmd->port = (cmd->supported & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE;
59023c3320cb039debfb94b27e8e9bfe26dd47692c3Ben Hutchings	cmd->phy_address = p->phy->mdio.prtad;
591205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	cmd->transceiver = XCVR_EXTERNAL;
592205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	cmd->autoneg = p->link_config.autoneg;
593205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	cmd->maxtxpkt = 0;
594205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	cmd->maxrxpkt = 0;
5958199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	return 0;
5968199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
5978199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
5988199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic int speed_duplex_to_caps(int speed, int duplex)
5998199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
6008199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	int cap = 0;
6018199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
6028199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	switch (speed) {
6038199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	case SPEED_10:
6048199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		if (duplex == DUPLEX_FULL)
6058199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			cap = SUPPORTED_10baseT_Full;
6068199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		else
6078199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			cap = SUPPORTED_10baseT_Half;
6088199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		break;
6098199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	case SPEED_100:
6108199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		if (duplex == DUPLEX_FULL)
6118199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			cap = SUPPORTED_100baseT_Full;
6128199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		else
6138199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			cap = SUPPORTED_100baseT_Half;
6148199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		break;
6158199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	case SPEED_1000:
6168199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		if (duplex == DUPLEX_FULL)
6178199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			cap = SUPPORTED_1000baseT_Full;
6188199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		else
6198199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			cap = SUPPORTED_1000baseT_Half;
6208199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		break;
6218199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	case SPEED_10000:
6228199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		if (duplex == DUPLEX_FULL)
6238199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			cap = SUPPORTED_10000baseT_Full;
6248199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	}
6258199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	return cap;
6268199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
6278199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
6288199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter#define ADVERTISED_MASK (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \
6298199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		      ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \
6308199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		      ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full | \
6318199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		      ADVERTISED_10000baseT_Full)
6328199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
6338199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic int set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
6348199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
635c3ccc12339afa2633c72131e2aa97d52d9ca1b8aWang Chen	struct adapter *adapter = dev->ml_priv;
6368199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	struct port_info *p = &adapter->port[dev->if_port];
6378199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	struct link_config *lc = &p->link_config;
6388199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
6398199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (!(lc->supported & SUPPORTED_Autoneg))
640559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone		return -EOPNOTSUPP;             /* can't change speed/duplex */
6418199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
6428199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (cmd->autoneg == AUTONEG_DISABLE) {
64325db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny		u32 speed = ethtool_cmd_speed(cmd);
64425db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny		int cap = speed_duplex_to_caps(speed, cmd->duplex);
6458199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
64625db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny		if (!(lc->supported & cap) || (speed == SPEED_1000))
6478199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			return -EINVAL;
64825db0338813a8915457636b1f6abe6a28fa73f8dDavid Decotigny		lc->requested_speed = speed;
6498199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		lc->requested_duplex = cmd->duplex;
6508199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		lc->advertising = 0;
6518199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	} else {
6528199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		cmd->advertising &= ADVERTISED_MASK;
6538199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		if (cmd->advertising & (cmd->advertising - 1))
6548199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			cmd->advertising = lc->supported;
6558199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		cmd->advertising &= lc->supported;
6568199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		if (!cmd->advertising)
6578199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			return -EINVAL;
6588199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		lc->requested_speed = SPEED_INVALID;
6598199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		lc->requested_duplex = DUPLEX_INVALID;
6608199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		lc->advertising = cmd->advertising | ADVERTISED_Autoneg;
6618199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	}
6628199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	lc->autoneg = cmd->autoneg;
6638199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (netif_running(dev))
6648199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		t1_link_start(p->phy, p->mac, lc);
6658199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	return 0;
6668199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
6678199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
6688199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic void get_pauseparam(struct net_device *dev,
6698199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			   struct ethtool_pauseparam *epause)
6708199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
671c3ccc12339afa2633c72131e2aa97d52d9ca1b8aWang Chen	struct adapter *adapter = dev->ml_priv;
6728199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	struct port_info *p = &adapter->port[dev->if_port];
6738199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
6748199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	epause->autoneg = (p->link_config.requested_fc & PAUSE_AUTONEG) != 0;
6758199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	epause->rx_pause = (p->link_config.fc & PAUSE_RX) != 0;
6768199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	epause->tx_pause = (p->link_config.fc & PAUSE_TX) != 0;
6778199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
6788199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
6798199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic int set_pauseparam(struct net_device *dev,
6808199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			  struct ethtool_pauseparam *epause)
6818199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
682c3ccc12339afa2633c72131e2aa97d52d9ca1b8aWang Chen	struct adapter *adapter = dev->ml_priv;
6838199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	struct port_info *p = &adapter->port[dev->if_port];
6848199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	struct link_config *lc = &p->link_config;
6858199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
6868199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (epause->autoneg == AUTONEG_DISABLE)
6878199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		lc->requested_fc = 0;
6888199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	else if (lc->supported & SUPPORTED_Autoneg)
6898199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		lc->requested_fc = PAUSE_AUTONEG;
6908199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	else
6918199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		return -EINVAL;
6928199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
6938199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (epause->rx_pause)
6948199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		lc->requested_fc |= PAUSE_RX;
6958199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (epause->tx_pause)
6968199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		lc->requested_fc |= PAUSE_TX;
6978199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (lc->autoneg == AUTONEG_ENABLE) {
6988199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		if (netif_running(dev))
6998199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			t1_link_start(p->phy, p->mac, lc);
7008199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	} else {
7018199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
7028199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		if (netif_running(dev))
7038199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			p->mac->ops->set_speed_duplex_fc(p->mac, -1, -1,
7048199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter							 lc->fc);
7058199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	}
7068199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	return 0;
7078199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
7088199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
7098199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
7108199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
711c3ccc12339afa2633c72131e2aa97d52d9ca1b8aWang Chen	struct adapter *adapter = dev->ml_priv;
7128199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	int jumbo_fl = t1_is_T1B(adapter) ? 1 : 0;
7138199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
7148199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	e->rx_max_pending = MAX_RX_BUFFERS;
7158199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	e->rx_jumbo_max_pending = MAX_RX_JUMBO_BUFFERS;
7168199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	e->tx_max_pending = MAX_CMDQ_ENTRIES;
7178199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
7188199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	e->rx_pending = adapter->params.sge.freelQ_size[!jumbo_fl];
7198199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	e->rx_jumbo_pending = adapter->params.sge.freelQ_size[jumbo_fl];
7208199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	e->tx_pending = adapter->params.sge.cmdQ_size[0];
7218199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
7228199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
7238199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
7248199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
725c3ccc12339afa2633c72131e2aa97d52d9ca1b8aWang Chen	struct adapter *adapter = dev->ml_priv;
7268199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	int jumbo_fl = t1_is_T1B(adapter) ? 1 : 0;
7278199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
7288199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (e->rx_pending > MAX_RX_BUFFERS || e->rx_mini_pending ||
7298199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	    e->rx_jumbo_pending > MAX_RX_JUMBO_BUFFERS ||
7308199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	    e->tx_pending > MAX_CMDQ_ENTRIES ||
7318199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	    e->rx_pending < MIN_FL_ENTRIES ||
7328199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	    e->rx_jumbo_pending < MIN_FL_ENTRIES ||
7338199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	    e->tx_pending < (adapter->params.nports + 1) * (MAX_SKB_FRAGS + 1))
7348199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		return -EINVAL;
7358199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
7368199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (adapter->flags & FULL_INIT_DONE)
737356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu		return -EBUSY;
7388199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
7398199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	adapter->params.sge.freelQ_size[!jumbo_fl] = e->rx_pending;
7408199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	adapter->params.sge.freelQ_size[jumbo_fl] = e->rx_jumbo_pending;
7418199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	adapter->params.sge.cmdQ_size[0] = e->tx_pending;
7428199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	adapter->params.sge.cmdQ_size[1] = e->tx_pending > MAX_CMDQ1_ENTRIES ?
7438199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		MAX_CMDQ1_ENTRIES : e->tx_pending;
7448199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	return 0;
7458199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
7468199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
7478199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
7488199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
749c3ccc12339afa2633c72131e2aa97d52d9ca1b8aWang Chen	struct adapter *adapter = dev->ml_priv;
7508199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
7517fe26a60e08f38c797851fb3b444d753af616112Stephen Hemminger	adapter->params.sge.rx_coalesce_usecs = c->rx_coalesce_usecs;
752356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu	adapter->params.sge.coalesce_enable = c->use_adaptive_rx_coalesce;
7538199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	adapter->params.sge.sample_interval_usecs = c->rate_sample_interval;
7548199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	t1_sge_set_coalesce_params(adapter->sge, &adapter->params.sge);
7558199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	return 0;
7568199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
7578199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
7588199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
7598199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
760c3ccc12339afa2633c72131e2aa97d52d9ca1b8aWang Chen	struct adapter *adapter = dev->ml_priv;
7618199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
762559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	c->rx_coalesce_usecs = adapter->params.sge.rx_coalesce_usecs;
7638199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	c->rate_sample_interval = adapter->params.sge.sample_interval_usecs;
7648199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	c->use_adaptive_rx_coalesce = adapter->params.sge.coalesce_enable;
7658199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	return 0;
7668199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
7678199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
7688199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic int get_eeprom_len(struct net_device *dev)
7698199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
770c3ccc12339afa2633c72131e2aa97d52d9ca1b8aWang Chen	struct adapter *adapter = dev->ml_priv;
771f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
772356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu	return t1_is_asic(adapter) ? EEPROM_SIZE : 0;
7738199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
7748199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
7758199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter#define EEPROM_MAGIC(ap) \
7768199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	(PCI_VENDOR_ID_CHELSIO | ((ap)->params.chip_version << 16))
7778199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
7788199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic int get_eeprom(struct net_device *dev, struct ethtool_eeprom *e,
7798199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		      u8 *data)
7808199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
7818199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	int i;
7828199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	u8 buf[EEPROM_SIZE] __attribute__((aligned(4)));
783c3ccc12339afa2633c72131e2aa97d52d9ca1b8aWang Chen	struct adapter *adapter = dev->ml_priv;
7848199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
7858199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	e->magic = EEPROM_MAGIC(adapter);
7868199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	for (i = e->offset & ~3; i < e->offset + e->len; i += sizeof(u32))
787ac390c60a833192e87fb09ed8d67f5d1a84306c8Al Viro		t1_seeprom_read(adapter, i, (__le32 *)&buf[i]);
7888199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	memcpy(data, buf + e->offset, e->len);
7898199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	return 0;
7908199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
7918199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
7927282d491ecaee9883233a0e27283c4c79486279aJeff Garzikstatic const struct ethtool_ops t1_ethtool_ops = {
7938199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	.get_settings      = get_settings,
7948199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	.set_settings      = set_settings,
7958199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	.get_drvinfo       = get_drvinfo,
7968199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	.get_msglevel      = get_msglevel,
7978199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	.set_msglevel      = set_msglevel,
7988199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	.get_ringparam     = get_sge_param,
7998199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	.set_ringparam     = set_sge_param,
8008199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	.get_coalesce      = get_coalesce,
8018199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	.set_coalesce      = set_coalesce,
8028199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	.get_eeprom_len    = get_eeprom_len,
8038199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	.get_eeprom        = get_eeprom,
8048199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	.get_pauseparam    = get_pauseparam,
8058199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	.set_pauseparam    = set_pauseparam,
8068199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	.get_link          = ethtool_op_get_link,
8078199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	.get_strings       = get_strings,
808b9f2c0440d806e01968c3ed4def930a43be248adJeff Garzik	.get_sset_count	   = get_sset_count,
8098199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	.get_ethtool_stats = get_stats,
810559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	.get_regs_len      = get_regs_len,
811559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	.get_regs          = get_regs,
8128199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter};
8138199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
8148199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic int t1_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
8158199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
816c3ccc12339afa2633c72131e2aa97d52d9ca1b8aWang Chen	struct adapter *adapter = dev->ml_priv;
81723c3320cb039debfb94b27e8e9bfe26dd47692c3Ben Hutchings	struct mdio_if_info *mdio = &adapter->port[dev->if_port].phy->mdio;
8188199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
81923c3320cb039debfb94b27e8e9bfe26dd47692c3Ben Hutchings	return mdio_mii_ioctl(mdio, if_mii(req), cmd);
8208199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
8218199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
8228199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic int t1_change_mtu(struct net_device *dev, int new_mtu)
8238199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
8248199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	int ret;
825c3ccc12339afa2633c72131e2aa97d52d9ca1b8aWang Chen	struct adapter *adapter = dev->ml_priv;
8268199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	struct cmac *mac = adapter->port[dev->if_port].mac;
8278199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
8288199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (!mac->ops->set_mtu)
829356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu		return -EOPNOTSUPP;
8308199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (new_mtu < 68)
831356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu		return -EINVAL;
8328199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if ((ret = mac->ops->set_mtu(mac, new_mtu)))
8338199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		return ret;
8348199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	dev->mtu = new_mtu;
8358199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	return 0;
8368199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
8378199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
8388199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic int t1_set_mac_addr(struct net_device *dev, void *p)
8398199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
840c3ccc12339afa2633c72131e2aa97d52d9ca1b8aWang Chen	struct adapter *adapter = dev->ml_priv;
8418199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	struct cmac *mac = adapter->port[dev->if_port].mac;
8428199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	struct sockaddr *addr = p;
8438199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
8448199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (!mac->ops->macaddress_set)
8458199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		return -EOPNOTSUPP;
8468199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
8478199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
8488199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	mac->ops->macaddress_set(mac, dev->dev_addr);
8498199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	return 0;
8508199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
8518199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
852c8f44affb7244f2ac3e703cab13d55ede27621bbMichał Mirosławstatic netdev_features_t t1_fix_features(struct net_device *dev,
853c8f44affb7244f2ac3e703cab13d55ede27621bbMichał Mirosław	netdev_features_t features)
8548199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
855133b08513a99d44d9ed916bb83e46343f6ad2855Jiri Pirko	/*
856133b08513a99d44d9ed916bb83e46343f6ad2855Jiri Pirko	 * Since there is no support for separate rx/tx vlan accel
857133b08513a99d44d9ed916bb83e46343f6ad2855Jiri Pirko	 * enable/disable make sure tx flag is always in same state as rx.
858133b08513a99d44d9ed916bb83e46343f6ad2855Jiri Pirko	 */
859133b08513a99d44d9ed916bb83e46343f6ad2855Jiri Pirko	if (features & NETIF_F_HW_VLAN_RX)
860133b08513a99d44d9ed916bb83e46343f6ad2855Jiri Pirko		features |= NETIF_F_HW_VLAN_TX;
861133b08513a99d44d9ed916bb83e46343f6ad2855Jiri Pirko	else
862133b08513a99d44d9ed916bb83e46343f6ad2855Jiri Pirko		features &= ~NETIF_F_HW_VLAN_TX;
8638199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
864133b08513a99d44d9ed916bb83e46343f6ad2855Jiri Pirko	return features;
8658199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
8668199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
867c8f44affb7244f2ac3e703cab13d55ede27621bbMichał Mirosławstatic int t1_set_features(struct net_device *dev, netdev_features_t features)
868133b08513a99d44d9ed916bb83e46343f6ad2855Jiri Pirko{
869c8f44affb7244f2ac3e703cab13d55ede27621bbMichał Mirosław	netdev_features_t changed = dev->features ^ features;
870133b08513a99d44d9ed916bb83e46343f6ad2855Jiri Pirko	struct adapter *adapter = dev->ml_priv;
871133b08513a99d44d9ed916bb83e46343f6ad2855Jiri Pirko
872133b08513a99d44d9ed916bb83e46343f6ad2855Jiri Pirko	if (changed & NETIF_F_HW_VLAN_RX)
873133b08513a99d44d9ed916bb83e46343f6ad2855Jiri Pirko		t1_vlan_mode(adapter, features);
874133b08513a99d44d9ed916bb83e46343f6ad2855Jiri Pirko
875133b08513a99d44d9ed916bb83e46343f6ad2855Jiri Pirko	return 0;
876133b08513a99d44d9ed916bb83e46343f6ad2855Jiri Pirko}
8778199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter#ifdef CONFIG_NET_POLL_CONTROLLER
8788199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic void t1_netpoll(struct net_device *dev)
8798199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
880559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	unsigned long flags;
881c3ccc12339afa2633c72131e2aa97d52d9ca1b8aWang Chen	struct adapter *adapter = dev->ml_priv;
8828199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
883559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	local_irq_save(flags);
8847fe26a60e08f38c797851fb3b444d753af616112Stephen Hemminger	t1_interrupt(adapter->pdev->irq, adapter);
885559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	local_irq_restore(flags);
8868199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
8878199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter#endif
8888199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
8898199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter/*
8908199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter * Periodic accumulation of MAC statistics.  This is used only if the MAC
8918199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter * does not have any other way to prevent stats counter overflow.
8928199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter */
893c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howellsstatic void mac_stats_task(struct work_struct *work)
8948199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
8958199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	int i;
896c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells	struct adapter *adapter =
897c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells		container_of(work, struct adapter, stats_update_task.work);
8988199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
8998199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	for_each_port(adapter, i) {
9008199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		struct port_info *p = &adapter->port[i];
9018199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
9028199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		if (netif_running(p->dev))
9038199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			p->mac->ops->statistics_update(p->mac,
9048199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter						       MAC_STATS_UPDATE_FAST);
9058199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	}
9068199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
9078199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	/* Schedule the next statistics update if any port is active. */
9088199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	spin_lock(&adapter->work_lock);
9098199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (adapter->open_device_map & PORT_MASK)
9108199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		schedule_mac_stats_update(adapter,
9118199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter					  adapter->params.stats_update_period);
9128199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	spin_unlock(&adapter->work_lock);
9138199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
9148199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
9158199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter/*
9168199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter * Processes elmer0 external interrupts in process context.
9178199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter */
918c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howellsstatic void ext_intr_task(struct work_struct *work)
9198199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
920c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells	struct adapter *adapter =
921c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells		container_of(work, struct adapter, ext_intr_handler_task);
9228199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
923f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	t1_elmer0_ext_intr_handler(adapter);
9248199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
9258199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	/* Now reenable external interrupts */
926559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	spin_lock_irq(&adapter->async_lock);
9278199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	adapter->slow_intr_mask |= F_PL_INTR_EXT;
928559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	writel(F_PL_INTR_EXT, adapter->regs + A_PL_CAUSE);
929559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA,
930205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger		   adapter->regs + A_PL_ENABLE);
931559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	spin_unlock_irq(&adapter->async_lock);
9328199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
9338199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
9348199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter/*
9358199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter * Interrupt-context handler for elmer0 external interrupts.
9368199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter */
9378199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lametervoid t1_elmer0_ext_intr(struct adapter *adapter)
9388199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
9398199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	/*
9408199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	 * Schedule a task to handle external interrupts as we require
9418199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	 * a process context.  We disable EXT interrupts in the interim
9428199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	 * and let the task reenable them when it's done.
9438199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	 */
9448199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	adapter->slow_intr_mask &= ~F_PL_INTR_EXT;
945559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA,
946205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger		   adapter->regs + A_PL_ENABLE);
9478199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	schedule_work(&adapter->ext_intr_handler_task);
9488199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
9498199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
9508199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lametervoid t1_fatal_err(struct adapter *adapter)
9518199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
9528199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (adapter->flags & FULL_INIT_DONE) {
9538199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		t1_sge_stop(adapter->sge);
9548199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		t1_interrupts_disable(adapter);
9558199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	}
956c1f51212eb809849bdc68a856ae5f424dcf20d9bJoe Perches	pr_alert("%s: encountered fatal error, operation suspended\n",
9578199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		 adapter->name);
9588199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
9598199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
96080ff32b76f7969bf62206840c4e1d04674e41df9Stephen Hemmingerstatic const struct net_device_ops cxgb_netdev_ops = {
96180ff32b76f7969bf62206840c4e1d04674e41df9Stephen Hemminger	.ndo_open		= cxgb_open,
96280ff32b76f7969bf62206840c4e1d04674e41df9Stephen Hemminger	.ndo_stop		= cxgb_close,
963008298231abbeb91bc7be9e8b078607b816d1a4aStephen Hemminger	.ndo_start_xmit		= t1_start_xmit,
96480ff32b76f7969bf62206840c4e1d04674e41df9Stephen Hemminger	.ndo_get_stats		= t1_get_stats,
96580ff32b76f7969bf62206840c4e1d04674e41df9Stephen Hemminger	.ndo_validate_addr	= eth_validate_addr,
966afc4b13df143122f99a0eb10bfefb216c2806de0Jiri Pirko	.ndo_set_rx_mode	= t1_set_rxmode,
96780ff32b76f7969bf62206840c4e1d04674e41df9Stephen Hemminger	.ndo_do_ioctl		= t1_ioctl,
96880ff32b76f7969bf62206840c4e1d04674e41df9Stephen Hemminger	.ndo_change_mtu		= t1_change_mtu,
96980ff32b76f7969bf62206840c4e1d04674e41df9Stephen Hemminger	.ndo_set_mac_address	= t1_set_mac_addr,
970133b08513a99d44d9ed916bb83e46343f6ad2855Jiri Pirko	.ndo_fix_features	= t1_fix_features,
971133b08513a99d44d9ed916bb83e46343f6ad2855Jiri Pirko	.ndo_set_features	= t1_set_features,
97280ff32b76f7969bf62206840c4e1d04674e41df9Stephen Hemminger#ifdef CONFIG_NET_POLL_CONTROLLER
97380ff32b76f7969bf62206840c4e1d04674e41df9Stephen Hemminger	.ndo_poll_controller	= t1_netpoll,
97480ff32b76f7969bf62206840c4e1d04674e41df9Stephen Hemminger#endif
97580ff32b76f7969bf62206840c4e1d04674e41df9Stephen Hemminger};
97680ff32b76f7969bf62206840c4e1d04674e41df9Stephen Hemminger
9778199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic int __devinit init_one(struct pci_dev *pdev,
9788199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			      const struct pci_device_id *ent)
9798199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
9808199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	static int version_printed;
9818199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
9828199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	int i, err, pci_using_dac = 0;
9838199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	unsigned long mmio_start, mmio_len;
9848199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	const struct board_info *bi;
9858199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	struct adapter *adapter = NULL;
9868199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	struct port_info *pi;
9878199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
9888199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (!version_printed) {
989559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone		printk(KERN_INFO "%s - version %s\n", DRV_DESCRIPTION,
990559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone		       DRV_VERSION);
9918199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		++version_printed;
9928199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	}
9938199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
9948199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	err = pci_enable_device(pdev);
9958199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (err)
996205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger		return err;
9978199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
9988199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
999c1f51212eb809849bdc68a856ae5f424dcf20d9bJoe Perches		pr_err("%s: cannot find PCI device memory base address\n",
10008199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		       pci_name(pdev));
10018199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		err = -ENODEV;
10028199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		goto out_disable_pdev;
10038199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	}
10048199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
10056a35528a8346f6e6fd32ed7e51f04d1fa4ca2c01Yang Hongyang	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
10068199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		pci_using_dac = 1;
1007559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone
10086a35528a8346f6e6fd32ed7e51f04d1fa4ca2c01Yang Hongyang		if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) {
1009c1f51212eb809849bdc68a856ae5f424dcf20d9bJoe Perches			pr_err("%s: unable to obtain 64-bit DMA for "
10108199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			       "consistent allocations\n", pci_name(pdev));
10118199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			err = -ENODEV;
10128199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			goto out_disable_pdev;
10138199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		}
1014559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone
1015284901a90a9e0b812ca3f5f852cbbfb60d10249dYang Hongyang	} else if ((err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) != 0) {
1016c1f51212eb809849bdc68a856ae5f424dcf20d9bJoe Perches		pr_err("%s: no usable DMA configuration\n", pci_name(pdev));
10178199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		goto out_disable_pdev;
10188199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	}
10198199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
1020559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	err = pci_request_regions(pdev, DRV_NAME);
10218199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (err) {
1022c1f51212eb809849bdc68a856ae5f424dcf20d9bJoe Perches		pr_err("%s: cannot obtain PCI resources\n", pci_name(pdev));
10238199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		goto out_disable_pdev;
10248199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	}
10258199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
10268199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	pci_set_master(pdev);
10278199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
1028205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger	mmio_start = pci_resource_start(pdev, 0);
10298199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	mmio_len = pci_resource_len(pdev, 0);
10308199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	bi = t1_get_board_info(ent->driver_data);
10318199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
10328199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	for (i = 0; i < bi->port_number; ++i) {
10338199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		struct net_device *netdev;
10348199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
10358199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		netdev = alloc_etherdev(adapter ? 0 : sizeof(*adapter));
10368199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		if (!netdev) {
10378199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			err = -ENOMEM;
10388199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			goto out_free_dev;
10398199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		}
10408199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
10418199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		SET_NETDEV_DEV(netdev, &pdev->dev);
10428199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
10438199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		if (!adapter) {
1044c3ccc12339afa2633c72131e2aa97d52d9ca1b8aWang Chen			adapter = netdev_priv(netdev);
10458199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			adapter->pdev = pdev;
10468199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			adapter->port[0].dev = netdev;  /* so we don't leak it */
10478199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
10488199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			adapter->regs = ioremap(mmio_start, mmio_len);
10498199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			if (!adapter->regs) {
1050c1f51212eb809849bdc68a856ae5f424dcf20d9bJoe Perches				pr_err("%s: cannot map device registers\n",
10518199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter				       pci_name(pdev));
10528199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter				err = -ENOMEM;
10538199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter				goto out_free_dev;
10548199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			}
10558199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
10568199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			if (t1_get_board_rev(adapter, bi, &adapter->params)) {
10578199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter				err = -ENODEV;	  /* Can't handle this chip rev */
10588199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter				goto out_free_dev;
10598199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			}
10608199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
10618199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			adapter->name = pci_name(pdev);
10628199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			adapter->msg_enable = dflt_msg_enable;
10638199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			adapter->mmio_len = mmio_len;
10648199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
10658199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			spin_lock_init(&adapter->tpi_lock);
10668199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			spin_lock_init(&adapter->work_lock);
10678199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			spin_lock_init(&adapter->async_lock);
1068352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger			spin_lock_init(&adapter->mac_lock);
10698199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
10708199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			INIT_WORK(&adapter->ext_intr_handler_task,
1071c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells				  ext_intr_task);
1072c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells			INIT_DELAYED_WORK(&adapter->stats_update_task,
1073c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells					  mac_stats_task);
10748199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
10758199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			pci_set_drvdata(pdev, netdev);
10768199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		}
10778199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
10788199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		pi = &adapter->port[i];
10798199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		pi->dev = netdev;
10808199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		netif_carrier_off(netdev);
10818199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		netdev->irq = pdev->irq;
10828199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		netdev->if_port = i;
10838199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		netdev->mem_start = mmio_start;
10848199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		netdev->mem_end = mmio_start + mmio_len - 1;
1085c3ccc12339afa2633c72131e2aa97d52d9ca1b8aWang Chen		netdev->ml_priv = adapter;
108630f554f925335abad89aaa38eec6828242b27527Michał Mirosław		netdev->hw_features |= NETIF_F_SG | NETIF_F_IP_CSUM |
108730f554f925335abad89aaa38eec6828242b27527Michał Mirosław			NETIF_F_RXCSUM;
108830f554f925335abad89aaa38eec6828242b27527Michał Mirosław		netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM |
108930f554f925335abad89aaa38eec6828242b27527Michał Mirosław			NETIF_F_RXCSUM | NETIF_F_LLTX;
1090559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone
10918199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		if (pci_using_dac)
10928199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			netdev->features |= NETIF_F_HIGHDMA;
10938199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		if (vlan_tso_capable(adapter)) {
10948199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			netdev->features |=
10958199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter				NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
1096133b08513a99d44d9ed916bb83e46343f6ad2855Jiri Pirko			netdev->hw_features |= NETIF_F_HW_VLAN_RX;
1097f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
1098f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger			/* T204: disable TSO */
1099f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger			if (!(is_T2(adapter)) || bi->port_number != 4) {
110030f554f925335abad89aaa38eec6828242b27527Michał Mirosław				netdev->hw_features |= NETIF_F_TSO;
1101f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger				netdev->features |= NETIF_F_TSO;
1102f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger			}
11038199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		}
11048199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
110580ff32b76f7969bf62206840c4e1d04674e41df9Stephen Hemminger		netdev->netdev_ops = &cxgb_netdev_ops;
110630f554f925335abad89aaa38eec6828242b27527Michał Mirosław		netdev->hard_header_len += (netdev->hw_features & NETIF_F_TSO) ?
1107f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger			sizeof(struct cpl_tx_pkt_lso) : sizeof(struct cpl_tx_pkt);
110880ff32b76f7969bf62206840c4e1d04674e41df9Stephen Hemminger
1109bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger		netif_napi_add(netdev, &adapter->napi, t1_poll, 64);
11108199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
1111205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger		SET_ETHTOOL_OPS(netdev, &t1_ethtool_ops);
11128199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	}
11138199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
11148199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (t1_init_sw_modules(adapter, bi) < 0) {
11158199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		err = -ENODEV;
11168199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		goto out_free_dev;
11178199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	}
11188199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
11198199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	/*
11208199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	 * The card is now ready to go.  If any errors occur during device
11218199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	 * registration we do not fail the whole card but rather proceed only
11228199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	 * with the ports we manage to register successfully.  However we must
11238199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	 * register at least one net device.
11248199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	 */
11258199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	for (i = 0; i < bi->port_number; ++i) {
11268199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		err = register_netdev(adapter->port[i].dev);
11278199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		if (err)
1128c1f51212eb809849bdc68a856ae5f424dcf20d9bJoe Perches			pr_warning("%s: cannot register net device %s, skipping\n",
1129c1f51212eb809849bdc68a856ae5f424dcf20d9bJoe Perches				   pci_name(pdev), adapter->port[i].dev->name);
11308199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		else {
11318199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			/*
11328199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			 * Change the name we use for messages to the name of
11338199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			 * the first successfully registered interface.
11348199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			 */
11358199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter			if (!adapter->registered_device_map)
11368199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter				adapter->name = adapter->port[i].dev->name;
11378199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
1138205781510d2a55a5c231f6e51df5b6c4aa765143Stephen Hemminger			__set_bit(i, &adapter->registered_device_map);
11398199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		}
11408199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	}
11418199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (!adapter->registered_device_map) {
1142c1f51212eb809849bdc68a856ae5f424dcf20d9bJoe Perches		pr_err("%s: could not register any net devices\n",
11438199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		       pci_name(pdev));
11448199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		goto out_release_adapter_res;
11458199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	}
11468199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
11478199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	printk(KERN_INFO "%s: %s (rev %d), %s %dMHz/%d-bit\n", adapter->name,
11488199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	       bi->desc, adapter->params.chip_revision,
11498199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	       adapter->params.pci.is_pcix ? "PCIX" : "PCI",
11508199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	       adapter->params.pci.speed, adapter->params.pci.width);
1151f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
1152f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	/*
1153f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	 * Set the T1B ASIC and memory clocks.
1154f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	 */
1155f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	if (t1powersave)
1156f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		adapter->t1powersave = LCLOCK;	/* HW default is powersave mode. */
1157f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	else
1158f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		adapter->t1powersave = HCLOCK;
1159f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	if (t1_is_T1B(adapter))
1160f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		t1_clock(adapter, t1powersave);
1161f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
11628199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	return 0;
11638199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
1164356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieuout_release_adapter_res:
11658199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	t1_free_sw_modules(adapter);
1166356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieuout_free_dev:
11678199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	if (adapter) {
1168e487647abbe66390b99f9a32ede4688b255282ddStephen Hemminger		if (adapter->regs)
1169e487647abbe66390b99f9a32ede4688b255282ddStephen Hemminger			iounmap(adapter->regs);
11708199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter		for (i = bi->port_number - 1; i >= 0; --i)
1171e487647abbe66390b99f9a32ede4688b255282ddStephen Hemminger			if (adapter->port[i].dev)
1172e487647abbe66390b99f9a32ede4688b255282ddStephen Hemminger				free_netdev(adapter->port[i].dev);
11738199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	}
11748199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	pci_release_regions(pdev);
1175356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieuout_disable_pdev:
11768199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	pci_disable_device(pdev);
11778199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	pci_set_drvdata(pdev, NULL);
11788199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	return err;
11798199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
11808199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
1181f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemmingerstatic void bit_bang(struct adapter *adapter, int bitdata, int nbits)
1182f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger{
1183f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	int data;
1184f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	int i;
1185f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	u32 val;
1186f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
1187f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	enum {
1188f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		S_CLOCK = 1 << 3,
1189f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		S_DATA = 1 << 4
1190f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	};
1191f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
1192f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	for (i = (nbits - 1); i > -1; i--) {
1193f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
1194f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		udelay(50);
1195f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
1196f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		data = ((bitdata >> i) & 0x1);
1197f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		__t1_tpi_read(adapter, A_ELMER0_GPO, &val);
1198f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
1199f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		if (data)
1200f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger			val |= S_DATA;
1201f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		else
1202f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger			val &= ~S_DATA;
1203f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
1204f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		udelay(50);
1205f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
1206f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		/* Set SCLOCK low */
1207f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		val &= ~S_CLOCK;
1208f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		__t1_tpi_write(adapter, A_ELMER0_GPO, val);
1209f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
1210f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		udelay(50);
1211f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
1212f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		/* Write SCLOCK high */
1213f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		val |= S_CLOCK;
1214f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		__t1_tpi_write(adapter, A_ELMER0_GPO, val);
1215f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
1216f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	}
1217f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger}
1218f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
1219f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemmingerstatic int t1_clock(struct adapter *adapter, int mode)
1220f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger{
1221f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	u32 val;
1222f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	int M_CORE_VAL;
1223f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	int M_MEM_VAL;
1224f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
1225f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	enum {
1226356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu		M_CORE_BITS	= 9,
1227356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu		T_CORE_VAL	= 0,
1228356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu		T_CORE_BITS	= 2,
1229356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu		N_CORE_VAL	= 0,
1230356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu		N_CORE_BITS	= 2,
1231356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu		M_MEM_BITS	= 9,
1232356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu		T_MEM_VAL	= 0,
1233356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu		T_MEM_BITS	= 2,
1234356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu		N_MEM_VAL	= 0,
1235356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu		N_MEM_BITS	= 2,
1236356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu		NP_LOAD		= 1 << 17,
1237356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu		S_LOAD_MEM	= 1 << 5,
1238356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu		S_LOAD_CORE	= 1 << 6,
1239356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu		S_CLOCK		= 1 << 3
1240f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	};
1241f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
1242f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	if (!t1_is_T1B(adapter))
1243f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		return -ENODEV;	/* Can't re-clock this chip. */
1244f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
1245d7487421b629c5ca71ce23b10461ef0c3ad2c741Francois Romieu	if (mode & 2)
1246f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		return 0;	/* show current mode. */
1247f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
1248f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	if ((adapter->t1powersave & 1) == (mode & 1))
1249f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		return -EALREADY;	/* ASIC already running in mode. */
1250f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
1251f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	if ((mode & 1) == HCLOCK) {
1252f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		M_CORE_VAL = 0x14;
1253f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		M_MEM_VAL = 0x18;
1254f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		adapter->t1powersave = HCLOCK;	/* overclock */
1255f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	} else {
1256f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		M_CORE_VAL = 0xe;
1257f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		M_MEM_VAL = 0x10;
1258f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger		adapter->t1powersave = LCLOCK;	/* underclock */
1259f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	}
1260f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
1261f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	/* Don't interrupt this serial stream! */
1262f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	spin_lock(&adapter->tpi_lock);
1263f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
1264f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	/* Initialize for ASIC core */
1265f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	__t1_tpi_read(adapter, A_ELMER0_GPO, &val);
1266f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	val |= NP_LOAD;
1267f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	udelay(50);
1268f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	__t1_tpi_write(adapter, A_ELMER0_GPO, val);
1269f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	udelay(50);
1270f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	__t1_tpi_read(adapter, A_ELMER0_GPO, &val);
1271f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	val &= ~S_LOAD_CORE;
1272f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	val &= ~S_CLOCK;
1273f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	__t1_tpi_write(adapter, A_ELMER0_GPO, val);
1274f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	udelay(50);
1275f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
1276f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	/* Serial program the ASIC clock synthesizer */
1277f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	bit_bang(adapter, T_CORE_VAL, T_CORE_BITS);
1278f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	bit_bang(adapter, N_CORE_VAL, N_CORE_BITS);
1279f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	bit_bang(adapter, M_CORE_VAL, M_CORE_BITS);
1280f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	udelay(50);
1281f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
1282f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	/* Finish ASIC core */
1283f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	__t1_tpi_read(adapter, A_ELMER0_GPO, &val);
1284f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	val |= S_LOAD_CORE;
1285f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	udelay(50);
1286f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	__t1_tpi_write(adapter, A_ELMER0_GPO, val);
1287f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	udelay(50);
1288f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	__t1_tpi_read(adapter, A_ELMER0_GPO, &val);
1289f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	val &= ~S_LOAD_CORE;
1290f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	udelay(50);
1291f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	__t1_tpi_write(adapter, A_ELMER0_GPO, val);
1292f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	udelay(50);
1293f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
1294f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	/* Initialize for memory */
1295f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	__t1_tpi_read(adapter, A_ELMER0_GPO, &val);
1296f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	val |= NP_LOAD;
1297f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	udelay(50);
1298f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	__t1_tpi_write(adapter, A_ELMER0_GPO, val);
1299f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	udelay(50);
1300f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	__t1_tpi_read(adapter, A_ELMER0_GPO, &val);
1301f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	val &= ~S_LOAD_MEM;
1302f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	val &= ~S_CLOCK;
1303f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	udelay(50);
1304f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	__t1_tpi_write(adapter, A_ELMER0_GPO, val);
1305f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	udelay(50);
1306f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
1307f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	/* Serial program the memory clock synthesizer */
1308f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	bit_bang(adapter, T_MEM_VAL, T_MEM_BITS);
1309f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	bit_bang(adapter, N_MEM_VAL, N_MEM_BITS);
1310f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	bit_bang(adapter, M_MEM_VAL, M_MEM_BITS);
1311f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	udelay(50);
1312f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
1313f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	/* Finish memory */
1314f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	__t1_tpi_read(adapter, A_ELMER0_GPO, &val);
1315f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	val |= S_LOAD_MEM;
1316f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	udelay(50);
1317f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	__t1_tpi_write(adapter, A_ELMER0_GPO, val);
1318f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	udelay(50);
1319f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	__t1_tpi_read(adapter, A_ELMER0_GPO, &val);
1320f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	val &= ~S_LOAD_MEM;
1321f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	udelay(50);
1322f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	__t1_tpi_write(adapter, A_ELMER0_GPO, val);
1323f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
1324f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	spin_unlock(&adapter->tpi_lock);
1325f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
1326f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger	return 0;
1327f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger}
1328f1d3d38af75789f1b82969b83b69cab540609789Stephen Hemminger
13298199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic inline void t1_sw_reset(struct pci_dev *pdev)
13308199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
13318199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	pci_write_config_dword(pdev, A_PCICFG_PM_CSR, 3);
13328199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	pci_write_config_dword(pdev, A_PCICFG_PM_CSR, 0);
13338199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
13348199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
13358199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic void __devexit remove_one(struct pci_dev *pdev)
13368199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
13378199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	struct net_device *dev = pci_get_drvdata(pdev);
1338c3ccc12339afa2633c72131e2aa97d52d9ca1b8aWang Chen	struct adapter *adapter = dev->ml_priv;
133947cbe6f47d854410d5c296098d87cf8151517c20Francois Romieu	int i;
13408199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
134147cbe6f47d854410d5c296098d87cf8151517c20Francois Romieu	for_each_port(adapter, i) {
134247cbe6f47d854410d5c296098d87cf8151517c20Francois Romieu		if (test_bit(i, &adapter->registered_device_map))
134347cbe6f47d854410d5c296098d87cf8151517c20Francois Romieu			unregister_netdev(adapter->port[i].dev);
134447cbe6f47d854410d5c296098d87cf8151517c20Francois Romieu	}
13458199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
134647cbe6f47d854410d5c296098d87cf8151517c20Francois Romieu	t1_free_sw_modules(adapter);
134747cbe6f47d854410d5c296098d87cf8151517c20Francois Romieu	iounmap(adapter->regs);
1348e487647abbe66390b99f9a32ede4688b255282ddStephen Hemminger
134947cbe6f47d854410d5c296098d87cf8151517c20Francois Romieu	while (--i >= 0) {
135047cbe6f47d854410d5c296098d87cf8151517c20Francois Romieu		if (adapter->port[i].dev)
135147cbe6f47d854410d5c296098d87cf8151517c20Francois Romieu			free_netdev(adapter->port[i].dev);
13528199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	}
135347cbe6f47d854410d5c296098d87cf8151517c20Francois Romieu
135447cbe6f47d854410d5c296098d87cf8151517c20Francois Romieu	pci_release_regions(pdev);
135547cbe6f47d854410d5c296098d87cf8151517c20Francois Romieu	pci_disable_device(pdev);
135647cbe6f47d854410d5c296098d87cf8151517c20Francois Romieu	pci_set_drvdata(pdev, NULL);
135747cbe6f47d854410d5c296098d87cf8151517c20Francois Romieu	t1_sw_reset(pdev);
13588199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
13598199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
13608199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic struct pci_driver driver = {
1361559fb51ba7e66fe298b8355fabde1275b7def35fScott Bardone	.name     = DRV_NAME,
13628199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	.id_table = t1_pci_tbl,
13638199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	.probe    = init_one,
13648199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	.remove   = __devexit_p(remove_one),
13658199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter};
13668199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
13678199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic int __init t1_init_module(void)
13688199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
1369299176206b266f204be859adf9e66efd06628ab2Jeff Garzik	return pci_register_driver(&driver);
13708199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
13718199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
13728199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameterstatic void __exit t1_cleanup_module(void)
13738199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter{
13748199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter	pci_unregister_driver(&driver);
13758199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter}
13768199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lameter
13778199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lametermodule_init(t1_init_module);
13788199d3a79c224bbe5943fa08684e1f93a17881b0Christoph Lametermodule_exit(t1_cleanup_module);
1379