blob: 27be6c8693150a2c52a81d42b68281ca07df21f0 [file] [log] [blame]
Francois Romieu890e8d02005-07-30 13:08:43 +02001/*
2 sis190.c: Silicon Integrated Systems SiS190 ethernet driver
3
4 Copyright (c) 2003 K.M. Liu <kmliu@sis.com>
5 Copyright (c) 2003, 2004 Jeff Garzik <jgarzik@pobox.com>
6 Copyright (c) 2003, 2004, 2005 Francois Romieu <romieu@fr.zoreil.com>
7
Francois Romieu40292fb2005-07-30 13:12:06 +02008 Based on r8169.c, tg3.c, 8139cp.c, skge.c, epic100.c and SiS 190/191
9 genuine driver.
Francois Romieu890e8d02005-07-30 13:08:43 +020010
11 This software may be used and distributed according to the terms of
12 the GNU General Public License (GPL), incorporated herein by reference.
13 Drivers based on or derived from this code fall under the GPL and must
14 retain the authorship, copyright and license notice. This file is not
15 a complete program and may only be used when the entire operating
16 system is licensed under the GPL.
17
18 See the file COPYING in this distribution for more information.
19
Joe Perchesad06ab22010-02-17 20:00:17 +000020*/
21
22#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
Francois Romieu890e8d02005-07-30 13:08:43 +020023
Alexey Dobriyana6b7a402011-06-06 10:43:46 +000024#include <linux/interrupt.h>
Francois Romieu890e8d02005-07-30 13:08:43 +020025#include <linux/module.h>
26#include <linux/moduleparam.h>
27#include <linux/netdevice.h>
Francois Romieu43afb942005-07-30 13:10:21 +020028#include <linux/rtnetlink.h>
Francois Romieu890e8d02005-07-30 13:08:43 +020029#include <linux/etherdevice.h>
30#include <linux/ethtool.h>
31#include <linux/pci.h>
32#include <linux/mii.h>
33#include <linux/delay.h>
34#include <linux/crc32.h>
35#include <linux/dma-mapping.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090036#include <linux/slab.h>
Francois Romieu890e8d02005-07-30 13:08:43 +020037#include <asm/irq.h>
38
Francois Romieufcb98212005-07-30 13:15:22 +020039#define PHY_MAX_ADDR 32
40#define PHY_ID_ANY 0x1f
41#define MII_REG_ANY 0x1f
42
Riccardo Ghetta08326db2010-02-17 09:28:58 +000043#define DRV_VERSION "1.4"
Francois Romieu890e8d02005-07-30 13:08:43 +020044#define DRV_NAME "sis190"
45#define SIS190_DRIVER_NAME DRV_NAME " Gigabit Ethernet driver " DRV_VERSION
Francois Romieu890e8d02005-07-30 13:08:43 +020046
Francois Romieu890e8d02005-07-30 13:08:43 +020047#define sis190_rx_skb netif_rx
48#define sis190_rx_quota(count, quota) count
Francois Romieu890e8d02005-07-30 13:08:43 +020049
Francois Romieubcad5e52005-07-30 13:13:47 +020050#define NUM_TX_DESC 64 /* [8..1024] */
51#define NUM_RX_DESC 64 /* [8..8192] */
Francois Romieu890e8d02005-07-30 13:08:43 +020052#define TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc))
53#define RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc))
54#define RX_BUF_SIZE 1536
Francois Romieu8b5641d2005-07-30 13:13:03 +020055#define RX_BUF_MASK 0xfff8
Francois Romieu890e8d02005-07-30 13:08:43 +020056
57#define SIS190_REGS_SIZE 0x80
58#define SIS190_TX_TIMEOUT (6*HZ)
59#define SIS190_PHY_TIMEOUT (10*HZ)
60#define SIS190_MSG_DEFAULT (NETIF_MSG_DRV | NETIF_MSG_PROBE | \
61 NETIF_MSG_LINK | NETIF_MSG_IFUP | \
62 NETIF_MSG_IFDOWN)
63
64/* Enhanced PHY access register bit definitions */
65#define EhnMIIread 0x0000
66#define EhnMIIwrite 0x0020
67#define EhnMIIdataShift 16
68#define EhnMIIpmdShift 6 /* 7016 only */
69#define EhnMIIregShift 11
70#define EhnMIIreq 0x0010
71#define EhnMIInotDone 0x0010
72
73/* Write/read MMIO register */
74#define SIS_W8(reg, val) writeb ((val), ioaddr + (reg))
75#define SIS_W16(reg, val) writew ((val), ioaddr + (reg))
76#define SIS_W32(reg, val) writel ((val), ioaddr + (reg))
77#define SIS_R8(reg) readb (ioaddr + (reg))
78#define SIS_R16(reg) readw (ioaddr + (reg))
79#define SIS_R32(reg) readl (ioaddr + (reg))
80
81#define SIS_PCI_COMMIT() SIS_R32(IntrControl)
82
83enum sis190_registers {
84 TxControl = 0x00,
85 TxDescStartAddr = 0x04,
Francois Romieu188f23b2005-07-30 13:11:43 +020086 rsv0 = 0x08, // reserved
87 TxSts = 0x0c, // unused (Control/Status)
Francois Romieu890e8d02005-07-30 13:08:43 +020088 RxControl = 0x10,
89 RxDescStartAddr = 0x14,
Francois Romieu188f23b2005-07-30 13:11:43 +020090 rsv1 = 0x18, // reserved
91 RxSts = 0x1c, // unused
Francois Romieu890e8d02005-07-30 13:08:43 +020092 IntrStatus = 0x20,
93 IntrMask = 0x24,
94 IntrControl = 0x28,
Lucas De Marchi25985ed2011-03-30 22:57:33 -030095 IntrTimer = 0x2c, // unused (Interrupt Timer)
Francois Romieu188f23b2005-07-30 13:11:43 +020096 PMControl = 0x30, // unused (Power Mgmt Control/Status)
97 rsv2 = 0x34, // reserved
Francois Romieu890e8d02005-07-30 13:08:43 +020098 ROMControl = 0x38,
99 ROMInterface = 0x3c,
100 StationControl = 0x40,
101 GMIIControl = 0x44,
Francois Romieu188f23b2005-07-30 13:11:43 +0200102 GIoCR = 0x48, // unused (GMAC IO Compensation)
103 GIoCtrl = 0x4c, // unused (GMAC IO Control)
Francois Romieu890e8d02005-07-30 13:08:43 +0200104 TxMacControl = 0x50,
Francois Romieu188f23b2005-07-30 13:11:43 +0200105 TxLimit = 0x54, // unused (Tx MAC Timer/TryLimit)
106 RGDelay = 0x58, // unused (RGMII Tx Internal Delay)
107 rsv3 = 0x5c, // reserved
Francois Romieu890e8d02005-07-30 13:08:43 +0200108 RxMacControl = 0x60,
109 RxMacAddr = 0x62,
110 RxHashTable = 0x68,
111 // Undocumented = 0x6c,
Francois Romieu188f23b2005-07-30 13:11:43 +0200112 RxWolCtrl = 0x70,
113 RxWolData = 0x74, // unused (Rx WOL Data Access)
114 RxMPSControl = 0x78, // unused (Rx MPS Control)
115 rsv4 = 0x7c, // reserved
Francois Romieu890e8d02005-07-30 13:08:43 +0200116};
117
118enum sis190_register_content {
119 /* IntrStatus */
120 SoftInt = 0x40000000, // unused
121 Timeup = 0x20000000, // unused
122 PauseFrame = 0x00080000, // unused
123 MagicPacket = 0x00040000, // unused
124 WakeupFrame = 0x00020000, // unused
125 LinkChange = 0x00010000,
126 RxQEmpty = 0x00000080,
127 RxQInt = 0x00000040,
128 TxQ1Empty = 0x00000020, // unused
129 TxQ1Int = 0x00000010,
130 TxQ0Empty = 0x00000008, // unused
131 TxQ0Int = 0x00000004,
132 RxHalt = 0x00000002,
133 TxHalt = 0x00000001,
134
Francois Romieu890e8d02005-07-30 13:08:43 +0200135 /* {Rx/Tx}CmdBits */
136 CmdReset = 0x10,
137 CmdRxEnb = 0x08, // unused
138 CmdTxEnb = 0x01,
139 RxBufEmpty = 0x01, // unused
140
141 /* Cfg9346Bits */
142 Cfg9346_Lock = 0x00, // unused
143 Cfg9346_Unlock = 0xc0, // unused
144
145 /* RxMacControl */
146 AcceptErr = 0x20, // unused
147 AcceptRunt = 0x10, // unused
148 AcceptBroadcast = 0x0800,
149 AcceptMulticast = 0x0400,
150 AcceptMyPhys = 0x0200,
151 AcceptAllPhys = 0x0100,
152
153 /* RxConfigBits */
154 RxCfgFIFOShift = 13,
155 RxCfgDMAShift = 8, // 0x1a in RxControl ?
156
157 /* TxConfigBits */
158 TxInterFrameGapShift = 24,
159 TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */
160
Francois Romieu890e8d02005-07-30 13:08:43 +0200161 LinkStatus = 0x02, // unused
162 FullDup = 0x01, // unused
163
164 /* TBICSRBit */
165 TBILinkOK = 0x02000000, // unused
166};
167
168struct TxDesc {
Francois Romieu3cec93c2005-07-30 13:14:18 +0200169 __le32 PSize;
170 __le32 status;
171 __le32 addr;
172 __le32 size;
Francois Romieu890e8d02005-07-30 13:08:43 +0200173};
174
175struct RxDesc {
Francois Romieu3cec93c2005-07-30 13:14:18 +0200176 __le32 PSize;
177 __le32 status;
178 __le32 addr;
179 __le32 size;
Francois Romieu890e8d02005-07-30 13:08:43 +0200180};
181
182enum _DescStatusBit {
183 /* _Desc.status */
Francois Romieubcad5e52005-07-30 13:13:47 +0200184 OWNbit = 0x80000000, // RXOWN/TXOWN
185 INTbit = 0x40000000, // RXINT/TXINT
186 CRCbit = 0x00020000, // CRCOFF/CRCEN
187 PADbit = 0x00010000, // PREADD/PADEN
Francois Romieu890e8d02005-07-30 13:08:43 +0200188 /* _Desc.size */
Francois Romieubcad5e52005-07-30 13:13:47 +0200189 RingEnd = 0x80000000,
190 /* TxDesc.status */
191 LSEN = 0x08000000, // TSO ? -- FR
192 IPCS = 0x04000000,
193 TCPCS = 0x02000000,
194 UDPCS = 0x01000000,
195 BSTEN = 0x00800000,
196 EXTEN = 0x00400000,
197 DEFEN = 0x00200000,
198 BKFEN = 0x00100000,
199 CRSEN = 0x00080000,
200 COLEN = 0x00040000,
201 THOL3 = 0x30000000,
202 THOL2 = 0x20000000,
203 THOL1 = 0x10000000,
204 THOL0 = 0x00000000,
Francois Romieu697c2692007-11-21 22:30:37 +0100205
206 WND = 0x00080000,
207 TABRT = 0x00040000,
208 FIFO = 0x00020000,
209 LINK = 0x00010000,
210 ColCountMask = 0x0000ffff,
Francois Romieubcad5e52005-07-30 13:13:47 +0200211 /* RxDesc.status */
212 IPON = 0x20000000,
213 TCPON = 0x10000000,
214 UDPON = 0x08000000,
215 Wakup = 0x00400000,
216 Magic = 0x00200000,
217 Pause = 0x00100000,
218 DEFbit = 0x00200000,
219 BCAST = 0x000c0000,
220 MCAST = 0x00080000,
221 UCAST = 0x00040000,
222 /* RxDesc.PSize */
223 TAGON = 0x80000000,
224 RxDescCountMask = 0x7f000000, // multi-desc pkt when > 1 ? -- FR
225 ABORT = 0x00800000,
226 SHORT = 0x00400000,
227 LIMIT = 0x00200000,
228 MIIER = 0x00100000,
229 OVRUN = 0x00080000,
230 NIBON = 0x00040000,
231 COLON = 0x00020000,
232 CRCOK = 0x00010000,
Francois Romieu890e8d02005-07-30 13:08:43 +0200233 RxSizeMask = 0x0000ffff
Francois Romieubcad5e52005-07-30 13:13:47 +0200234 /*
235 * The asic could apparently do vlan, TSO, jumbo (sis191 only) and
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300236 * provide two (unused with Linux) Tx queues. No publicly
Francois Romieubcad5e52005-07-30 13:13:47 +0200237 * available documentation alas.
238 */
Francois Romieu890e8d02005-07-30 13:08:43 +0200239};
240
Francois Romieu40292fb2005-07-30 13:12:06 +0200241enum sis190_eeprom_access_register_bits {
242 EECS = 0x00000001, // unused
243 EECLK = 0x00000002, // unused
244 EEDO = 0x00000008, // unused
245 EEDI = 0x00000004, // unused
246 EEREQ = 0x00000080,
247 EEROP = 0x00000200,
248 EEWOP = 0x00000100 // unused
249};
250
Francois Romieu830fb7d2005-07-30 13:12:37 +0200251/* EEPROM Addresses */
252enum sis190_eeprom_address {
253 EEPROMSignature = 0x00,
254 EEPROMCLK = 0x01, // unused
255 EEPROMInfo = 0x02,
256 EEPROMMACAddr = 0x03
257};
258
Francois Romieu900eb9d2005-09-03 00:55:27 +0200259enum sis190_feature {
260 F_HAS_RGMII = 1,
Francois Romieuc3d6f1f2005-09-03 00:56:57 +0200261 F_PHY_88E1111 = 2,
262 F_PHY_BCM5461 = 4
Francois Romieu900eb9d2005-09-03 00:55:27 +0200263};
264
Francois Romieu890e8d02005-07-30 13:08:43 +0200265struct sis190_private {
266 void __iomem *mmio_addr;
267 struct pci_dev *pci_dev;
David Howellsc4028952006-11-22 14:57:56 +0000268 struct net_device *dev;
Francois Romieu890e8d02005-07-30 13:08:43 +0200269 spinlock_t lock;
270 u32 rx_buf_sz;
271 u32 cur_rx;
272 u32 cur_tx;
273 u32 dirty_rx;
274 u32 dirty_tx;
275 dma_addr_t rx_dma;
276 dma_addr_t tx_dma;
277 struct RxDesc *RxDescRing;
278 struct TxDesc *TxDescRing;
279 struct sk_buff *Rx_skbuff[NUM_RX_DESC];
280 struct sk_buff *Tx_skbuff[NUM_TX_DESC];
281 struct work_struct phy_task;
282 struct timer_list timer;
283 u32 msg_enable;
Francois Romieu43afb942005-07-30 13:10:21 +0200284 struct mii_if_info mii_if;
Francois Romieufcb98212005-07-30 13:15:22 +0200285 struct list_head first_phy;
Francois Romieu900eb9d2005-09-03 00:55:27 +0200286 u32 features;
Riccardo Ghetta08326db2010-02-17 09:28:58 +0000287 u32 negotiated_lpa;
Herton Ronaldo Krzesinskib88aafd2010-03-02 03:44:41 -0800288 enum {
289 LNK_OFF,
290 LNK_ON,
291 LNK_AUTONEG,
292 } link_status;
Francois Romieufcb98212005-07-30 13:15:22 +0200293};
294
295struct sis190_phy {
296 struct list_head list;
297 int phy_id;
298 u16 id[2];
299 u16 status;
300 u8 type;
301};
302
303enum sis190_phy_type {
304 UNKNOWN = 0x00,
305 HOME = 0x01,
306 LAN = 0x02,
307 MIX = 0x03
308};
309
310static struct mii_chip_info {
311 const char *name;
312 u16 id[2];
313 unsigned int type;
Francois Romieu900eb9d2005-09-03 00:55:27 +0200314 u32 feature;
Francois Romieufcb98212005-07-30 13:15:22 +0200315} mii_chip_table[] = {
Riccardo Ghetta856f8f42009-06-04 09:05:07 +0000316 { "Atheros PHY", { 0x004d, 0xd010 }, LAN, 0 },
Francois Romieu708f6e22008-10-20 23:37:55 +0200317 { "Atheros PHY AR8012", { 0x004d, 0xd020 }, LAN, 0 },
Francois Romieuc3d6f1f2005-09-03 00:56:57 +0200318 { "Broadcom PHY BCM5461", { 0x0020, 0x60c0 }, LAN, F_PHY_BCM5461 },
Francois Romieubd7a4442007-03-29 00:18:50 +0200319 { "Broadcom PHY AC131", { 0x0143, 0xbc70 }, LAN, 0 },
Francois Romieu900eb9d2005-09-03 00:55:27 +0200320 { "Agere PHY ET1101B", { 0x0282, 0xf010 }, LAN, 0 },
321 { "Marvell PHY 88E1111", { 0x0141, 0x0cc0 }, LAN, F_PHY_88E1111 },
322 { "Realtek PHY RTL8201", { 0x0000, 0x8200 }, LAN, 0 },
Francois Romieufcb98212005-07-30 13:15:22 +0200323 { NULL, }
Francois Romieu890e8d02005-07-30 13:08:43 +0200324};
325
Jesper Juhl3c6bee12006-01-09 20:54:01 -0800326static const struct {
Francois Romieu890e8d02005-07-30 13:08:43 +0200327 const char *name;
Francois Romieu890e8d02005-07-30 13:08:43 +0200328} sis_chip_info[] = {
Francois Romieue7976372005-09-03 00:57:51 +0200329 { "SiS 190 PCI Fast Ethernet adapter" },
330 { "SiS 191 PCI Gigabit Ethernet adapter" },
Francois Romieu890e8d02005-07-30 13:08:43 +0200331};
332
Benoit Taine9baa3c32014-08-08 15:56:03 +0200333static const struct pci_device_id sis190_pci_tbl[] = {
Francois Romieu890e8d02005-07-30 13:08:43 +0200334 { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0190), 0, 0, 0 },
Francois Romieue7976372005-09-03 00:57:51 +0200335 { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0191), 0, 0, 1 },
Francois Romieu890e8d02005-07-30 13:08:43 +0200336 { 0, },
337};
338
339MODULE_DEVICE_TABLE(pci, sis190_pci_tbl);
340
341static int rx_copybreak = 200;
342
343static struct {
344 u32 msg_enable;
345} debug = { -1 };
346
Riccardo Ghettac3223d22009-06-04 09:04:55 +0000347MODULE_DESCRIPTION("SiS sis190/191 Gigabit Ethernet driver");
Francois Romieu890e8d02005-07-30 13:08:43 +0200348module_param(rx_copybreak, int, 0);
349MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
350module_param_named(debug, debug.msg_enable, int, 0);
351MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
352MODULE_AUTHOR("K.M. Liu <kmliu@sis.com>, Ueimor <romieu@fr.zoreil.com>");
353MODULE_VERSION(DRV_VERSION);
354MODULE_LICENSE("GPL");
355
356static const u32 sis190_intr_mask =
Francois Romieu21461382005-09-03 00:54:25 +0200357 RxQEmpty | RxQInt | TxQ1Int | TxQ0Int | RxHalt | TxHalt | LinkChange;
Francois Romieu890e8d02005-07-30 13:08:43 +0200358
359/*
360 * Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
361 * The chips use a 64 element hash table based on the Ethernet CRC.
362 */
Arjan van de Venf71e1302006-03-03 21:33:57 -0500363static const int multicast_filter_limit = 32;
Francois Romieu890e8d02005-07-30 13:08:43 +0200364
365static void __mdio_cmd(void __iomem *ioaddr, u32 ctl)
366{
367 unsigned int i;
368
369 SIS_W32(GMIIControl, ctl);
370
371 msleep(1);
372
373 for (i = 0; i < 100; i++) {
374 if (!(SIS_R32(GMIIControl) & EhnMIInotDone))
375 break;
376 msleep(1);
377 }
378
Francois Romieu7bf3f232007-11-17 16:56:43 +0100379 if (i > 99)
Joe Perchesad06ab22010-02-17 20:00:17 +0000380 pr_err("PHY command failed !\n");
Francois Romieu890e8d02005-07-30 13:08:43 +0200381}
382
Francois Romieu9ede1092005-07-30 13:14:38 +0200383static void mdio_write(void __iomem *ioaddr, int phy_id, int reg, int val)
Francois Romieu890e8d02005-07-30 13:08:43 +0200384{
Francois Romieu890e8d02005-07-30 13:08:43 +0200385 __mdio_cmd(ioaddr, EhnMIIreq | EhnMIIwrite |
Francois Romieu9ede1092005-07-30 13:14:38 +0200386 (((u32) reg) << EhnMIIregShift) | (phy_id << EhnMIIpmdShift) |
Francois Romieu890e8d02005-07-30 13:08:43 +0200387 (((u32) val) << EhnMIIdataShift));
388}
389
Francois Romieu9ede1092005-07-30 13:14:38 +0200390static int mdio_read(void __iomem *ioaddr, int phy_id, int reg)
Francois Romieu890e8d02005-07-30 13:08:43 +0200391{
Francois Romieu890e8d02005-07-30 13:08:43 +0200392 __mdio_cmd(ioaddr, EhnMIIreq | EhnMIIread |
Francois Romieu9ede1092005-07-30 13:14:38 +0200393 (((u32) reg) << EhnMIIregShift) | (phy_id << EhnMIIpmdShift));
Francois Romieu890e8d02005-07-30 13:08:43 +0200394
395 return (u16) (SIS_R32(GMIIControl) >> EhnMIIdataShift);
396}
397
Francois Romieu43afb942005-07-30 13:10:21 +0200398static void __mdio_write(struct net_device *dev, int phy_id, int reg, int val)
399{
400 struct sis190_private *tp = netdev_priv(dev);
401
Francois Romieu9ede1092005-07-30 13:14:38 +0200402 mdio_write(tp->mmio_addr, phy_id, reg, val);
Francois Romieu43afb942005-07-30 13:10:21 +0200403}
404
405static int __mdio_read(struct net_device *dev, int phy_id, int reg)
406{
407 struct sis190_private *tp = netdev_priv(dev);
408
Francois Romieu9ede1092005-07-30 13:14:38 +0200409 return mdio_read(tp->mmio_addr, phy_id, reg);
Francois Romieu43afb942005-07-30 13:10:21 +0200410}
411
Francois Romieufc10c392005-07-30 13:15:01 +0200412static u16 mdio_read_latched(void __iomem *ioaddr, int phy_id, int reg)
413{
414 mdio_read(ioaddr, phy_id, reg);
415 return mdio_read(ioaddr, phy_id, reg);
416}
417
Bill Pembertonfe80f562012-12-03 09:23:35 -0500418static u16 sis190_read_eeprom(void __iomem *ioaddr, u32 reg)
Francois Romieu890e8d02005-07-30 13:08:43 +0200419{
Francois Romieu40292fb2005-07-30 13:12:06 +0200420 u16 data = 0xffff;
Francois Romieu890e8d02005-07-30 13:08:43 +0200421 unsigned int i;
Francois Romieu890e8d02005-07-30 13:08:43 +0200422
423 if (!(SIS_R32(ROMControl) & 0x0002))
424 return 0;
425
Francois Romieu40292fb2005-07-30 13:12:06 +0200426 SIS_W32(ROMInterface, EEREQ | EEROP | (reg << 10));
Francois Romieu890e8d02005-07-30 13:08:43 +0200427
428 for (i = 0; i < 200; i++) {
Francois Romieu40292fb2005-07-30 13:12:06 +0200429 if (!(SIS_R32(ROMInterface) & EEREQ)) {
430 data = (SIS_R32(ROMInterface) & 0xffff0000) >> 16;
Francois Romieu890e8d02005-07-30 13:08:43 +0200431 break;
Francois Romieu40292fb2005-07-30 13:12:06 +0200432 }
Francois Romieu890e8d02005-07-30 13:08:43 +0200433 msleep(1);
434 }
435
Francois Romieu890e8d02005-07-30 13:08:43 +0200436 return data;
437}
438
439static void sis190_irq_mask_and_ack(void __iomem *ioaddr)
440{
441 SIS_W32(IntrMask, 0x00);
442 SIS_W32(IntrStatus, 0xffffffff);
443 SIS_PCI_COMMIT();
444}
445
446static void sis190_asic_down(void __iomem *ioaddr)
447{
448 /* Stop the chip's Tx and Rx DMA processes. */
449
450 SIS_W32(TxControl, 0x1a00);
451 SIS_W32(RxControl, 0x1a00);
452
453 sis190_irq_mask_and_ack(ioaddr);
454}
455
456static void sis190_mark_as_last_descriptor(struct RxDesc *desc)
457{
458 desc->size |= cpu_to_le32(RingEnd);
459}
460
461static inline void sis190_give_to_asic(struct RxDesc *desc, u32 rx_buf_sz)
462{
463 u32 eor = le32_to_cpu(desc->size) & RingEnd;
464
465 desc->PSize = 0x0;
Francois Romieu8b5641d2005-07-30 13:13:03 +0200466 desc->size = cpu_to_le32((rx_buf_sz & RX_BUF_MASK) | eor);
Francois Romieu890e8d02005-07-30 13:08:43 +0200467 wmb();
468 desc->status = cpu_to_le32(OWNbit | INTbit);
469}
470
471static inline void sis190_map_to_asic(struct RxDesc *desc, dma_addr_t mapping,
472 u32 rx_buf_sz)
473{
474 desc->addr = cpu_to_le32(mapping);
475 sis190_give_to_asic(desc, rx_buf_sz);
476}
477
478static inline void sis190_make_unusable_by_asic(struct RxDesc *desc)
479{
480 desc->PSize = 0x0;
Al Viro961994a2007-12-15 01:44:33 +0000481 desc->addr = cpu_to_le32(0xdeadbeef);
Francois Romieu890e8d02005-07-30 13:08:43 +0200482 desc->size &= cpu_to_le32(RingEnd);
483 wmb();
484 desc->status = 0x0;
485}
486
Stephen Hemminger35aeb782008-04-27 14:54:32 +0200487static struct sk_buff *sis190_alloc_rx_skb(struct sis190_private *tp,
488 struct RxDesc *desc)
Francois Romieu890e8d02005-07-30 13:08:43 +0200489{
Stephen Hemminger35aeb782008-04-27 14:54:32 +0200490 u32 rx_buf_sz = tp->rx_buf_sz;
Francois Romieu890e8d02005-07-30 13:08:43 +0200491 struct sk_buff *skb;
kirjanov@gmail.come382c302010-02-24 08:41:18 +0000492 dma_addr_t mapping;
Francois Romieu890e8d02005-07-30 13:08:43 +0200493
Stephen Hemminger35aeb782008-04-27 14:54:32 +0200494 skb = netdev_alloc_skb(tp->dev, rx_buf_sz);
kirjanov@gmail.come382c302010-02-24 08:41:18 +0000495 if (unlikely(!skb))
496 goto skb_alloc_failed;
497 mapping = pci_map_single(tp->pci_dev, skb->data, tp->rx_buf_sz,
498 PCI_DMA_FROMDEVICE);
499 if (pci_dma_mapping_error(tp->pci_dev, mapping))
500 goto out;
501 sis190_map_to_asic(desc, mapping, rx_buf_sz);
Francois Romieu890e8d02005-07-30 13:08:43 +0200502
Stephen Hemminger4709aa52008-04-27 14:36:59 +0200503 return skb;
kirjanov@gmail.come382c302010-02-24 08:41:18 +0000504
505out:
506 dev_kfree_skb_any(skb);
507skb_alloc_failed:
508 sis190_make_unusable_by_asic(desc);
509 return NULL;
Francois Romieu890e8d02005-07-30 13:08:43 +0200510}
511
512static u32 sis190_rx_fill(struct sis190_private *tp, struct net_device *dev,
513 u32 start, u32 end)
514{
515 u32 cur;
516
517 for (cur = start; cur < end; cur++) {
Stephen Hemminger4709aa52008-04-27 14:36:59 +0200518 unsigned int i = cur % NUM_RX_DESC;
Francois Romieu890e8d02005-07-30 13:08:43 +0200519
520 if (tp->Rx_skbuff[i])
521 continue;
522
Stephen Hemminger35aeb782008-04-27 14:54:32 +0200523 tp->Rx_skbuff[i] = sis190_alloc_rx_skb(tp, tp->RxDescRing + i);
524
Stephen Hemminger4709aa52008-04-27 14:36:59 +0200525 if (!tp->Rx_skbuff[i])
Francois Romieu890e8d02005-07-30 13:08:43 +0200526 break;
527 }
528 return cur - start;
529}
530
Francois Romieu47e47812008-04-27 17:59:52 +0200531static bool sis190_try_rx_copy(struct sis190_private *tp,
532 struct sk_buff **sk_buff, int pkt_size,
533 dma_addr_t addr)
Francois Romieu890e8d02005-07-30 13:08:43 +0200534{
Francois Romieu47e47812008-04-27 17:59:52 +0200535 struct sk_buff *skb;
536 bool done = false;
Francois Romieu890e8d02005-07-30 13:08:43 +0200537
Francois Romieu47e47812008-04-27 17:59:52 +0200538 if (pkt_size >= rx_copybreak)
539 goto out;
Francois Romieu890e8d02005-07-30 13:08:43 +0200540
Eric Dumazet89d71a62009-10-13 05:34:20 +0000541 skb = netdev_alloc_skb_ip_align(tp->dev, pkt_size);
Francois Romieu47e47812008-04-27 17:59:52 +0200542 if (!skb)
543 goto out;
544
Riccardo Ghetta744c6b22009-06-07 19:47:58 +0000545 pci_dma_sync_single_for_cpu(tp->pci_dev, addr, tp->rx_buf_sz,
546 PCI_DMA_FROMDEVICE);
Francois Romieu47e47812008-04-27 17:59:52 +0200547 skb_copy_to_linear_data(skb, sk_buff[0]->data, pkt_size);
548 *sk_buff = skb;
549 done = true;
550out:
551 return done;
Francois Romieu890e8d02005-07-30 13:08:43 +0200552}
553
Francois Romieubcad5e52005-07-30 13:13:47 +0200554static inline int sis190_rx_pkt_err(u32 status, struct net_device_stats *stats)
555{
556#define ErrMask (OVRUN | SHORT | LIMIT | MIIER | NIBON | COLON | ABORT)
557
558 if ((status & CRCOK) && !(status & ErrMask))
559 return 0;
560
561 if (!(status & CRCOK))
562 stats->rx_crc_errors++;
563 else if (status & OVRUN)
564 stats->rx_over_errors++;
565 else if (status & (SHORT | LIMIT))
566 stats->rx_length_errors++;
567 else if (status & (MIIER | NIBON | COLON))
568 stats->rx_frame_errors++;
569
570 stats->rx_errors++;
571 return -1;
572}
573
Francois Romieu890e8d02005-07-30 13:08:43 +0200574static int sis190_rx_interrupt(struct net_device *dev,
575 struct sis190_private *tp, void __iomem *ioaddr)
576{
Jeff Garzik09f75cd2007-10-03 17:41:50 -0700577 struct net_device_stats *stats = &dev->stats;
Francois Romieu890e8d02005-07-30 13:08:43 +0200578 u32 rx_left, cur_rx = tp->cur_rx;
579 u32 delta, count;
580
581 rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
582 rx_left = sis190_rx_quota(rx_left, (u32) dev->quota);
583
584 for (; rx_left > 0; rx_left--, cur_rx++) {
585 unsigned int entry = cur_rx % NUM_RX_DESC;
586 struct RxDesc *desc = tp->RxDescRing + entry;
587 u32 status;
588
Al Viro961994a2007-12-15 01:44:33 +0000589 if (le32_to_cpu(desc->status) & OWNbit)
Francois Romieu890e8d02005-07-30 13:08:43 +0200590 break;
591
592 status = le32_to_cpu(desc->PSize);
593
Joe Perchesad06ab22010-02-17 20:00:17 +0000594 //netif_info(tp, intr, dev, "Rx PSize = %08x\n", status);
Francois Romieu890e8d02005-07-30 13:08:43 +0200595
Francois Romieubcad5e52005-07-30 13:13:47 +0200596 if (sis190_rx_pkt_err(status, stats) < 0)
Francois Romieu890e8d02005-07-30 13:08:43 +0200597 sis190_give_to_asic(desc, tp->rx_buf_sz);
Francois Romieubcad5e52005-07-30 13:13:47 +0200598 else {
Francois Romieu890e8d02005-07-30 13:08:43 +0200599 struct sk_buff *skb = tp->Rx_skbuff[entry];
Francois Romieu47e47812008-04-27 17:59:52 +0200600 dma_addr_t addr = le32_to_cpu(desc->addr);
Francois Romieu890e8d02005-07-30 13:08:43 +0200601 int pkt_size = (status & RxSizeMask) - 4;
Francois Romieu47e47812008-04-27 17:59:52 +0200602 struct pci_dev *pdev = tp->pci_dev;
Francois Romieu890e8d02005-07-30 13:08:43 +0200603
604 if (unlikely(pkt_size > tp->rx_buf_sz)) {
Joe Perchesad06ab22010-02-17 20:00:17 +0000605 netif_info(tp, intr, dev,
606 "(frag) status = %08x\n", status);
Francois Romieu890e8d02005-07-30 13:08:43 +0200607 stats->rx_dropped++;
608 stats->rx_length_errors++;
609 sis190_give_to_asic(desc, tp->rx_buf_sz);
610 continue;
611 }
612
Francois Romieu890e8d02005-07-30 13:08:43 +0200613
Francois Romieu47e47812008-04-27 17:59:52 +0200614 if (sis190_try_rx_copy(tp, &skb, pkt_size, addr)) {
615 pci_dma_sync_single_for_device(pdev, addr,
616 tp->rx_buf_sz, PCI_DMA_FROMDEVICE);
617 sis190_give_to_asic(desc, tp->rx_buf_sz);
618 } else {
619 pci_unmap_single(pdev, addr, tp->rx_buf_sz,
620 PCI_DMA_FROMDEVICE);
Francois Romieu890e8d02005-07-30 13:08:43 +0200621 tp->Rx_skbuff[entry] = NULL;
622 sis190_make_unusable_by_asic(desc);
623 }
624
Francois Romieu890e8d02005-07-30 13:08:43 +0200625 skb_put(skb, pkt_size);
626 skb->protocol = eth_type_trans(skb, dev);
627
628 sis190_rx_skb(skb);
629
Francois Romieu890e8d02005-07-30 13:08:43 +0200630 stats->rx_packets++;
Francois Romieubcad5e52005-07-30 13:13:47 +0200631 stats->rx_bytes += pkt_size;
632 if ((status & BCAST) == MCAST)
633 stats->multicast++;
Francois Romieu890e8d02005-07-30 13:08:43 +0200634 }
635 }
636 count = cur_rx - tp->cur_rx;
637 tp->cur_rx = cur_rx;
638
639 delta = sis190_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx);
Joe Perchesad06ab22010-02-17 20:00:17 +0000640 if (!delta && count)
641 netif_info(tp, intr, dev, "no Rx buffer allocated\n");
Francois Romieu890e8d02005-07-30 13:08:43 +0200642 tp->dirty_rx += delta;
643
Joe Perchesad06ab22010-02-17 20:00:17 +0000644 if ((tp->dirty_rx + NUM_RX_DESC) == tp->cur_rx)
645 netif_emerg(tp, intr, dev, "Rx buffers exhausted\n");
Francois Romieu890e8d02005-07-30 13:08:43 +0200646
647 return count;
648}
649
650static void sis190_unmap_tx_skb(struct pci_dev *pdev, struct sk_buff *skb,
651 struct TxDesc *desc)
652{
653 unsigned int len;
654
655 len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
656
657 pci_unmap_single(pdev, le32_to_cpu(desc->addr), len, PCI_DMA_TODEVICE);
658
659 memset(desc, 0x00, sizeof(*desc));
660}
661
Francois Romieu697c2692007-11-21 22:30:37 +0100662static inline int sis190_tx_pkt_err(u32 status, struct net_device_stats *stats)
663{
664#define TxErrMask (WND | TABRT | FIFO | LINK)
665
666 if (!unlikely(status & TxErrMask))
667 return 0;
668
669 if (status & WND)
670 stats->tx_window_errors++;
671 if (status & TABRT)
672 stats->tx_aborted_errors++;
673 if (status & FIFO)
674 stats->tx_fifo_errors++;
675 if (status & LINK)
676 stats->tx_carrier_errors++;
677
678 stats->tx_errors++;
679
680 return -1;
681}
682
Francois Romieu890e8d02005-07-30 13:08:43 +0200683static void sis190_tx_interrupt(struct net_device *dev,
684 struct sis190_private *tp, void __iomem *ioaddr)
685{
Francois Romieu697c2692007-11-21 22:30:37 +0100686 struct net_device_stats *stats = &dev->stats;
Francois Romieu890e8d02005-07-30 13:08:43 +0200687 u32 pending, dirty_tx = tp->dirty_tx;
688 /*
689 * It would not be needed if queueing was allowed to be enabled
690 * again too early (hint: think preempt and unclocked smp systems).
691 */
692 unsigned int queue_stopped;
693
694 smp_rmb();
695 pending = tp->cur_tx - dirty_tx;
696 queue_stopped = (pending == NUM_TX_DESC);
697
698 for (; pending; pending--, dirty_tx++) {
699 unsigned int entry = dirty_tx % NUM_TX_DESC;
700 struct TxDesc *txd = tp->TxDescRing + entry;
Francois Romieu697c2692007-11-21 22:30:37 +0100701 u32 status = le32_to_cpu(txd->status);
Francois Romieu890e8d02005-07-30 13:08:43 +0200702 struct sk_buff *skb;
703
Francois Romieu697c2692007-11-21 22:30:37 +0100704 if (status & OWNbit)
Francois Romieu890e8d02005-07-30 13:08:43 +0200705 break;
706
707 skb = tp->Tx_skbuff[entry];
708
Francois Romieu697c2692007-11-21 22:30:37 +0100709 if (likely(sis190_tx_pkt_err(status, stats) == 0)) {
710 stats->tx_packets++;
711 stats->tx_bytes += skb->len;
712 stats->collisions += ((status & ColCountMask) - 1);
713 }
Francois Romieu890e8d02005-07-30 13:08:43 +0200714
715 sis190_unmap_tx_skb(tp->pci_dev, skb, txd);
716 tp->Tx_skbuff[entry] = NULL;
717 dev_kfree_skb_irq(skb);
718 }
719
720 if (tp->dirty_tx != dirty_tx) {
721 tp->dirty_tx = dirty_tx;
722 smp_wmb();
723 if (queue_stopped)
724 netif_wake_queue(dev);
725 }
726}
727
728/*
729 * The interrupt handler does all of the Rx thread work and cleans up after
730 * the Tx thread.
731 */
Francois Romieu480c2862012-03-09 11:56:08 +0100732static irqreturn_t sis190_irq(int irq, void *__dev)
Francois Romieu890e8d02005-07-30 13:08:43 +0200733{
734 struct net_device *dev = __dev;
735 struct sis190_private *tp = netdev_priv(dev);
736 void __iomem *ioaddr = tp->mmio_addr;
737 unsigned int handled = 0;
738 u32 status;
739
740 status = SIS_R32(IntrStatus);
741
742 if ((status == 0xffffffff) || !status)
743 goto out;
744
745 handled = 1;
746
747 if (unlikely(!netif_running(dev))) {
748 sis190_asic_down(ioaddr);
749 goto out;
750 }
751
752 SIS_W32(IntrStatus, status);
753
Joe Perchesad06ab22010-02-17 20:00:17 +0000754// netif_info(tp, intr, dev, "status = %08x\n", status);
Francois Romieu890e8d02005-07-30 13:08:43 +0200755
756 if (status & LinkChange) {
Joe Perchesad06ab22010-02-17 20:00:17 +0000757 netif_info(tp, intr, dev, "link change\n");
Herton Ronaldo Krzesinskib88aafd2010-03-02 03:44:41 -0800758 del_timer(&tp->timer);
Francois Romieu890e8d02005-07-30 13:08:43 +0200759 schedule_work(&tp->phy_task);
760 }
761
762 if (status & RxQInt)
763 sis190_rx_interrupt(dev, tp, ioaddr);
764
765 if (status & TxQ0Int)
766 sis190_tx_interrupt(dev, tp, ioaddr);
767out:
768 return IRQ_RETVAL(handled);
769}
770
Francois Romieu4405d3b2005-07-30 13:09:20 +0200771#ifdef CONFIG_NET_POLL_CONTROLLER
772static void sis190_netpoll(struct net_device *dev)
773{
774 struct sis190_private *tp = netdev_priv(dev);
Francois Romieu480c2862012-03-09 11:56:08 +0100775 const int irq = tp->pci_dev->irq;
Francois Romieu4405d3b2005-07-30 13:09:20 +0200776
Francois Romieu480c2862012-03-09 11:56:08 +0100777 disable_irq(irq);
778 sis190_irq(irq, dev);
779 enable_irq(irq);
Francois Romieu4405d3b2005-07-30 13:09:20 +0200780}
781#endif
782
Francois Romieu890e8d02005-07-30 13:08:43 +0200783static void sis190_free_rx_skb(struct sis190_private *tp,
784 struct sk_buff **sk_buff, struct RxDesc *desc)
785{
786 struct pci_dev *pdev = tp->pci_dev;
787
788 pci_unmap_single(pdev, le32_to_cpu(desc->addr), tp->rx_buf_sz,
789 PCI_DMA_FROMDEVICE);
790 dev_kfree_skb(*sk_buff);
791 *sk_buff = NULL;
792 sis190_make_unusable_by_asic(desc);
793}
794
795static void sis190_rx_clear(struct sis190_private *tp)
796{
797 unsigned int i;
798
799 for (i = 0; i < NUM_RX_DESC; i++) {
800 if (!tp->Rx_skbuff[i])
801 continue;
802 sis190_free_rx_skb(tp, tp->Rx_skbuff + i, tp->RxDescRing + i);
803 }
804}
805
806static void sis190_init_ring_indexes(struct sis190_private *tp)
807{
808 tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0;
809}
810
811static int sis190_init_ring(struct net_device *dev)
812{
813 struct sis190_private *tp = netdev_priv(dev);
814
815 sis190_init_ring_indexes(tp);
816
817 memset(tp->Tx_skbuff, 0x0, NUM_TX_DESC * sizeof(struct sk_buff *));
818 memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *));
819
820 if (sis190_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC)
821 goto err_rx_clear;
822
823 sis190_mark_as_last_descriptor(tp->RxDescRing + NUM_RX_DESC - 1);
824
825 return 0;
826
827err_rx_clear:
828 sis190_rx_clear(tp);
829 return -ENOMEM;
830}
831
832static void sis190_set_rx_mode(struct net_device *dev)
833{
834 struct sis190_private *tp = netdev_priv(dev);
835 void __iomem *ioaddr = tp->mmio_addr;
836 unsigned long flags;
837 u32 mc_filter[2]; /* Multicast hash filter */
838 u16 rx_mode;
839
840 if (dev->flags & IFF_PROMISC) {
Francois Romieu890e8d02005-07-30 13:08:43 +0200841 rx_mode =
842 AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
843 AcceptAllPhys;
844 mc_filter[1] = mc_filter[0] = 0xffffffff;
Jiri Pirko4cd24ea2010-02-08 04:30:35 +0000845 } else if ((netdev_mc_count(dev) > multicast_filter_limit) ||
Francois Romieu890e8d02005-07-30 13:08:43 +0200846 (dev->flags & IFF_ALLMULTI)) {
847 /* Too many to filter perfectly -- accept all multicasts. */
848 rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
849 mc_filter[1] = mc_filter[0] = 0xffffffff;
850 } else {
Jiri Pirko22bedad32010-04-01 21:22:57 +0000851 struct netdev_hw_addr *ha;
Francois Romieu890e8d02005-07-30 13:08:43 +0200852
853 rx_mode = AcceptBroadcast | AcceptMyPhys;
854 mc_filter[1] = mc_filter[0] = 0;
Jiri Pirko22bedad32010-04-01 21:22:57 +0000855 netdev_for_each_mc_addr(ha, dev) {
Francois Romieu890e8d02005-07-30 13:08:43 +0200856 int bit_nr =
Jiri Pirko22bedad32010-04-01 21:22:57 +0000857 ether_crc(ETH_ALEN, ha->addr) & 0x3f;
Francois Romieu890e8d02005-07-30 13:08:43 +0200858 mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
859 rx_mode |= AcceptMulticast;
860 }
861 }
862
863 spin_lock_irqsave(&tp->lock, flags);
864
865 SIS_W16(RxMacControl, rx_mode | 0x2);
866 SIS_W32(RxHashTable, mc_filter[0]);
867 SIS_W32(RxHashTable + 4, mc_filter[1]);
868
869 spin_unlock_irqrestore(&tp->lock, flags);
870}
871
872static void sis190_soft_reset(void __iomem *ioaddr)
873{
874 SIS_W32(IntrControl, 0x8000);
875 SIS_PCI_COMMIT();
Francois Romieu890e8d02005-07-30 13:08:43 +0200876 SIS_W32(IntrControl, 0x0);
877 sis190_asic_down(ioaddr);
Francois Romieu890e8d02005-07-30 13:08:43 +0200878}
879
880static void sis190_hw_start(struct net_device *dev)
881{
882 struct sis190_private *tp = netdev_priv(dev);
883 void __iomem *ioaddr = tp->mmio_addr;
884
885 sis190_soft_reset(ioaddr);
886
887 SIS_W32(TxDescStartAddr, tp->tx_dma);
888 SIS_W32(RxDescStartAddr, tp->rx_dma);
889
890 SIS_W32(IntrStatus, 0xffffffff);
891 SIS_W32(IntrMask, 0x0);
Francois Romieu890e8d02005-07-30 13:08:43 +0200892 SIS_W32(GMIIControl, 0x0);
893 SIS_W32(TxMacControl, 0x60);
894 SIS_W16(RxMacControl, 0x02);
895 SIS_W32(RxHashTable, 0x0);
896 SIS_W32(0x6c, 0x0);
Francois Romieu188f23b2005-07-30 13:11:43 +0200897 SIS_W32(RxWolCtrl, 0x0);
898 SIS_W32(RxWolData, 0x0);
Francois Romieu890e8d02005-07-30 13:08:43 +0200899
900 SIS_PCI_COMMIT();
901
902 sis190_set_rx_mode(dev);
903
904 /* Enable all known interrupts by setting the interrupt mask. */
905 SIS_W32(IntrMask, sis190_intr_mask);
906
907 SIS_W32(TxControl, 0x1a00 | CmdTxEnb);
908 SIS_W32(RxControl, 0x1a1d);
909
910 netif_start_queue(dev);
911}
912
David Howellsc4028952006-11-22 14:57:56 +0000913static void sis190_phy_task(struct work_struct *work)
Francois Romieu890e8d02005-07-30 13:08:43 +0200914{
David Howellsc4028952006-11-22 14:57:56 +0000915 struct sis190_private *tp =
916 container_of(work, struct sis190_private, phy_task);
917 struct net_device *dev = tp->dev;
Francois Romieu890e8d02005-07-30 13:08:43 +0200918 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu9ede1092005-07-30 13:14:38 +0200919 int phy_id = tp->mii_if.phy_id;
Francois Romieu890e8d02005-07-30 13:08:43 +0200920 u16 val;
921
Francois Romieu43afb942005-07-30 13:10:21 +0200922 rtnl_lock();
923
Francois Romieuc014f6c2007-02-15 23:37:29 +0100924 if (!netif_running(dev))
925 goto out_unlock;
926
Francois Romieu9ede1092005-07-30 13:14:38 +0200927 val = mdio_read(ioaddr, phy_id, MII_BMCR);
Francois Romieu890e8d02005-07-30 13:08:43 +0200928 if (val & BMCR_RESET) {
929 // FIXME: needlessly high ? -- FR 02/07/2005
930 mod_timer(&tp->timer, jiffies + HZ/10);
Herton Ronaldo Krzesinskib88aafd2010-03-02 03:44:41 -0800931 goto out_unlock;
932 }
933
934 val = mdio_read_latched(ioaddr, phy_id, MII_BMSR);
935 if (!(val & BMSR_ANEGCOMPLETE) && tp->link_status != LNK_AUTONEG) {
Francois Romieu21461382005-09-03 00:54:25 +0200936 netif_carrier_off(dev);
Joe Perchesad06ab22010-02-17 20:00:17 +0000937 netif_warn(tp, link, dev, "auto-negotiating...\n");
Herton Ronaldo Krzesinskib88aafd2010-03-02 03:44:41 -0800938 tp->link_status = LNK_AUTONEG;
939 } else if ((val & BMSR_LSTATUS) && tp->link_status != LNK_ON) {
Francois Romieu890e8d02005-07-30 13:08:43 +0200940 /* Rejoice ! */
941 struct {
942 int val;
Francois Romieu6614a6d2005-09-03 00:56:16 +0200943 u32 ctl;
Francois Romieu890e8d02005-07-30 13:08:43 +0200944 const char *msg;
Francois Romieu890e8d02005-07-30 13:08:43 +0200945 } reg31[] = {
Riccardo Ghetta1feede02009-06-04 09:05:20 +0000946 { LPA_1000FULL, 0x07000c00 | 0x00001000,
Francois Romieu6614a6d2005-09-03 00:56:16 +0200947 "1000 Mbps Full Duplex" },
Riccardo Ghetta1feede02009-06-04 09:05:20 +0000948 { LPA_1000HALF, 0x07000c00,
Francois Romieu6614a6d2005-09-03 00:56:16 +0200949 "1000 Mbps Half Duplex" },
950 { LPA_100FULL, 0x04000800 | 0x00001000,
951 "100 Mbps Full Duplex" },
952 { LPA_100HALF, 0x04000800,
953 "100 Mbps Half Duplex" },
954 { LPA_10FULL, 0x04000400 | 0x00001000,
955 "10 Mbps Full Duplex" },
956 { LPA_10HALF, 0x04000400,
957 "10 Mbps Half Duplex" },
958 { 0, 0x04000400, "unknown" }
Riccardo Ghetta1feede02009-06-04 09:05:20 +0000959 }, *p = NULL;
960 u16 adv, autoexp, gigadv, gigrec;
Francois Romieu890e8d02005-07-30 13:08:43 +0200961
Francois Romieu9ede1092005-07-30 13:14:38 +0200962 val = mdio_read(ioaddr, phy_id, 0x1f);
Joe Perchesad06ab22010-02-17 20:00:17 +0000963 netif_info(tp, link, dev, "mii ext = %04x\n", val);
Francois Romieu890e8d02005-07-30 13:08:43 +0200964
Francois Romieu9ede1092005-07-30 13:14:38 +0200965 val = mdio_read(ioaddr, phy_id, MII_LPA);
Francois Romieu8348b4d2005-07-30 13:16:14 +0200966 adv = mdio_read(ioaddr, phy_id, MII_ADVERTISE);
Riccardo Ghetta1feede02009-06-04 09:05:20 +0000967 autoexp = mdio_read(ioaddr, phy_id, MII_EXPANSION);
Joe Perchesad06ab22010-02-17 20:00:17 +0000968 netif_info(tp, link, dev, "mii lpa=%04x adv=%04x exp=%04x\n",
969 val, adv, autoexp);
Francois Romieu8348b4d2005-07-30 13:16:14 +0200970
Riccardo Ghetta1feede02009-06-04 09:05:20 +0000971 if (val & LPA_NPAGE && autoexp & EXPANSION_NWAY) {
972 /* check for gigabit speed */
973 gigadv = mdio_read(ioaddr, phy_id, MII_CTRL1000);
974 gigrec = mdio_read(ioaddr, phy_id, MII_STAT1000);
975 val = (gigadv & (gigrec >> 2));
976 if (val & ADVERTISE_1000FULL)
977 p = reg31;
978 else if (val & ADVERTISE_1000HALF)
979 p = reg31 + 1;
980 }
981 if (!p) {
982 val &= adv;
Francois Romieu890e8d02005-07-30 13:08:43 +0200983
Riccardo Ghetta1feede02009-06-04 09:05:20 +0000984 for (p = reg31; p->val; p++) {
985 if ((val & p->val) == p->val)
986 break;
987 }
Francois Romieu890e8d02005-07-30 13:08:43 +0200988 }
Francois Romieu6614a6d2005-09-03 00:56:16 +0200989
990 p->ctl |= SIS_R32(StationControl) & ~0x0f001c00;
991
Francois Romieuc3d6f1f2005-09-03 00:56:57 +0200992 if ((tp->features & F_HAS_RGMII) &&
993 (tp->features & F_PHY_BCM5461)) {
994 // Set Tx Delay in RGMII mode.
995 mdio_write(ioaddr, phy_id, 0x18, 0xf1c7);
996 udelay(200);
997 mdio_write(ioaddr, phy_id, 0x1c, 0x8c00);
998 p->ctl |= 0x03000000;
999 }
1000
Francois Romieu6614a6d2005-09-03 00:56:16 +02001001 SIS_W32(StationControl, p->ctl);
1002
Francois Romieuc3d6f1f2005-09-03 00:56:57 +02001003 if (tp->features & F_HAS_RGMII) {
1004 SIS_W32(RGDelay, 0x0441);
1005 SIS_W32(RGDelay, 0x0440);
1006 }
1007
Riccardo Ghetta08326db2010-02-17 09:28:58 +00001008 tp->negotiated_lpa = p->val;
1009
Joe Perchesad06ab22010-02-17 20:00:17 +00001010 netif_info(tp, link, dev, "link on %s mode\n", p->msg);
Francois Romieu890e8d02005-07-30 13:08:43 +02001011 netif_carrier_on(dev);
Herton Ronaldo Krzesinskib88aafd2010-03-02 03:44:41 -08001012 tp->link_status = LNK_ON;
1013 } else if (!(val & BMSR_LSTATUS) && tp->link_status != LNK_AUTONEG)
1014 tp->link_status = LNK_OFF;
1015 mod_timer(&tp->timer, jiffies + SIS190_PHY_TIMEOUT);
Francois Romieu43afb942005-07-30 13:10:21 +02001016
Francois Romieuc014f6c2007-02-15 23:37:29 +01001017out_unlock:
Francois Romieu43afb942005-07-30 13:10:21 +02001018 rtnl_unlock();
Francois Romieu890e8d02005-07-30 13:08:43 +02001019}
1020
1021static void sis190_phy_timer(unsigned long __opaque)
1022{
1023 struct net_device *dev = (struct net_device *)__opaque;
1024 struct sis190_private *tp = netdev_priv(dev);
1025
1026 if (likely(netif_running(dev)))
1027 schedule_work(&tp->phy_task);
1028}
1029
1030static inline void sis190_delete_timer(struct net_device *dev)
1031{
1032 struct sis190_private *tp = netdev_priv(dev);
1033
1034 del_timer_sync(&tp->timer);
1035}
1036
1037static inline void sis190_request_timer(struct net_device *dev)
1038{
1039 struct sis190_private *tp = netdev_priv(dev);
1040 struct timer_list *timer = &tp->timer;
1041
1042 init_timer(timer);
1043 timer->expires = jiffies + SIS190_PHY_TIMEOUT;
1044 timer->data = (unsigned long)dev;
1045 timer->function = sis190_phy_timer;
1046 add_timer(timer);
1047}
1048
1049static void sis190_set_rxbufsize(struct sis190_private *tp,
1050 struct net_device *dev)
1051{
1052 unsigned int mtu = dev->mtu;
1053
1054 tp->rx_buf_sz = (mtu > RX_BUF_SIZE) ? mtu + ETH_HLEN + 8 : RX_BUF_SIZE;
Francois Romieu8b5641d2005-07-30 13:13:03 +02001055 /* RxDesc->size has a licence to kill the lower bits */
1056 if (tp->rx_buf_sz & 0x07) {
1057 tp->rx_buf_sz += 8;
1058 tp->rx_buf_sz &= RX_BUF_MASK;
1059 }
Francois Romieu890e8d02005-07-30 13:08:43 +02001060}
1061
1062static int sis190_open(struct net_device *dev)
1063{
1064 struct sis190_private *tp = netdev_priv(dev);
1065 struct pci_dev *pdev = tp->pci_dev;
1066 int rc = -ENOMEM;
1067
1068 sis190_set_rxbufsize(tp, dev);
1069
1070 /*
1071 * Rx and Tx descriptors need 256 bytes alignment.
1072 * pci_alloc_consistent() guarantees a stronger alignment.
1073 */
1074 tp->TxDescRing = pci_alloc_consistent(pdev, TX_RING_BYTES, &tp->tx_dma);
1075 if (!tp->TxDescRing)
1076 goto out;
1077
1078 tp->RxDescRing = pci_alloc_consistent(pdev, RX_RING_BYTES, &tp->rx_dma);
1079 if (!tp->RxDescRing)
1080 goto err_free_tx_0;
1081
1082 rc = sis190_init_ring(dev);
1083 if (rc < 0)
1084 goto err_free_rx_1;
1085
Francois Romieu890e8d02005-07-30 13:08:43 +02001086 sis190_request_timer(dev);
1087
Francois Romieu480c2862012-03-09 11:56:08 +01001088 rc = request_irq(pdev->irq, sis190_irq, IRQF_SHARED, dev->name, dev);
Francois Romieu890e8d02005-07-30 13:08:43 +02001089 if (rc < 0)
1090 goto err_release_timer_2;
1091
1092 sis190_hw_start(dev);
1093out:
1094 return rc;
1095
1096err_release_timer_2:
1097 sis190_delete_timer(dev);
1098 sis190_rx_clear(tp);
1099err_free_rx_1:
Francois Romieu480c2862012-03-09 11:56:08 +01001100 pci_free_consistent(pdev, RX_RING_BYTES, tp->RxDescRing, tp->rx_dma);
Francois Romieu890e8d02005-07-30 13:08:43 +02001101err_free_tx_0:
Francois Romieu480c2862012-03-09 11:56:08 +01001102 pci_free_consistent(pdev, TX_RING_BYTES, tp->TxDescRing, tp->tx_dma);
Francois Romieu890e8d02005-07-30 13:08:43 +02001103 goto out;
1104}
1105
1106static void sis190_tx_clear(struct sis190_private *tp)
1107{
1108 unsigned int i;
1109
1110 for (i = 0; i < NUM_TX_DESC; i++) {
1111 struct sk_buff *skb = tp->Tx_skbuff[i];
1112
1113 if (!skb)
1114 continue;
1115
1116 sis190_unmap_tx_skb(tp->pci_dev, skb, tp->TxDescRing + i);
1117 tp->Tx_skbuff[i] = NULL;
1118 dev_kfree_skb(skb);
1119
Jeff Garzik09f75cd2007-10-03 17:41:50 -07001120 tp->dev->stats.tx_dropped++;
Francois Romieu890e8d02005-07-30 13:08:43 +02001121 }
1122 tp->cur_tx = tp->dirty_tx = 0;
1123}
1124
1125static void sis190_down(struct net_device *dev)
1126{
1127 struct sis190_private *tp = netdev_priv(dev);
1128 void __iomem *ioaddr = tp->mmio_addr;
1129 unsigned int poll_locked = 0;
1130
1131 sis190_delete_timer(dev);
1132
1133 netif_stop_queue(dev);
1134
Francois Romieu890e8d02005-07-30 13:08:43 +02001135 do {
1136 spin_lock_irq(&tp->lock);
1137
1138 sis190_asic_down(ioaddr);
1139
1140 spin_unlock_irq(&tp->lock);
1141
Francois Romieu480c2862012-03-09 11:56:08 +01001142 synchronize_irq(tp->pci_dev->irq);
Francois Romieu890e8d02005-07-30 13:08:43 +02001143
Stephen Hemmingerbea33482007-10-03 16:41:36 -07001144 if (!poll_locked)
Francois Romieu890e8d02005-07-30 13:08:43 +02001145 poll_locked++;
Francois Romieu890e8d02005-07-30 13:08:43 +02001146
1147 synchronize_sched();
1148
1149 } while (SIS_R32(IntrMask));
1150
1151 sis190_tx_clear(tp);
1152 sis190_rx_clear(tp);
1153}
1154
1155static int sis190_close(struct net_device *dev)
1156{
1157 struct sis190_private *tp = netdev_priv(dev);
1158 struct pci_dev *pdev = tp->pci_dev;
1159
1160 sis190_down(dev);
1161
Francois Romieu480c2862012-03-09 11:56:08 +01001162 free_irq(pdev->irq, dev);
Francois Romieu890e8d02005-07-30 13:08:43 +02001163
Francois Romieu890e8d02005-07-30 13:08:43 +02001164 pci_free_consistent(pdev, TX_RING_BYTES, tp->TxDescRing, tp->tx_dma);
1165 pci_free_consistent(pdev, RX_RING_BYTES, tp->RxDescRing, tp->rx_dma);
1166
1167 tp->TxDescRing = NULL;
1168 tp->RxDescRing = NULL;
1169
1170 return 0;
1171}
1172
Stephen Hemminger613573252009-08-31 19:50:58 +00001173static netdev_tx_t sis190_start_xmit(struct sk_buff *skb,
1174 struct net_device *dev)
Francois Romieu890e8d02005-07-30 13:08:43 +02001175{
1176 struct sis190_private *tp = netdev_priv(dev);
1177 void __iomem *ioaddr = tp->mmio_addr;
1178 u32 len, entry, dirty_tx;
1179 struct TxDesc *desc;
1180 dma_addr_t mapping;
1181
1182 if (unlikely(skb->len < ETH_ZLEN)) {
Herbert Xu5b057c62006-06-23 02:06:41 -07001183 if (skb_padto(skb, ETH_ZLEN)) {
Jeff Garzik09f75cd2007-10-03 17:41:50 -07001184 dev->stats.tx_dropped++;
Francois Romieu890e8d02005-07-30 13:08:43 +02001185 goto out;
1186 }
1187 len = ETH_ZLEN;
1188 } else {
1189 len = skb->len;
1190 }
1191
1192 entry = tp->cur_tx % NUM_TX_DESC;
1193 desc = tp->TxDescRing + entry;
1194
1195 if (unlikely(le32_to_cpu(desc->status) & OWNbit)) {
1196 netif_stop_queue(dev);
Joe Perchesad06ab22010-02-17 20:00:17 +00001197 netif_err(tp, tx_err, dev,
1198 "BUG! Tx Ring full when queue awake!\n");
Francois Romieu890e8d02005-07-30 13:08:43 +02001199 return NETDEV_TX_BUSY;
1200 }
1201
1202 mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE);
kirjanov@gmail.come382c302010-02-24 08:41:18 +00001203 if (pci_dma_mapping_error(tp->pci_dev, mapping)) {
1204 netif_err(tp, tx_err, dev,
1205 "PCI mapping failed, dropping packet");
1206 return NETDEV_TX_BUSY;
1207 }
Francois Romieu890e8d02005-07-30 13:08:43 +02001208
1209 tp->Tx_skbuff[entry] = skb;
1210
1211 desc->PSize = cpu_to_le32(len);
1212 desc->addr = cpu_to_le32(mapping);
1213
1214 desc->size = cpu_to_le32(len);
1215 if (entry == (NUM_TX_DESC - 1))
1216 desc->size |= cpu_to_le32(RingEnd);
1217
1218 wmb();
1219
1220 desc->status = cpu_to_le32(OWNbit | INTbit | DEFbit | CRCbit | PADbit);
Riccardo Ghetta08326db2010-02-17 09:28:58 +00001221 if (tp->negotiated_lpa & (LPA_1000HALF | LPA_100HALF | LPA_10HALF)) {
1222 /* Half Duplex */
1223 desc->status |= cpu_to_le32(COLEN | CRSEN | BKFEN);
1224 if (tp->negotiated_lpa & (LPA_1000HALF | LPA_1000FULL))
1225 desc->status |= cpu_to_le32(EXTEN | BSTEN); /* gigabit HD */
1226 }
Francois Romieu890e8d02005-07-30 13:08:43 +02001227
1228 tp->cur_tx++;
1229
1230 smp_wmb();
1231
1232 SIS_W32(TxControl, 0x1a00 | CmdReset | CmdTxEnb);
1233
Francois Romieu890e8d02005-07-30 13:08:43 +02001234 dirty_tx = tp->dirty_tx;
1235 if ((tp->cur_tx - NUM_TX_DESC) == dirty_tx) {
1236 netif_stop_queue(dev);
1237 smp_rmb();
1238 if (dirty_tx != tp->dirty_tx)
1239 netif_wake_queue(dev);
1240 }
1241out:
1242 return NETDEV_TX_OK;
1243}
1244
Francois Romieufcb98212005-07-30 13:15:22 +02001245static void sis190_free_phy(struct list_head *first_phy)
1246{
1247 struct sis190_phy *cur, *next;
1248
1249 list_for_each_entry_safe(cur, next, first_phy, list) {
1250 kfree(cur);
1251 }
1252}
1253
1254/**
1255 * sis190_default_phy - Select default PHY for sis190 mac.
1256 * @dev: the net device to probe for
1257 *
1258 * Select first detected PHY with link as default.
1259 * If no one is link on, select PHY whose types is HOME as default.
1260 * If HOME doesn't exist, select LAN.
1261 */
1262static u16 sis190_default_phy(struct net_device *dev)
1263{
1264 struct sis190_phy *phy, *phy_home, *phy_default, *phy_lan;
1265 struct sis190_private *tp = netdev_priv(dev);
1266 struct mii_if_info *mii_if = &tp->mii_if;
1267 void __iomem *ioaddr = tp->mmio_addr;
1268 u16 status;
1269
1270 phy_home = phy_default = phy_lan = NULL;
1271
1272 list_for_each_entry(phy, &tp->first_phy, list) {
1273 status = mdio_read_latched(ioaddr, phy->phy_id, MII_BMSR);
1274
1275 // Link ON & Not select default PHY & not ghost PHY.
1276 if ((status & BMSR_LSTATUS) &&
1277 !phy_default &&
1278 (phy->type != UNKNOWN)) {
1279 phy_default = phy;
1280 } else {
1281 status = mdio_read(ioaddr, phy->phy_id, MII_BMCR);
1282 mdio_write(ioaddr, phy->phy_id, MII_BMCR,
1283 status | BMCR_ANENABLE | BMCR_ISOLATE);
1284 if (phy->type == HOME)
1285 phy_home = phy;
1286 else if (phy->type == LAN)
1287 phy_lan = phy;
1288 }
1289 }
1290
1291 if (!phy_default) {
1292 if (phy_home)
1293 phy_default = phy_home;
1294 else if (phy_lan)
1295 phy_default = phy_lan;
1296 else
françois romieuc2f3f3a2009-06-17 11:43:11 +00001297 phy_default = list_first_entry(&tp->first_phy,
Francois Romieufcb98212005-07-30 13:15:22 +02001298 struct sis190_phy, list);
1299 }
1300
1301 if (mii_if->phy_id != phy_default->phy_id) {
1302 mii_if->phy_id = phy_default->phy_id;
Joe Perchesad06ab22010-02-17 20:00:17 +00001303 if (netif_msg_probe(tp))
1304 pr_info("%s: Using transceiver at address %d as default\n",
1305 pci_name(tp->pci_dev), mii_if->phy_id);
Francois Romieufcb98212005-07-30 13:15:22 +02001306 }
1307
1308 status = mdio_read(ioaddr, mii_if->phy_id, MII_BMCR);
1309 status &= (~BMCR_ISOLATE);
1310
1311 mdio_write(ioaddr, mii_if->phy_id, MII_BMCR, status);
1312 status = mdio_read_latched(ioaddr, mii_if->phy_id, MII_BMSR);
1313
1314 return status;
1315}
1316
1317static void sis190_init_phy(struct net_device *dev, struct sis190_private *tp,
1318 struct sis190_phy *phy, unsigned int phy_id,
1319 u16 mii_status)
1320{
1321 void __iomem *ioaddr = tp->mmio_addr;
1322 struct mii_chip_info *p;
1323
1324 INIT_LIST_HEAD(&phy->list);
1325 phy->status = mii_status;
1326 phy->phy_id = phy_id;
1327
1328 phy->id[0] = mdio_read(ioaddr, phy_id, MII_PHYSID1);
1329 phy->id[1] = mdio_read(ioaddr, phy_id, MII_PHYSID2);
1330
1331 for (p = mii_chip_table; p->type; p++) {
1332 if ((p->id[0] == phy->id[0]) &&
1333 (p->id[1] == (phy->id[1] & 0xfff0))) {
1334 break;
1335 }
1336 }
1337
1338 if (p->id[1]) {
1339 phy->type = (p->type == MIX) ?
1340 ((mii_status & (BMSR_100FULL | BMSR_100HALF)) ?
1341 LAN : HOME) : p->type;
Francois Romieu900eb9d2005-09-03 00:55:27 +02001342 tp->features |= p->feature;
Joe Perchesad06ab22010-02-17 20:00:17 +00001343 if (netif_msg_probe(tp))
1344 pr_info("%s: %s transceiver at address %d\n",
1345 pci_name(tp->pci_dev), p->name, phy_id);
Riccardo Ghettac3223d22009-06-04 09:04:55 +00001346 } else {
Francois Romieufcb98212005-07-30 13:15:22 +02001347 phy->type = UNKNOWN;
Joe Perchesad06ab22010-02-17 20:00:17 +00001348 if (netif_msg_probe(tp))
1349 pr_info("%s: unknown PHY 0x%x:0x%x transceiver at address %d\n",
1350 pci_name(tp->pci_dev),
1351 phy->id[0], (phy->id[1] & 0xfff0), phy_id);
Riccardo Ghettac3223d22009-06-04 09:04:55 +00001352 }
Francois Romieufcb98212005-07-30 13:15:22 +02001353}
1354
Francois Romieu900eb9d2005-09-03 00:55:27 +02001355static void sis190_mii_probe_88e1111_fixup(struct sis190_private *tp)
1356{
1357 if (tp->features & F_PHY_88E1111) {
1358 void __iomem *ioaddr = tp->mmio_addr;
1359 int phy_id = tp->mii_if.phy_id;
1360 u16 reg[2][2] = {
1361 { 0x808b, 0x0ce1 },
1362 { 0x808f, 0x0c60 }
1363 }, *p;
1364
1365 p = (tp->features & F_HAS_RGMII) ? reg[0] : reg[1];
1366
1367 mdio_write(ioaddr, phy_id, 0x1b, p[0]);
1368 udelay(200);
1369 mdio_write(ioaddr, phy_id, 0x14, p[1]);
1370 udelay(200);
1371 }
1372}
1373
Francois Romieufcb98212005-07-30 13:15:22 +02001374/**
1375 * sis190_mii_probe - Probe MII PHY for sis190
1376 * @dev: the net device to probe for
1377 *
1378 * Search for total of 32 possible mii phy addresses.
1379 * Identify and set current phy if found one,
1380 * return error if it failed to found.
1381 */
Bill Pembertonfe80f562012-12-03 09:23:35 -05001382static int sis190_mii_probe(struct net_device *dev)
Francois Romieufcb98212005-07-30 13:15:22 +02001383{
1384 struct sis190_private *tp = netdev_priv(dev);
1385 struct mii_if_info *mii_if = &tp->mii_if;
1386 void __iomem *ioaddr = tp->mmio_addr;
1387 int phy_id;
1388 int rc = 0;
1389
1390 INIT_LIST_HEAD(&tp->first_phy);
1391
1392 for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) {
1393 struct sis190_phy *phy;
1394 u16 status;
1395
1396 status = mdio_read_latched(ioaddr, phy_id, MII_BMSR);
1397
1398 // Try next mii if the current one is not accessible.
1399 if (status == 0xffff || status == 0x0000)
1400 continue;
1401
1402 phy = kmalloc(sizeof(*phy), GFP_KERNEL);
1403 if (!phy) {
1404 sis190_free_phy(&tp->first_phy);
1405 rc = -ENOMEM;
1406 goto out;
1407 }
1408
1409 sis190_init_phy(dev, tp, phy, phy_id, status);
1410
1411 list_add(&tp->first_phy, &phy->list);
1412 }
1413
1414 if (list_empty(&tp->first_phy)) {
Joe Perchesad06ab22010-02-17 20:00:17 +00001415 if (netif_msg_probe(tp))
1416 pr_info("%s: No MII transceivers found!\n",
1417 pci_name(tp->pci_dev));
Francois Romieufcb98212005-07-30 13:15:22 +02001418 rc = -EIO;
1419 goto out;
1420 }
1421
1422 /* Select default PHY for mac */
1423 sis190_default_phy(dev);
1424
Francois Romieu900eb9d2005-09-03 00:55:27 +02001425 sis190_mii_probe_88e1111_fixup(tp);
1426
Francois Romieufcb98212005-07-30 13:15:22 +02001427 mii_if->dev = dev;
1428 mii_if->mdio_read = __mdio_read;
1429 mii_if->mdio_write = __mdio_write;
1430 mii_if->phy_id_mask = PHY_ID_ANY;
1431 mii_if->reg_num_mask = MII_REG_ANY;
1432out:
1433 return rc;
1434}
1435
Adrian Bunkc2b75f02007-12-11 23:23:56 +01001436static void sis190_mii_remove(struct net_device *dev)
Francois Romieufcb98212005-07-30 13:15:22 +02001437{
1438 struct sis190_private *tp = netdev_priv(dev);
1439
1440 sis190_free_phy(&tp->first_phy);
1441}
1442
Francois Romieu890e8d02005-07-30 13:08:43 +02001443static void sis190_release_board(struct pci_dev *pdev)
1444{
1445 struct net_device *dev = pci_get_drvdata(pdev);
1446 struct sis190_private *tp = netdev_priv(dev);
1447
1448 iounmap(tp->mmio_addr);
1449 pci_release_regions(pdev);
1450 pci_disable_device(pdev);
1451 free_netdev(dev);
1452}
1453
Bill Pembertonfe80f562012-12-03 09:23:35 -05001454static struct net_device *sis190_init_board(struct pci_dev *pdev)
Francois Romieu890e8d02005-07-30 13:08:43 +02001455{
1456 struct sis190_private *tp;
1457 struct net_device *dev;
1458 void __iomem *ioaddr;
1459 int rc;
1460
1461 dev = alloc_etherdev(sizeof(*tp));
1462 if (!dev) {
Francois Romieu890e8d02005-07-30 13:08:43 +02001463 rc = -ENOMEM;
1464 goto err_out_0;
1465 }
1466
Francois Romieu890e8d02005-07-30 13:08:43 +02001467 SET_NETDEV_DEV(dev, &pdev->dev);
1468
1469 tp = netdev_priv(dev);
David Howellsc4028952006-11-22 14:57:56 +00001470 tp->dev = dev;
Francois Romieu890e8d02005-07-30 13:08:43 +02001471 tp->msg_enable = netif_msg_init(debug.msg_enable, SIS190_MSG_DEFAULT);
1472
1473 rc = pci_enable_device(pdev);
1474 if (rc < 0) {
Joe Perchesad06ab22010-02-17 20:00:17 +00001475 if (netif_msg_probe(tp))
1476 pr_err("%s: enable failure\n", pci_name(pdev));
Francois Romieu890e8d02005-07-30 13:08:43 +02001477 goto err_free_dev_1;
1478 }
1479
1480 rc = -ENODEV;
1481
1482 if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
Joe Perchesad06ab22010-02-17 20:00:17 +00001483 if (netif_msg_probe(tp))
1484 pr_err("%s: region #0 is no MMIO resource\n",
1485 pci_name(pdev));
Francois Romieu890e8d02005-07-30 13:08:43 +02001486 goto err_pci_disable_2;
1487 }
1488 if (pci_resource_len(pdev, 0) < SIS190_REGS_SIZE) {
Joe Perchesad06ab22010-02-17 20:00:17 +00001489 if (netif_msg_probe(tp))
1490 pr_err("%s: invalid PCI region size(s)\n",
1491 pci_name(pdev));
Francois Romieu890e8d02005-07-30 13:08:43 +02001492 goto err_pci_disable_2;
1493 }
1494
1495 rc = pci_request_regions(pdev, DRV_NAME);
1496 if (rc < 0) {
Joe Perchesad06ab22010-02-17 20:00:17 +00001497 if (netif_msg_probe(tp))
1498 pr_err("%s: could not request regions\n",
1499 pci_name(pdev));
Francois Romieu890e8d02005-07-30 13:08:43 +02001500 goto err_pci_disable_2;
1501 }
1502
Yang Hongyang284901a2009-04-06 19:01:15 -07001503 rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
Francois Romieu890e8d02005-07-30 13:08:43 +02001504 if (rc < 0) {
Joe Perchesad06ab22010-02-17 20:00:17 +00001505 if (netif_msg_probe(tp))
1506 pr_err("%s: DMA configuration failed\n",
1507 pci_name(pdev));
Francois Romieu890e8d02005-07-30 13:08:43 +02001508 goto err_free_res_3;
1509 }
1510
1511 pci_set_master(pdev);
1512
1513 ioaddr = ioremap(pci_resource_start(pdev, 0), SIS190_REGS_SIZE);
1514 if (!ioaddr) {
Joe Perchesad06ab22010-02-17 20:00:17 +00001515 if (netif_msg_probe(tp))
1516 pr_err("%s: cannot remap MMIO, aborting\n",
1517 pci_name(pdev));
Francois Romieu890e8d02005-07-30 13:08:43 +02001518 rc = -EIO;
1519 goto err_free_res_3;
1520 }
1521
1522 tp->pci_dev = pdev;
1523 tp->mmio_addr = ioaddr;
Herton Ronaldo Krzesinskib88aafd2010-03-02 03:44:41 -08001524 tp->link_status = LNK_OFF;
Francois Romieu890e8d02005-07-30 13:08:43 +02001525
1526 sis190_irq_mask_and_ack(ioaddr);
1527
1528 sis190_soft_reset(ioaddr);
1529out:
1530 return dev;
1531
1532err_free_res_3:
1533 pci_release_regions(pdev);
1534err_pci_disable_2:
1535 pci_disable_device(pdev);
1536err_free_dev_1:
1537 free_netdev(dev);
1538err_out_0:
1539 dev = ERR_PTR(rc);
1540 goto out;
1541}
1542
1543static void sis190_tx_timeout(struct net_device *dev)
1544{
1545 struct sis190_private *tp = netdev_priv(dev);
1546 void __iomem *ioaddr = tp->mmio_addr;
1547 u8 tmp8;
1548
1549 /* Disable Tx, if not already */
1550 tmp8 = SIS_R8(TxControl);
1551 if (tmp8 & CmdTxEnb)
1552 SIS_W8(TxControl, tmp8 & ~CmdTxEnb);
1553
Joe Perchesad06ab22010-02-17 20:00:17 +00001554 netif_info(tp, tx_err, dev, "Transmit timeout, status %08x %08x\n",
1555 SIS_R32(TxControl), SIS_R32(TxSts));
Francois Romieu188f23b2005-07-30 13:11:43 +02001556
Francois Romieu890e8d02005-07-30 13:08:43 +02001557 /* Disable interrupts by clearing the interrupt mask. */
1558 SIS_W32(IntrMask, 0x0000);
1559
1560 /* Stop a shared interrupt from scavenging while we are. */
1561 spin_lock_irq(&tp->lock);
1562 sis190_tx_clear(tp);
1563 spin_unlock_irq(&tp->lock);
1564
1565 /* ...and finally, reset everything. */
1566 sis190_hw_start(dev);
1567
1568 netif_wake_queue(dev);
1569}
1570
Francois Romieu900eb9d2005-09-03 00:55:27 +02001571static void sis190_set_rgmii(struct sis190_private *tp, u8 reg)
1572{
1573 tp->features |= (reg & 0x80) ? F_HAS_RGMII : 0;
1574}
1575
Bill Pembertonfe80f562012-12-03 09:23:35 -05001576static int sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev,
Greg Kroah-Hartman1dd06ae2012-12-06 14:30:56 +00001577 struct net_device *dev)
Francois Romieu830fb7d2005-07-30 13:12:37 +02001578{
1579 struct sis190_private *tp = netdev_priv(dev);
1580 void __iomem *ioaddr = tp->mmio_addr;
1581 u16 sig;
1582 int i;
1583
Joe Perchesad06ab22010-02-17 20:00:17 +00001584 if (netif_msg_probe(tp))
1585 pr_info("%s: Read MAC address from EEPROM\n", pci_name(pdev));
Francois Romieu830fb7d2005-07-30 13:12:37 +02001586
1587 /* Check to see if there is a sane EEPROM */
1588 sig = (u16) sis190_read_eeprom(ioaddr, EEPROMSignature);
1589
1590 if ((sig == 0xffff) || (sig == 0x0000)) {
Joe Perchesad06ab22010-02-17 20:00:17 +00001591 if (netif_msg_probe(tp))
1592 pr_info("%s: Error EEPROM read %x\n",
1593 pci_name(pdev), sig);
Francois Romieu830fb7d2005-07-30 13:12:37 +02001594 return -EIO;
1595 }
1596
1597 /* Get MAC address from EEPROM */
Joe Perches6a3c9102011-11-16 09:38:02 +00001598 for (i = 0; i < ETH_ALEN / 2; i++) {
Al Viro961994a2007-12-15 01:44:33 +00001599 u16 w = sis190_read_eeprom(ioaddr, EEPROMMACAddr + i);
Francois Romieu830fb7d2005-07-30 13:12:37 +02001600
Al Viro961994a2007-12-15 01:44:33 +00001601 ((__le16 *)dev->dev_addr)[i] = cpu_to_le16(w);
Francois Romieu830fb7d2005-07-30 13:12:37 +02001602 }
1603
Francois Romieu900eb9d2005-09-03 00:55:27 +02001604 sis190_set_rgmii(tp, sis190_read_eeprom(ioaddr, EEPROMInfo));
1605
Francois Romieu830fb7d2005-07-30 13:12:37 +02001606 return 0;
1607}
1608
1609/**
Francois Romieuebc71642007-12-04 22:58:41 +01001610 * sis190_get_mac_addr_from_apc - Get MAC address for SiS96x model
Francois Romieu830fb7d2005-07-30 13:12:37 +02001611 * @pdev: PCI device
1612 * @dev: network device to get address for
1613 *
Francois Romieuebc71642007-12-04 22:58:41 +01001614 * SiS96x model, use APC CMOS RAM to store MAC address.
Francois Romieu830fb7d2005-07-30 13:12:37 +02001615 * APC CMOS RAM is accessed through ISA bridge.
1616 * MAC address is read into @net_dev->dev_addr.
1617 */
Bill Pembertonfe80f562012-12-03 09:23:35 -05001618static int sis190_get_mac_addr_from_apc(struct pci_dev *pdev,
Greg Kroah-Hartman1dd06ae2012-12-06 14:30:56 +00001619 struct net_device *dev)
Francois Romieu830fb7d2005-07-30 13:12:37 +02001620{
Bill Pembertonfe80f562012-12-03 09:23:35 -05001621 static const u16 ids[] = { 0x0965, 0x0966, 0x0968 };
Francois Romieu830fb7d2005-07-30 13:12:37 +02001622 struct sis190_private *tp = netdev_priv(dev);
1623 struct pci_dev *isa_bridge;
1624 u8 reg, tmp8;
Francois Romieuebc71642007-12-04 22:58:41 +01001625 unsigned int i;
Francois Romieu830fb7d2005-07-30 13:12:37 +02001626
Joe Perchesad06ab22010-02-17 20:00:17 +00001627 if (netif_msg_probe(tp))
1628 pr_info("%s: Read MAC address from APC\n", pci_name(pdev));
Francois Romieu830fb7d2005-07-30 13:12:37 +02001629
Francois Romieuebc71642007-12-04 22:58:41 +01001630 for (i = 0; i < ARRAY_SIZE(ids); i++) {
1631 isa_bridge = pci_get_device(PCI_VENDOR_ID_SI, ids[i], NULL);
1632 if (isa_bridge)
1633 break;
1634 }
Neil Muller8eb7ad62007-08-01 17:52:04 +02001635
Francois Romieu830fb7d2005-07-30 13:12:37 +02001636 if (!isa_bridge) {
Joe Perchesad06ab22010-02-17 20:00:17 +00001637 if (netif_msg_probe(tp))
1638 pr_info("%s: Can not find ISA bridge\n",
1639 pci_name(pdev));
Francois Romieu830fb7d2005-07-30 13:12:37 +02001640 return -EIO;
1641 }
1642
1643 /* Enable port 78h & 79h to access APC Registers. */
1644 pci_read_config_byte(isa_bridge, 0x48, &tmp8);
1645 reg = (tmp8 & ~0x02);
1646 pci_write_config_byte(isa_bridge, 0x48, reg);
1647 udelay(50);
1648 pci_read_config_byte(isa_bridge, 0x48, &reg);
1649
Joe Perches6a3c9102011-11-16 09:38:02 +00001650 for (i = 0; i < ETH_ALEN; i++) {
Francois Romieu830fb7d2005-07-30 13:12:37 +02001651 outb(0x9 + i, 0x78);
1652 dev->dev_addr[i] = inb(0x79);
1653 }
1654
1655 outb(0x12, 0x78);
1656 reg = inb(0x79);
1657
Francois Romieu900eb9d2005-09-03 00:55:27 +02001658 sis190_set_rgmii(tp, reg);
1659
Francois Romieu830fb7d2005-07-30 13:12:37 +02001660 /* Restore the value to ISA Bridge */
1661 pci_write_config_byte(isa_bridge, 0x48, tmp8);
1662 pci_dev_put(isa_bridge);
1663
1664 return 0;
1665}
1666
1667/**
1668 * sis190_init_rxfilter - Initialize the Rx filter
1669 * @dev: network device to initialize
1670 *
1671 * Set receive filter address to our MAC address
1672 * and enable packet filtering.
1673 */
1674static inline void sis190_init_rxfilter(struct net_device *dev)
1675{
1676 struct sis190_private *tp = netdev_priv(dev);
1677 void __iomem *ioaddr = tp->mmio_addr;
1678 u16 ctl;
1679 int i;
1680
1681 ctl = SIS_R16(RxMacControl);
1682 /*
1683 * Disable packet filtering before setting filter.
1684 * Note: SiS's driver writes 32 bits but RxMacControl is 16 bits
1685 * only and followed by RxMacAddr (6 bytes). Strange. -- FR
1686 */
1687 SIS_W16(RxMacControl, ctl & ~0x0f00);
1688
Joe Perches6a3c9102011-11-16 09:38:02 +00001689 for (i = 0; i < ETH_ALEN; i++)
Francois Romieu830fb7d2005-07-30 13:12:37 +02001690 SIS_W8(RxMacAddr + i, dev->dev_addr[i]);
1691
1692 SIS_W16(RxMacControl, ctl);
1693 SIS_PCI_COMMIT();
1694}
1695
Greg Kroah-Hartman1dd06ae2012-12-06 14:30:56 +00001696static int sis190_get_mac_addr(struct pci_dev *pdev, struct net_device *dev)
Francois Romieu830fb7d2005-07-30 13:12:37 +02001697{
Francois Romieu563e0ae2008-02-18 21:20:32 +01001698 int rc;
Francois Romieu830fb7d2005-07-30 13:12:37 +02001699
Francois Romieu563e0ae2008-02-18 21:20:32 +01001700 rc = sis190_get_mac_addr_from_eeprom(pdev, dev);
1701 if (rc < 0) {
1702 u8 reg;
Francois Romieu830fb7d2005-07-30 13:12:37 +02001703
Francois Romieu563e0ae2008-02-18 21:20:32 +01001704 pci_read_config_byte(pdev, 0x73, &reg);
1705
1706 if (reg & 0x00000001)
1707 rc = sis190_get_mac_addr_from_apc(pdev, dev);
1708 }
1709 return rc;
Francois Romieu830fb7d2005-07-30 13:12:37 +02001710}
1711
Francois Romieu890e8d02005-07-30 13:08:43 +02001712static void sis190_set_speed_auto(struct net_device *dev)
1713{
1714 struct sis190_private *tp = netdev_priv(dev);
1715 void __iomem *ioaddr = tp->mmio_addr;
Francois Romieu9ede1092005-07-30 13:14:38 +02001716 int phy_id = tp->mii_if.phy_id;
Francois Romieu890e8d02005-07-30 13:08:43 +02001717 int val;
1718
Joe Perchesad06ab22010-02-17 20:00:17 +00001719 netif_info(tp, link, dev, "Enabling Auto-negotiation\n");
Francois Romieu890e8d02005-07-30 13:08:43 +02001720
Francois Romieu9ede1092005-07-30 13:14:38 +02001721 val = mdio_read(ioaddr, phy_id, MII_ADVERTISE);
Francois Romieu890e8d02005-07-30 13:08:43 +02001722
1723 // Enable 10/100 Full/Half Mode, leave MII_ADVERTISE bit4:0
1724 // unchanged.
Francois Romieu9ede1092005-07-30 13:14:38 +02001725 mdio_write(ioaddr, phy_id, MII_ADVERTISE, (val & ADVERTISE_SLCT) |
Francois Romieu890e8d02005-07-30 13:08:43 +02001726 ADVERTISE_100FULL | ADVERTISE_10FULL |
1727 ADVERTISE_100HALF | ADVERTISE_10HALF);
1728
1729 // Enable 1000 Full Mode.
Francois Romieu9ede1092005-07-30 13:14:38 +02001730 mdio_write(ioaddr, phy_id, MII_CTRL1000, ADVERTISE_1000FULL);
Francois Romieu890e8d02005-07-30 13:08:43 +02001731
1732 // Enable auto-negotiation and restart auto-negotiation.
Francois Romieu9ede1092005-07-30 13:14:38 +02001733 mdio_write(ioaddr, phy_id, MII_BMCR,
Francois Romieu890e8d02005-07-30 13:08:43 +02001734 BMCR_ANENABLE | BMCR_ANRESTART | BMCR_RESET);
1735}
1736
Francois Romieu43afb942005-07-30 13:10:21 +02001737static int sis190_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1738{
1739 struct sis190_private *tp = netdev_priv(dev);
1740
1741 return mii_ethtool_gset(&tp->mii_if, cmd);
1742}
1743
1744static int sis190_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1745{
1746 struct sis190_private *tp = netdev_priv(dev);
1747
1748 return mii_ethtool_sset(&tp->mii_if, cmd);
1749}
1750
Francois Romieu890e8d02005-07-30 13:08:43 +02001751static void sis190_get_drvinfo(struct net_device *dev,
1752 struct ethtool_drvinfo *info)
1753{
1754 struct sis190_private *tp = netdev_priv(dev);
1755
Rick Jones23020ab2011-11-09 09:58:07 +00001756 strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
1757 strlcpy(info->version, DRV_VERSION, sizeof(info->version));
1758 strlcpy(info->bus_info, pci_name(tp->pci_dev),
1759 sizeof(info->bus_info));
Francois Romieu890e8d02005-07-30 13:08:43 +02001760}
1761
1762static int sis190_get_regs_len(struct net_device *dev)
1763{
1764 return SIS190_REGS_SIZE;
1765}
1766
1767static void sis190_get_regs(struct net_device *dev, struct ethtool_regs *regs,
1768 void *p)
1769{
1770 struct sis190_private *tp = netdev_priv(dev);
1771 unsigned long flags;
1772
Francois Romieu890e8d02005-07-30 13:08:43 +02001773 spin_lock_irqsave(&tp->lock, flags);
1774 memcpy_fromio(p, tp->mmio_addr, regs->len);
1775 spin_unlock_irqrestore(&tp->lock, flags);
1776}
1777
Francois Romieu43afb942005-07-30 13:10:21 +02001778static int sis190_nway_reset(struct net_device *dev)
1779{
1780 struct sis190_private *tp = netdev_priv(dev);
1781
1782 return mii_nway_restart(&tp->mii_if);
1783}
1784
Francois Romieu890e8d02005-07-30 13:08:43 +02001785static u32 sis190_get_msglevel(struct net_device *dev)
1786{
1787 struct sis190_private *tp = netdev_priv(dev);
1788
1789 return tp->msg_enable;
1790}
1791
1792static void sis190_set_msglevel(struct net_device *dev, u32 value)
1793{
1794 struct sis190_private *tp = netdev_priv(dev);
1795
1796 tp->msg_enable = value;
1797}
1798
Jeff Garzik7282d492006-09-13 14:30:00 -04001799static const struct ethtool_ops sis190_ethtool_ops = {
Francois Romieu43afb942005-07-30 13:10:21 +02001800 .get_settings = sis190_get_settings,
1801 .set_settings = sis190_set_settings,
Francois Romieu890e8d02005-07-30 13:08:43 +02001802 .get_drvinfo = sis190_get_drvinfo,
1803 .get_regs_len = sis190_get_regs_len,
1804 .get_regs = sis190_get_regs,
1805 .get_link = ethtool_op_get_link,
1806 .get_msglevel = sis190_get_msglevel,
1807 .set_msglevel = sis190_set_msglevel,
Francois Romieu43afb942005-07-30 13:10:21 +02001808 .nway_reset = sis190_nway_reset,
Francois Romieu890e8d02005-07-30 13:08:43 +02001809};
1810
Francois Romieu43afb942005-07-30 13:10:21 +02001811static int sis190_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1812{
1813 struct sis190_private *tp = netdev_priv(dev);
1814
1815 return !netif_running(dev) ? -EINVAL :
1816 generic_mii_ioctl(&tp->mii_if, if_mii(ifr), cmd, NULL);
1817}
1818
Klement Fishfe661012011-07-28 06:03:22 +00001819static int sis190_mac_addr(struct net_device *dev, void *p)
1820{
1821 int rc;
1822
1823 rc = eth_mac_addr(dev, p);
1824 if (!rc)
1825 sis190_init_rxfilter(dev);
1826 return rc;
1827}
1828
Stephen Hemminger97488c52009-01-07 17:35:41 -08001829static const struct net_device_ops sis190_netdev_ops = {
1830 .ndo_open = sis190_open,
1831 .ndo_stop = sis190_close,
1832 .ndo_do_ioctl = sis190_ioctl,
1833 .ndo_start_xmit = sis190_start_xmit,
1834 .ndo_tx_timeout = sis190_tx_timeout,
Jiri Pirkoafc4b132011-08-16 06:29:01 +00001835 .ndo_set_rx_mode = sis190_set_rx_mode,
Stephen Hemminger97488c52009-01-07 17:35:41 -08001836 .ndo_change_mtu = eth_change_mtu,
Klement Fishfe661012011-07-28 06:03:22 +00001837 .ndo_set_mac_address = sis190_mac_addr,
Stephen Hemminger97488c52009-01-07 17:35:41 -08001838 .ndo_validate_addr = eth_validate_addr,
1839#ifdef CONFIG_NET_POLL_CONTROLLER
1840 .ndo_poll_controller = sis190_netpoll,
1841#endif
1842};
1843
Bill Pembertonfe80f562012-12-03 09:23:35 -05001844static int sis190_init_one(struct pci_dev *pdev,
Greg Kroah-Hartman1dd06ae2012-12-06 14:30:56 +00001845 const struct pci_device_id *ent)
Francois Romieu890e8d02005-07-30 13:08:43 +02001846{
1847 static int printed_version = 0;
1848 struct sis190_private *tp;
1849 struct net_device *dev;
1850 void __iomem *ioaddr;
Francois Romieu830fb7d2005-07-30 13:12:37 +02001851 int rc;
Francois Romieu890e8d02005-07-30 13:08:43 +02001852
1853 if (!printed_version) {
Joe Perchesad06ab22010-02-17 20:00:17 +00001854 if (netif_msg_drv(&debug))
1855 pr_info(SIS190_DRIVER_NAME " loaded\n");
Francois Romieu890e8d02005-07-30 13:08:43 +02001856 printed_version = 1;
1857 }
1858
1859 dev = sis190_init_board(pdev);
1860 if (IS_ERR(dev)) {
1861 rc = PTR_ERR(dev);
1862 goto out;
1863 }
1864
Francois Romieu10487fb2006-02-16 22:17:00 +01001865 pci_set_drvdata(pdev, dev);
1866
Francois Romieu890e8d02005-07-30 13:08:43 +02001867 tp = netdev_priv(dev);
1868 ioaddr = tp->mmio_addr;
1869
Francois Romieu830fb7d2005-07-30 13:12:37 +02001870 rc = sis190_get_mac_addr(pdev, dev);
1871 if (rc < 0)
1872 goto err_release_board;
Francois Romieu890e8d02005-07-30 13:08:43 +02001873
Francois Romieu830fb7d2005-07-30 13:12:37 +02001874 sis190_init_rxfilter(dev);
Francois Romieu890e8d02005-07-30 13:08:43 +02001875
David Howellsc4028952006-11-22 14:57:56 +00001876 INIT_WORK(&tp->phy_task, sis190_phy_task);
Francois Romieu890e8d02005-07-30 13:08:43 +02001877
Stephen Hemminger97488c52009-01-07 17:35:41 -08001878 dev->netdev_ops = &sis190_netdev_ops;
1879
Wilfried Klaebe7ad24ea2014-05-11 00:12:32 +00001880 dev->ethtool_ops = &sis190_ethtool_ops;
Stephen Hemminger97488c52009-01-07 17:35:41 -08001881 dev->watchdog_timeo = SIS190_TX_TIMEOUT;
Francois Romieu890e8d02005-07-30 13:08:43 +02001882
1883 spin_lock_init(&tp->lock);
Francois Romieu890e8d02005-07-30 13:08:43 +02001884
Francois Romieufcb98212005-07-30 13:15:22 +02001885 rc = sis190_mii_probe(dev);
1886 if (rc < 0)
Francois Romieu3690b6c2005-08-26 00:30:37 +02001887 goto err_release_board;
1888
1889 rc = register_netdev(dev);
1890 if (rc < 0)
1891 goto err_remove_mii;
1892
Joe Perchesad06ab22010-02-17 20:00:17 +00001893 if (netif_msg_probe(tp)) {
1894 netdev_info(dev, "%s: %s at %p (IRQ: %d), %pM\n",
1895 pci_name(pdev),
1896 sis_chip_info[ent->driver_data].name,
Francois Romieu480c2862012-03-09 11:56:08 +01001897 ioaddr, pdev->irq, dev->dev_addr);
Joe Perchesad06ab22010-02-17 20:00:17 +00001898 netdev_info(dev, "%s mode.\n",
1899 (tp->features & F_HAS_RGMII) ? "RGMII" : "GMII");
1900 }
Francois Romieu900eb9d2005-09-03 00:55:27 +02001901
Francois Romieu890e8d02005-07-30 13:08:43 +02001902 netif_carrier_off(dev);
1903
1904 sis190_set_speed_auto(dev);
1905out:
1906 return rc;
Francois Romieu830fb7d2005-07-30 13:12:37 +02001907
Francois Romieu3690b6c2005-08-26 00:30:37 +02001908err_remove_mii:
1909 sis190_mii_remove(dev);
Francois Romieu830fb7d2005-07-30 13:12:37 +02001910err_release_board:
1911 sis190_release_board(pdev);
1912 goto out;
Francois Romieu890e8d02005-07-30 13:08:43 +02001913}
1914
Bill Pembertonfe80f562012-12-03 09:23:35 -05001915static void sis190_remove_one(struct pci_dev *pdev)
Francois Romieu890e8d02005-07-30 13:08:43 +02001916{
1917 struct net_device *dev = pci_get_drvdata(pdev);
Tejun Heo23f333a2010-12-12 16:45:14 +01001918 struct sis190_private *tp = netdev_priv(dev);
Francois Romieu890e8d02005-07-30 13:08:43 +02001919
Francois Romieufcb98212005-07-30 13:15:22 +02001920 sis190_mii_remove(dev);
Tejun Heo23f333a2010-12-12 16:45:14 +01001921 cancel_work_sync(&tp->phy_task);
Francois Romieu890e8d02005-07-30 13:08:43 +02001922 unregister_netdev(dev);
1923 sis190_release_board(pdev);
Francois Romieu890e8d02005-07-30 13:08:43 +02001924}
1925
1926static struct pci_driver sis190_pci_driver = {
1927 .name = DRV_NAME,
1928 .id_table = sis190_pci_tbl,
1929 .probe = sis190_init_one,
Bill Pembertonfe80f562012-12-03 09:23:35 -05001930 .remove = sis190_remove_one,
Francois Romieu890e8d02005-07-30 13:08:43 +02001931};
1932
Peter Hüwe52a58f9d2013-05-21 12:42:10 +00001933module_pci_driver(sis190_pci_driver);