blob: b1a8b4b9e1a3507370d708158c823ae27651a7ce [file] [log] [blame]
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001/**************************************************************************
2 *
3 * Copyright 2000-2006 Alacritech, Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following
13 * disclaimer in the documentation and/or other materials provided
14 * with the distribution.
15 *
16 * Alternatively, this software may be distributed under the terms of the
17 * GNU General Public License ("GPL") version 2 as published by the Free
18 * Software Foundation.
19 *
20 * THIS SOFTWARE IS PROVIDED BY ALACRITECH, INC. ``AS IS'' AND ANY
21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ALACRITECH, INC. OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
27 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * The views and conclusions contained in the software and documentation
34 * are those of the authors and should not be interpreted as representing
35 * official policies, either expressed or implied, of Alacritech, Inc.
36 *
37 **************************************************************************/
38
39/*
40 * FILENAME: slicoss.c
41 *
42 * The SLICOSS driver for Alacritech's IS-NIC products.
43 *
44 * This driver is supposed to support:
45 *
46 * Mojave cards (single port PCI Gigabit) both copper and fiber
47 * Oasis cards (single and dual port PCI-x Gigabit) copper and fiber
48 * Kalahari cards (dual and quad port PCI-e Gigabit) copper and fiber
49 *
Justin P. Mattock493b67b2012-06-18 07:42:24 -070050 * The driver was actually tested on Oasis and Kalahari cards.
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -070051 *
52 *
53 * NOTE: This is the standard, non-accelerated version of Alacritech's
54 * IS-NIC driver.
55 */
56
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -070057
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -070058#define KLUDGE_FOR_4GB_BOUNDARY 1
59#define DEBUG_MICROCODE 1
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -070060#define DBG 1
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -070061#define SLIC_INTERRUPT_PROCESS_LIMIT 1
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -070062#define SLIC_OFFLOAD_IP_CHECKSUM 1
63#define STATS_TIMER_INTERVAL 2
64#define PING_TIMER_INTERVAL 1
Rashika Kheria1f6876c2013-10-19 13:15:53 +053065#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -070066
67#include <linux/kernel.h>
68#include <linux/string.h>
69#include <linux/errno.h>
70#include <linux/ioport.h>
71#include <linux/slab.h>
72#include <linux/interrupt.h>
73#include <linux/timer.h>
74#include <linux/pci.h>
75#include <linux/spinlock.h>
76#include <linux/init.h>
77#include <linux/bitops.h>
78#include <linux/io.h>
79#include <linux/netdevice.h>
Peter Huewe97b3e0e2013-02-19 05:18:52 +010080#include <linux/crc32.h>
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -070081#include <linux/etherdevice.h>
82#include <linux/skbuff.h>
83#include <linux/delay.h>
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -070084#include <linux/seq_file.h>
85#include <linux/kthread.h>
86#include <linux/module.h>
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -070087
Lior Dotan470c5732008-11-05 16:02:20 +020088#include <linux/firmware.h>
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -070089#include <linux/types.h>
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -070090#include <linux/dma-mapping.h>
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -070091#include <linux/mii.h>
92#include <linux/if_vlan.h>
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -070093#include <asm/unaligned.h>
94
95#include <linux/ethtool.h>
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -070096#include <linux/uaccess.h>
Greg Kroah-Hartman77faefa2009-02-26 13:59:12 -080097#include "slichw.h"
98#include "slic.h"
99
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700100static uint slic_first_init = 1;
Ksenija Stanojevic1cd09892015-02-23 18:47:07 +0100101static char *slic_banner = "Alacritech SLIC Technology(tm) Server and Storage Accelerator (Non-Accelerated)";
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700102
103static char *slic_proc_version = "2.0.351 2006/07/14 12:26:00";
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700104
Lior Dotane9eff9d2008-10-04 07:10:28 +0300105static struct base_driver slic_global = { {}, 0, 0, 0, 1, NULL, NULL };
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700106static int intagg_delay = 100;
107static u32 dynamic_intagg;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700108static unsigned int rcv_count;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700109
110#define DRV_NAME "slicoss"
111#define DRV_VERSION "2.0.1"
112#define DRV_AUTHOR "Alacritech, Inc. Engineering"
113#define DRV_DESCRIPTION "Alacritech SLIC Techonology(tm) "\
114 "Non-Accelerated Driver"
115#define DRV_COPYRIGHT "Copyright 2000-2006 Alacritech, Inc. "\
116 "All rights reserved."
117#define PFX DRV_NAME " "
118
119MODULE_AUTHOR(DRV_AUTHOR);
120MODULE_DESCRIPTION(DRV_DESCRIPTION);
121MODULE_LICENSE("Dual BSD/GPL");
122
123module_param(dynamic_intagg, int, 0);
124MODULE_PARM_DESC(dynamic_intagg, "Dynamic Interrupt Aggregation Setting");
125module_param(intagg_delay, int, 0);
126MODULE_PARM_DESC(intagg_delay, "uSec Interrupt Aggregation Delay");
127
Jingoo Han41e043f2013-12-03 08:26:00 +0900128static const struct pci_device_id slic_pci_tbl[] = {
kirjanov@gmail.com5d372902009-12-18 10:59:04 +0300129 { PCI_DEVICE(PCI_VENDOR_ID_ALACRITECH, SLIC_1GB_DEVICE_ID) },
130 { PCI_DEVICE(PCI_VENDOR_ID_ALACRITECH, SLIC_2GB_DEVICE_ID) },
131 { 0 }
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700132};
133
134MODULE_DEVICE_TABLE(pci, slic_pci_tbl);
135
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800136static inline void slic_reg32_write(void __iomem *reg, u32 value, bool flush)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700137{
138 writel(value, reg);
139 if (flush)
140 mb();
141}
142
Greg Kroah-Hartman28980a32009-02-25 17:43:28 -0800143static inline void slic_reg64_write(struct adapter *adapter, void __iomem *reg,
144 u32 value, void __iomem *regh, u32 paddrh,
145 bool flush)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700146{
David Matlackeafe6002015-05-11 20:40:35 -0700147 unsigned long flags;
148
149 spin_lock_irqsave(&adapter->bit64reglock, flags);
David Matlack36bf51a2015-05-11 20:40:36 -0700150 writel(paddrh, regh);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700151 writel(value, reg);
152 if (flush)
153 mb();
David Matlackeafe6002015-05-11 20:40:35 -0700154 spin_unlock_irqrestore(&adapter->bit64reglock, flags);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700155}
156
Lior Dotane9eff9d2008-10-04 07:10:28 +0300157static void slic_mcast_set_bit(struct adapter *adapter, char *address)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700158{
Lior Dotane9eff9d2008-10-04 07:10:28 +0300159 unsigned char crcpoly;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700160
161 /* Get the CRC polynomial for the mac address */
Peter Huewe97b3e0e2013-02-19 05:18:52 +0100162 /* we use bits 1-8 (lsb), bitwise reversed,
163 * msb (= lsb bit 0 before bitrev) is automatically discarded */
Aya Mahfouza659b3e2015-03-04 07:34:52 +0200164 crcpoly = ether_crc(ETH_ALEN, address)>>23;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700165
166 /* We only have space on the SLIC for 64 entries. Lop
167 * off the top two bits. (2^6 = 64)
168 */
169 crcpoly &= 0x3F;
170
171 /* OR in the new bit into our 64 bit mask. */
Lior Dotane9eff9d2008-10-04 07:10:28 +0300172 adapter->mcastmask |= (u64) 1 << crcpoly;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700173}
174
Lior Dotane9eff9d2008-10-04 07:10:28 +0300175static void slic_mcast_set_mask(struct adapter *adapter)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700176{
Lior Dotane9eff9d2008-10-04 07:10:28 +0300177 __iomem struct slic_regs *slic_regs = adapter->slic_regs;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700178
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700179 if (adapter->macopts & (MAC_ALLMCAST | MAC_PROMISC)) {
180 /* Turn on all multicast addresses. We have to do this for
181 * promiscuous mode as well as ALLMCAST mode. It saves the
182 * Microcode from having to keep state about the MAC
183 * configuration.
184 */
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800185 slic_reg32_write(&slic_regs->slic_mcastlow, 0xFFFFFFFF, FLUSH);
186 slic_reg32_write(&slic_regs->slic_mcasthigh, 0xFFFFFFFF,
187 FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700188 } else {
189 /* Commit our multicast mast to the SLIC by writing to the
190 * multicast address mask registers
191 */
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800192 slic_reg32_write(&slic_regs->slic_mcastlow,
193 (u32)(adapter->mcastmask & 0xFFFFFFFF), FLUSH);
194 slic_reg32_write(&slic_regs->slic_mcasthigh,
195 (u32)((adapter->mcastmask >> 32) & 0xFFFFFFFF), FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700196 }
197}
198
Lior Dotane9eff9d2008-10-04 07:10:28 +0300199static void slic_timer_ping(ulong dev)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700200{
Lior Dotane9eff9d2008-10-04 07:10:28 +0300201 struct adapter *adapter;
202 struct sliccard *card;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700203
Wang Chen4bcd4262008-12-06 23:59:10 -0800204 adapter = netdev_priv((struct net_device *)dev);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700205 card = adapter->card;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700206
Greg Kroah-Hartmandb7a6732009-02-25 17:28:05 -0800207 adapter->pingtimer.expires = jiffies + (PING_TIMER_INTERVAL * HZ);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700208 add_timer(&adapter->pingtimer);
209}
210
Lior Dotane9eff9d2008-10-04 07:10:28 +0300211static void slic_unmap_mmio_space(struct adapter *adapter)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700212{
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700213 if (adapter->slic_regs)
214 iounmap(adapter->slic_regs);
215 adapter->slic_regs = NULL;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700216}
217
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700218/*
219 * slic_link_config
220 *
221 * Write phy control to configure link duplex/speed
222 *
223 */
Lior Dotane9eff9d2008-10-04 07:10:28 +0300224static void slic_link_config(struct adapter *adapter,
225 u32 linkspeed, u32 linkduplex)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700226{
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800227 u32 __iomem *wphy;
Lior Dotane9eff9d2008-10-04 07:10:28 +0300228 u32 speed;
229 u32 duplex;
230 u32 phy_config;
231 u32 phy_advreg;
232 u32 phy_gctlreg;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700233
Greg Kroah-Hartmane8bc9b72009-02-26 14:43:03 -0800234 if (adapter->state != ADAPT_UP)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700235 return;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700236
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700237 if (linkspeed > LINK_1000MB)
238 linkspeed = LINK_AUTOSPEED;
239 if (linkduplex > LINK_AUTOD)
240 linkduplex = LINK_AUTOD;
241
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800242 wphy = &adapter->slic_regs->slic_wphy;
243
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700244 if ((linkspeed == LINK_AUTOSPEED) || (linkspeed == LINK_1000MB)) {
245 if (adapter->flags & ADAPT_FLAGS_FIBERMEDIA) {
246 /* We've got a fiber gigabit interface, and register
247 * 4 is different in fiber mode than in copper mode
248 */
249
250 /* advertise FD only @1000 Mb */
251 phy_advreg = (MIICR_REG_4 | (PAR_ADV1000XFD));
252 /* enable PAUSE frames */
253 phy_advreg |= PAR_ASYMPAUSE_FIBER;
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800254 slic_reg32_write(wphy, phy_advreg, FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700255
256 if (linkspeed == LINK_AUTOSPEED) {
257 /* reset phy, enable auto-neg */
258 phy_config =
259 (MIICR_REG_PCR |
260 (PCR_RESET | PCR_AUTONEG |
261 PCR_AUTONEG_RST));
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800262 slic_reg32_write(wphy, phy_config, FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700263 } else { /* forced 1000 Mb FD*/
264 /* power down phy to break link
265 this may not work) */
266 phy_config = (MIICR_REG_PCR | PCR_POWERDOWN);
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800267 slic_reg32_write(wphy, phy_config, FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700268 /* wait, Marvell says 1 sec,
269 try to get away with 10 ms */
Lior Dotane9eff9d2008-10-04 07:10:28 +0300270 mdelay(10);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700271
272 /* disable auto-neg, set speed/duplex,
273 soft reset phy, powerup */
274 phy_config =
275 (MIICR_REG_PCR |
276 (PCR_RESET | PCR_SPEED_1000 |
277 PCR_DUPLEX_FULL));
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800278 slic_reg32_write(wphy, phy_config, FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700279 }
280 } else { /* copper gigabit */
281
282 /* Auto-Negotiate or 1000 Mb must be auto negotiated
283 * We've got a copper gigabit interface, and
284 * register 4 is different in copper mode than
285 * in fiber mode
286 */
287 if (linkspeed == LINK_AUTOSPEED) {
288 /* advertise 10/100 Mb modes */
289 phy_advreg =
290 (MIICR_REG_4 |
291 (PAR_ADV100FD | PAR_ADV100HD | PAR_ADV10FD
292 | PAR_ADV10HD));
293 } else {
294 /* linkspeed == LINK_1000MB -
295 don't advertise 10/100 Mb modes */
296 phy_advreg = MIICR_REG_4;
297 }
298 /* enable PAUSE frames */
299 phy_advreg |= PAR_ASYMPAUSE;
300 /* required by the Cicada PHY */
301 phy_advreg |= PAR_802_3;
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800302 slic_reg32_write(wphy, phy_advreg, FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700303 /* advertise FD only @1000 Mb */
304 phy_gctlreg = (MIICR_REG_9 | (PGC_ADV1000FD));
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800305 slic_reg32_write(wphy, phy_gctlreg, FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700306
307 if (adapter->subsysid != SLIC_1GB_CICADA_SUBSYS_ID) {
308 /* if a Marvell PHY
309 enable auto crossover */
310 phy_config =
311 (MIICR_REG_16 | (MRV_REG16_XOVERON));
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800312 slic_reg32_write(wphy, phy_config, FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700313
314 /* reset phy, enable auto-neg */
315 phy_config =
316 (MIICR_REG_PCR |
317 (PCR_RESET | PCR_AUTONEG |
318 PCR_AUTONEG_RST));
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800319 slic_reg32_write(wphy, phy_config, FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700320 } else { /* it's a Cicada PHY */
321 /* enable and restart auto-neg (don't reset) */
322 phy_config =
323 (MIICR_REG_PCR |
324 (PCR_AUTONEG | PCR_AUTONEG_RST));
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800325 slic_reg32_write(wphy, phy_config, FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700326 }
327 }
328 } else {
329 /* Forced 10/100 */
330 if (linkspeed == LINK_10MB)
331 speed = 0;
332 else
333 speed = PCR_SPEED_100;
334 if (linkduplex == LINK_HALFD)
335 duplex = 0;
336 else
337 duplex = PCR_DUPLEX_FULL;
338
339 if (adapter->subsysid != SLIC_1GB_CICADA_SUBSYS_ID) {
340 /* if a Marvell PHY
341 disable auto crossover */
342 phy_config = (MIICR_REG_16 | (MRV_REG16_XOVEROFF));
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800343 slic_reg32_write(wphy, phy_config, FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700344 }
345
346 /* power down phy to break link (this may not work) */
347 phy_config = (MIICR_REG_PCR | (PCR_POWERDOWN | speed | duplex));
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800348 slic_reg32_write(wphy, phy_config, FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700349
350 /* wait, Marvell says 1 sec, try to get away with 10 ms */
Lior Dotane9eff9d2008-10-04 07:10:28 +0300351 mdelay(10);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700352
353 if (adapter->subsysid != SLIC_1GB_CICADA_SUBSYS_ID) {
354 /* if a Marvell PHY
355 disable auto-neg, set speed,
356 soft reset phy, powerup */
357 phy_config =
358 (MIICR_REG_PCR | (PCR_RESET | speed | duplex));
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800359 slic_reg32_write(wphy, phy_config, FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700360 } else { /* it's a Cicada PHY */
361 /* disable auto-neg, set speed, powerup */
362 phy_config = (MIICR_REG_PCR | (speed | duplex));
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800363 slic_reg32_write(wphy, phy_config, FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700364 }
365 }
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700366}
367
Lior Dotane9eff9d2008-10-04 07:10:28 +0300368static int slic_card_download_gbrcv(struct adapter *adapter)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700369{
Lior Dotan470c5732008-11-05 16:02:20 +0200370 const struct firmware *fw;
371 const char *file = "";
372 int ret;
Lior Dotane9eff9d2008-10-04 07:10:28 +0300373 __iomem struct slic_regs *slic_regs = adapter->slic_regs;
374 u32 codeaddr;
Lior Dotan874073e2009-01-22 09:38:15 +0200375 u32 instruction;
376 int index = 0;
Lior Dotane9eff9d2008-10-04 07:10:28 +0300377 u32 rcvucodelen = 0;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700378
379 switch (adapter->devid) {
380 case SLIC_2GB_DEVICE_ID:
Lior Dotana390c472009-01-30 09:51:49 +0200381 file = "slicoss/oasisrcvucode.sys";
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700382 break;
383 case SLIC_1GB_DEVICE_ID:
Lior Dotana390c472009-01-30 09:51:49 +0200384 file = "slicoss/gbrcvucode.sys";
Lior Dotan470c5732008-11-05 16:02:20 +0200385 break;
386 default:
Devendra Naga651d4bc2012-08-26 12:36:56 +0530387 return -ENOENT;
Lior Dotan470c5732008-11-05 16:02:20 +0200388 }
389
390 ret = request_firmware(&fw, file, &adapter->pcidev->dev);
391 if (ret) {
Greg Kroah-Hartman4bee4f62009-02-26 15:32:42 -0800392 dev_err(&adapter->pcidev->dev,
David Matlack811e8432014-05-23 21:04:55 -0700393 "Failed to load firmware %s\n", file);
Lior Dotan470c5732008-11-05 16:02:20 +0200394 return ret;
395 }
396
Lior Dotan874073e2009-01-22 09:38:15 +0200397 rcvucodelen = *(u32 *)(fw->data + index);
398 index += 4;
Lior Dotan470c5732008-11-05 16:02:20 +0200399 switch (adapter->devid) {
400 case SLIC_2GB_DEVICE_ID:
Devendra Naga7ee34ab2012-08-26 12:42:50 +0530401 if (rcvucodelen != OasisRcvUCodeLen) {
402 release_firmware(fw);
Lior Dotan470c5732008-11-05 16:02:20 +0200403 return -EINVAL;
Devendra Naga7ee34ab2012-08-26 12:42:50 +0530404 }
Lior Dotan470c5732008-11-05 16:02:20 +0200405 break;
406 case SLIC_1GB_DEVICE_ID:
Devendra Naga7ee34ab2012-08-26 12:42:50 +0530407 if (rcvucodelen != GBRcvUCodeLen) {
408 release_firmware(fw);
Lior Dotan470c5732008-11-05 16:02:20 +0200409 return -EINVAL;
Devendra Naga7ee34ab2012-08-26 12:42:50 +0530410 }
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700411 break;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700412 }
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700413 /* start download */
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800414 slic_reg32_write(&slic_regs->slic_rcv_wcs, SLIC_RCVWCS_BEGIN, FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700415 /* download the rcv sequencer ucode */
416 for (codeaddr = 0; codeaddr < rcvucodelen; codeaddr++) {
417 /* write out instruction address */
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800418 slic_reg32_write(&slic_regs->slic_rcv_wcs, codeaddr, FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700419
Lior Dotan874073e2009-01-22 09:38:15 +0200420 instruction = *(u32 *)(fw->data + index);
421 index += 4;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700422 /* write out the instruction data low addr */
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800423 slic_reg32_write(&slic_regs->slic_rcv_wcs, instruction, FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700424
Lior Dotan874073e2009-01-22 09:38:15 +0200425 instruction = *(u8 *)(fw->data + index);
426 index++;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700427 /* write out the instruction data high addr */
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800428 slic_reg32_write(&slic_regs->slic_rcv_wcs, (u8)instruction,
429 FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700430 }
431
432 /* download finished */
Lior Dotan470c5732008-11-05 16:02:20 +0200433 release_firmware(fw);
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800434 slic_reg32_write(&slic_regs->slic_rcv_wcs, SLIC_RCVWCS_FINISH, FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700435 return 0;
436}
437
Ben Hutchings5d929a72010-01-13 23:36:09 +0000438MODULE_FIRMWARE("slicoss/oasisrcvucode.sys");
439MODULE_FIRMWARE("slicoss/gbrcvucode.sys");
440
Lior Dotane9eff9d2008-10-04 07:10:28 +0300441static int slic_card_download(struct adapter *adapter)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700442{
Lior Dotan470c5732008-11-05 16:02:20 +0200443 const struct firmware *fw;
444 const char *file = "";
445 int ret;
Lior Dotane9eff9d2008-10-04 07:10:28 +0300446 u32 section;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700447 int thissectionsize;
448 int codeaddr;
Lior Dotane9eff9d2008-10-04 07:10:28 +0300449 __iomem struct slic_regs *slic_regs = adapter->slic_regs;
Lior Dotan874073e2009-01-22 09:38:15 +0200450 u32 instruction;
Lior Dotane9eff9d2008-10-04 07:10:28 +0300451 u32 baseaddress;
Lior Dotane9eff9d2008-10-04 07:10:28 +0300452 u32 i;
453 u32 numsects = 0;
454 u32 sectsize[3];
455 u32 sectstart[3];
Lior Dotan874073e2009-01-22 09:38:15 +0200456 int ucode_start, index = 0;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700457
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700458 switch (adapter->devid) {
459 case SLIC_2GB_DEVICE_ID:
Lior Dotana390c472009-01-30 09:51:49 +0200460 file = "slicoss/oasisdownload.sys";
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700461 break;
462 case SLIC_1GB_DEVICE_ID:
Lior Dotana390c472009-01-30 09:51:49 +0200463 file = "slicoss/gbdownload.sys";
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700464 break;
465 default:
Devendra Naga670d1452012-10-22 18:15:41 -0400466 return -ENOENT;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700467 }
Lior Dotan470c5732008-11-05 16:02:20 +0200468 ret = request_firmware(&fw, file, &adapter->pcidev->dev);
469 if (ret) {
Greg Kroah-Hartman4bee4f62009-02-26 15:32:42 -0800470 dev_err(&adapter->pcidev->dev,
David Matlack811e8432014-05-23 21:04:55 -0700471 "Failed to load firmware %s\n", file);
Lior Dotan470c5732008-11-05 16:02:20 +0200472 return ret;
473 }
Lior Dotan874073e2009-01-22 09:38:15 +0200474 numsects = *(u32 *)(fw->data + index);
475 index += 4;
Lior Dotan874073e2009-01-22 09:38:15 +0200476 for (i = 0; i < numsects; i++) {
477 sectsize[i] = *(u32 *)(fw->data + index);
478 index += 4;
479 }
480 for (i = 0; i < numsects; i++) {
481 sectstart[i] = *(u32 *)(fw->data + index);
482 index += 4;
483 }
484 ucode_start = index;
485 instruction = *(u32 *)(fw->data + index);
486 index += 4;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700487 for (section = 0; section < numsects; section++) {
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700488 baseaddress = sectstart[section];
489 thissectionsize = sectsize[section] >> 3;
490
491 for (codeaddr = 0; codeaddr < thissectionsize; codeaddr++) {
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700492 /* Write out instruction address */
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800493 slic_reg32_write(&slic_regs->slic_wcs,
494 baseaddress + codeaddr, FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700495 /* Write out instruction to low addr */
Sean Cleator17d2c642014-12-02 23:45:00 +0000496 slic_reg32_write(&slic_regs->slic_wcs,
497 instruction, FLUSH);
Lior Dotan874073e2009-01-22 09:38:15 +0200498 instruction = *(u32 *)(fw->data + index);
499 index += 4;
500
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700501 /* Write out instruction to high addr */
Sean Cleator17d2c642014-12-02 23:45:00 +0000502 slic_reg32_write(&slic_regs->slic_wcs,
503 instruction, FLUSH);
Lior Dotan874073e2009-01-22 09:38:15 +0200504 instruction = *(u32 *)(fw->data + index);
505 index += 4;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700506 }
507 }
Lior Dotan874073e2009-01-22 09:38:15 +0200508 index = ucode_start;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700509 for (section = 0; section < numsects; section++) {
Lior Dotan874073e2009-01-22 09:38:15 +0200510 instruction = *(u32 *)(fw->data + index);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700511 baseaddress = sectstart[section];
512 if (baseaddress < 0x8000)
513 continue;
514 thissectionsize = sectsize[section] >> 3;
515
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700516 for (codeaddr = 0; codeaddr < thissectionsize; codeaddr++) {
517 /* Write out instruction address */
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800518 slic_reg32_write(&slic_regs->slic_wcs,
519 SLIC_WCS_COMPARE | (baseaddress + codeaddr),
520 FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700521 /* Write out instruction to low addr */
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800522 slic_reg32_write(&slic_regs->slic_wcs, instruction,
523 FLUSH);
Lior Dotan874073e2009-01-22 09:38:15 +0200524 instruction = *(u32 *)(fw->data + index);
525 index += 4;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700526 /* Write out instruction to high addr */
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800527 slic_reg32_write(&slic_regs->slic_wcs, instruction,
528 FLUSH);
Lior Dotan874073e2009-01-22 09:38:15 +0200529 instruction = *(u32 *)(fw->data + index);
530 index += 4;
531
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700532 /* Check SRAM location zero. If it is non-zero. Abort.*/
Lior Dotan874073e2009-01-22 09:38:15 +0200533/* failure = readl((u32 __iomem *)&slic_regs->slic_reset);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700534 if (failure) {
Lior Dotan470c5732008-11-05 16:02:20 +0200535 release_firmware(fw);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700536 return -EIO;
Lior Dotan874073e2009-01-22 09:38:15 +0200537 }*/
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700538 }
539 }
Lior Dotan470c5732008-11-05 16:02:20 +0200540 release_firmware(fw);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700541 /* Everything OK, kick off the card */
Lior Dotane9eff9d2008-10-04 07:10:28 +0300542 mdelay(10);
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800543 slic_reg32_write(&slic_regs->slic_wcs, SLIC_WCS_START, FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700544
545 /* stall for 20 ms, long enough for ucode to init card
546 and reach mainloop */
Lior Dotane9eff9d2008-10-04 07:10:28 +0300547 mdelay(20);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700548
Kulikov Vasiliyd1939782010-06-30 17:02:45 +0400549 return 0;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700550}
551
Ben Hutchings5d929a72010-01-13 23:36:09 +0000552MODULE_FIRMWARE("slicoss/oasisdownload.sys");
553MODULE_FIRMWARE("slicoss/gbdownload.sys");
554
Lior Dotane9eff9d2008-10-04 07:10:28 +0300555static void slic_adapter_set_hwaddr(struct adapter *adapter)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700556{
Lior Dotane9eff9d2008-10-04 07:10:28 +0300557 struct sliccard *card = adapter->card;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700558
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700559 if ((adapter->card) && (card->config_set)) {
560 memcpy(adapter->macaddr,
561 card->config.MacInfo[adapter->functionnumber].macaddrA,
Lior Dotane9eff9d2008-10-04 07:10:28 +0300562 sizeof(struct slic_config_mac));
Joe Perchesae7d27c2013-12-05 15:57:26 -0800563 if (is_zero_ether_addr(adapter->currmacaddr))
564 memcpy(adapter->currmacaddr, adapter->macaddr,
565 ETH_ALEN);
566 if (adapter->netdev)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700567 memcpy(adapter->netdev->dev_addr, adapter->currmacaddr,
Joe Perchesae7d27c2013-12-05 15:57:26 -0800568 ETH_ALEN);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700569 }
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700570}
571
Lior Dotane9eff9d2008-10-04 07:10:28 +0300572static void slic_intagg_set(struct adapter *adapter, u32 value)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700573{
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800574 slic_reg32_write(&adapter->slic_regs->slic_intagg, value, FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700575 adapter->card->loadlevel_current = value;
576}
577
Lior Dotane9eff9d2008-10-04 07:10:28 +0300578static void slic_soft_reset(struct adapter *adapter)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700579{
580 if (adapter->card->state == CARD_UP) {
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800581 slic_reg32_write(&adapter->slic_regs->slic_quiesce, 0, FLUSH);
Lior Dotane9eff9d2008-10-04 07:10:28 +0300582 mdelay(1);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700583 }
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700584
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800585 slic_reg32_write(&adapter->slic_regs->slic_reset, SLIC_RESET_MAGIC,
586 FLUSH);
Lior Dotane9eff9d2008-10-04 07:10:28 +0300587 mdelay(1);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700588}
589
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +0000590static void slic_mac_address_config(struct adapter *adapter)
591{
592 u32 value;
593 u32 value2;
594 __iomem struct slic_regs *slic_regs = adapter->slic_regs;
595
Ebru Akagunduz438c5822014-10-23 16:10:16 +0300596 value = ntohl(*(__be32 *) &adapter->currmacaddr[2]);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +0000597 slic_reg32_write(&slic_regs->slic_wraddral, value, FLUSH);
598 slic_reg32_write(&slic_regs->slic_wraddrbl, value, FLUSH);
599
600 value2 = (u32) ((adapter->currmacaddr[0] << 8 |
601 adapter->currmacaddr[1]) & 0xFFFF);
602
603 slic_reg32_write(&slic_regs->slic_wraddrah, value2, FLUSH);
604 slic_reg32_write(&slic_regs->slic_wraddrbh, value2, FLUSH);
605
606 /* Write our multicast mask out to the card. This is done */
607 /* here in addition to the slic_mcast_addr_set routine */
608 /* because ALL_MCAST may have been enabled or disabled */
609 slic_mcast_set_mask(adapter);
610}
611
612static void slic_mac_config(struct adapter *adapter)
613{
614 u32 value;
615 __iomem struct slic_regs *slic_regs = adapter->slic_regs;
616
617 /* Setup GMAC gaps */
618 if (adapter->linkspeed == LINK_1000MB) {
619 value = ((GMCR_GAPBB_1000 << GMCR_GAPBB_SHIFT) |
620 (GMCR_GAPR1_1000 << GMCR_GAPR1_SHIFT) |
621 (GMCR_GAPR2_1000 << GMCR_GAPR2_SHIFT));
622 } else {
623 value = ((GMCR_GAPBB_100 << GMCR_GAPBB_SHIFT) |
624 (GMCR_GAPR1_100 << GMCR_GAPR1_SHIFT) |
625 (GMCR_GAPR2_100 << GMCR_GAPR2_SHIFT));
626 }
627
628 /* enable GMII */
629 if (adapter->linkspeed == LINK_1000MB)
630 value |= GMCR_GBIT;
631
632 /* enable fullduplex */
633 if ((adapter->linkduplex == LINK_FULLD)
634 || (adapter->macopts & MAC_LOOPBACK)) {
635 value |= GMCR_FULLD;
636 }
637
638 /* write mac config */
639 slic_reg32_write(&slic_regs->slic_wmcfg, value, FLUSH);
640
641 /* setup mac addresses */
642 slic_mac_address_config(adapter);
643}
644
Lior Dotane9eff9d2008-10-04 07:10:28 +0300645static void slic_config_set(struct adapter *adapter, bool linkchange)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700646{
Lior Dotane9eff9d2008-10-04 07:10:28 +0300647 u32 value;
648 u32 RcrReset;
649 __iomem struct slic_regs *slic_regs = adapter->slic_regs;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700650
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700651 if (linkchange) {
652 /* Setup MAC */
653 slic_mac_config(adapter);
654 RcrReset = GRCR_RESET;
655 } else {
656 slic_mac_address_config(adapter);
657 RcrReset = 0;
658 }
659
660 if (adapter->linkduplex == LINK_FULLD) {
661 /* setup xmtcfg */
662 value = (GXCR_RESET | /* Always reset */
663 GXCR_XMTEN | /* Enable transmit */
664 GXCR_PAUSEEN); /* Enable pause */
665
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800666 slic_reg32_write(&slic_regs->slic_wxcfg, value, FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700667
668 /* Setup rcvcfg last */
669 value = (RcrReset | /* Reset, if linkchange */
670 GRCR_CTLEN | /* Enable CTL frames */
671 GRCR_ADDRAEN | /* Address A enable */
672 GRCR_RCVBAD | /* Rcv bad frames */
673 (GRCR_HASHSIZE << GRCR_HASHSIZE_SHIFT));
674 } else {
675 /* setup xmtcfg */
676 value = (GXCR_RESET | /* Always reset */
677 GXCR_XMTEN); /* Enable transmit */
678
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800679 slic_reg32_write(&slic_regs->slic_wxcfg, value, FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700680
681 /* Setup rcvcfg last */
682 value = (RcrReset | /* Reset, if linkchange */
683 GRCR_ADDRAEN | /* Address A enable */
684 GRCR_RCVBAD | /* Rcv bad frames */
685 (GRCR_HASHSIZE << GRCR_HASHSIZE_SHIFT));
686 }
687
688 if (adapter->state != ADAPT_DOWN) {
689 /* Only enable receive if we are restarting or running */
690 value |= GRCR_RCVEN;
691 }
692
693 if (adapter->macopts & MAC_PROMISC)
694 value |= GRCR_RCVALL;
695
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800696 slic_reg32_write(&slic_regs->slic_wrcfg, value, FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700697}
698
699/*
700 * Turn off RCV and XMT, power down PHY
701 */
Lior Dotane9eff9d2008-10-04 07:10:28 +0300702static void slic_config_clear(struct adapter *adapter)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700703{
Lior Dotane9eff9d2008-10-04 07:10:28 +0300704 u32 value;
705 u32 phy_config;
706 __iomem struct slic_regs *slic_regs = adapter->slic_regs;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700707
708 /* Setup xmtcfg */
709 value = (GXCR_RESET | /* Always reset */
710 GXCR_PAUSEEN); /* Enable pause */
711
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800712 slic_reg32_write(&slic_regs->slic_wxcfg, value, FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700713
714 value = (GRCR_RESET | /* Always reset */
715 GRCR_CTLEN | /* Enable CTL frames */
716 GRCR_ADDRAEN | /* Address A enable */
717 (GRCR_HASHSIZE << GRCR_HASHSIZE_SHIFT));
718
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800719 slic_reg32_write(&slic_regs->slic_wrcfg, value, FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700720
721 /* power down phy */
722 phy_config = (MIICR_REG_PCR | (PCR_POWERDOWN));
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800723 slic_reg32_write(&slic_regs->slic_wphy, phy_config, FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700724}
725
Lior Dotane9eff9d2008-10-04 07:10:28 +0300726static bool slic_mac_filter(struct adapter *adapter,
727 struct ether_header *ether_frame)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700728{
Denis Kirjanov9092de62010-07-30 13:26:06 +0000729 struct net_device *netdev = adapter->netdev;
Lior Dotane9eff9d2008-10-04 07:10:28 +0300730 u32 opts = adapter->macopts;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700731
Greg Kroah-Hartmane8bc9b72009-02-26 14:43:03 -0800732 if (opts & MAC_PROMISC)
Greg Kroah-Hartmanb5744882009-02-25 17:16:44 -0800733 return true;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700734
Joe Perchesae7d27c2013-12-05 15:57:26 -0800735 if (is_broadcast_ether_addr(ether_frame->ether_dhost)) {
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700736 if (opts & MAC_BCAST) {
737 adapter->rcv_broadcasts++;
Greg Kroah-Hartmanb5744882009-02-25 17:16:44 -0800738 return true;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700739 }
Vincent Heuken351e8362014-06-23 05:09:18 -0700740
741 return false;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700742 }
743
Joe Perchesae7d27c2013-12-05 15:57:26 -0800744 if (is_multicast_ether_addr(ether_frame->ether_dhost)) {
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700745 if (opts & MAC_ALLMCAST) {
746 adapter->rcv_multicasts++;
Denis Kirjanov9092de62010-07-30 13:26:06 +0000747 netdev->stats.multicast++;
Greg Kroah-Hartmanb5744882009-02-25 17:16:44 -0800748 return true;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700749 }
750 if (opts & MAC_MCAST) {
Lior Dotane9eff9d2008-10-04 07:10:28 +0300751 struct mcast_address *mcaddr = adapter->mcastaddrs;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700752
753 while (mcaddr) {
Joe Perches83294192013-09-01 12:15:47 -0700754 if (ether_addr_equal(mcaddr->address,
755 ether_frame->ether_dhost)) {
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700756 adapter->rcv_multicasts++;
Denis Kirjanov9092de62010-07-30 13:26:06 +0000757 netdev->stats.multicast++;
Greg Kroah-Hartmanb5744882009-02-25 17:16:44 -0800758 return true;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700759 }
760 mcaddr = mcaddr->next;
761 }
Vincent Heuken351e8362014-06-23 05:09:18 -0700762
Greg Kroah-Hartmanb5744882009-02-25 17:16:44 -0800763 return false;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700764 }
Vincent Heuken351e8362014-06-23 05:09:18 -0700765
766 return false;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700767 }
768 if (opts & MAC_DIRECTED) {
769 adapter->rcv_unicasts++;
Greg Kroah-Hartmanb5744882009-02-25 17:16:44 -0800770 return true;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700771 }
Greg Kroah-Hartmanb5744882009-02-25 17:16:44 -0800772 return false;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700773
774}
775
Lior Dotane9eff9d2008-10-04 07:10:28 +0300776static int slic_mac_set_address(struct net_device *dev, void *ptr)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700777{
kirjanov@gmail.comf8771fa2009-12-18 10:54:27 +0300778 struct adapter *adapter = netdev_priv(dev);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700779 struct sockaddr *addr = ptr;
780
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700781 if (netif_running(dev))
782 return -EBUSY;
783 if (!adapter)
784 return -EBUSY;
Greg Kroah-Hartmane8bc9b72009-02-26 14:43:03 -0800785
kirjanov@gmail.coma71b9972009-12-18 10:52:45 +0300786 if (!is_valid_ether_addr(addr->sa_data))
787 return -EINVAL;
788
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700789 memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
790 memcpy(adapter->currmacaddr, addr->sa_data, dev->addr_len);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700791
Greg Kroah-Hartmanb5744882009-02-25 17:16:44 -0800792 slic_config_set(adapter, true);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700793 return 0;
794}
795
Lior Dotane9eff9d2008-10-04 07:10:28 +0300796static void slic_timer_load_check(ulong cardaddr)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700797{
Lior Dotane9eff9d2008-10-04 07:10:28 +0300798 struct sliccard *card = (struct sliccard *)cardaddr;
799 struct adapter *adapter = card->master;
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800800 u32 __iomem *intagg;
Lior Dotane9eff9d2008-10-04 07:10:28 +0300801 u32 load = card->events;
802 u32 level = 0;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700803
804 if ((adapter) && (adapter->state == ADAPT_UP) &&
805 (card->state == CARD_UP) && (slic_global.dynamic_intagg)) {
Peter Huewe81372112013-02-19 05:13:50 +0100806 intagg = &adapter->slic_regs->slic_intagg;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700807 if (adapter->devid == SLIC_1GB_DEVICE_ID) {
808 if (adapter->linkspeed == LINK_1000MB)
809 level = 100;
810 else {
811 if (load > SLIC_LOAD_5)
812 level = SLIC_INTAGG_5;
813 else if (load > SLIC_LOAD_4)
814 level = SLIC_INTAGG_4;
815 else if (load > SLIC_LOAD_3)
816 level = SLIC_INTAGG_3;
817 else if (load > SLIC_LOAD_2)
818 level = SLIC_INTAGG_2;
819 else if (load > SLIC_LOAD_1)
820 level = SLIC_INTAGG_1;
821 else
822 level = SLIC_INTAGG_0;
823 }
824 if (card->loadlevel_current != level) {
825 card->loadlevel_current = level;
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800826 slic_reg32_write(intagg, level, FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700827 }
828 } else {
829 if (load > SLIC_LOAD_5)
830 level = SLIC_INTAGG_5;
831 else if (load > SLIC_LOAD_4)
832 level = SLIC_INTAGG_4;
833 else if (load > SLIC_LOAD_3)
834 level = SLIC_INTAGG_3;
835 else if (load > SLIC_LOAD_2)
836 level = SLIC_INTAGG_2;
837 else if (load > SLIC_LOAD_1)
838 level = SLIC_INTAGG_1;
839 else
840 level = SLIC_INTAGG_0;
841 if (card->loadlevel_current != level) {
842 card->loadlevel_current = level;
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -0800843 slic_reg32_write(intagg, level, FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700844 }
845 }
846 }
847 card->events = 0;
Greg Kroah-Hartmandb7a6732009-02-25 17:28:05 -0800848 card->loadtimer.expires = jiffies + (SLIC_LOADTIMER_PERIOD * HZ);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700849 add_timer(&card->loadtimer);
850}
851
Lior Dotane9eff9d2008-10-04 07:10:28 +0300852static int slic_upr_queue_request(struct adapter *adapter,
853 u32 upr_request,
854 u32 upr_data,
855 u32 upr_data_h,
856 u32 upr_buffer, u32 upr_buffer_h)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700857{
Lior Dotane9eff9d2008-10-04 07:10:28 +0300858 struct slic_upr *upr;
859 struct slic_upr *uprqueue;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700860
Lior Dotane9eff9d2008-10-04 07:10:28 +0300861 upr = kmalloc(sizeof(struct slic_upr), GFP_ATOMIC);
Greg Kroah-Hartmane8bc9b72009-02-26 14:43:03 -0800862 if (!upr)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700863 return -ENOMEM;
Greg Kroah-Hartmane8bc9b72009-02-26 14:43:03 -0800864
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700865 upr->adapter = adapter->port;
866 upr->upr_request = upr_request;
867 upr->upr_data = upr_data;
868 upr->upr_buffer = upr_buffer;
869 upr->upr_data_h = upr_data_h;
870 upr->upr_buffer_h = upr_buffer_h;
871 upr->next = NULL;
872 if (adapter->upr_list) {
873 uprqueue = adapter->upr_list;
874
875 while (uprqueue->next)
876 uprqueue = uprqueue->next;
877 uprqueue->next = upr;
878 } else {
879 adapter->upr_list = upr;
880 }
Kulikov Vasiliyd1939782010-06-30 17:02:45 +0400881 return 0;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700882}
883
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +0000884static void slic_upr_start(struct adapter *adapter)
885{
886 struct slic_upr *upr;
887 __iomem struct slic_regs *slic_regs = adapter->slic_regs;
888/*
889 char * ptr1;
890 char * ptr2;
891 uint cmdoffset;
892*/
893 upr = adapter->upr_list;
894 if (!upr)
895 return;
896 if (adapter->upr_busy)
897 return;
898 adapter->upr_busy = 1;
899
900 switch (upr->upr_request) {
901 case SLIC_UPR_STATS:
902 if (upr->upr_data_h == 0) {
903 slic_reg32_write(&slic_regs->slic_stats, upr->upr_data,
904 FLUSH);
905 } else {
906 slic_reg64_write(adapter, &slic_regs->slic_stats64,
907 upr->upr_data,
908 &slic_regs->slic_addr_upper,
909 upr->upr_data_h, FLUSH);
910 }
911 break;
912
913 case SLIC_UPR_RLSR:
914 slic_reg64_write(adapter, &slic_regs->slic_rlsr, upr->upr_data,
915 &slic_regs->slic_addr_upper, upr->upr_data_h,
916 FLUSH);
917 break;
918
919 case SLIC_UPR_RCONFIG:
920 slic_reg64_write(adapter, &slic_regs->slic_rconfig,
921 upr->upr_data, &slic_regs->slic_addr_upper,
922 upr->upr_data_h, FLUSH);
923 break;
924 case SLIC_UPR_PING:
925 slic_reg32_write(&slic_regs->slic_ping, 1, FLUSH);
926 break;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +0000927 }
928}
929
Lior Dotane9eff9d2008-10-04 07:10:28 +0300930static int slic_upr_request(struct adapter *adapter,
931 u32 upr_request,
932 u32 upr_data,
933 u32 upr_data_h,
934 u32 upr_buffer, u32 upr_buffer_h)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700935{
David Matlackeafe6002015-05-11 20:40:35 -0700936 unsigned long flags;
Kulikov Vasiliy3746bfd2010-06-27 17:20:46 +0400937 int rc;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700938
David Matlackeafe6002015-05-11 20:40:35 -0700939 spin_lock_irqsave(&adapter->upr_lock, flags);
Kulikov Vasiliy3746bfd2010-06-27 17:20:46 +0400940 rc = slic_upr_queue_request(adapter,
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700941 upr_request,
942 upr_data,
943 upr_data_h, upr_buffer, upr_buffer_h);
Kulikov Vasiliy3746bfd2010-06-27 17:20:46 +0400944 if (rc)
945 goto err_unlock_irq;
946
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700947 slic_upr_start(adapter);
Kulikov Vasiliy3746bfd2010-06-27 17:20:46 +0400948err_unlock_irq:
David Matlackeafe6002015-05-11 20:40:35 -0700949 spin_unlock_irqrestore(&adapter->upr_lock, flags);
Kulikov Vasiliy3746bfd2010-06-27 17:20:46 +0400950 return rc;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -0700951}
952
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +0000953static void slic_link_upr_complete(struct adapter *adapter, u32 isr)
954{
955 u32 linkstatus = adapter->pshmem->linkstatus;
956 uint linkup;
957 unsigned char linkspeed;
958 unsigned char linkduplex;
959
960 if ((isr & ISR_UPCERR) || (isr & ISR_UPCBSY)) {
961 struct slic_shmem *pshmem;
962
Joe Perches01d0a9b2013-02-26 16:33:11 -0800963 pshmem = (struct slic_shmem *)(unsigned long)
964 adapter->phys_shmem;
Denis Kirjanov1033f1f2010-08-04 19:24:08 +0000965#if BITS_PER_LONG == 64
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +0000966 slic_upr_queue_request(adapter,
967 SLIC_UPR_RLSR,
968 SLIC_GET_ADDR_LOW(&pshmem->linkstatus),
969 SLIC_GET_ADDR_HIGH(&pshmem->linkstatus),
970 0, 0);
Denis Kirjanov1033f1f2010-08-04 19:24:08 +0000971#else
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +0000972 slic_upr_queue_request(adapter,
973 SLIC_UPR_RLSR,
974 (u32) &pshmem->linkstatus,
975 SLIC_GET_ADDR_HIGH(pshmem), 0, 0);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +0000976#endif
977 return;
978 }
979 if (adapter->state != ADAPT_UP)
980 return;
981
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +0000982 linkup = linkstatus & GIG_LINKUP ? LINK_UP : LINK_DOWN;
983 if (linkstatus & GIG_SPEED_1000)
984 linkspeed = LINK_1000MB;
985 else if (linkstatus & GIG_SPEED_100)
986 linkspeed = LINK_100MB;
987 else
988 linkspeed = LINK_10MB;
989
990 if (linkstatus & GIG_FULLDUPLEX)
991 linkduplex = LINK_FULLD;
992 else
993 linkduplex = LINK_HALFD;
994
995 if ((adapter->linkstate == LINK_DOWN) && (linkup == LINK_DOWN))
996 return;
997
998 /* link up event, but nothing has changed */
999 if ((adapter->linkstate == LINK_UP) &&
1000 (linkup == LINK_UP) &&
1001 (adapter->linkspeed == linkspeed) &&
1002 (adapter->linkduplex == linkduplex))
1003 return;
1004
1005 /* link has changed at this point */
1006
1007 /* link has gone from up to down */
1008 if (linkup == LINK_DOWN) {
1009 adapter->linkstate = LINK_DOWN;
1010 return;
1011 }
1012
1013 /* link has gone from down to up */
1014 adapter->linkspeed = linkspeed;
1015 adapter->linkduplex = linkduplex;
1016
1017 if (adapter->linkstate != LINK_UP) {
1018 /* setup the mac */
1019 slic_config_set(adapter, true);
1020 adapter->linkstate = LINK_UP;
1021 netif_start_queue(adapter->netdev);
1022 }
1023}
1024
Lior Dotane9eff9d2008-10-04 07:10:28 +03001025static void slic_upr_request_complete(struct adapter *adapter, u32 isr)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001026{
Lior Dotane9eff9d2008-10-04 07:10:28 +03001027 struct sliccard *card = adapter->card;
1028 struct slic_upr *upr;
David Matlackeafe6002015-05-11 20:40:35 -07001029 unsigned long flags;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001030
David Matlackeafe6002015-05-11 20:40:35 -07001031 spin_lock_irqsave(&adapter->upr_lock, flags);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001032 upr = adapter->upr_list;
1033 if (!upr) {
David Matlackeafe6002015-05-11 20:40:35 -07001034 spin_unlock_irqrestore(&adapter->upr_lock, flags);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001035 return;
1036 }
1037 adapter->upr_list = upr->next;
1038 upr->next = NULL;
1039 adapter->upr_busy = 0;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001040 switch (upr->upr_request) {
1041 case SLIC_UPR_STATS:
1042 {
Lior Dotane9eff9d2008-10-04 07:10:28 +03001043 struct slic_stats *slicstats =
1044 (struct slic_stats *) &adapter->pshmem->inicstats;
1045 struct slic_stats *newstats = slicstats;
1046 struct slic_stats *old = &adapter->inicstats_prev;
1047 struct slicnet_stats *stst = &adapter->slic_stats;
Greg Kroah-Hartman3467db12009-02-26 14:01:22 -08001048
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001049 if (isr & ISR_UPCERR) {
Greg Kroah-Hartman4bee4f62009-02-26 15:32:42 -08001050 dev_err(&adapter->netdev->dev,
1051 "SLIC_UPR_STATS command failed isr[%x]\n",
1052 isr);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001053
1054 break;
1055 }
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001056 UPDATE_STATS_GB(stst->tcp.xmit_tcp_segs,
1057 newstats->xmit_tcp_segs_gb,
1058 old->xmit_tcp_segs_gb);
1059
1060 UPDATE_STATS_GB(stst->tcp.xmit_tcp_bytes,
1061 newstats->xmit_tcp_bytes_gb,
1062 old->xmit_tcp_bytes_gb);
1063
1064 UPDATE_STATS_GB(stst->tcp.rcv_tcp_segs,
1065 newstats->rcv_tcp_segs_gb,
1066 old->rcv_tcp_segs_gb);
1067
1068 UPDATE_STATS_GB(stst->tcp.rcv_tcp_bytes,
1069 newstats->rcv_tcp_bytes_gb,
1070 old->rcv_tcp_bytes_gb);
1071
1072 UPDATE_STATS_GB(stst->iface.xmt_bytes,
1073 newstats->xmit_bytes_gb,
1074 old->xmit_bytes_gb);
1075
1076 UPDATE_STATS_GB(stst->iface.xmt_ucast,
1077 newstats->xmit_unicasts_gb,
1078 old->xmit_unicasts_gb);
1079
1080 UPDATE_STATS_GB(stst->iface.rcv_bytes,
1081 newstats->rcv_bytes_gb,
1082 old->rcv_bytes_gb);
1083
1084 UPDATE_STATS_GB(stst->iface.rcv_ucast,
1085 newstats->rcv_unicasts_gb,
1086 old->rcv_unicasts_gb);
1087
1088 UPDATE_STATS_GB(stst->iface.xmt_errors,
1089 newstats->xmit_collisions_gb,
1090 old->xmit_collisions_gb);
1091
1092 UPDATE_STATS_GB(stst->iface.xmt_errors,
1093 newstats->xmit_excess_collisions_gb,
1094 old->xmit_excess_collisions_gb);
1095
1096 UPDATE_STATS_GB(stst->iface.xmt_errors,
1097 newstats->xmit_other_error_gb,
1098 old->xmit_other_error_gb);
1099
1100 UPDATE_STATS_GB(stst->iface.rcv_errors,
1101 newstats->rcv_other_error_gb,
1102 old->rcv_other_error_gb);
1103
1104 UPDATE_STATS_GB(stst->iface.rcv_discards,
1105 newstats->rcv_drops_gb,
1106 old->rcv_drops_gb);
1107
1108 if (newstats->rcv_drops_gb > old->rcv_drops_gb) {
1109 adapter->rcv_drops +=
1110 (newstats->rcv_drops_gb -
1111 old->rcv_drops_gb);
1112 }
Lior Dotane9eff9d2008-10-04 07:10:28 +03001113 memcpy(old, newstats, sizeof(struct slic_stats));
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001114 break;
1115 }
1116 case SLIC_UPR_RLSR:
1117 slic_link_upr_complete(adapter, isr);
1118 break;
1119 case SLIC_UPR_RCONFIG:
1120 break;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001121 case SLIC_UPR_PING:
1122 card->pingstatus |= (isr & ISR_PINGDSMASK);
1123 break;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001124 }
Lior Dotane9eff9d2008-10-04 07:10:28 +03001125 kfree(upr);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001126 slic_upr_start(adapter);
David Matlackeafe6002015-05-11 20:40:35 -07001127 spin_unlock_irqrestore(&adapter->upr_lock, flags);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001128}
1129
David Matlack47a401a2014-05-22 21:38:45 -07001130static int slic_config_get(struct adapter *adapter, u32 config, u32 config_h)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001131{
David Matlack47a401a2014-05-22 21:38:45 -07001132 return slic_upr_request(adapter, SLIC_UPR_RCONFIG, config, config_h,
1133 0, 0);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001134}
1135
1136/*
David Matlack55b62cd2014-05-19 22:03:59 -07001137 * Compute a checksum of the EEPROM according to RFC 1071.
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001138 */
David Matlack55b62cd2014-05-19 22:03:59 -07001139static u16 slic_eeprom_cksum(void *eeprom, unsigned len)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001140{
David Matlack55b62cd2014-05-19 22:03:59 -07001141 u16 *wp = eeprom;
1142 u32 checksum = 0;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001143
David Matlack55b62cd2014-05-19 22:03:59 -07001144 while (len > 1) {
1145 checksum += *(wp++);
1146 len -= 2;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001147 }
1148
David Matlack55b62cd2014-05-19 22:03:59 -07001149 if (len > 0)
1150 checksum += *(u8 *) wp;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001151
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001152
David Matlack55b62cd2014-05-19 22:03:59 -07001153 while (checksum >> 16)
1154 checksum = (checksum & 0xFFFF) + ((checksum >> 16) & 0xFFFF);
1155
1156 return ~checksum;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001157}
1158
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001159static void slic_rspqueue_free(struct adapter *adapter)
1160{
1161 int i;
1162 struct slic_rspqueue *rspq = &adapter->rspqueue;
1163
1164 for (i = 0; i < rspq->num_pages; i++) {
1165 if (rspq->vaddr[i]) {
1166 pci_free_consistent(adapter->pcidev, PAGE_SIZE,
1167 rspq->vaddr[i], rspq->paddr[i]);
1168 }
1169 rspq->vaddr[i] = NULL;
1170 rspq->paddr[i] = 0;
1171 }
1172 rspq->offset = 0;
1173 rspq->pageindex = 0;
1174 rspq->rspbuf = NULL;
1175}
1176
Lior Dotane9eff9d2008-10-04 07:10:28 +03001177static int slic_rspqueue_init(struct adapter *adapter)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001178{
1179 int i;
Lior Dotane9eff9d2008-10-04 07:10:28 +03001180 struct slic_rspqueue *rspq = &adapter->rspqueue;
1181 __iomem struct slic_regs *slic_regs = adapter->slic_regs;
1182 u32 paddrh = 0;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001183
Lior Dotane9eff9d2008-10-04 07:10:28 +03001184 memset(rspq, 0, sizeof(struct slic_rspqueue));
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001185
1186 rspq->num_pages = SLIC_RSPQ_PAGES_GB;
1187
1188 for (i = 0; i < rspq->num_pages; i++) {
Joe Perches8b983be2014-08-08 14:24:48 -07001189 rspq->vaddr[i] = pci_zalloc_consistent(adapter->pcidev,
1190 PAGE_SIZE,
1191 &rspq->paddr[i]);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001192 if (!rspq->vaddr[i]) {
Greg Kroah-Hartman4bee4f62009-02-26 15:32:42 -08001193 dev_err(&adapter->pcidev->dev,
1194 "pci_alloc_consistent failed\n");
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001195 slic_rspqueue_free(adapter);
Kulikov Vasiliyd1939782010-06-30 17:02:45 +04001196 return -ENOMEM;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001197 }
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001198
1199 if (paddrh == 0) {
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -08001200 slic_reg32_write(&slic_regs->slic_rbar,
1201 (rspq->paddr[i] | SLIC_RSPQ_BUFSINPAGE),
1202 DONT_FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001203 } else {
Greg Kroah-Hartman28980a32009-02-25 17:43:28 -08001204 slic_reg64_write(adapter, &slic_regs->slic_rbar64,
1205 (rspq->paddr[i] | SLIC_RSPQ_BUFSINPAGE),
1206 &slic_regs->slic_addr_upper,
1207 paddrh, DONT_FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001208 }
1209 }
1210 rspq->offset = 0;
1211 rspq->pageindex = 0;
Lior Dotane9eff9d2008-10-04 07:10:28 +03001212 rspq->rspbuf = (struct slic_rspbuf *)rspq->vaddr[0];
Kulikov Vasiliyd1939782010-06-30 17:02:45 +04001213 return 0;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001214}
1215
Lior Dotane9eff9d2008-10-04 07:10:28 +03001216static struct slic_rspbuf *slic_rspqueue_getnext(struct adapter *adapter)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001217{
Lior Dotane9eff9d2008-10-04 07:10:28 +03001218 struct slic_rspqueue *rspq = &adapter->rspqueue;
1219 struct slic_rspbuf *buf;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001220
1221 if (!(rspq->rspbuf->status))
1222 return NULL;
1223
1224 buf = rspq->rspbuf;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001225 if (++rspq->offset < SLIC_RSPQ_BUFSINPAGE) {
1226 rspq->rspbuf++;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001227 } else {
Greg Kroah-Hartman28980a32009-02-25 17:43:28 -08001228 slic_reg64_write(adapter, &adapter->slic_regs->slic_rbar64,
1229 (rspq->paddr[rspq->pageindex] | SLIC_RSPQ_BUFSINPAGE),
1230 &adapter->slic_regs->slic_addr_upper, 0, DONT_FLUSH);
Peter Huewe6d1b80f2013-02-19 05:18:50 +01001231 rspq->pageindex = (rspq->pageindex + 1) % rspq->num_pages;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001232 rspq->offset = 0;
Lior Dotane9eff9d2008-10-04 07:10:28 +03001233 rspq->rspbuf = (struct slic_rspbuf *)
1234 rspq->vaddr[rspq->pageindex];
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001235 }
Devendra Naga40991e42012-10-22 18:16:07 -04001236
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001237 return buf;
1238}
1239
Lior Dotane9eff9d2008-10-04 07:10:28 +03001240static void slic_cmdqmem_free(struct adapter *adapter)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001241{
Lior Dotane9eff9d2008-10-04 07:10:28 +03001242 struct slic_cmdqmem *cmdqmem = &adapter->cmdqmem;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001243 int i;
1244
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001245 for (i = 0; i < SLIC_CMDQ_MAXPAGES; i++) {
1246 if (cmdqmem->pages[i]) {
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001247 pci_free_consistent(adapter->pcidev,
1248 PAGE_SIZE,
Lior Dotane9eff9d2008-10-04 07:10:28 +03001249 (void *) cmdqmem->pages[i],
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001250 cmdqmem->dma_pages[i]);
1251 }
1252 }
Lior Dotane9eff9d2008-10-04 07:10:28 +03001253 memset(cmdqmem, 0, sizeof(struct slic_cmdqmem));
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001254}
1255
Lior Dotane9eff9d2008-10-04 07:10:28 +03001256static u32 *slic_cmdqmem_addpage(struct adapter *adapter)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001257{
Lior Dotane9eff9d2008-10-04 07:10:28 +03001258 struct slic_cmdqmem *cmdqmem = &adapter->cmdqmem;
1259 u32 *pageaddr;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001260
1261 if (cmdqmem->pagecnt >= SLIC_CMDQ_MAXPAGES)
1262 return NULL;
1263 pageaddr = pci_alloc_consistent(adapter->pcidev,
1264 PAGE_SIZE,
1265 &cmdqmem->dma_pages[cmdqmem->pagecnt]);
1266 if (!pageaddr)
1267 return NULL;
Devendra Naga40991e42012-10-22 18:16:07 -04001268
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001269 cmdqmem->pages[cmdqmem->pagecnt] = pageaddr;
1270 cmdqmem->pagecnt++;
1271 return pageaddr;
1272}
1273
Lior Dotane9eff9d2008-10-04 07:10:28 +03001274static void slic_cmdq_free(struct adapter *adapter)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001275{
Lior Dotane9eff9d2008-10-04 07:10:28 +03001276 struct slic_hostcmd *cmd;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001277
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001278 cmd = adapter->cmdq_all.head;
1279 while (cmd) {
1280 if (cmd->busy) {
1281 struct sk_buff *tempskb;
1282
1283 tempskb = cmd->skb;
1284 if (tempskb) {
1285 cmd->skb = NULL;
1286 dev_kfree_skb_irq(tempskb);
1287 }
1288 }
1289 cmd = cmd->next_all;
1290 }
Lior Dotane9eff9d2008-10-04 07:10:28 +03001291 memset(&adapter->cmdq_all, 0, sizeof(struct slic_cmdqueue));
1292 memset(&adapter->cmdq_free, 0, sizeof(struct slic_cmdqueue));
1293 memset(&adapter->cmdq_done, 0, sizeof(struct slic_cmdqueue));
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001294 slic_cmdqmem_free(adapter);
1295}
1296
Lior Dotane9eff9d2008-10-04 07:10:28 +03001297static void slic_cmdq_addcmdpage(struct adapter *adapter, u32 *page)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001298{
Lior Dotane9eff9d2008-10-04 07:10:28 +03001299 struct slic_hostcmd *cmd;
1300 struct slic_hostcmd *prev;
1301 struct slic_hostcmd *tail;
1302 struct slic_cmdqueue *cmdq;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001303 int cmdcnt;
Lior Dotane9eff9d2008-10-04 07:10:28 +03001304 void *cmdaddr;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001305 ulong phys_addr;
Lior Dotane9eff9d2008-10-04 07:10:28 +03001306 u32 phys_addrl;
1307 u32 phys_addrh;
1308 struct slic_handle *pslic_handle;
David Matlackeafe6002015-05-11 20:40:35 -07001309 unsigned long flags;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001310
1311 cmdaddr = page;
Lior Dotane9eff9d2008-10-04 07:10:28 +03001312 cmd = (struct slic_hostcmd *)cmdaddr;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001313 cmdcnt = 0;
1314
Lior Dotane9eff9d2008-10-04 07:10:28 +03001315 phys_addr = virt_to_bus((void *)page);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001316 phys_addrl = SLIC_GET_ADDR_LOW(phys_addr);
1317 phys_addrh = SLIC_GET_ADDR_HIGH(phys_addr);
1318
1319 prev = NULL;
1320 tail = cmd;
1321 while ((cmdcnt < SLIC_CMDQ_CMDSINPAGE) &&
1322 (adapter->slic_handle_ix < 256)) {
1323 /* Allocate and initialize a SLIC_HANDLE for this command */
David Matlackeafe6002015-05-11 20:40:35 -07001324 spin_lock_irqsave(&adapter->handle_lock, flags);
Monam Agarwalb0a0fb12014-03-09 18:40:23 +05301325 pslic_handle = adapter->pfree_slic_handles;
Monam Agarwalbcadb1d2014-03-27 20:01:01 +05301326 adapter->pfree_slic_handles = pslic_handle->next;
David Matlackeafe6002015-05-11 20:40:35 -07001327 spin_unlock_irqrestore(&adapter->handle_lock, flags);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001328 pslic_handle->type = SLIC_HANDLE_CMD;
Lior Dotane9eff9d2008-10-04 07:10:28 +03001329 pslic_handle->address = (void *) cmd;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001330 pslic_handle->offset = (ushort) adapter->slic_handle_ix++;
1331 pslic_handle->other_handle = NULL;
1332 pslic_handle->next = NULL;
1333
1334 cmd->pslic_handle = pslic_handle;
1335 cmd->cmd64.hosthandle = pslic_handle->token.handle_token;
Greg Kroah-Hartmanb5744882009-02-25 17:16:44 -08001336 cmd->busy = false;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001337 cmd->paddrl = phys_addrl;
1338 cmd->paddrh = phys_addrh;
1339 cmd->next_all = prev;
1340 cmd->next = prev;
1341 prev = cmd;
1342 phys_addrl += SLIC_HOSTCMD_SIZE;
1343 cmdaddr += SLIC_HOSTCMD_SIZE;
1344
Lior Dotane9eff9d2008-10-04 07:10:28 +03001345 cmd = (struct slic_hostcmd *)cmdaddr;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001346 cmdcnt++;
1347 }
1348
1349 cmdq = &adapter->cmdq_all;
1350 cmdq->count += cmdcnt; /* SLIC_CMDQ_CMDSINPAGE; mooktodo */
1351 tail->next_all = cmdq->head;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001352 cmdq->head = prev;
1353 cmdq = &adapter->cmdq_free;
David Matlackeafe6002015-05-11 20:40:35 -07001354 spin_lock_irqsave(&cmdq->lock, flags);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001355 cmdq->count += cmdcnt; /* SLIC_CMDQ_CMDSINPAGE; mooktodo */
1356 tail->next = cmdq->head;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001357 cmdq->head = prev;
David Matlackeafe6002015-05-11 20:40:35 -07001358 spin_unlock_irqrestore(&cmdq->lock, flags);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001359}
1360
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001361static int slic_cmdq_init(struct adapter *adapter)
1362{
1363 int i;
1364 u32 *pageaddr;
1365
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001366 memset(&adapter->cmdq_all, 0, sizeof(struct slic_cmdqueue));
1367 memset(&adapter->cmdq_free, 0, sizeof(struct slic_cmdqueue));
1368 memset(&adapter->cmdq_done, 0, sizeof(struct slic_cmdqueue));
David Matlackeafe6002015-05-11 20:40:35 -07001369 spin_lock_init(&adapter->cmdq_all.lock);
1370 spin_lock_init(&adapter->cmdq_free.lock);
1371 spin_lock_init(&adapter->cmdq_done.lock);
Devendra Nagabae5c3d2012-10-23 18:08:43 -04001372 memset(&adapter->cmdqmem, 0, sizeof(struct slic_cmdqmem));
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001373 adapter->slic_handle_ix = 1;
1374 for (i = 0; i < SLIC_CMDQ_INITPAGES; i++) {
1375 pageaddr = slic_cmdqmem_addpage(adapter);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001376 if (!pageaddr) {
1377 slic_cmdq_free(adapter);
1378 return -ENOMEM;
1379 }
1380 slic_cmdq_addcmdpage(adapter, pageaddr);
1381 }
1382 adapter->slic_handle_ix = 1;
1383
1384 return 0;
1385}
1386
1387static void slic_cmdq_reset(struct adapter *adapter)
1388{
1389 struct slic_hostcmd *hcmd;
1390 struct sk_buff *skb;
1391 u32 outstanding;
David Matlackeafe6002015-05-11 20:40:35 -07001392 unsigned long flags;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001393
David Matlackeafe6002015-05-11 20:40:35 -07001394 spin_lock_irqsave(&adapter->cmdq_free.lock, flags);
Dan Carpenter46d74c32015-05-19 15:25:24 +03001395 spin_lock(&adapter->cmdq_done.lock);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001396 outstanding = adapter->cmdq_all.count - adapter->cmdq_done.count;
1397 outstanding -= adapter->cmdq_free.count;
1398 hcmd = adapter->cmdq_all.head;
1399 while (hcmd) {
1400 if (hcmd->busy) {
1401 skb = hcmd->skb;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001402 hcmd->busy = 0;
1403 hcmd->skb = NULL;
1404 dev_kfree_skb_irq(skb);
1405 }
1406 hcmd = hcmd->next_all;
1407 }
1408 adapter->cmdq_free.count = 0;
1409 adapter->cmdq_free.head = NULL;
1410 adapter->cmdq_free.tail = NULL;
1411 adapter->cmdq_done.count = 0;
1412 adapter->cmdq_done.head = NULL;
1413 adapter->cmdq_done.tail = NULL;
1414 adapter->cmdq_free.head = adapter->cmdq_all.head;
1415 hcmd = adapter->cmdq_all.head;
1416 while (hcmd) {
1417 adapter->cmdq_free.count++;
1418 hcmd->next = hcmd->next_all;
1419 hcmd = hcmd->next_all;
1420 }
1421 if (adapter->cmdq_free.count != adapter->cmdq_all.count) {
1422 dev_err(&adapter->netdev->dev,
1423 "free_count %d != all count %d\n",
1424 adapter->cmdq_free.count, adapter->cmdq_all.count);
1425 }
Dan Carpenter46d74c32015-05-19 15:25:24 +03001426 spin_unlock(&adapter->cmdq_done.lock);
David Matlackeafe6002015-05-11 20:40:35 -07001427 spin_unlock_irqrestore(&adapter->cmdq_free.lock, flags);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001428}
1429
1430static void slic_cmdq_getdone(struct adapter *adapter)
1431{
1432 struct slic_cmdqueue *done_cmdq = &adapter->cmdq_done;
1433 struct slic_cmdqueue *free_cmdq = &adapter->cmdq_free;
David Matlackeafe6002015-05-11 20:40:35 -07001434 unsigned long flags;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001435
David Matlackeafe6002015-05-11 20:40:35 -07001436 spin_lock_irqsave(&done_cmdq->lock, flags);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001437
1438 free_cmdq->head = done_cmdq->head;
1439 free_cmdq->count = done_cmdq->count;
1440 done_cmdq->head = NULL;
1441 done_cmdq->tail = NULL;
1442 done_cmdq->count = 0;
David Matlackeafe6002015-05-11 20:40:35 -07001443 spin_unlock_irqrestore(&done_cmdq->lock, flags);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001444}
1445
Lior Dotane9eff9d2008-10-04 07:10:28 +03001446static struct slic_hostcmd *slic_cmdq_getfree(struct adapter *adapter)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001447{
Lior Dotane9eff9d2008-10-04 07:10:28 +03001448 struct slic_cmdqueue *cmdq = &adapter->cmdq_free;
1449 struct slic_hostcmd *cmd = NULL;
David Matlackeafe6002015-05-11 20:40:35 -07001450 unsigned long flags;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001451
1452lock_and_retry:
David Matlackeafe6002015-05-11 20:40:35 -07001453 spin_lock_irqsave(&cmdq->lock, flags);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001454retry:
1455 cmd = cmdq->head;
1456 if (cmd) {
1457 cmdq->head = cmd->next;
1458 cmdq->count--;
David Matlackeafe6002015-05-11 20:40:35 -07001459 spin_unlock_irqrestore(&cmdq->lock, flags);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001460 } else {
1461 slic_cmdq_getdone(adapter);
1462 cmd = cmdq->head;
1463 if (cmd) {
1464 goto retry;
1465 } else {
Lior Dotane9eff9d2008-10-04 07:10:28 +03001466 u32 *pageaddr;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001467
David Matlackeafe6002015-05-11 20:40:35 -07001468 spin_unlock_irqrestore(&cmdq->lock, flags);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001469 pageaddr = slic_cmdqmem_addpage(adapter);
1470 if (pageaddr) {
1471 slic_cmdq_addcmdpage(adapter, pageaddr);
1472 goto lock_and_retry;
1473 }
1474 }
1475 }
1476 return cmd;
1477}
1478
Lior Dotane9eff9d2008-10-04 07:10:28 +03001479static void slic_cmdq_putdone_irq(struct adapter *adapter,
1480 struct slic_hostcmd *cmd)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001481{
Lior Dotane9eff9d2008-10-04 07:10:28 +03001482 struct slic_cmdqueue *cmdq = &adapter->cmdq_done;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001483
David Matlackeafe6002015-05-11 20:40:35 -07001484 spin_lock(&cmdq->lock);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001485 cmd->busy = 0;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001486 cmd->next = cmdq->head;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001487 cmdq->head = cmd;
1488 cmdq->count++;
1489 if ((adapter->xmitq_full) && (cmdq->count > 10))
1490 netif_wake_queue(adapter->netdev);
David Matlackeafe6002015-05-11 20:40:35 -07001491 spin_unlock(&cmdq->lock);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001492}
1493
Lior Dotane9eff9d2008-10-04 07:10:28 +03001494static int slic_rcvqueue_fill(struct adapter *adapter)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001495{
Lior Dotane9eff9d2008-10-04 07:10:28 +03001496 void *paddr;
1497 u32 paddrl;
1498 u32 paddrh;
1499 struct slic_rcvqueue *rcvq = &adapter->rcvqueue;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001500 int i = 0;
Greg Kroah-Hartman4bee4f62009-02-26 15:32:42 -08001501 struct device *dev = &adapter->netdev->dev;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001502
1503 while (i < SLIC_RCVQ_FILLENTRIES) {
Lior Dotane9eff9d2008-10-04 07:10:28 +03001504 struct slic_rcvbuf *rcvbuf;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001505 struct sk_buff *skb;
1506#ifdef KLUDGE_FOR_4GB_BOUNDARY
1507retry_rcvqfill:
1508#endif
1509 skb = alloc_skb(SLIC_RCVQ_RCVBUFSIZE, GFP_ATOMIC);
1510 if (skb) {
Joe Perches01d0a9b2013-02-26 16:33:11 -08001511 paddr = (void *)(unsigned long)
1512 pci_map_single(adapter->pcidev,
1513 skb->data,
1514 SLIC_RCVQ_RCVBUFSIZE,
1515 PCI_DMA_FROMDEVICE);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001516 paddrl = SLIC_GET_ADDR_LOW(paddr);
1517 paddrh = SLIC_GET_ADDR_HIGH(paddr);
1518
1519 skb->len = SLIC_RCVBUF_HEADSIZE;
Lior Dotane9eff9d2008-10-04 07:10:28 +03001520 rcvbuf = (struct slic_rcvbuf *)skb->head;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001521 rcvbuf->status = 0;
1522 skb->next = NULL;
1523#ifdef KLUDGE_FOR_4GB_BOUNDARY
1524 if (paddrl == 0) {
Greg Kroah-Hartman4bee4f62009-02-26 15:32:42 -08001525 dev_err(dev, "%s: LOW 32bits PHYSICAL ADDRESS == 0\n",
1526 __func__);
1527 dev_err(dev, "skb[%p] PROBLEM\n", skb);
Sean Cleator17d2c642014-12-02 23:45:00 +00001528 dev_err(dev, " skbdata[%p]\n",
1529 skb->data);
Greg Kroah-Hartman4bee4f62009-02-26 15:32:42 -08001530 dev_err(dev, " skblen[%x]\n", skb->len);
1531 dev_err(dev, " paddr[%p]\n", paddr);
1532 dev_err(dev, " paddrl[%x]\n", paddrl);
1533 dev_err(dev, " paddrh[%x]\n", paddrh);
Sean Cleator17d2c642014-12-02 23:45:00 +00001534 dev_err(dev, " rcvq->head[%p]\n",
1535 rcvq->head);
1536 dev_err(dev, " rcvq->tail[%p]\n",
1537 rcvq->tail);
1538 dev_err(dev, " rcvq->count[%x]\n",
1539 rcvq->count);
Greg Kroah-Hartman4bee4f62009-02-26 15:32:42 -08001540 dev_err(dev, "SKIP THIS SKB!!!!!!!!\n");
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001541 goto retry_rcvqfill;
1542 }
1543#else
1544 if (paddrl == 0) {
Greg Kroah-Hartman4bee4f62009-02-26 15:32:42 -08001545 dev_err(dev, "%s: LOW 32bits PHYSICAL ADDRESS == 0\n",
1546 __func__);
1547 dev_err(dev, "skb[%p] PROBLEM\n", skb);
Sean Cleator17d2c642014-12-02 23:45:00 +00001548 dev_err(dev, " skbdata[%p]\n",
1549 skb->data);
Greg Kroah-Hartman4bee4f62009-02-26 15:32:42 -08001550 dev_err(dev, " skblen[%x]\n", skb->len);
1551 dev_err(dev, " paddr[%p]\n", paddr);
1552 dev_err(dev, " paddrl[%x]\n", paddrl);
1553 dev_err(dev, " paddrh[%x]\n", paddrh);
Sean Cleator17d2c642014-12-02 23:45:00 +00001554 dev_err(dev, " rcvq->head[%p]\n",
1555 rcvq->head);
1556 dev_err(dev, " rcvq->tail[%p]\n",
1557 rcvq->tail);
1558 dev_err(dev, " rcvq->count[%x]\n",
1559 rcvq->count);
Greg Kroah-Hartman4bee4f62009-02-26 15:32:42 -08001560 dev_err(dev, "GIVE TO CARD ANYWAY\n");
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001561 }
1562#endif
1563 if (paddrh == 0) {
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -08001564 slic_reg32_write(&adapter->slic_regs->slic_hbar,
1565 (u32)paddrl, DONT_FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001566 } else {
Greg Kroah-Hartman28980a32009-02-25 17:43:28 -08001567 slic_reg64_write(adapter,
1568 &adapter->slic_regs->slic_hbar64,
1569 paddrl,
1570 &adapter->slic_regs->slic_addr_upper,
1571 paddrh, DONT_FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001572 }
1573 if (rcvq->head)
1574 rcvq->tail->next = skb;
1575 else
1576 rcvq->head = skb;
1577 rcvq->tail = skb;
1578 rcvq->count++;
1579 i++;
1580 } else {
Greg Kroah-Hartman4bee4f62009-02-26 15:32:42 -08001581 dev_err(&adapter->netdev->dev,
1582 "slic_rcvqueue_fill could only get [%d] skbuffs\n",
1583 i);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001584 break;
1585 }
1586 }
1587 return i;
1588}
1589
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001590static void slic_rcvqueue_free(struct adapter *adapter)
1591{
1592 struct slic_rcvqueue *rcvq = &adapter->rcvqueue;
1593 struct sk_buff *skb;
1594
1595 while (rcvq->head) {
1596 skb = rcvq->head;
1597 rcvq->head = rcvq->head->next;
1598 dev_kfree_skb(skb);
1599 }
1600 rcvq->tail = NULL;
1601 rcvq->head = NULL;
1602 rcvq->count = 0;
1603}
1604
1605static int slic_rcvqueue_init(struct adapter *adapter)
1606{
1607 int i, count;
1608 struct slic_rcvqueue *rcvq = &adapter->rcvqueue;
1609
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001610 rcvq->tail = NULL;
1611 rcvq->head = NULL;
1612 rcvq->size = SLIC_RCVQ_ENTRIES;
1613 rcvq->errors = 0;
1614 rcvq->count = 0;
Tina Johnsondb9c9302014-10-25 23:13:41 +05301615 i = SLIC_RCVQ_ENTRIES / SLIC_RCVQ_FILLENTRIES;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001616 count = 0;
1617 while (i) {
1618 count += slic_rcvqueue_fill(adapter);
1619 i--;
1620 }
1621 if (rcvq->count < SLIC_RCVQ_MINENTRIES) {
1622 slic_rcvqueue_free(adapter);
1623 return -ENOMEM;
1624 }
1625 return 0;
1626}
1627
1628static struct sk_buff *slic_rcvqueue_getnext(struct adapter *adapter)
1629{
1630 struct slic_rcvqueue *rcvq = &adapter->rcvqueue;
1631 struct sk_buff *skb;
1632 struct slic_rcvbuf *rcvbuf;
1633 int count;
1634
1635 if (rcvq->count) {
1636 skb = rcvq->head;
1637 rcvbuf = (struct slic_rcvbuf *)skb->head;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001638
1639 if (rcvbuf->status & IRHDDR_SVALID) {
1640 rcvq->head = rcvq->head->next;
1641 skb->next = NULL;
1642 rcvq->count--;
1643 } else {
1644 skb = NULL;
1645 }
1646 } else {
1647 dev_err(&adapter->netdev->dev,
1648 "RcvQ Empty!! rcvq[%p] count[%x]\n", rcvq, rcvq->count);
1649 skb = NULL;
1650 }
1651 while (rcvq->count < SLIC_RCVQ_FILLTHRESH) {
1652 count = slic_rcvqueue_fill(adapter);
1653 if (!count)
1654 break;
1655 }
1656 if (skb)
1657 rcvq->errors = 0;
1658 return skb;
1659}
1660
Lior Dotane9eff9d2008-10-04 07:10:28 +03001661static u32 slic_rcvqueue_reinsert(struct adapter *adapter, struct sk_buff *skb)
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001662{
Lior Dotane9eff9d2008-10-04 07:10:28 +03001663 struct slic_rcvqueue *rcvq = &adapter->rcvqueue;
1664 void *paddr;
1665 u32 paddrl;
1666 u32 paddrh;
1667 struct slic_rcvbuf *rcvbuf = (struct slic_rcvbuf *)skb->head;
Greg Kroah-Hartman4bee4f62009-02-26 15:32:42 -08001668 struct device *dev;
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001669
Joe Perches01d0a9b2013-02-26 16:33:11 -08001670 paddr = (void *)(unsigned long)
1671 pci_map_single(adapter->pcidev, skb->head,
1672 SLIC_RCVQ_RCVBUFSIZE, PCI_DMA_FROMDEVICE);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001673 rcvbuf->status = 0;
1674 skb->next = NULL;
1675
1676 paddrl = SLIC_GET_ADDR_LOW(paddr);
1677 paddrh = SLIC_GET_ADDR_HIGH(paddr);
1678
1679 if (paddrl == 0) {
Greg Kroah-Hartman4bee4f62009-02-26 15:32:42 -08001680 dev = &adapter->netdev->dev;
1681 dev_err(dev, "%s: LOW 32bits PHYSICAL ADDRESS == 0\n",
1682 __func__);
1683 dev_err(dev, "skb[%p] PROBLEM\n", skb);
1684 dev_err(dev, " skbdata[%p]\n", skb->data);
1685 dev_err(dev, " skblen[%x]\n", skb->len);
1686 dev_err(dev, " paddr[%p]\n", paddr);
1687 dev_err(dev, " paddrl[%x]\n", paddrl);
1688 dev_err(dev, " paddrh[%x]\n", paddrh);
1689 dev_err(dev, " rcvq->head[%p]\n", rcvq->head);
1690 dev_err(dev, " rcvq->tail[%p]\n", rcvq->tail);
1691 dev_err(dev, " rcvq->count[%x]\n", rcvq->count);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001692 }
1693 if (paddrh == 0) {
Greg Kroah-Hartman62f691a2009-02-25 18:10:25 -08001694 slic_reg32_write(&adapter->slic_regs->slic_hbar, (u32)paddrl,
1695 DONT_FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001696 } else {
Greg Kroah-Hartman28980a32009-02-25 17:43:28 -08001697 slic_reg64_write(adapter, &adapter->slic_regs->slic_hbar64,
1698 paddrl, &adapter->slic_regs->slic_addr_upper,
1699 paddrh, DONT_FLUSH);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07001700 }
1701 if (rcvq->head)
1702 rcvq->tail->next = skb;
1703 else
1704 rcvq->head = skb;
1705 rcvq->tail = skb;
1706 rcvq->count++;
1707 return rcvq->count;
1708}
1709
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001710/*
1711 * slic_link_event_handler -
1712 *
1713 * Initiate a link configuration sequence. The link configuration begins
1714 * by issuing a READ_LINK_STATUS command to the Utility Processor on the
1715 * SLIC. Since the command finishes asynchronously, the slic_upr_comlete
1716 * routine will follow it up witha UP configuration write command, which
1717 * will also complete asynchronously.
1718 *
1719 */
Sudip Mukherjee78affe62015-09-17 22:14:32 +05301720static int slic_link_event_handler(struct adapter *adapter)
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001721{
1722 int status;
1723 struct slic_shmem *pshmem;
1724
1725 if (adapter->state != ADAPT_UP) {
1726 /* Adapter is not operational. Ignore. */
Sudip Mukherjee78affe62015-09-17 22:14:32 +05301727 return -ENODEV;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001728 }
1729
Joe Perches01d0a9b2013-02-26 16:33:11 -08001730 pshmem = (struct slic_shmem *)(unsigned long)adapter->phys_shmem;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001731
Denis Kirjanov1033f1f2010-08-04 19:24:08 +00001732#if BITS_PER_LONG == 64
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001733 status = slic_upr_request(adapter,
1734 SLIC_UPR_RLSR,
1735 SLIC_GET_ADDR_LOW(&pshmem->linkstatus),
1736 SLIC_GET_ADDR_HIGH(&pshmem->linkstatus),
1737 0, 0);
Denis Kirjanov1033f1f2010-08-04 19:24:08 +00001738#else
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001739 status = slic_upr_request(adapter, SLIC_UPR_RLSR,
1740 (u32) &pshmem->linkstatus, /* no 4GB wrap guaranteed */
1741 0, 0, 0);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001742#endif
Sudip Mukherjee78affe62015-09-17 22:14:32 +05301743 return status;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001744}
1745
1746static void slic_init_cleanup(struct adapter *adapter)
1747{
1748 if (adapter->intrregistered) {
1749 adapter->intrregistered = 0;
1750 free_irq(adapter->netdev->irq, adapter->netdev);
1751
1752 }
1753 if (adapter->pshmem) {
1754 pci_free_consistent(adapter->pcidev,
1755 sizeof(struct slic_shmem),
1756 adapter->pshmem, adapter->phys_shmem);
1757 adapter->pshmem = NULL;
Joe Perches01d0a9b2013-02-26 16:33:11 -08001758 adapter->phys_shmem = (dma_addr_t)(unsigned long)NULL;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001759 }
1760
1761 if (adapter->pingtimerset) {
1762 adapter->pingtimerset = 0;
1763 del_timer(&adapter->pingtimer);
1764 }
1765
1766 slic_rspqueue_free(adapter);
1767 slic_cmdq_free(adapter);
1768 slic_rcvqueue_free(adapter);
1769}
1770
1771/*
1772 * Allocate a mcast_address structure to hold the multicast address.
1773 * Link it in.
1774 */
1775static int slic_mcast_add_list(struct adapter *adapter, char *address)
1776{
1777 struct mcast_address *mcaddr, *mlist;
1778
1779 /* Check to see if it already exists */
1780 mlist = adapter->mcastaddrs;
1781 while (mlist) {
Joe Perches83294192013-09-01 12:15:47 -07001782 if (ether_addr_equal(mlist->address, address))
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001783 return 0;
1784 mlist = mlist->next;
1785 }
1786
1787 /* Doesn't already exist. Allocate a structure to hold it */
1788 mcaddr = kmalloc(sizeof(struct mcast_address), GFP_ATOMIC);
1789 if (mcaddr == NULL)
1790 return 1;
1791
Dilek Uzulmezf999ac02014-10-07 02:50:28 +03001792 ether_addr_copy(mcaddr->address, address);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001793
1794 mcaddr->next = adapter->mcastaddrs;
1795 adapter->mcastaddrs = mcaddr;
1796
1797 return 0;
1798}
1799
1800static void slic_mcast_set_list(struct net_device *dev)
1801{
1802 struct adapter *adapter = netdev_priv(dev);
1803 int status = 0;
1804 char *addresses;
1805 struct netdev_hw_addr *ha;
1806
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001807 netdev_for_each_mc_addr(ha, dev) {
1808 addresses = (char *) &ha->addr;
1809 status = slic_mcast_add_list(adapter, addresses);
1810 if (status != 0)
1811 break;
1812 slic_mcast_set_bit(adapter, addresses);
1813 }
1814
1815 if (adapter->devflags_prev != dev->flags) {
1816 adapter->macopts = MAC_DIRECTED;
1817 if (dev->flags) {
1818 if (dev->flags & IFF_BROADCAST)
1819 adapter->macopts |= MAC_BCAST;
1820 if (dev->flags & IFF_PROMISC)
1821 adapter->macopts |= MAC_PROMISC;
1822 if (dev->flags & IFF_ALLMULTI)
1823 adapter->macopts |= MAC_ALLMCAST;
1824 if (dev->flags & IFF_MULTICAST)
1825 adapter->macopts |= MAC_MCAST;
1826 }
1827 adapter->devflags_prev = dev->flags;
1828 slic_config_set(adapter, true);
1829 } else {
1830 if (status == 0)
1831 slic_mcast_set_mask(adapter);
1832 }
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001833}
1834
1835#define XMIT_FAIL_LINK_STATE 1
1836#define XMIT_FAIL_ZERO_LENGTH 2
1837#define XMIT_FAIL_HOSTCMD_FAIL 3
1838
1839static void slic_xmit_build_request(struct adapter *adapter,
1840 struct slic_hostcmd *hcmd, struct sk_buff *skb)
1841{
1842 struct slic_host64_cmd *ihcmd;
1843 ulong phys_addr;
1844
1845 ihcmd = &hcmd->cmd64;
1846
Aya Mahfouz6e28c2a2015-03-04 08:19:50 +02001847 ihcmd->flags = adapter->port << IHFLG_IFSHFT;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001848 ihcmd->command = IHCMD_XMT_REQ;
1849 ihcmd->u.slic_buffers.totlen = skb->len;
1850 phys_addr = pci_map_single(adapter->pcidev, skb->data, skb->len,
1851 PCI_DMA_TODEVICE);
1852 ihcmd->u.slic_buffers.bufs[0].paddrl = SLIC_GET_ADDR_LOW(phys_addr);
1853 ihcmd->u.slic_buffers.bufs[0].paddrh = SLIC_GET_ADDR_HIGH(phys_addr);
1854 ihcmd->u.slic_buffers.bufs[0].length = skb->len;
Denis Kirjanov1033f1f2010-08-04 19:24:08 +00001855#if BITS_PER_LONG == 64
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001856 hcmd->cmdsize = (u32) ((((u64)&ihcmd->u.slic_buffers.bufs[1] -
1857 (u64) hcmd) + 31) >> 5);
Denis Kirjanov1033f1f2010-08-04 19:24:08 +00001858#else
Aya Mahfouza659b3e2015-03-04 07:34:52 +02001859 hcmd->cmdsize = (((u32)&ihcmd->u.slic_buffers.bufs[1] -
1860 (u32)hcmd) + 31) >> 5;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001861#endif
1862}
1863
1864static void slic_xmit_fail(struct adapter *adapter,
1865 struct sk_buff *skb,
1866 void *cmd, u32 skbtype, u32 status)
1867{
1868 if (adapter->xmitq_full)
1869 netif_stop_queue(adapter->netdev);
1870 if ((cmd == NULL) && (status <= XMIT_FAIL_HOSTCMD_FAIL)) {
1871 switch (status) {
1872 case XMIT_FAIL_LINK_STATE:
1873 dev_err(&adapter->netdev->dev,
Monam Agarwal5d5b44b2014-02-28 00:43:20 +05301874 "reject xmit skb[%p: %x] linkstate[%s] adapter[%s:%d] card[%s:%d]\n",
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001875 skb, skb->pkt_type,
1876 SLIC_LINKSTATE(adapter->linkstate),
1877 SLIC_ADAPTER_STATE(adapter->state),
1878 adapter->state,
1879 SLIC_CARD_STATE(adapter->card->state),
1880 adapter->card->state);
1881 break;
1882 case XMIT_FAIL_ZERO_LENGTH:
1883 dev_err(&adapter->netdev->dev,
1884 "xmit_start skb->len == 0 skb[%p] type[%x]\n",
1885 skb, skb->pkt_type);
1886 break;
1887 case XMIT_FAIL_HOSTCMD_FAIL:
1888 dev_err(&adapter->netdev->dev,
Sean Cleator17d2c642014-12-02 23:45:00 +00001889 "xmit_start skb[%p] type[%x] No host commands available\n",
1890 skb, skb->pkt_type);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001891 break;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001892 }
1893 }
1894 dev_kfree_skb(skb);
Denis Kirjanov9092de62010-07-30 13:26:06 +00001895 adapter->netdev->stats.tx_dropped++;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001896}
1897
1898static void slic_rcv_handle_error(struct adapter *adapter,
1899 struct slic_rcvbuf *rcvbuf)
1900{
1901 struct slic_hddr_wds *hdr = (struct slic_hddr_wds *)rcvbuf->data;
Denis Kirjanov9092de62010-07-30 13:26:06 +00001902 struct net_device *netdev = adapter->netdev;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001903
1904 if (adapter->devid != SLIC_1GB_DEVICE_ID) {
1905 if (hdr->frame_status14 & VRHSTAT_802OE)
1906 adapter->if_events.oflow802++;
1907 if (hdr->frame_status14 & VRHSTAT_TPOFLO)
1908 adapter->if_events.Tprtoflow++;
1909 if (hdr->frame_status_b14 & VRHSTATB_802UE)
1910 adapter->if_events.uflow802++;
1911 if (hdr->frame_status_b14 & VRHSTATB_RCVE) {
1912 adapter->if_events.rcvearly++;
Denis Kirjanov9092de62010-07-30 13:26:06 +00001913 netdev->stats.rx_fifo_errors++;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001914 }
1915 if (hdr->frame_status_b14 & VRHSTATB_BUFF) {
1916 adapter->if_events.Bufov++;
Denis Kirjanov9092de62010-07-30 13:26:06 +00001917 netdev->stats.rx_over_errors++;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001918 }
1919 if (hdr->frame_status_b14 & VRHSTATB_CARRE) {
1920 adapter->if_events.Carre++;
Denis Kirjanov9092de62010-07-30 13:26:06 +00001921 netdev->stats.tx_carrier_errors++;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001922 }
1923 if (hdr->frame_status_b14 & VRHSTATB_LONGE)
1924 adapter->if_events.Longe++;
1925 if (hdr->frame_status_b14 & VRHSTATB_PREA)
1926 adapter->if_events.Invp++;
1927 if (hdr->frame_status_b14 & VRHSTATB_CRC) {
1928 adapter->if_events.Crc++;
Denis Kirjanov9092de62010-07-30 13:26:06 +00001929 netdev->stats.rx_crc_errors++;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001930 }
1931 if (hdr->frame_status_b14 & VRHSTATB_DRBL)
1932 adapter->if_events.Drbl++;
1933 if (hdr->frame_status_b14 & VRHSTATB_CODE)
1934 adapter->if_events.Code++;
1935 if (hdr->frame_status_b14 & VRHSTATB_TPCSUM)
1936 adapter->if_events.TpCsum++;
1937 if (hdr->frame_status_b14 & VRHSTATB_TPHLEN)
1938 adapter->if_events.TpHlen++;
1939 if (hdr->frame_status_b14 & VRHSTATB_IPCSUM)
1940 adapter->if_events.IpCsum++;
1941 if (hdr->frame_status_b14 & VRHSTATB_IPLERR)
1942 adapter->if_events.IpLen++;
1943 if (hdr->frame_status_b14 & VRHSTATB_IPHERR)
1944 adapter->if_events.IpHlen++;
1945 } else {
1946 if (hdr->frame_statusGB & VGBSTAT_XPERR) {
1947 u32 xerr = hdr->frame_statusGB >> VGBSTAT_XERRSHFT;
1948
1949 if (xerr == VGBSTAT_XCSERR)
1950 adapter->if_events.TpCsum++;
1951 if (xerr == VGBSTAT_XUFLOW)
1952 adapter->if_events.Tprtoflow++;
1953 if (xerr == VGBSTAT_XHLEN)
1954 adapter->if_events.TpHlen++;
1955 }
1956 if (hdr->frame_statusGB & VGBSTAT_NETERR) {
1957 u32 nerr =
1958 (hdr->
1959 frame_statusGB >> VGBSTAT_NERRSHFT) &
1960 VGBSTAT_NERRMSK;
1961 if (nerr == VGBSTAT_NCSERR)
1962 adapter->if_events.IpCsum++;
1963 if (nerr == VGBSTAT_NUFLOW)
1964 adapter->if_events.IpLen++;
1965 if (nerr == VGBSTAT_NHLEN)
1966 adapter->if_events.IpHlen++;
1967 }
1968 if (hdr->frame_statusGB & VGBSTAT_LNKERR) {
1969 u32 lerr = hdr->frame_statusGB & VGBSTAT_LERRMSK;
1970
1971 if (lerr == VGBSTAT_LDEARLY)
1972 adapter->if_events.rcvearly++;
1973 if (lerr == VGBSTAT_LBOFLO)
1974 adapter->if_events.Bufov++;
1975 if (lerr == VGBSTAT_LCODERR)
1976 adapter->if_events.Code++;
1977 if (lerr == VGBSTAT_LDBLNBL)
1978 adapter->if_events.Drbl++;
1979 if (lerr == VGBSTAT_LCRCERR)
1980 adapter->if_events.Crc++;
1981 if (lerr == VGBSTAT_LOFLO)
1982 adapter->if_events.oflow802++;
1983 if (lerr == VGBSTAT_LUFLO)
1984 adapter->if_events.uflow802++;
1985 }
1986 }
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001987}
1988
1989#define TCP_OFFLOAD_FRAME_PUSHFLAG 0x10000000
1990#define M_FAST_PATH 0x0040
1991
1992static void slic_rcv_handler(struct adapter *adapter)
1993{
Denis Kirjanov9092de62010-07-30 13:26:06 +00001994 struct net_device *netdev = adapter->netdev;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00001995 struct sk_buff *skb;
1996 struct slic_rcvbuf *rcvbuf;
1997 u32 frames = 0;
1998
1999 while ((skb = slic_rcvqueue_getnext(adapter))) {
2000 u32 rx_bytes;
2001
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002002 rcvbuf = (struct slic_rcvbuf *)skb->head;
2003 adapter->card->events++;
2004 if (rcvbuf->status & IRHDDR_ERR) {
2005 adapter->rx_errors++;
2006 slic_rcv_handle_error(adapter, rcvbuf);
2007 slic_rcvqueue_reinsert(adapter, skb);
2008 continue;
2009 }
2010
2011 if (!slic_mac_filter(adapter, (struct ether_header *)
2012 rcvbuf->data)) {
2013 slic_rcvqueue_reinsert(adapter, skb);
2014 continue;
2015 }
2016 skb_pull(skb, SLIC_RCVBUF_HEADSIZE);
2017 rx_bytes = (rcvbuf->length & IRHDDR_FLEN_MSK);
2018 skb_put(skb, rx_bytes);
Denis Kirjanov9092de62010-07-30 13:26:06 +00002019 netdev->stats.rx_packets++;
2020 netdev->stats.rx_bytes += rx_bytes;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002021#if SLIC_OFFLOAD_IP_CHECKSUM
2022 skb->ip_summed = CHECKSUM_UNNECESSARY;
2023#endif
2024
2025 skb->dev = adapter->netdev;
2026 skb->protocol = eth_type_trans(skb, skb->dev);
2027 netif_rx(skb);
2028
2029 ++frames;
2030#if SLIC_INTERRUPT_PROCESS_LIMIT
2031 if (frames >= SLIC_RCVQ_MAX_PROCESS_ISR) {
2032 adapter->rcv_interrupt_yields++;
2033 break;
2034 }
2035#endif
2036 }
2037 adapter->max_isr_rcvs = max(adapter->max_isr_rcvs, frames);
2038}
2039
2040static void slic_xmit_complete(struct adapter *adapter)
2041{
2042 struct slic_hostcmd *hcmd;
2043 struct slic_rspbuf *rspbuf;
2044 u32 frames = 0;
2045 struct slic_handle_word slic_handle_word;
2046
2047 do {
2048 rspbuf = slic_rspqueue_getnext(adapter);
2049 if (!rspbuf)
2050 break;
2051 adapter->xmit_completes++;
2052 adapter->card->events++;
2053 /*
2054 Get the complete host command buffer
2055 */
2056 slic_handle_word.handle_token = rspbuf->hosthandle;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002057 hcmd =
2058 (struct slic_hostcmd *)
2059 adapter->slic_handles[slic_handle_word.handle_index].
2060 address;
2061/* hcmd = (struct slic_hostcmd *) rspbuf->hosthandle; */
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002062 if (hcmd->type == SLIC_CMD_DUMB) {
2063 if (hcmd->skb)
2064 dev_kfree_skb_irq(hcmd->skb);
2065 slic_cmdq_putdone_irq(adapter, hcmd);
2066 }
2067 rspbuf->status = 0;
2068 rspbuf->hosthandle = 0;
2069 frames++;
2070 } while (1);
2071 adapter->max_isr_xmits = max(adapter->max_isr_xmits, frames);
2072}
2073
Rashika Kheriaf66626e2013-10-19 13:17:10 +05302074static void slic_interrupt_card_up(u32 isr, struct adapter *adapter,
2075 struct net_device *dev)
2076{
2077 if (isr & ~ISR_IO) {
2078 if (isr & ISR_ERR) {
2079 adapter->error_interrupts++;
2080 if (isr & ISR_RMISS) {
2081 int count;
2082 int pre_count;
2083 int errors;
2084
2085 struct slic_rcvqueue *rcvq =
2086 &adapter->rcvqueue;
2087
2088 adapter->error_rmiss_interrupts++;
2089
2090 if (!rcvq->errors)
2091 rcv_count = rcvq->count;
2092 pre_count = rcvq->count;
2093 errors = rcvq->errors;
2094
2095 while (rcvq->count < SLIC_RCVQ_FILLTHRESH) {
2096 count = slic_rcvqueue_fill(adapter);
2097 if (!count)
2098 break;
2099 }
2100 } else if (isr & ISR_XDROP) {
2101 dev_err(&dev->dev,
Sean Cleator17d2c642014-12-02 23:45:00 +00002102 "isr & ISR_ERR [%x] ISR_XDROP\n",
2103 isr);
Rashika Kheriaf66626e2013-10-19 13:17:10 +05302104 } else {
2105 dev_err(&dev->dev,
2106 "isr & ISR_ERR [%x]\n",
2107 isr);
2108 }
2109 }
2110
2111 if (isr & ISR_LEVENT) {
2112 adapter->linkevent_interrupts++;
2113 slic_link_event_handler(adapter);
2114 }
2115
2116 if ((isr & ISR_UPC) || (isr & ISR_UPCERR) ||
2117 (isr & ISR_UPCBSY)) {
2118 adapter->upr_interrupts++;
2119 slic_upr_request_complete(adapter, isr);
2120 }
2121 }
2122
2123 if (isr & ISR_RCV) {
2124 adapter->rcv_interrupts++;
2125 slic_rcv_handler(adapter);
2126 }
2127
2128 if (isr & ISR_CMD) {
2129 adapter->xmit_interrupts++;
2130 slic_xmit_complete(adapter);
2131 }
2132}
2133
2134
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002135static irqreturn_t slic_interrupt(int irq, void *dev_id)
2136{
2137 struct net_device *dev = (struct net_device *)dev_id;
2138 struct adapter *adapter = netdev_priv(dev);
2139 u32 isr;
2140
2141 if ((adapter->pshmem) && (adapter->pshmem->isr)) {
2142 slic_reg32_write(&adapter->slic_regs->slic_icr,
2143 ICR_INT_MASK, FLUSH);
2144 isr = adapter->isrcopy = adapter->pshmem->isr;
2145 adapter->pshmem->isr = 0;
2146 adapter->num_isrs++;
2147 switch (adapter->card->state) {
2148 case CARD_UP:
Rashika Kheriaf66626e2013-10-19 13:17:10 +05302149 slic_interrupt_card_up(isr, adapter, dev);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002150 break;
2151
2152 case CARD_DOWN:
2153 if ((isr & ISR_UPC) ||
2154 (isr & ISR_UPCERR) || (isr & ISR_UPCBSY)) {
2155 adapter->upr_interrupts++;
2156 slic_upr_request_complete(adapter, isr);
2157 }
2158 break;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002159 }
2160
2161 adapter->isrcopy = 0;
2162 adapter->all_reg_writes += 2;
2163 adapter->isr_reg_writes++;
2164 slic_reg32_write(&adapter->slic_regs->slic_isr, 0, FLUSH);
2165 } else {
2166 adapter->false_interrupts++;
2167 }
2168 return IRQ_HANDLED;
2169}
2170
2171#define NORMAL_ETHFRAME 0
2172
2173static netdev_tx_t slic_xmit_start(struct sk_buff *skb, struct net_device *dev)
2174{
2175 struct sliccard *card;
2176 struct adapter *adapter = netdev_priv(dev);
2177 struct slic_hostcmd *hcmd = NULL;
2178 u32 status = 0;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002179 void *offloadcmd = NULL;
2180
2181 card = adapter->card;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002182 if ((adapter->linkstate != LINK_UP) ||
2183 (adapter->state != ADAPT_UP) || (card->state != CARD_UP)) {
2184 status = XMIT_FAIL_LINK_STATE;
2185 goto xmit_fail;
2186
2187 } else if (skb->len == 0) {
2188 status = XMIT_FAIL_ZERO_LENGTH;
2189 goto xmit_fail;
2190 }
2191
Peter Huewecbb09202013-02-19 05:18:49 +01002192 hcmd = slic_cmdq_getfree(adapter);
2193 if (!hcmd) {
2194 adapter->xmitq_full = 1;
2195 status = XMIT_FAIL_HOSTCMD_FAIL;
2196 goto xmit_fail;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002197 }
Peter Huewecbb09202013-02-19 05:18:49 +01002198 hcmd->skb = skb;
2199 hcmd->busy = 1;
2200 hcmd->type = SLIC_CMD_DUMB;
2201 slic_xmit_build_request(adapter, hcmd, skb);
Denis Kirjanov9092de62010-07-30 13:26:06 +00002202 dev->stats.tx_packets++;
2203 dev->stats.tx_bytes += skb->len;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002204
2205#ifdef DEBUG_DUMP
2206 if (adapter->kill_card) {
2207 struct slic_host64_cmd ihcmd;
2208
2209 ihcmd = &hcmd->cmd64;
2210
2211 ihcmd->flags |= 0x40;
2212 adapter->kill_card = 0; /* only do this once */
2213 }
2214#endif
2215 if (hcmd->paddrh == 0) {
2216 slic_reg32_write(&adapter->slic_regs->slic_cbar,
2217 (hcmd->paddrl | hcmd->cmdsize), DONT_FLUSH);
2218 } else {
2219 slic_reg64_write(adapter, &adapter->slic_regs->slic_cbar64,
2220 (hcmd->paddrl | hcmd->cmdsize),
2221 &adapter->slic_regs->slic_addr_upper,
2222 hcmd->paddrh, DONT_FLUSH);
2223 }
2224xmit_done:
2225 return NETDEV_TX_OK;
2226xmit_fail:
Peter Huewecbb09202013-02-19 05:18:49 +01002227 slic_xmit_fail(adapter, skb, offloadcmd, NORMAL_ETHFRAME, status);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002228 goto xmit_done;
2229}
2230
2231
2232static void slic_adapter_freeresources(struct adapter *adapter)
2233{
2234 slic_init_cleanup(adapter);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002235 adapter->error_interrupts = 0;
2236 adapter->rcv_interrupts = 0;
2237 adapter->xmit_interrupts = 0;
2238 adapter->linkevent_interrupts = 0;
2239 adapter->upr_interrupts = 0;
2240 adapter->num_isrs = 0;
2241 adapter->xmit_completes = 0;
2242 adapter->rcv_broadcasts = 0;
2243 adapter->rcv_multicasts = 0;
2244 adapter->rcv_unicasts = 0;
2245}
2246
David Matlackeafe6002015-05-11 20:40:35 -07002247static int slic_adapter_allocresources(struct adapter *adapter,
2248 unsigned long *flags)
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002249{
2250 if (!adapter->intrregistered) {
2251 int retval;
2252
David Matlackeafe6002015-05-11 20:40:35 -07002253 spin_unlock_irqrestore(&slic_global.driver_lock, *flags);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002254
2255 retval = request_irq(adapter->netdev->irq,
2256 &slic_interrupt,
2257 IRQF_SHARED,
2258 adapter->netdev->name, adapter->netdev);
2259
David Matlackeafe6002015-05-11 20:40:35 -07002260 spin_lock_irqsave(&slic_global.driver_lock, *flags);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002261
2262 if (retval) {
2263 dev_err(&adapter->netdev->dev,
2264 "request_irq (%s) FAILED [%x]\n",
2265 adapter->netdev->name, retval);
2266 return retval;
2267 }
2268 adapter->intrregistered = 1;
2269 }
2270 return 0;
2271}
2272
2273/*
2274 * slic_if_init
2275 *
2276 * Perform initialization of our slic interface.
2277 *
2278 */
David Matlackeafe6002015-05-11 20:40:35 -07002279static int slic_if_init(struct adapter *adapter, unsigned long *flags)
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002280{
2281 struct sliccard *card = adapter->card;
2282 struct net_device *dev = adapter->netdev;
2283 __iomem struct slic_regs *slic_regs = adapter->slic_regs;
2284 struct slic_shmem *pshmem;
2285 int rc;
2286
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002287 /* adapter should be down at this point */
2288 if (adapter->state != ADAPT_DOWN) {
2289 dev_err(&dev->dev, "%s: adapter->state != ADAPT_DOWN\n",
2290 __func__);
2291 rc = -EIO;
2292 goto err;
2293 }
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002294
2295 adapter->devflags_prev = dev->flags;
2296 adapter->macopts = MAC_DIRECTED;
2297 if (dev->flags) {
2298 if (dev->flags & IFF_BROADCAST)
2299 adapter->macopts |= MAC_BCAST;
2300 if (dev->flags & IFF_PROMISC)
2301 adapter->macopts |= MAC_PROMISC;
2302 if (dev->flags & IFF_ALLMULTI)
2303 adapter->macopts |= MAC_ALLMCAST;
2304 if (dev->flags & IFF_MULTICAST)
2305 adapter->macopts |= MAC_MCAST;
2306 }
David Matlackeafe6002015-05-11 20:40:35 -07002307 rc = slic_adapter_allocresources(adapter, flags);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002308 if (rc) {
Haneen Mohammedeb856202015-03-06 22:05:05 +03002309 dev_err(&dev->dev, "slic_adapter_allocresources FAILED %x\n",
2310 rc);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002311 slic_adapter_freeresources(adapter);
2312 goto err;
2313 }
2314
2315 if (!adapter->queues_initialized) {
Cruz Julian Bishop83682cd2013-01-14 12:29:08 +10002316 rc = slic_rspqueue_init(adapter);
2317 if (rc)
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002318 goto err;
Cruz Julian Bishop83682cd2013-01-14 12:29:08 +10002319 rc = slic_cmdq_init(adapter);
2320 if (rc)
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002321 goto err;
Cruz Julian Bishop83682cd2013-01-14 12:29:08 +10002322 rc = slic_rcvqueue_init(adapter);
2323 if (rc)
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002324 goto err;
2325 adapter->queues_initialized = 1;
2326 }
2327
2328 slic_reg32_write(&slic_regs->slic_icr, ICR_INT_OFF, FLUSH);
2329 mdelay(1);
2330
2331 if (!adapter->isp_initialized) {
David Matlackeafe6002015-05-11 20:40:35 -07002332 unsigned long flags;
Ciprian Manea740d6c12015-07-26 22:26:18 +01002333
Joe Perches01d0a9b2013-02-26 16:33:11 -08002334 pshmem = (struct slic_shmem *)(unsigned long)
2335 adapter->phys_shmem;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002336
David Matlackeafe6002015-05-11 20:40:35 -07002337 spin_lock_irqsave(&adapter->bit64reglock, flags);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002338
Denis Kirjanov1033f1f2010-08-04 19:24:08 +00002339#if BITS_PER_LONG == 64
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002340 slic_reg32_write(&slic_regs->slic_addr_upper,
2341 SLIC_GET_ADDR_HIGH(&pshmem->isr), DONT_FLUSH);
2342 slic_reg32_write(&slic_regs->slic_isp,
2343 SLIC_GET_ADDR_LOW(&pshmem->isr), FLUSH);
Denis Kirjanov1033f1f2010-08-04 19:24:08 +00002344#else
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002345 slic_reg32_write(&slic_regs->slic_addr_upper, 0, DONT_FLUSH);
Sean Cleator17d2c642014-12-02 23:45:00 +00002346 slic_reg32_write(&slic_regs->slic_isp, (u32)&pshmem->isr,
2347 FLUSH);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002348#endif
David Matlackeafe6002015-05-11 20:40:35 -07002349 spin_unlock_irqrestore(&adapter->bit64reglock, flags);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002350 adapter->isp_initialized = 1;
2351 }
2352
2353 adapter->state = ADAPT_UP;
2354 if (!card->loadtimerset) {
Aya Mahfouz7d2b3cf2015-02-19 08:00:56 +02002355 setup_timer(&card->loadtimer, &slic_timer_load_check,
2356 (ulong)card);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002357 card->loadtimer.expires =
2358 jiffies + (SLIC_LOADTIMER_PERIOD * HZ);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002359 add_timer(&card->loadtimer);
2360
2361 card->loadtimerset = 1;
2362 }
2363
2364 if (!adapter->pingtimerset) {
Aya Mahfouz7d2b3cf2015-02-19 08:00:56 +02002365 setup_timer(&adapter->pingtimer, &slic_timer_ping, (ulong)dev);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002366 adapter->pingtimer.expires =
2367 jiffies + (PING_TIMER_INTERVAL * HZ);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002368 add_timer(&adapter->pingtimer);
2369 adapter->pingtimerset = 1;
2370 adapter->card->pingstatus = ISR_PINGMASK;
2371 }
2372
2373 /*
2374 * clear any pending events, then enable interrupts
2375 */
2376 adapter->isrcopy = 0;
2377 adapter->pshmem->isr = 0;
2378 slic_reg32_write(&slic_regs->slic_isr, 0, FLUSH);
2379 slic_reg32_write(&slic_regs->slic_icr, ICR_INT_ON, FLUSH);
2380
2381 slic_link_config(adapter, LINK_AUTOSPEED, LINK_AUTOD);
2382 slic_link_event_handler(adapter);
2383
2384err:
2385 return rc;
2386}
2387
2388static int slic_entry_open(struct net_device *dev)
2389{
2390 struct adapter *adapter = netdev_priv(dev);
2391 struct sliccard *card = adapter->card;
David Matlackeafe6002015-05-11 20:40:35 -07002392 unsigned long flags;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002393 int status;
2394
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002395 netif_stop_queue(adapter->netdev);
2396
David Matlackeafe6002015-05-11 20:40:35 -07002397 spin_lock_irqsave(&slic_global.driver_lock, flags);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002398 if (!adapter->activated) {
2399 card->adapters_activated++;
2400 slic_global.num_slic_ports_active++;
2401 adapter->activated = 1;
2402 }
David Matlackeafe6002015-05-11 20:40:35 -07002403 status = slic_if_init(adapter, &flags);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002404
2405 if (status != 0) {
2406 if (adapter->activated) {
2407 card->adapters_activated--;
2408 slic_global.num_slic_ports_active--;
2409 adapter->activated = 0;
2410 }
Devendra Naga71329962012-09-05 15:33:48 +05302411 goto spin_unlock;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002412 }
2413 if (!card->master)
2414 card->master = adapter;
2415
Devendra Naga71329962012-09-05 15:33:48 +05302416spin_unlock:
David Matlackeafe6002015-05-11 20:40:35 -07002417 spin_unlock_irqrestore(&slic_global.driver_lock, flags);
Devendra Naga71329962012-09-05 15:33:48 +05302418 return status;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002419}
2420
2421static void slic_card_cleanup(struct sliccard *card)
2422{
2423 if (card->loadtimerset) {
2424 card->loadtimerset = 0;
Kirill Tkhai161737a62014-02-10 22:36:23 +04002425 del_timer_sync(&card->loadtimer);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002426 }
2427
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002428 kfree(card);
2429}
2430
Bill Pembertonecb4f382012-11-19 13:26:48 -05002431static void slic_entry_remove(struct pci_dev *pcidev)
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002432{
2433 struct net_device *dev = pci_get_drvdata(pcidev);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002434 struct adapter *adapter = netdev_priv(dev);
2435 struct sliccard *card;
2436 struct mcast_address *mcaddr, *mlist;
2437
David Matlackdedabbb2014-05-05 21:02:37 -07002438 unregister_netdev(dev);
2439
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002440 slic_adapter_freeresources(adapter);
2441 slic_unmap_mmio_space(adapter);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002442
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002443 /* free multicast addresses */
2444 mlist = adapter->mcastaddrs;
2445 while (mlist) {
2446 mcaddr = mlist;
2447 mlist = mlist->next;
2448 kfree(mcaddr);
2449 }
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002450 card = adapter->card;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002451 card->adapters_allocated--;
2452 adapter->allocated = 0;
2453 if (!card->adapters_allocated) {
2454 struct sliccard *curr_card = slic_global.slic_card;
Quentin Lambert0d0e9d92014-08-04 21:10:24 +02002455
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002456 if (curr_card == card) {
2457 slic_global.slic_card = card->next;
2458 } else {
2459 while (curr_card->next != card)
2460 curr_card = curr_card->next;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002461 curr_card->next = card->next;
2462 }
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002463 slic_global.num_slic_cards--;
2464 slic_card_cleanup(card);
2465 }
Vasiliy Kulikov20caa142010-09-28 21:08:08 +04002466 free_netdev(dev);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002467 pci_release_regions(pcidev);
Devendra Nagad99b5ac2012-07-11 11:54:15 +05452468 pci_disable_device(pcidev);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002469}
2470
2471static int slic_entry_halt(struct net_device *dev)
2472{
2473 struct adapter *adapter = netdev_priv(dev);
2474 struct sliccard *card = adapter->card;
2475 __iomem struct slic_regs *slic_regs = adapter->slic_regs;
David Matlackeafe6002015-05-11 20:40:35 -07002476 unsigned long flags;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002477
David Matlackeafe6002015-05-11 20:40:35 -07002478 spin_lock_irqsave(&slic_global.driver_lock, flags);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002479 netif_stop_queue(adapter->netdev);
2480 adapter->state = ADAPT_DOWN;
2481 adapter->linkstate = LINK_DOWN;
2482 adapter->upr_list = NULL;
2483 adapter->upr_busy = 0;
2484 adapter->devflags_prev = 0;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002485 slic_reg32_write(&slic_regs->slic_icr, ICR_INT_OFF, FLUSH);
2486 adapter->all_reg_writes++;
2487 adapter->icr_reg_writes++;
2488 slic_config_clear(adapter);
2489 if (adapter->activated) {
2490 card->adapters_activated--;
2491 slic_global.num_slic_ports_active--;
2492 adapter->activated = 0;
2493 }
2494#ifdef AUTOMATIC_RESET
2495 slic_reg32_write(&slic_regs->slic_reset_iface, 0, FLUSH);
2496#endif
2497 /*
2498 * Reset the adapter's cmd queues
2499 */
2500 slic_cmdq_reset(adapter);
2501
2502#ifdef AUTOMATIC_RESET
2503 if (!card->adapters_activated)
2504 slic_card_init(card, adapter);
2505#endif
2506
David Matlackeafe6002015-05-11 20:40:35 -07002507 spin_unlock_irqrestore(&slic_global.driver_lock, flags);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002508 return 0;
2509}
2510
2511static struct net_device_stats *slic_get_stats(struct net_device *dev)
2512{
2513 struct adapter *adapter = netdev_priv(dev);
2514
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002515 dev->stats.collisions = adapter->slic_stats.iface.xmit_collisions;
2516 dev->stats.rx_errors = adapter->slic_stats.iface.rcv_errors;
2517 dev->stats.tx_errors = adapter->slic_stats.iface.xmt_errors;
2518 dev->stats.rx_missed_errors = adapter->slic_stats.iface.rcv_discards;
2519 dev->stats.tx_heartbeat_errors = 0;
2520 dev->stats.tx_aborted_errors = 0;
2521 dev->stats.tx_window_errors = 0;
2522 dev->stats.tx_fifo_errors = 0;
2523 dev->stats.rx_frame_errors = 0;
2524 dev->stats.rx_length_errors = 0;
2525
2526 return &dev->stats;
2527}
2528
2529static int slic_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
2530{
2531 struct adapter *adapter = netdev_priv(dev);
2532 struct ethtool_cmd edata;
2533 struct ethtool_cmd ecmd;
2534 u32 data[7];
2535 u32 intagg;
2536
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002537 switch (cmd) {
2538 case SIOCSLICSETINTAGG:
2539 if (copy_from_user(data, rq->ifr_data, 28))
2540 return -EFAULT;
2541 intagg = data[0];
Haneen Mohammedeb856202015-03-06 22:05:05 +03002542 dev_err(&dev->dev, "set interrupt aggregation to %d\n",
2543 intagg);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002544 slic_intagg_set(adapter, intagg);
2545 return 0;
2546
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002547 case SIOCETHTOOL:
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002548 if (copy_from_user(&ecmd, rq->ifr_data, sizeof(ecmd)))
2549 return -EFAULT;
2550
2551 if (ecmd.cmd == ETHTOOL_GSET) {
Dan Carpenter986d7582013-04-04 09:29:42 +03002552 memset(&edata, 0, sizeof(edata));
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002553 edata.supported = (SUPPORTED_10baseT_Half |
2554 SUPPORTED_10baseT_Full |
2555 SUPPORTED_100baseT_Half |
2556 SUPPORTED_100baseT_Full |
2557 SUPPORTED_Autoneg | SUPPORTED_MII);
2558 edata.port = PORT_MII;
2559 edata.transceiver = XCVR_INTERNAL;
2560 edata.phy_address = 0;
2561 if (adapter->linkspeed == LINK_100MB)
2562 edata.speed = SPEED_100;
2563 else if (adapter->linkspeed == LINK_10MB)
2564 edata.speed = SPEED_10;
2565 else
2566 edata.speed = 0;
2567
2568 if (adapter->linkduplex == LINK_FULLD)
2569 edata.duplex = DUPLEX_FULL;
2570 else
2571 edata.duplex = DUPLEX_HALF;
2572
2573 edata.autoneg = AUTONEG_ENABLE;
2574 edata.maxtxpkt = 1;
2575 edata.maxrxpkt = 1;
2576 if (copy_to_user(rq->ifr_data, &edata, sizeof(edata)))
2577 return -EFAULT;
2578
2579 } else if (ecmd.cmd == ETHTOOL_SSET) {
2580 if (!capable(CAP_NET_ADMIN))
2581 return -EPERM;
2582
2583 if (adapter->linkspeed == LINK_100MB)
2584 edata.speed = SPEED_100;
2585 else if (adapter->linkspeed == LINK_10MB)
2586 edata.speed = SPEED_10;
2587 else
2588 edata.speed = 0;
2589
2590 if (adapter->linkduplex == LINK_FULLD)
2591 edata.duplex = DUPLEX_FULL;
2592 else
2593 edata.duplex = DUPLEX_HALF;
2594
2595 edata.autoneg = AUTONEG_ENABLE;
2596 edata.maxtxpkt = 1;
2597 edata.maxrxpkt = 1;
2598 if ((ecmd.speed != edata.speed) ||
2599 (ecmd.duplex != edata.duplex)) {
2600 u32 speed;
2601 u32 duplex;
2602
2603 if (ecmd.speed == SPEED_10)
2604 speed = 0;
2605 else
2606 speed = PCR_SPEED_100;
2607 if (ecmd.duplex == DUPLEX_FULL)
2608 duplex = PCR_DUPLEX_FULL;
2609 else
2610 duplex = 0;
2611 slic_link_config(adapter, speed, duplex);
2612 slic_link_event_handler(adapter);
2613 }
2614 }
2615 return 0;
2616 default:
2617 return -EOPNOTSUPP;
2618 }
2619}
2620
2621static void slic_config_pci(struct pci_dev *pcidev)
2622{
2623 u16 pci_command;
2624 u16 new_command;
2625
2626 pci_read_config_word(pcidev, PCI_COMMAND, &pci_command);
2627
2628 new_command = pci_command | PCI_COMMAND_MASTER
2629 | PCI_COMMAND_MEMORY
2630 | PCI_COMMAND_INVALIDATE
2631 | PCI_COMMAND_PARITY | PCI_COMMAND_SERR | PCI_COMMAND_FAST_BACK;
2632 if (pci_command != new_command)
2633 pci_write_config_word(pcidev, PCI_COMMAND, new_command);
2634}
2635
2636static int slic_card_init(struct sliccard *card, struct adapter *adapter)
2637{
2638 __iomem struct slic_regs *slic_regs = adapter->slic_regs;
2639 struct slic_eeprom *peeprom;
2640 struct oslic_eeprom *pOeeprom;
2641 dma_addr_t phys_config;
2642 u32 phys_configh;
2643 u32 phys_configl;
2644 u32 i = 0;
2645 struct slic_shmem *pshmem;
2646 int status;
2647 uint macaddrs = card->card_size;
2648 ushort eecodesize;
2649 ushort dramsize;
2650 ushort ee_chksum;
2651 ushort calc_chksum;
2652 struct slic_config_mac *pmac;
2653 unsigned char fruformat;
2654 unsigned char oemfruformat;
2655 struct atk_fru *patkfru;
2656 union oemfru *poemfru;
David Matlackeafe6002015-05-11 20:40:35 -07002657 unsigned long flags;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002658
2659 /* Reset everything except PCI configuration space */
2660 slic_soft_reset(adapter);
2661
2662 /* Download the microcode */
2663 status = slic_card_download(adapter);
David Matlack811e8432014-05-23 21:04:55 -07002664 if (status)
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002665 return status;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002666
2667 if (!card->config_set) {
2668 peeprom = pci_alloc_consistent(adapter->pcidev,
2669 sizeof(struct slic_eeprom),
2670 &phys_config);
2671
2672 phys_configl = SLIC_GET_ADDR_LOW(phys_config);
2673 phys_configh = SLIC_GET_ADDR_HIGH(phys_config);
2674
2675 if (!peeprom) {
2676 dev_err(&adapter->pcidev->dev,
David Matlack811e8432014-05-23 21:04:55 -07002677 "Failed to allocate DMA memory for EEPROM.\n");
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002678 return -ENOMEM;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002679 }
Vincent Heuken351e8362014-06-23 05:09:18 -07002680
2681 memset(peeprom, 0, sizeof(struct slic_eeprom));
2682
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002683 slic_reg32_write(&slic_regs->slic_icr, ICR_INT_OFF, FLUSH);
2684 mdelay(1);
Joe Perches01d0a9b2013-02-26 16:33:11 -08002685 pshmem = (struct slic_shmem *)(unsigned long)
2686 adapter->phys_shmem;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002687
David Matlackeafe6002015-05-11 20:40:35 -07002688 spin_lock_irqsave(&adapter->bit64reglock, flags);
David Matlack0783c632014-05-05 21:02:36 -07002689 slic_reg32_write(&slic_regs->slic_addr_upper,
2690 SLIC_GET_ADDR_HIGH(&pshmem->isr), DONT_FLUSH);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002691 slic_reg32_write(&slic_regs->slic_isp,
2692 SLIC_GET_ADDR_LOW(&pshmem->isr), FLUSH);
David Matlackeafe6002015-05-11 20:40:35 -07002693 spin_unlock_irqrestore(&adapter->bit64reglock, flags);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002694
David Matlack47a401a2014-05-22 21:38:45 -07002695 status = slic_config_get(adapter, phys_configl, phys_configh);
2696 if (status) {
2697 dev_err(&adapter->pcidev->dev,
2698 "Failed to fetch config data from device.\n");
2699 goto card_init_err;
2700 }
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002701
2702 for (;;) {
2703 if (adapter->pshmem->isr) {
2704 if (adapter->pshmem->isr & ISR_UPC) {
2705 adapter->pshmem->isr = 0;
2706 slic_reg64_write(adapter,
2707 &slic_regs->slic_isp, 0,
2708 &slic_regs->slic_addr_upper,
2709 0, FLUSH);
2710 slic_reg32_write(&slic_regs->slic_isr,
2711 0, FLUSH);
2712
2713 slic_upr_request_complete(adapter, 0);
2714 break;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002715 }
Vincent Heuken351e8362014-06-23 05:09:18 -07002716
2717 adapter->pshmem->isr = 0;
2718 slic_reg32_write(&slic_regs->slic_isr,
2719 0, FLUSH);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002720 } else {
2721 mdelay(1);
2722 i++;
2723 if (i > 5000) {
2724 dev_err(&adapter->pcidev->dev,
David Matlack811e8432014-05-23 21:04:55 -07002725 "Fetch of config data timed out.\n");
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002726 slic_reg64_write(adapter,
2727 &slic_regs->slic_isp, 0,
2728 &slic_regs->slic_addr_upper,
2729 0, FLUSH);
David Matlack47a401a2014-05-22 21:38:45 -07002730 status = -EINVAL;
2731 goto card_init_err;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002732 }
2733 }
2734 }
2735
2736 switch (adapter->devid) {
2737 /* Oasis card */
2738 case SLIC_2GB_DEVICE_ID:
2739 /* extract EEPROM data and pointers to EEPROM data */
2740 pOeeprom = (struct oslic_eeprom *) peeprom;
2741 eecodesize = pOeeprom->EecodeSize;
2742 dramsize = pOeeprom->DramSize;
2743 pmac = pOeeprom->MacInfo;
2744 fruformat = pOeeprom->FruFormat;
2745 patkfru = &pOeeprom->AtkFru;
2746 oemfruformat = pOeeprom->OemFruFormat;
2747 poemfru = &pOeeprom->OemFru;
2748 macaddrs = 2;
2749 /* Minor kludge for Oasis card
2750 get 2 MAC addresses from the
2751 EEPROM to ensure that function 1
2752 gets the Port 1 MAC address */
2753 break;
2754 default:
2755 /* extract EEPROM data and pointers to EEPROM data */
2756 eecodesize = peeprom->EecodeSize;
2757 dramsize = peeprom->DramSize;
2758 pmac = peeprom->u2.mac.MacInfo;
2759 fruformat = peeprom->FruFormat;
2760 patkfru = &peeprom->AtkFru;
2761 oemfruformat = peeprom->OemFruFormat;
2762 poemfru = &peeprom->OemFru;
2763 break;
2764 }
2765
2766 card->config.EepromValid = false;
2767
2768 /* see if the EEPROM is valid by checking it's checksum */
2769 if ((eecodesize <= MAX_EECODE_SIZE) &&
2770 (eecodesize >= MIN_EECODE_SIZE)) {
2771
2772 ee_chksum =
2773 *(u16 *) ((char *) peeprom + (eecodesize - 2));
2774 /*
2775 calculate the EEPROM checksum
2776 */
David Matlack55b62cd2014-05-19 22:03:59 -07002777 calc_chksum = slic_eeprom_cksum(peeprom,
2778 eecodesize - 2);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002779 /*
2780 if the ucdoe chksum flag bit worked,
Cruz Julian Bishop7864a0a2013-01-14 12:29:07 +10002781 we wouldn't need this
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002782 */
2783 if (ee_chksum == calc_chksum)
2784 card->config.EepromValid = true;
2785 }
2786 /* copy in the DRAM size */
2787 card->config.DramSize = dramsize;
2788
2789 /* copy in the MAC address(es) */
2790 for (i = 0; i < macaddrs; i++) {
2791 memcpy(&card->config.MacInfo[i],
2792 &pmac[i], sizeof(struct slic_config_mac));
2793 }
2794
2795 /* copy the Alacritech FRU information */
2796 card->config.FruFormat = fruformat;
2797 memcpy(&card->config.AtkFru, patkfru,
2798 sizeof(struct atk_fru));
2799
2800 pci_free_consistent(adapter->pcidev,
2801 sizeof(struct slic_eeprom),
2802 peeprom, phys_config);
2803
David Matlack28277a52014-05-19 22:04:00 -07002804 if (!card->config.EepromValid) {
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002805 slic_reg64_write(adapter, &slic_regs->slic_isp, 0,
2806 &slic_regs->slic_addr_upper,
2807 0, FLUSH);
David Matlack811e8432014-05-23 21:04:55 -07002808 dev_err(&adapter->pcidev->dev, "EEPROM invalid.\n");
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002809 return -EINVAL;
2810 }
2811
2812 card->config_set = 1;
2813 }
2814
David Matlack811e8432014-05-23 21:04:55 -07002815 status = slic_card_download_gbrcv(adapter);
2816 if (status)
2817 return status;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002818
2819 if (slic_global.dynamic_intagg)
2820 slic_intagg_set(adapter, 0);
2821 else
2822 slic_intagg_set(adapter, intagg_delay);
2823
2824 /*
2825 * Initialize ping status to "ok"
2826 */
2827 card->pingstatus = ISR_PINGMASK;
2828
2829 /*
2830 * Lastly, mark our card state as up and return success
2831 */
2832 card->state = CARD_UP;
2833 card->reset_in_progress = 0;
2834
2835 return 0;
David Matlack47a401a2014-05-22 21:38:45 -07002836
2837card_init_err:
2838 pci_free_consistent(adapter->pcidev, sizeof(struct slic_eeprom),
2839 peeprom, phys_config);
2840 return status;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002841}
2842
2843static void slic_init_driver(void)
2844{
2845 if (slic_first_init) {
2846 slic_first_init = 0;
David Matlackeafe6002015-05-11 20:40:35 -07002847 spin_lock_init(&slic_global.driver_lock);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002848 }
2849}
2850
2851static void slic_init_adapter(struct net_device *netdev,
2852 struct pci_dev *pcidev,
2853 const struct pci_device_id *pci_tbl_entry,
2854 void __iomem *memaddr, int chip_idx)
2855{
2856 ushort index;
2857 struct slic_handle *pslic_handle;
2858 struct adapter *adapter = netdev_priv(netdev);
2859
2860/* adapter->pcidev = pcidev;*/
2861 adapter->vendid = pci_tbl_entry->vendor;
2862 adapter->devid = pci_tbl_entry->device;
2863 adapter->subsysid = pci_tbl_entry->subdevice;
2864 adapter->busnumber = pcidev->bus->number;
2865 adapter->slotnumber = ((pcidev->devfn >> 3) & 0x1F);
2866 adapter->functionnumber = (pcidev->devfn & 0x7);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002867 adapter->slic_regs = (__iomem struct slic_regs *)memaddr;
2868 adapter->irq = pcidev->irq;
2869/* adapter->netdev = netdev;*/
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002870 adapter->chipid = chip_idx;
2871 adapter->port = 0; /*adapter->functionnumber;*/
2872 adapter->cardindex = adapter->port;
David Matlackeafe6002015-05-11 20:40:35 -07002873 spin_lock_init(&adapter->upr_lock);
2874 spin_lock_init(&adapter->bit64reglock);
2875 spin_lock_init(&adapter->adapter_lock);
2876 spin_lock_init(&adapter->reset_lock);
2877 spin_lock_init(&adapter->handle_lock);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002878
2879 adapter->card_size = 1;
2880 /*
2881 Initialize slic_handle array
2882 */
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002883 /*
2884 Start with 1. 0 is an invalid host handle.
2885 */
2886 for (index = 1, pslic_handle = &adapter->slic_handles[1];
2887 index < SLIC_CMDQ_MAXCMDS; index++, pslic_handle++) {
2888
2889 pslic_handle->token.handle_index = index;
2890 pslic_handle->type = SLIC_HANDLE_FREE;
2891 pslic_handle->next = adapter->pfree_slic_handles;
2892 adapter->pfree_slic_handles = pslic_handle;
2893 }
2894 adapter->pshmem = (struct slic_shmem *)
2895 pci_alloc_consistent(adapter->pcidev,
2896 sizeof(struct slic_shmem),
2897 &adapter->
2898 phys_shmem);
Devendra Nagab8131fc2012-09-05 15:33:47 +05302899 if (adapter->pshmem)
2900 memset(adapter->pshmem, 0, sizeof(struct slic_shmem));
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002901}
2902
2903static const struct net_device_ops slic_netdev_ops = {
2904 .ndo_open = slic_entry_open,
2905 .ndo_stop = slic_entry_halt,
2906 .ndo_start_xmit = slic_xmit_start,
2907 .ndo_do_ioctl = slic_ioctl,
2908 .ndo_set_mac_address = slic_mac_set_address,
2909 .ndo_get_stats = slic_get_stats,
Jiri Pirkoafc4b132011-08-16 06:29:01 +00002910 .ndo_set_rx_mode = slic_mcast_set_list,
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002911 .ndo_validate_addr = eth_validate_addr,
2912 .ndo_change_mtu = eth_change_mtu,
2913};
2914
2915static u32 slic_card_locate(struct adapter *adapter)
2916{
2917 struct sliccard *card = slic_global.slic_card;
2918 struct physcard *physcard = slic_global.phys_card;
2919 ushort card_hostid;
2920 u16 __iomem *hostid_reg;
2921 uint i;
2922 uint rdhostid_offset = 0;
2923
2924 switch (adapter->devid) {
2925 case SLIC_2GB_DEVICE_ID:
2926 rdhostid_offset = SLIC_RDHOSTID_2GB;
2927 break;
2928 case SLIC_1GB_DEVICE_ID:
2929 rdhostid_offset = SLIC_RDHOSTID_1GB;
2930 break;
2931 default:
Devendra Naga0ab19002012-07-09 23:04:20 +05302932 return -ENODEV;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002933 }
2934
2935 hostid_reg =
2936 (u16 __iomem *) (((u8 __iomem *) (adapter->slic_regs)) +
2937 rdhostid_offset);
2938
2939 /* read the 16 bit hostid from SRAM */
2940 card_hostid = (ushort) readw(hostid_reg);
2941
2942 /* Initialize a new card structure if need be */
2943 if (card_hostid == SLIC_HOSTID_DEFAULT) {
2944 card = kzalloc(sizeof(struct sliccard), GFP_KERNEL);
2945 if (card == NULL)
2946 return -ENOMEM;
2947
2948 card->next = slic_global.slic_card;
2949 slic_global.slic_card = card;
2950 card->busnumber = adapter->busnumber;
2951 card->slotnumber = adapter->slotnumber;
2952
2953 /* Find an available cardnum */
2954 for (i = 0; i < SLIC_MAX_CARDS; i++) {
2955 if (slic_global.cardnuminuse[i] == 0) {
2956 slic_global.cardnuminuse[i] = 1;
2957 card->cardnum = i;
2958 break;
2959 }
2960 }
2961 slic_global.num_slic_cards++;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002962 } else {
2963 /* Card exists, find the card this adapter belongs to */
2964 while (card) {
2965 if (card->cardnum == card_hostid)
2966 break;
2967 card = card->next;
2968 }
2969 }
2970
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002971 if (!card)
2972 return -ENXIO;
2973 /* Put the adapter in the card's adapter list */
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002974 if (!card->adapter[adapter->port]) {
2975 card->adapter[adapter->port] = adapter;
2976 adapter->card = card;
2977 }
2978
2979 card->card_size = 1; /* one port per *logical* card */
2980
2981 while (physcard) {
2982 for (i = 0; i < SLIC_MAX_PORTS; i++) {
Peter Huewe20d403e2013-02-19 05:18:51 +01002983 if (physcard->adapter[i])
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002984 break;
2985 }
Peter Huewe20d403e2013-02-19 05:18:51 +01002986 if (i == SLIC_MAX_PORTS)
2987 break;
2988
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00002989 if (physcard->adapter[i]->slotnumber == adapter->slotnumber)
2990 break;
2991 physcard = physcard->next;
2992 }
2993 if (!physcard) {
2994 /* no structure allocated for this physical card yet */
2995 physcard = kzalloc(sizeof(struct physcard), GFP_ATOMIC);
Devendra Naga34ec83f2012-10-25 02:11:51 -04002996 if (!physcard) {
2997 if (card_hostid == SLIC_HOSTID_DEFAULT)
2998 kfree(card);
Devendra Naga06088822012-10-23 18:04:32 -04002999 return -ENOMEM;
Devendra Naga34ec83f2012-10-25 02:11:51 -04003000 }
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00003001
3002 physcard->next = slic_global.phys_card;
3003 slic_global.phys_card = physcard;
3004 physcard->adapters_allocd = 1;
3005 } else {
3006 physcard->adapters_allocd++;
3007 }
3008 /* Note - this is ZERO relative */
3009 adapter->physport = physcard->adapters_allocd - 1;
3010
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00003011 physcard->adapter[adapter->physport] = adapter;
3012 adapter->physcard = physcard;
3013
3014 return 0;
3015}
3016
Bill Pembertona0c2feb2012-11-19 13:22:02 -05003017static int slic_entry_probe(struct pci_dev *pcidev,
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00003018 const struct pci_device_id *pci_tbl_entry)
3019{
3020 static int cards_found;
3021 static int did_version;
3022 int err = -ENODEV;
3023 struct net_device *netdev;
3024 struct adapter *adapter;
3025 void __iomem *memmapped_ioaddr = NULL;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00003026 ulong mmio_start = 0;
3027 ulong mmio_len = 0;
3028 struct sliccard *card = NULL;
3029 int pci_using_dac = 0;
3030
3031 slic_global.dynamic_intagg = dynamic_intagg;
3032
3033 err = pci_enable_device(pcidev);
3034
3035 if (err)
3036 return err;
3037
David Matlack04cc3c82014-05-05 21:02:34 -07003038 if (did_version++ == 0) {
3039 dev_info(&pcidev->dev, "%s\n", slic_banner);
3040 dev_info(&pcidev->dev, "%s\n", slic_proc_version);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00003041 }
3042
3043 if (!pci_set_dma_mask(pcidev, DMA_BIT_MASK(64))) {
3044 pci_using_dac = 1;
Wei Yongjun1154eb52013-05-13 14:04:58 +08003045 err = pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(64));
3046 if (err) {
Rashika Kheria79b0ae82013-10-19 13:17:59 +05303047 dev_err(&pcidev->dev, "unable to obtain 64-bit DMA for consistent allocations\n");
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00003048 goto err_out_disable_pci;
3049 }
Wei Yongjun1154eb52013-05-13 14:04:58 +08003050 } else {
3051 err = pci_set_dma_mask(pcidev, DMA_BIT_MASK(32));
3052 if (err) {
3053 dev_err(&pcidev->dev, "no usable DMA configuration\n");
3054 goto err_out_disable_pci;
3055 }
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00003056 pci_using_dac = 0;
3057 pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(32));
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00003058 }
3059
3060 err = pci_request_regions(pcidev, DRV_NAME);
3061 if (err) {
3062 dev_err(&pcidev->dev, "can't obtain PCI resources\n");
3063 goto err_out_disable_pci;
3064 }
3065
3066 pci_set_master(pcidev);
3067
3068 netdev = alloc_etherdev(sizeof(struct adapter));
3069 if (!netdev) {
3070 err = -ENOMEM;
3071 goto err_out_exit_slic_probe;
3072 }
3073
3074 SET_NETDEV_DEV(netdev, &pcidev->dev);
3075
3076 pci_set_drvdata(pcidev, netdev);
3077 adapter = netdev_priv(netdev);
3078 adapter->netdev = netdev;
3079 adapter->pcidev = pcidev;
3080 if (pci_using_dac)
3081 netdev->features |= NETIF_F_HIGHDMA;
3082
3083 mmio_start = pci_resource_start(pcidev, 0);
3084 mmio_len = pci_resource_len(pcidev, 0);
3085
3086
3087/* memmapped_ioaddr = (u32)ioremap_nocache(mmio_start, mmio_len);*/
3088 memmapped_ioaddr = ioremap(mmio_start, mmio_len);
3089 if (!memmapped_ioaddr) {
3090 dev_err(&pcidev->dev, "cannot remap MMIO region %lx @ %lx\n",
3091 mmio_len, mmio_start);
Wei Yongjun1154eb52013-05-13 14:04:58 +08003092 err = -ENOMEM;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00003093 goto err_out_free_netdev;
3094 }
3095
3096 slic_config_pci(pcidev);
3097
3098 slic_init_driver();
3099
3100 slic_init_adapter(netdev,
3101 pcidev, pci_tbl_entry, memmapped_ioaddr, cards_found);
3102
Wei Yongjun1154eb52013-05-13 14:04:58 +08003103 err = slic_card_locate(adapter);
3104 if (err) {
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00003105 dev_err(&pcidev->dev, "cannot locate card\n");
Kristina Martšenkoeea7c702014-03-18 17:05:56 +02003106 goto err_out_unmap;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00003107 }
3108
3109 card = adapter->card;
3110
3111 if (!adapter->allocated) {
3112 card->adapters_allocated++;
3113 adapter->allocated = 1;
3114 }
3115
David Matlack65bc0aa2014-05-05 21:02:31 -07003116 err = slic_card_init(card, adapter);
3117 if (err)
3118 goto err_out_unmap;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00003119
David Matlack65bc0aa2014-05-05 21:02:31 -07003120 slic_adapter_set_hwaddr(adapter);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00003121
David Matlack563dce32014-05-05 21:02:33 -07003122 netdev->base_addr = (unsigned long) memmapped_ioaddr;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00003123 netdev->irq = adapter->irq;
3124 netdev->netdev_ops = &slic_netdev_ops;
3125
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00003126 strcpy(netdev->name, "eth%d");
3127 err = register_netdev(netdev);
3128 if (err) {
3129 dev_err(&pcidev->dev, "Cannot register net device, aborting.\n");
3130 goto err_out_unmap;
3131 }
3132
3133 cards_found++;
3134
David Matlack65bc0aa2014-05-05 21:02:31 -07003135 return 0;
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00003136
3137err_out_unmap:
3138 iounmap(memmapped_ioaddr);
Denis Kirjanov4d6ea9c2010-07-10 07:12:46 +00003139err_out_free_netdev:
3140 free_netdev(netdev);
3141err_out_exit_slic_probe:
3142 pci_release_regions(pcidev);
3143err_out_disable_pci:
3144 pci_disable_device(pcidev);
3145 return err;
3146}
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07003147
3148static struct pci_driver slic_driver = {
3149 .name = DRV_NAME,
3150 .id_table = slic_pci_tbl,
3151 .probe = slic_entry_probe,
Bill Pemberton2e0d79c2012-11-19 13:20:59 -05003152 .remove = slic_entry_remove,
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07003153};
3154
3155static int __init slic_module_init(void)
3156{
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07003157 slic_init_driver();
3158
Greg Kroah-Hartmane8bc9b72009-02-26 14:43:03 -08003159 return pci_register_driver(&slic_driver);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07003160}
3161
3162static void __exit slic_module_cleanup(void)
3163{
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07003164 pci_unregister_driver(&slic_driver);
Greg Kroah-Hartman4d6f6af2008-03-19 14:27:25 -07003165}
3166
3167module_init(slic_module_init);
3168module_exit(slic_module_cleanup);