blob: b23cbc678345e032479d6a22ae67989fcd26a4a5 [file] [log] [blame]
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001/**************************************************************************
2 *
3 * Copyright (C) 2000-2008 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 * THIS SOFTWARE IS PROVIDED BY ALACRITECH, INC. ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ALACRITECH, INC. OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * The views and conclusions contained in the software and documentation
30 * are those of the authors and should not be interpreted as representing
31 * official policies, either expressed or implied, of Alacritech, Inc.
32 *
33 **************************************************************************/
34
35/*
36 * FILENAME: sxg.c
37 *
38 * The SXG driver for Alacritech's 10Gbe products.
39 *
40 * NOTE: This is the standard, non-accelerated version of Alacritech's
41 * IS-NIC driver.
42 */
43
44#include <linux/kernel.h>
45#include <linux/string.h>
46#include <linux/errno.h>
47#include <linux/module.h>
48#include <linux/moduleparam.h>
49#include <linux/ioport.h>
50#include <linux/slab.h>
51#include <linux/interrupt.h>
52#include <linux/timer.h>
53#include <linux/pci.h>
54#include <linux/spinlock.h>
55#include <linux/init.h>
56#include <linux/netdevice.h>
57#include <linux/etherdevice.h>
58#include <linux/ethtool.h>
59#include <linux/skbuff.h>
60#include <linux/delay.h>
61#include <linux/types.h>
62#include <linux/dma-mapping.h>
63#include <linux/mii.h>
64
65#define SLIC_DUMP_ENABLED 0
66#define SLIC_GET_STATS_ENABLED 0
67#define LINUX_FREES_ADAPTER_RESOURCES 1
68#define SXG_OFFLOAD_IP_CHECKSUM 0
69#define SXG_POWER_MANAGEMENT_ENABLED 0
70#define VPCI 0
71#define DBG 1
72#define ATK_DEBUG 1
73
74#include "sxg_os.h"
75#include "sxghw.h"
76#include "sxghif.h"
77#include "sxg.h"
78#include "sxgdbg.h"
79
80#include "sxgphycode.h"
81#include "saharadbgdownload.h"
82
J.R. Mauro73b07062008-10-28 18:42:02 -040083static int sxg_allocate_buffer_memory(struct adapter_t *adapter, u32 Size,
Mithlesh Thukral942798b2009-01-05 21:14:34 +053084 enum sxg_buffer_type BufferType);
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +053085static void sxg_allocate_rcvblock_complete(struct adapter_t *adapter,
86 void *RcvBlock,
87 dma_addr_t PhysicalAddress,
88 u32 Length);
J.R. Mauro73b07062008-10-28 18:42:02 -040089static void sxg_allocate_sgl_buffer_complete(struct adapter_t *adapter,
Mithlesh Thukral942798b2009-01-05 21:14:34 +053090 struct sxg_scatter_gather *SxgSgl,
J.R. Mauro5c7514e2008-10-05 20:38:52 -040091 dma_addr_t PhysicalAddress,
92 u32 Length);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -070093
94static void sxg_mcast_init_crc32(void);
Mithlesh Thukral942798b2009-01-05 21:14:34 +053095static int sxg_entry_open(struct net_device *dev);
96static int sxg_entry_halt(struct net_device *dev);
97static int sxg_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
98static int sxg_send_packets(struct sk_buff *skb, struct net_device *dev);
J.R. Mauro73b07062008-10-28 18:42:02 -040099static int sxg_transmit_packet(struct adapter_t *adapter, struct sk_buff *skb);
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530100static void sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
101 struct sxg_scatter_gather *SxgSgl);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700102
J.R. Mauro73b07062008-10-28 18:42:02 -0400103static void sxg_handle_interrupt(struct adapter_t *adapter);
104static int sxg_process_isr(struct adapter_t *adapter, u32 MessageId);
105static u32 sxg_process_event_queue(struct adapter_t *adapter, u32 RssId);
106static void sxg_complete_slow_send(struct adapter_t *adapter);
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530107static struct sk_buff *sxg_slow_receive(struct adapter_t *adapter,
108 struct sxg_event *Event);
J.R. Mauro73b07062008-10-28 18:42:02 -0400109static void sxg_process_rcv_error(struct adapter_t *adapter, u32 ErrorStatus);
110static bool sxg_mac_filter(struct adapter_t *adapter,
111 struct ether_header *EtherHdr, ushort length);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700112
113#if SLIC_GET_STATS_ENABLED
Mithlesh Thukral942798b2009-01-05 21:14:34 +0530114static struct net_device_stats *sxg_get_stats(struct net_device *dev);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700115#endif
116
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +0530117void SxgFreeResources(struct adapter_t *adapter);
118void SxgFreeRcvBlocks(struct adapter_t *adapter);
119
Greg Kroah-Hartmanc6c25ed2008-10-21 10:41:45 -0700120#define XXXTODO 0
121
Mithlesh Thukral942798b2009-01-05 21:14:34 +0530122static int sxg_mac_set_address(struct net_device *dev, void *ptr);
123static void sxg_mcast_set_list(struct net_device *dev);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700124
J.R. Mauro73b07062008-10-28 18:42:02 -0400125static void sxg_adapter_set_hwaddr(struct adapter_t *adapter);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700126
J.R. Mauro73b07062008-10-28 18:42:02 -0400127static void sxg_unmap_mmio_space(struct adapter_t *adapter);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700128
J.R. Mauro73b07062008-10-28 18:42:02 -0400129static int sxg_initialize_adapter(struct adapter_t *adapter);
130static void sxg_stock_rcv_buffers(struct adapter_t *adapter);
131static void sxg_complete_descriptor_blocks(struct adapter_t *adapter,
J.R. Mauro5c7514e2008-10-05 20:38:52 -0400132 unsigned char Index);
J.R. Mauro73b07062008-10-28 18:42:02 -0400133static int sxg_initialize_link(struct adapter_t *adapter);
134static int sxg_phy_init(struct adapter_t *adapter);
135static void sxg_link_event(struct adapter_t *adapter);
136static enum SXG_LINK_STATE sxg_get_link_state(struct adapter_t *adapter);
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530137static void sxg_link_state(struct adapter_t *adapter,
138 enum SXG_LINK_STATE LinkState);
J.R. Mauro73b07062008-10-28 18:42:02 -0400139static int sxg_write_mdio_reg(struct adapter_t *adapter,
J.R. Mauro5c7514e2008-10-05 20:38:52 -0400140 u32 DevAddr, u32 RegAddr, u32 Value);
J.R. Mauro73b07062008-10-28 18:42:02 -0400141static int sxg_read_mdio_reg(struct adapter_t *adapter,
J.R. Mauro5c7514e2008-10-05 20:38:52 -0400142 u32 DevAddr, u32 RegAddr, u32 *pValue);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700143
144static unsigned int sxg_first_init = 1;
145static char *sxg_banner =
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530146 "Alacritech SLIC Technology(tm) Server and Storage \
147 10Gbe Accelerator (Non-Accelerated)\n";
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700148
149static int sxg_debug = 1;
150static int debug = -1;
Mithlesh Thukral942798b2009-01-05 21:14:34 +0530151static struct net_device *head_netdevice = NULL;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700152
Mithlesh Thukral942798b2009-01-05 21:14:34 +0530153static struct sxgbase_driver sxg_global = {
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700154 .dynamic_intagg = 1,
155};
156static int intagg_delay = 100;
157static u32 dynamic_intagg = 0;
158
159#define DRV_NAME "sxg"
160#define DRV_VERSION "1.0.1"
161#define DRV_AUTHOR "Alacritech, Inc. Engineering"
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530162#define DRV_DESCRIPTION \
163 "Alacritech SLIC Techonology(tm) Non-Accelerated 10Gbe Driver"
164#define DRV_COPYRIGHT \
165 "Copyright 2000-2008 Alacritech, Inc. All rights reserved."
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700166
167MODULE_AUTHOR(DRV_AUTHOR);
168MODULE_DESCRIPTION(DRV_DESCRIPTION);
169MODULE_LICENSE("GPL");
170
171module_param(dynamic_intagg, int, 0);
172MODULE_PARM_DESC(dynamic_intagg, "Dynamic Interrupt Aggregation Setting");
173module_param(intagg_delay, int, 0);
174MODULE_PARM_DESC(intagg_delay, "uSec Interrupt Aggregation Delay");
175
176static struct pci_device_id sxg_pci_tbl[] __devinitdata = {
177 {PCI_DEVICE(SXG_VENDOR_ID, SXG_DEVICE_ID)},
178 {0,}
179};
J.R. Mauro5c7514e2008-10-05 20:38:52 -0400180
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700181MODULE_DEVICE_TABLE(pci, sxg_pci_tbl);
182
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700183static inline void sxg_reg32_write(void __iomem *reg, u32 value, bool flush)
184{
185 writel(value, reg);
186 if (flush)
187 mb();
188}
189
J.R. Mauro73b07062008-10-28 18:42:02 -0400190static inline void sxg_reg64_write(struct adapter_t *adapter, void __iomem *reg,
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700191 u64 value, u32 cpu)
192{
193 u32 value_high = (u32) (value >> 32);
194 u32 value_low = (u32) (value & 0x00000000FFFFFFFF);
195 unsigned long flags;
196
197 spin_lock_irqsave(&adapter->Bit64RegLock, flags);
198 writel(value_high, (void __iomem *)(&adapter->UcodeRegs[cpu].Upper));
199 writel(value_low, reg);
200 spin_unlock_irqrestore(&adapter->Bit64RegLock, flags);
201}
202
203static void sxg_init_driver(void)
204{
205 if (sxg_first_init) {
206 DBG_ERROR("sxg: %s sxg_first_init set jiffies[%lx]\n",
Harvey Harrisone88bd232008-10-17 14:46:10 -0700207 __func__, jiffies);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700208 sxg_first_init = 0;
209 spin_lock_init(&sxg_global.driver_lock);
210 }
211}
212
J.R. Mauro73b07062008-10-28 18:42:02 -0400213static void sxg_dbg_macaddrs(struct adapter_t *adapter)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700214{
215 DBG_ERROR(" (%s) curr %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
216 adapter->netdev->name, adapter->currmacaddr[0],
217 adapter->currmacaddr[1], adapter->currmacaddr[2],
218 adapter->currmacaddr[3], adapter->currmacaddr[4],
219 adapter->currmacaddr[5]);
220 DBG_ERROR(" (%s) mac %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
221 adapter->netdev->name, adapter->macaddr[0],
222 adapter->macaddr[1], adapter->macaddr[2],
223 adapter->macaddr[3], adapter->macaddr[4],
224 adapter->macaddr[5]);
225 return;
226}
227
J.R. Maurob243c4a2008-10-20 19:28:58 -0400228/* SXG Globals */
Mithlesh Thukral942798b2009-01-05 21:14:34 +0530229static struct sxg_driver SxgDriver;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700230
231#ifdef ATKDBG
Mithlesh Thukral942798b2009-01-05 21:14:34 +0530232static struct sxg_trace_buffer LSxgTraceBuffer;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700233#endif /* ATKDBG */
Mithlesh Thukral942798b2009-01-05 21:14:34 +0530234static struct sxg_trace_buffer *SxgTraceBuffer = NULL;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700235
236/*
237 * sxg_download_microcode
238 *
239 * Download Microcode to Sahara adapter
240 *
241 * Arguments -
242 * adapter - A pointer to our adapter structure
243 * UcodeSel - microcode file selection
244 *
245 * Return
246 * int
247 */
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530248static bool sxg_download_microcode(struct adapter_t *adapter,
249 enum SXG_UCODE_SEL UcodeSel)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700250{
Mithlesh Thukral942798b2009-01-05 21:14:34 +0530251 struct sxg_hw_regs *HwRegs = adapter->HwRegs;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700252 u32 Section;
253 u32 ThisSectionSize;
J.R. Mauro5c7514e2008-10-05 20:38:52 -0400254 u32 *Instruction = NULL;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700255 u32 BaseAddress, AddressOffset, Address;
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530256 /* u32 Failure; */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700257 u32 ValueRead;
258 u32 i;
259 u32 numSections = 0;
260 u32 sectionSize[16];
261 u32 sectionStart[16];
262
263 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DnldUcod",
264 adapter, 0, 0, 0);
Harvey Harrisone88bd232008-10-17 14:46:10 -0700265 DBG_ERROR("sxg: %s ENTER\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700266
267 switch (UcodeSel) {
J.R. Maurob243c4a2008-10-20 19:28:58 -0400268 case SXG_UCODE_SAHARA: /* Sahara operational ucode */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700269 numSections = SNumSections;
270 for (i = 0; i < numSections; i++) {
271 sectionSize[i] = SSectionSize[i];
272 sectionStart[i] = SSectionStart[i];
273 }
274 break;
275 default:
276 printk(KERN_ERR KBUILD_MODNAME
277 ": Woah, big error with the microcode!\n");
278 break;
279 }
280
281 DBG_ERROR("sxg: RESET THE CARD\n");
J.R. Maurob243c4a2008-10-20 19:28:58 -0400282 /* First, reset the card */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700283 WRITE_REG(HwRegs->Reset, 0xDEAD, FLUSH);
284
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +0530285 /*
286 * Download each section of the microcode as specified in
287 * its download file. The *download.c file is generated using
288 * the saharaobjtoc facility which converts the metastep .obj
289 * file to a .c file which contains a two dimentional array.
290 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700291 for (Section = 0; Section < numSections; Section++) {
292 DBG_ERROR("sxg: SECTION # %d\n", Section);
293 switch (UcodeSel) {
294 case SXG_UCODE_SAHARA:
295 Instruction = (u32 *) & SaharaUCode[Section][0];
296 break;
297 default:
298 ASSERT(0);
299 break;
300 }
301 BaseAddress = sectionStart[Section];
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530302 /* Size in instructions */
303 ThisSectionSize = sectionSize[Section] / 12;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700304 for (AddressOffset = 0; AddressOffset < ThisSectionSize;
305 AddressOffset++) {
306 Address = BaseAddress + AddressOffset;
307 ASSERT((Address & ~MICROCODE_ADDRESS_MASK) == 0);
J.R. Maurob243c4a2008-10-20 19:28:58 -0400308 /* Write instruction bits 31 - 0 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700309 WRITE_REG(HwRegs->UcodeDataLow, *Instruction, FLUSH);
J.R. Maurob243c4a2008-10-20 19:28:58 -0400310 /* Write instruction bits 63-32 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700311 WRITE_REG(HwRegs->UcodeDataMiddle, *(Instruction + 1),
312 FLUSH);
J.R. Maurob243c4a2008-10-20 19:28:58 -0400313 /* Write instruction bits 95-64 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700314 WRITE_REG(HwRegs->UcodeDataHigh, *(Instruction + 2),
315 FLUSH);
J.R. Maurob243c4a2008-10-20 19:28:58 -0400316 /* Write instruction address with the WRITE bit set */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700317 WRITE_REG(HwRegs->UcodeAddr,
318 (Address | MICROCODE_ADDRESS_WRITE), FLUSH);
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +0530319 /*
320 * Sahara bug in the ucode download logic - the write to DataLow
321 * for the next instruction could get corrupted. To avoid this,
322 * write to DataLow again for this instruction (which may get
323 * corrupted, but it doesn't matter), then increment the address
324 * and write the data for the next instruction to DataLow. That
325 * write should succeed.
326 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700327 WRITE_REG(HwRegs->UcodeDataLow, *Instruction, TRUE);
J.R. Maurob243c4a2008-10-20 19:28:58 -0400328 /* Advance 3 u32S to start of next instruction */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700329 Instruction += 3;
330 }
331 }
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +0530332 /*
333 * Now repeat the entire operation reading the instruction back and
334 * checking for parity errors
335 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700336 for (Section = 0; Section < numSections; Section++) {
337 DBG_ERROR("sxg: check SECTION # %d\n", Section);
338 switch (UcodeSel) {
339 case SXG_UCODE_SAHARA:
340 Instruction = (u32 *) & SaharaUCode[Section][0];
341 break;
342 default:
343 ASSERT(0);
344 break;
345 }
346 BaseAddress = sectionStart[Section];
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530347 /* Size in instructions */
348 ThisSectionSize = sectionSize[Section] / 12;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700349 for (AddressOffset = 0; AddressOffset < ThisSectionSize;
350 AddressOffset++) {
351 Address = BaseAddress + AddressOffset;
J.R. Maurob243c4a2008-10-20 19:28:58 -0400352 /* Write the address with the READ bit set */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700353 WRITE_REG(HwRegs->UcodeAddr,
354 (Address | MICROCODE_ADDRESS_READ), FLUSH);
J.R. Maurob243c4a2008-10-20 19:28:58 -0400355 /* Read it back and check parity bit. */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700356 READ_REG(HwRegs->UcodeAddr, ValueRead);
357 if (ValueRead & MICROCODE_ADDRESS_PARITY) {
358 DBG_ERROR("sxg: %s PARITY ERROR\n",
Harvey Harrisone88bd232008-10-17 14:46:10 -0700359 __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700360
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530361 return FALSE; /* Parity error */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700362 }
363 ASSERT((ValueRead & MICROCODE_ADDRESS_MASK) == Address);
J.R. Maurob243c4a2008-10-20 19:28:58 -0400364 /* Read the instruction back and compare */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700365 READ_REG(HwRegs->UcodeDataLow, ValueRead);
366 if (ValueRead != *Instruction) {
367 DBG_ERROR("sxg: %s MISCOMPARE LOW\n",
Harvey Harrisone88bd232008-10-17 14:46:10 -0700368 __func__);
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530369 return FALSE; /* Miscompare */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700370 }
371 READ_REG(HwRegs->UcodeDataMiddle, ValueRead);
372 if (ValueRead != *(Instruction + 1)) {
373 DBG_ERROR("sxg: %s MISCOMPARE MIDDLE\n",
Harvey Harrisone88bd232008-10-17 14:46:10 -0700374 __func__);
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530375 return FALSE; /* Miscompare */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700376 }
377 READ_REG(HwRegs->UcodeDataHigh, ValueRead);
378 if (ValueRead != *(Instruction + 2)) {
379 DBG_ERROR("sxg: %s MISCOMPARE HIGH\n",
Harvey Harrisone88bd232008-10-17 14:46:10 -0700380 __func__);
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530381 return FALSE; /* Miscompare */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700382 }
J.R. Maurob243c4a2008-10-20 19:28:58 -0400383 /* Advance 3 u32S to start of next instruction */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700384 Instruction += 3;
385 }
386 }
387
J.R. Maurob243c4a2008-10-20 19:28:58 -0400388 /* Everything OK, Go. */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700389 WRITE_REG(HwRegs->UcodeAddr, MICROCODE_ADDRESS_GO, FLUSH);
390
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +0530391 /*
392 * Poll the CardUp register to wait for microcode to initialize
393 * Give up after 10,000 attemps (500ms).
394 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700395 for (i = 0; i < 10000; i++) {
396 udelay(50);
397 READ_REG(adapter->UcodeRegs[0].CardUp, ValueRead);
398 if (ValueRead == 0xCAFE) {
Harvey Harrisone88bd232008-10-17 14:46:10 -0700399 DBG_ERROR("sxg: %s BOO YA 0xCAFE\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700400 break;
401 }
402 }
403 if (i == 10000) {
Harvey Harrisone88bd232008-10-17 14:46:10 -0700404 DBG_ERROR("sxg: %s TIMEOUT\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700405
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530406 return FALSE; /* Timeout */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700407 }
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +0530408 /*
409 * Now write the LoadSync register. This is used to
410 * synchronize with the card so it can scribble on the memory
411 * that contained 0xCAFE from the "CardUp" step above
412 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700413 if (UcodeSel == SXG_UCODE_SAHARA) {
414 WRITE_REG(adapter->UcodeRegs[0].LoadSync, 0, FLUSH);
415 }
416
417 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XDnldUcd",
418 adapter, 0, 0, 0);
Harvey Harrisone88bd232008-10-17 14:46:10 -0700419 DBG_ERROR("sxg: %s EXIT\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700420
421 return (TRUE);
422}
423
424/*
425 * sxg_allocate_resources - Allocate memory and locks
426 *
427 * Arguments -
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530428 * adapter - A pointer to our adapter structure
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700429 *
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530430 * Return - int
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700431 */
J.R. Mauro73b07062008-10-28 18:42:02 -0400432static int sxg_allocate_resources(struct adapter_t *adapter)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700433{
434 int status;
435 u32 i;
436 u32 RssIds, IsrCount;
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530437 /* struct sxg_xmt_ring *XmtRing; */
438 /* struct sxg_rcv_ring *RcvRing; */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700439
Harvey Harrisone88bd232008-10-17 14:46:10 -0700440 DBG_ERROR("%s ENTER\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700441
442 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "AllocRes",
443 adapter, 0, 0, 0);
444
J.R. Maurob243c4a2008-10-20 19:28:58 -0400445 /* Windows tells us how many CPUs it plans to use for */
446 /* RSS */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700447 RssIds = SXG_RSS_CPU_COUNT(adapter);
448 IsrCount = adapter->MsiEnabled ? RssIds : 1;
449
Harvey Harrisone88bd232008-10-17 14:46:10 -0700450 DBG_ERROR("%s Setup the spinlocks\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700451
J.R. Maurob243c4a2008-10-20 19:28:58 -0400452 /* Allocate spinlocks and initialize listheads first. */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700453 spin_lock_init(&adapter->RcvQLock);
454 spin_lock_init(&adapter->SglQLock);
455 spin_lock_init(&adapter->XmtZeroLock);
456 spin_lock_init(&adapter->Bit64RegLock);
457 spin_lock_init(&adapter->AdapterLock);
458
Harvey Harrisone88bd232008-10-17 14:46:10 -0700459 DBG_ERROR("%s Setup the lists\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700460
461 InitializeListHead(&adapter->FreeRcvBuffers);
462 InitializeListHead(&adapter->FreeRcvBlocks);
463 InitializeListHead(&adapter->AllRcvBlocks);
464 InitializeListHead(&adapter->FreeSglBuffers);
465 InitializeListHead(&adapter->AllSglBuffers);
466
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +0530467 /*
468 * Mark these basic allocations done. This flags essentially
469 * tells the SxgFreeResources routine that it can grab spinlocks
470 * and reference listheads.
471 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700472 adapter->BasicAllocations = TRUE;
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +0530473 /*
474 * Main allocation loop. Start with the maximum supported by
475 * the microcode and back off if memory allocation
476 * fails. If we hit a minimum, fail.
477 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700478
479 for (;;) {
Greg Kroah-Hartmand78404c2008-10-21 10:41:45 -0700480 DBG_ERROR("%s Allocate XmtRings size[%x]\n", __func__,
Mithlesh Thukral942798b2009-01-05 21:14:34 +0530481 (unsigned int)(sizeof(struct sxg_xmt_ring) * 1));
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700482
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +0530483 /*
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530484 * Start with big items first - receive and transmit rings.
485 * At the moment I'm going to keep the ring size fixed and
486 * adjust the TCBs if we fail. Later we might
487 * consider reducing the ring size as well..
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +0530488 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700489 adapter->XmtRings = pci_alloc_consistent(adapter->pcidev,
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530490 sizeof(struct sxg_xmt_ring) *
491 1,
492 &adapter->PXmtRings);
Harvey Harrisone88bd232008-10-17 14:46:10 -0700493 DBG_ERROR("%s XmtRings[%p]\n", __func__, adapter->XmtRings);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700494
495 if (!adapter->XmtRings) {
496 goto per_tcb_allocation_failed;
497 }
Mithlesh Thukral942798b2009-01-05 21:14:34 +0530498 memset(adapter->XmtRings, 0, sizeof(struct sxg_xmt_ring) * 1);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700499
Greg Kroah-Hartmand78404c2008-10-21 10:41:45 -0700500 DBG_ERROR("%s Allocate RcvRings size[%x]\n", __func__,
Mithlesh Thukral942798b2009-01-05 21:14:34 +0530501 (unsigned int)(sizeof(struct sxg_rcv_ring) * 1));
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700502 adapter->RcvRings =
503 pci_alloc_consistent(adapter->pcidev,
Mithlesh Thukral942798b2009-01-05 21:14:34 +0530504 sizeof(struct sxg_rcv_ring) * 1,
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700505 &adapter->PRcvRings);
Harvey Harrisone88bd232008-10-17 14:46:10 -0700506 DBG_ERROR("%s RcvRings[%p]\n", __func__, adapter->RcvRings);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700507 if (!adapter->RcvRings) {
508 goto per_tcb_allocation_failed;
509 }
Mithlesh Thukral942798b2009-01-05 21:14:34 +0530510 memset(adapter->RcvRings, 0, sizeof(struct sxg_rcv_ring) * 1);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700511 break;
512
513 per_tcb_allocation_failed:
J.R. Maurob243c4a2008-10-20 19:28:58 -0400514 /* an allocation failed. Free any successful allocations. */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700515 if (adapter->XmtRings) {
516 pci_free_consistent(adapter->pcidev,
Mithlesh Thukral942798b2009-01-05 21:14:34 +0530517 sizeof(struct sxg_xmt_ring) * 1,
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700518 adapter->XmtRings,
519 adapter->PXmtRings);
520 adapter->XmtRings = NULL;
521 }
522 if (adapter->RcvRings) {
523 pci_free_consistent(adapter->pcidev,
Mithlesh Thukral942798b2009-01-05 21:14:34 +0530524 sizeof(struct sxg_rcv_ring) * 1,
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700525 adapter->RcvRings,
526 adapter->PRcvRings);
527 adapter->RcvRings = NULL;
528 }
J.R. Maurob243c4a2008-10-20 19:28:58 -0400529 /* Loop around and try again.... */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700530 }
531
Harvey Harrisone88bd232008-10-17 14:46:10 -0700532 DBG_ERROR("%s Initialize RCV ZERO and XMT ZERO rings\n", __func__);
J.R. Maurob243c4a2008-10-20 19:28:58 -0400533 /* Initialize rcv zero and xmt zero rings */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700534 SXG_INITIALIZE_RING(adapter->RcvRingZeroInfo, SXG_RCV_RING_SIZE);
535 SXG_INITIALIZE_RING(adapter->XmtRingZeroInfo, SXG_XMT_RING_SIZE);
536
J.R. Maurob243c4a2008-10-20 19:28:58 -0400537 /* Sanity check receive data structure format */
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +0530538 /* ASSERT((adapter->ReceiveBufferSize == SXG_RCV_DATA_BUFFER_SIZE) ||
539 (adapter->ReceiveBufferSize == SXG_RCV_JUMBO_BUFFER_SIZE)); */
Mithlesh Thukral942798b2009-01-05 21:14:34 +0530540 ASSERT(sizeof(struct sxg_rcv_descriptor_block) ==
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700541 SXG_RCV_DESCRIPTOR_BLOCK_SIZE);
542
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +0530543 /*
544 * Allocate receive data buffers. We allocate a block of buffers and
545 * a corresponding descriptor block at once. See sxghw.h:SXG_RCV_BLOCK
546 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700547 for (i = 0; i < SXG_INITIAL_RCV_DATA_BUFFERS;
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530548 i += SXG_RCV_DESCRIPTORS_PER_BLOCK) {
549 sxg_allocate_buffer_memory(adapter,
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +0530550 SXG_RCV_BLOCK_SIZE(SXG_RCV_DATA_HDR_SIZE),
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700551 SXG_BUFFER_TYPE_RCV);
552 }
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +0530553 /*
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530554 * NBL resource allocation can fail in the 'AllocateComplete' routine,
555 * which doesn't return status. Make sure we got the number of buffers
556 * we requested
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +0530557 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700558 if (adapter->FreeRcvBufferCount < SXG_INITIAL_RCV_DATA_BUFFERS) {
559 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAResF6",
560 adapter, adapter->FreeRcvBufferCount, SXG_MAX_ENTRIES,
561 0);
562 return (STATUS_RESOURCES);
563 }
564
Greg Kroah-Hartmand78404c2008-10-21 10:41:45 -0700565 DBG_ERROR("%s Allocate EventRings size[%x]\n", __func__,
Mithlesh Thukral942798b2009-01-05 21:14:34 +0530566 (unsigned int)(sizeof(struct sxg_event_ring) * RssIds));
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700567
J.R. Maurob243c4a2008-10-20 19:28:58 -0400568 /* Allocate event queues. */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700569 adapter->EventRings = pci_alloc_consistent(adapter->pcidev,
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530570 sizeof(struct sxg_event_ring) *
571 RssIds,
572 &adapter->PEventRings);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700573
574 if (!adapter->EventRings) {
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530575 /* Caller will call SxgFreeAdapter to clean up above
576 * allocations */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700577 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAResF8",
578 adapter, SXG_MAX_ENTRIES, 0, 0);
579 status = STATUS_RESOURCES;
580 goto per_tcb_allocation_failed;
581 }
Mithlesh Thukral942798b2009-01-05 21:14:34 +0530582 memset(adapter->EventRings, 0, sizeof(struct sxg_event_ring) * RssIds);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700583
Harvey Harrisone88bd232008-10-17 14:46:10 -0700584 DBG_ERROR("%s Allocate ISR size[%x]\n", __func__, IsrCount);
J.R. Maurob243c4a2008-10-20 19:28:58 -0400585 /* Allocate ISR */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700586 adapter->Isr = pci_alloc_consistent(adapter->pcidev,
587 IsrCount, &adapter->PIsr);
588 if (!adapter->Isr) {
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530589 /* Caller will call SxgFreeAdapter to clean up above
590 * allocations */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700591 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAResF9",
592 adapter, SXG_MAX_ENTRIES, 0, 0);
593 status = STATUS_RESOURCES;
594 goto per_tcb_allocation_failed;
595 }
596 memset(adapter->Isr, 0, sizeof(u32) * IsrCount);
597
Greg Kroah-Hartmand78404c2008-10-21 10:41:45 -0700598 DBG_ERROR("%s Allocate shared XMT ring zero index location size[%x]\n",
599 __func__, (unsigned int)sizeof(u32));
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700600
J.R. Maurob243c4a2008-10-20 19:28:58 -0400601 /* Allocate shared XMT ring zero index location */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700602 adapter->XmtRingZeroIndex = pci_alloc_consistent(adapter->pcidev,
603 sizeof(u32),
604 &adapter->
605 PXmtRingZeroIndex);
606 if (!adapter->XmtRingZeroIndex) {
607 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAResF10",
608 adapter, SXG_MAX_ENTRIES, 0, 0);
609 status = STATUS_RESOURCES;
610 goto per_tcb_allocation_failed;
611 }
612 memset(adapter->XmtRingZeroIndex, 0, sizeof(u32));
613
614 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAlcResS",
615 adapter, SXG_MAX_ENTRIES, 0, 0);
616
Harvey Harrisone88bd232008-10-17 14:46:10 -0700617 DBG_ERROR("%s EXIT\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700618 return (STATUS_SUCCESS);
619}
620
621/*
622 * sxg_config_pci -
623 *
624 * Set up PCI Configuration space
625 *
626 * Arguments -
627 * pcidev - A pointer to our adapter structure
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700628 */
629static void sxg_config_pci(struct pci_dev *pcidev)
630{
631 u16 pci_command;
632 u16 new_command;
633
634 pci_read_config_word(pcidev, PCI_COMMAND, &pci_command);
Harvey Harrisone88bd232008-10-17 14:46:10 -0700635 DBG_ERROR("sxg: %s PCI command[%4.4x]\n", __func__, pci_command);
J.R. Maurob243c4a2008-10-20 19:28:58 -0400636 /* Set the command register */
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530637 new_command = pci_command | (
638 /* Memory Space Enable */
639 PCI_COMMAND_MEMORY |
640 /* Bus master enable */
641 PCI_COMMAND_MASTER |
642 /* Memory write and invalidate */
643 PCI_COMMAND_INVALIDATE |
644 /* Parity error response */
645 PCI_COMMAND_PARITY |
646 /* System ERR */
647 PCI_COMMAND_SERR |
648 /* Fast back-to-back */
649 PCI_COMMAND_FAST_BACK);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700650 if (pci_command != new_command) {
651 DBG_ERROR("%s -- Updating PCI COMMAND register %4.4x->%4.4x.\n",
Harvey Harrisone88bd232008-10-17 14:46:10 -0700652 __func__, pci_command, new_command);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700653 pci_write_config_word(pcidev, PCI_COMMAND, new_command);
654 }
655}
656
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +0530657/*
658 * sxg_read_config
659 * @adapter : Pointer to the adapter structure for the card
660 * This function will read the configuration data from EEPROM/FLASH
661 */
662static inline int sxg_read_config(struct adapter_t *adapter)
663{
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +0530664 /* struct sxg_config data; */
Mithlesh Thukral942798b2009-01-05 21:14:34 +0530665 struct sw_cfg_data *data;
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +0530666 dma_addr_t p_addr;
667 unsigned long status;
668 unsigned long i;
669
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530670 data = pci_alloc_consistent(adapter->pcidev,
671 sizeof(struct sw_cfg_data), &p_addr);
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +0530672 if(!data) {
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +0530673 /*
674 * We cant get even this much memory. Raise a hell
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +0530675 * Get out of here
676 */
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530677 printk(KERN_ERR"%s : Could not allocate memory for reading \
678 EEPROM\n", __FUNCTION__);
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +0530679 return -ENOMEM;
680 }
681
682 WRITE_REG(adapter->UcodeRegs[0].ConfigStat, SXG_CFG_TIMEOUT, TRUE);
683
684 WRITE_REG64(adapter, adapter->UcodeRegs[0].Config, p_addr, 0);
685 for(i=0; i<1000; i++) {
686 READ_REG(adapter->UcodeRegs[0].ConfigStat, status);
687 if (status != SXG_CFG_TIMEOUT)
688 break;
689 mdelay(1); /* Do we really need this */
690 }
691
692 switch(status) {
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530693 /* Config read from EEPROM succeeded */
694 case SXG_CFG_LOAD_EEPROM:
695 /* Config read from Flash succeeded */
696 case SXG_CFG_LOAD_FLASH:
697 /* Copy the MAC address to adapter structure */
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530698 /* TODO: We are not doing the remaining part : FRU,
699 * etc
700 */
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +0530701 memcpy(adapter->macaddr, data->MacAddr[0].MacAddr,
702 sizeof(struct sxg_config_mac));
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530703 break;
704 case SXG_CFG_TIMEOUT:
705 case SXG_CFG_LOAD_INVALID:
706 case SXG_CFG_LOAD_ERROR:
707 default: /* Fix default handler later */
708 printk(KERN_WARNING"%s : We could not read the config \
709 word. Status = %ld\n", __FUNCTION__, status);
710 break;
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +0530711 }
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530712 pci_free_consistent(adapter->pcidev, sizeof(struct sw_cfg_data), data,
713 p_addr);
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +0530714 if (adapter->netdev) {
715 memcpy(adapter->netdev->dev_addr, adapter->currmacaddr, 6);
716 memcpy(adapter->netdev->perm_addr, adapter->currmacaddr, 6);
717 }
718 printk("LINSYS : These are the new MAC address\n");
719 sxg_dbg_macaddrs(adapter);
720
721 return status;
722}
723
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700724static int sxg_entry_probe(struct pci_dev *pcidev,
725 const struct pci_device_id *pci_tbl_entry)
726{
727 static int did_version = 0;
728 int err;
729 struct net_device *netdev;
J.R. Mauro73b07062008-10-28 18:42:02 -0400730 struct adapter_t *adapter;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700731 void __iomem *memmapped_ioaddr;
732 u32 status = 0;
733 ulong mmio_start = 0;
734 ulong mmio_len = 0;
735
736 DBG_ERROR("sxg: %s 2.6 VERSION ENTER jiffies[%lx] cpu %d\n",
Harvey Harrisone88bd232008-10-17 14:46:10 -0700737 __func__, jiffies, smp_processor_id());
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700738
J.R. Maurob243c4a2008-10-20 19:28:58 -0400739 /* Initialize trace buffer */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700740#ifdef ATKDBG
741 SxgTraceBuffer = &LSxgTraceBuffer;
742 SXG_TRACE_INIT(SxgTraceBuffer, TRACE_NOISY);
743#endif
744
745 sxg_global.dynamic_intagg = dynamic_intagg;
746
747 err = pci_enable_device(pcidev);
748
749 DBG_ERROR("Call pci_enable_device(%p) status[%x]\n", pcidev, err);
750 if (err) {
751 return err;
752 }
753
754 if (sxg_debug > 0 && did_version++ == 0) {
755 printk(KERN_INFO "%s\n", sxg_banner);
756 printk(KERN_INFO "%s\n", DRV_VERSION);
757 }
758
759 if (!(err = pci_set_dma_mask(pcidev, DMA_64BIT_MASK))) {
760 DBG_ERROR("pci_set_dma_mask(DMA_64BIT_MASK) successful\n");
761 } else {
762 if ((err = pci_set_dma_mask(pcidev, DMA_32BIT_MASK))) {
763 DBG_ERROR
764 ("No usable DMA configuration, aborting err[%x]\n",
765 err);
766 return err;
767 }
768 DBG_ERROR("pci_set_dma_mask(DMA_32BIT_MASK) successful\n");
769 }
770
771 DBG_ERROR("Call pci_request_regions\n");
772
773 err = pci_request_regions(pcidev, DRV_NAME);
774 if (err) {
775 DBG_ERROR("pci_request_regions FAILED err[%x]\n", err);
776 return err;
777 }
778
779 DBG_ERROR("call pci_set_master\n");
780 pci_set_master(pcidev);
781
782 DBG_ERROR("call alloc_etherdev\n");
J.R. Mauro73b07062008-10-28 18:42:02 -0400783 netdev = alloc_etherdev(sizeof(struct adapter_t));
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700784 if (!netdev) {
785 err = -ENOMEM;
786 goto err_out_exit_sxg_probe;
787 }
788 DBG_ERROR("alloc_etherdev for slic netdev[%p]\n", netdev);
789
790 SET_NETDEV_DEV(netdev, &pcidev->dev);
791
792 pci_set_drvdata(pcidev, netdev);
793 adapter = netdev_priv(netdev);
794 adapter->netdev = netdev;
795 adapter->pcidev = pcidev;
796
797 mmio_start = pci_resource_start(pcidev, 0);
798 mmio_len = pci_resource_len(pcidev, 0);
799
800 DBG_ERROR("sxg: call ioremap(mmio_start[%lx], mmio_len[%lx])\n",
801 mmio_start, mmio_len);
802
803 memmapped_ioaddr = ioremap(mmio_start, mmio_len);
Harvey Harrisone88bd232008-10-17 14:46:10 -0700804 DBG_ERROR("sxg: %s MEMMAPPED_IOADDR [%p]\n", __func__,
J.R. Mauro5c7514e2008-10-05 20:38:52 -0400805 memmapped_ioaddr);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700806 if (!memmapped_ioaddr) {
807 DBG_ERROR("%s cannot remap MMIO region %lx @ %lx\n",
Harvey Harrisone88bd232008-10-17 14:46:10 -0700808 __func__, mmio_len, mmio_start);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700809 goto err_out_free_mmio_region;
810 }
811
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530812 DBG_ERROR("sxg: %s found Alacritech SXG PCI, MMIO at %p, start[%lx] \
813 len[%lx], IRQ %d.\n", __func__, memmapped_ioaddr, mmio_start,
814 mmio_len, pcidev->irq);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700815
J.R. Mauro5c7514e2008-10-05 20:38:52 -0400816 adapter->HwRegs = (void *)memmapped_ioaddr;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700817 adapter->base_addr = memmapped_ioaddr;
818
819 mmio_start = pci_resource_start(pcidev, 2);
820 mmio_len = pci_resource_len(pcidev, 2);
821
822 DBG_ERROR("sxg: call ioremap(mmio_start[%lx], mmio_len[%lx])\n",
823 mmio_start, mmio_len);
824
825 memmapped_ioaddr = ioremap(mmio_start, mmio_len);
J.R. Mauro5c7514e2008-10-05 20:38:52 -0400826 DBG_ERROR("sxg: %s MEMMAPPED_IOADDR [%p]\n", __func__,
827 memmapped_ioaddr);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700828 if (!memmapped_ioaddr) {
829 DBG_ERROR("%s cannot remap MMIO region %lx @ %lx\n",
Harvey Harrisone88bd232008-10-17 14:46:10 -0700830 __func__, mmio_len, mmio_start);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700831 goto err_out_free_mmio_region;
832 }
833
834 DBG_ERROR("sxg: %s found Alacritech SXG PCI, MMIO at %p, "
835 "start[%lx] len[%lx], IRQ %d.\n", __func__,
836 memmapped_ioaddr, mmio_start, mmio_len, pcidev->irq);
837
838 adapter->UcodeRegs = (void *)memmapped_ioaddr;
839
840 adapter->State = SXG_STATE_INITIALIZING;
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +0530841 /*
842 * Maintain a list of all adapters anchored by
843 * the global SxgDriver structure.
844 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700845 adapter->Next = SxgDriver.Adapters;
846 SxgDriver.Adapters = adapter;
847 adapter->AdapterID = ++SxgDriver.AdapterID;
848
J.R. Maurob243c4a2008-10-20 19:28:58 -0400849 /* Initialize CRC table used to determine multicast hash */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700850 sxg_mcast_init_crc32();
851
852 adapter->JumboEnabled = FALSE;
853 adapter->RssEnabled = FALSE;
854 if (adapter->JumboEnabled) {
855 adapter->FrameSize = JUMBOMAXFRAME;
856 adapter->ReceiveBufferSize = SXG_RCV_JUMBO_BUFFER_SIZE;
857 } else {
858 adapter->FrameSize = ETHERMAXFRAME;
859 adapter->ReceiveBufferSize = SXG_RCV_DATA_BUFFER_SIZE;
860 }
861
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530862 /*
863 * status = SXG_READ_EEPROM(adapter);
864 * if (!status) {
865 * goto sxg_init_bad;
866 * }
867 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700868
Harvey Harrisone88bd232008-10-17 14:46:10 -0700869 DBG_ERROR("sxg: %s ENTER sxg_config_pci\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700870 sxg_config_pci(pcidev);
Harvey Harrisone88bd232008-10-17 14:46:10 -0700871 DBG_ERROR("sxg: %s EXIT sxg_config_pci\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700872
Harvey Harrisone88bd232008-10-17 14:46:10 -0700873 DBG_ERROR("sxg: %s ENTER sxg_init_driver\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700874 sxg_init_driver();
Harvey Harrisone88bd232008-10-17 14:46:10 -0700875 DBG_ERROR("sxg: %s EXIT sxg_init_driver\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700876
877 adapter->vendid = pci_tbl_entry->vendor;
878 adapter->devid = pci_tbl_entry->device;
879 adapter->subsysid = pci_tbl_entry->subdevice;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700880 adapter->slotnumber = ((pcidev->devfn >> 3) & 0x1F);
881 adapter->functionnumber = (pcidev->devfn & 0x7);
882 adapter->memorylength = pci_resource_len(pcidev, 0);
883 adapter->irq = pcidev->irq;
884 adapter->next_netdevice = head_netdevice;
885 head_netdevice = netdev;
J.R. Maurob243c4a2008-10-20 19:28:58 -0400886 adapter->port = 0; /*adapter->functionnumber; */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700887
J.R. Maurob243c4a2008-10-20 19:28:58 -0400888 /* Allocate memory and other resources */
Harvey Harrisone88bd232008-10-17 14:46:10 -0700889 DBG_ERROR("sxg: %s ENTER sxg_allocate_resources\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700890 status = sxg_allocate_resources(adapter);
891 DBG_ERROR("sxg: %s EXIT sxg_allocate_resources status %x\n",
Harvey Harrisone88bd232008-10-17 14:46:10 -0700892 __func__, status);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700893 if (status != STATUS_SUCCESS) {
894 goto err_out_unmap;
895 }
896
Harvey Harrisone88bd232008-10-17 14:46:10 -0700897 DBG_ERROR("sxg: %s ENTER sxg_download_microcode\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700898 if (sxg_download_microcode(adapter, SXG_UCODE_SAHARA)) {
899 DBG_ERROR("sxg: %s ENTER sxg_adapter_set_hwaddr\n",
Harvey Harrisone88bd232008-10-17 14:46:10 -0700900 __func__);
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +0530901 sxg_read_config(adapter);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700902 sxg_adapter_set_hwaddr(adapter);
903 } else {
904 adapter->state = ADAPT_FAIL;
905 adapter->linkstate = LINK_DOWN;
906 DBG_ERROR("sxg_download_microcode FAILED status[%x]\n", status);
907 }
908
909 netdev->base_addr = (unsigned long)adapter->base_addr;
910 netdev->irq = adapter->irq;
911 netdev->open = sxg_entry_open;
912 netdev->stop = sxg_entry_halt;
913 netdev->hard_start_xmit = sxg_send_packets;
914 netdev->do_ioctl = sxg_ioctl;
915#if XXXTODO
916 netdev->set_mac_address = sxg_mac_set_address;
917#if SLIC_GET_STATS_ENABLED
918 netdev->get_stats = sxg_get_stats;
919#endif
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700920#endif
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +0530921 netdev->set_multicast_list = sxg_mcast_set_list;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700922
923 strcpy(netdev->name, "eth%d");
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530924 /* strcpy(netdev->name, pci_name(pcidev)); */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700925 if ((err = register_netdev(netdev))) {
926 DBG_ERROR("Cannot register net device, aborting. %s\n",
927 netdev->name);
928 goto err_out_unmap;
929 }
930
931 DBG_ERROR
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530932 ("sxg: %s addr 0x%lx, irq %d, MAC addr \
933 %02X:%02X:%02X:%02X:%02X:%02X\n",
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700934 netdev->name, netdev->base_addr, pcidev->irq, netdev->dev_addr[0],
935 netdev->dev_addr[1], netdev->dev_addr[2], netdev->dev_addr[3],
936 netdev->dev_addr[4], netdev->dev_addr[5]);
937
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530938 /* sxg_init_bad: */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700939 ASSERT(status == FALSE);
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +0530940 /* sxg_free_adapter(adapter); */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700941
Harvey Harrisone88bd232008-10-17 14:46:10 -0700942 DBG_ERROR("sxg: %s EXIT status[%x] jiffies[%lx] cpu %d\n", __func__,
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700943 status, jiffies, smp_processor_id());
944 return status;
945
946 err_out_unmap:
947 iounmap((void *)memmapped_ioaddr);
948
949 err_out_free_mmio_region:
950 release_mem_region(mmio_start, mmio_len);
951
952 err_out_exit_sxg_probe:
953
Harvey Harrisone88bd232008-10-17 14:46:10 -0700954 DBG_ERROR("%s EXIT jiffies[%lx] cpu %d\n", __func__, jiffies,
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700955 smp_processor_id());
956
957 return -ENODEV;
958}
959
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700960/*
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +0530961 * LINE BASE Interrupt routines..
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700962 *
963 * sxg_disable_interrupt
964 *
965 * DisableInterrupt Handler
966 *
967 * Arguments:
968 *
969 * adapter: Our adapter structure
970 *
971 * Return Value:
972 * None.
973 */
J.R. Mauro73b07062008-10-28 18:42:02 -0400974static void sxg_disable_interrupt(struct adapter_t *adapter)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700975{
976 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DisIntr",
977 adapter, adapter->InterruptsEnabled, 0, 0);
J.R. Maurob243c4a2008-10-20 19:28:58 -0400978 /* For now, RSS is disabled with line based interrupts */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700979 ASSERT(adapter->RssEnabled == FALSE);
980 ASSERT(adapter->MsiEnabled == FALSE);
J.R. Maurob243c4a2008-10-20 19:28:58 -0400981 /* Turn off interrupts by writing to the icr register. */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700982 WRITE_REG(adapter->UcodeRegs[0].Icr, SXG_ICR(0, SXG_ICR_DISABLE), TRUE);
983
984 adapter->InterruptsEnabled = 0;
985
986 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XDisIntr",
987 adapter, adapter->InterruptsEnabled, 0, 0);
988}
989
990/*
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -0700991 * sxg_enable_interrupt
992 *
993 * EnableInterrupt Handler
994 *
995 * Arguments:
996 *
997 * adapter: Our adapter structure
998 *
999 * Return Value:
1000 * None.
1001 */
J.R. Mauro73b07062008-10-28 18:42:02 -04001002static void sxg_enable_interrupt(struct adapter_t *adapter)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001003{
1004 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "EnIntr",
1005 adapter, adapter->InterruptsEnabled, 0, 0);
J.R. Maurob243c4a2008-10-20 19:28:58 -04001006 /* For now, RSS is disabled with line based interrupts */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001007 ASSERT(adapter->RssEnabled == FALSE);
1008 ASSERT(adapter->MsiEnabled == FALSE);
J.R. Maurob243c4a2008-10-20 19:28:58 -04001009 /* Turn on interrupts by writing to the icr register. */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001010 WRITE_REG(adapter->UcodeRegs[0].Icr, SXG_ICR(0, SXG_ICR_ENABLE), TRUE);
1011
1012 adapter->InterruptsEnabled = 1;
1013
1014 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XEnIntr",
1015 adapter, 0, 0, 0);
1016}
1017
1018/*
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001019 * sxg_isr - Process an line-based interrupt
1020 *
1021 * Arguments:
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05301022 * Context - Our adapter structure
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001023 * QueueDefault - Output parameter to queue to default CPU
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05301024 * TargetCpus - Output bitmap to schedule DPC's
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001025 *
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05301026 * Return Value: TRUE if our interrupt
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001027 */
1028static irqreturn_t sxg_isr(int irq, void *dev_id)
1029{
Mithlesh Thukral942798b2009-01-05 21:14:34 +05301030 struct net_device *dev = (struct net_device *) dev_id;
J.R. Mauro73b07062008-10-28 18:42:02 -04001031 struct adapter_t *adapter = (struct adapter_t *) netdev_priv(dev);
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05301032 /* u32 CpuMask = 0, i; */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001033
1034 adapter->Stats.NumInts++;
1035 if (adapter->Isr[0] == 0) {
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05301036 /*
1037 * The SLIC driver used to experience a number of spurious
1038 * interrupts due to the delay associated with the masking of
1039 * the interrupt (we'd bounce back in here). If we see that
1040 * again with Sahara,add a READ_REG of the Icr register after
1041 * the WRITE_REG below.
1042 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001043 adapter->Stats.FalseInts++;
1044 return IRQ_NONE;
1045 }
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05301046 /*
1047 * Move the Isr contents and clear the value in
1048 * shared memory, and mask interrupts
1049 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001050 adapter->IsrCopy[0] = adapter->Isr[0];
1051 adapter->Isr[0] = 0;
1052 WRITE_REG(adapter->UcodeRegs[0].Icr, SXG_ICR(0, SXG_ICR_MASK), TRUE);
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05301053 /* ASSERT(adapter->IsrDpcsPending == 0); */
J.R. Maurob243c4a2008-10-20 19:28:58 -04001054#if XXXTODO /* RSS Stuff */
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05301055 /*
1056 * If RSS is enabled and the ISR specifies SXG_ISR_EVENT, then
1057 * schedule DPC's based on event queues.
1058 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001059 if (adapter->RssEnabled && (adapter->IsrCopy[0] & SXG_ISR_EVENT)) {
1060 for (i = 0;
1061 i < adapter->RssSystemInfo->ProcessorInfo.RssCpuCount;
1062 i++) {
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05301063 struct sxg_event_ring *EventRing =
1064 &adapter->EventRings[i];
Mithlesh Thukral942798b2009-01-05 21:14:34 +05301065 struct sxg_event *Event =
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001066 &EventRing->Ring[adapter->NextEvent[i]];
J.R. Mauro5c7514e2008-10-05 20:38:52 -04001067 unsigned char Cpu =
1068 adapter->RssSystemInfo->RssIdToCpu[i];
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001069 if (Event->Status & EVENT_STATUS_VALID) {
1070 adapter->IsrDpcsPending++;
1071 CpuMask |= (1 << Cpu);
1072 }
1073 }
1074 }
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05301075 /*
1076 * Now, either schedule the CPUs specified by the CpuMask,
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05301077 * or queue default
1078 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001079 if (CpuMask) {
1080 *QueueDefault = FALSE;
1081 } else {
1082 adapter->IsrDpcsPending = 1;
1083 *QueueDefault = TRUE;
1084 }
1085 *TargetCpus = CpuMask;
1086#endif
J.R. Maurob243c4a2008-10-20 19:28:58 -04001087 /* There are no DPCs in Linux, so call the handler now */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001088 sxg_handle_interrupt(adapter);
1089
1090 return IRQ_HANDLED;
1091}
1092
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +05301093int debug_inthandler = 0;
1094
J.R. Mauro73b07062008-10-28 18:42:02 -04001095static void sxg_handle_interrupt(struct adapter_t *adapter)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001096{
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05301097 /* unsigned char RssId = 0; */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001098 u32 NewIsr;
1099
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +05301100 if (++debug_inthandler < 20) {
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001101 DBG_ERROR("Enter sxg_handle_interrupt ISR[%x]\n",
1102 adapter->IsrCopy[0]);
1103 }
1104 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "HndlIntr",
1105 adapter, adapter->IsrCopy[0], 0, 0);
J.R. Maurob243c4a2008-10-20 19:28:58 -04001106 /* For now, RSS is disabled with line based interrupts */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001107 ASSERT(adapter->RssEnabled == FALSE);
1108 ASSERT(adapter->MsiEnabled == FALSE);
1109 ASSERT(adapter->IsrCopy[0]);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001110
J.R. Maurob243c4a2008-10-20 19:28:58 -04001111 /* Always process the event queue. */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001112 sxg_process_event_queue(adapter,
1113 (adapter->RssEnabled ? /*RssId */ 0 : 0));
1114
J.R. Maurob243c4a2008-10-20 19:28:58 -04001115#if XXXTODO /* RSS stuff */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001116 if (--adapter->IsrDpcsPending) {
J.R. Maurob243c4a2008-10-20 19:28:58 -04001117 /* We're done. */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001118 ASSERT(adapter->RssEnabled);
1119 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DPCsPend",
1120 adapter, 0, 0, 0);
1121 return;
1122 }
1123#endif
J.R. Maurob243c4a2008-10-20 19:28:58 -04001124 /* Last (or only) DPC processes the ISR and clears the interrupt. */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001125 NewIsr = sxg_process_isr(adapter, 0);
J.R. Maurob243c4a2008-10-20 19:28:58 -04001126 /* Reenable interrupts */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001127 adapter->IsrCopy[0] = 0;
1128 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "ClearIsr",
1129 adapter, NewIsr, 0, 0);
1130
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +05301131 if (debug_inthandler < 20) {
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001132 DBG_ERROR
1133 ("Exit sxg_handle_interrupt2 after enabling interrupt\n");
1134 }
1135
1136 WRITE_REG(adapter->UcodeRegs[0].Isr, NewIsr, TRUE);
1137
1138 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XHndlInt",
1139 adapter, 0, 0, 0);
1140}
1141
1142/*
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001143 * sxg_process_isr - Process an interrupt. Called from the line-based and
1144 * message based interrupt DPC routines
1145 *
1146 * Arguments:
1147 * adapter - Our adapter structure
1148 * Queue - The ISR that needs processing
1149 *
1150 * Return Value:
1151 * None
1152 */
J.R. Mauro73b07062008-10-28 18:42:02 -04001153static int sxg_process_isr(struct adapter_t *adapter, u32 MessageId)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001154{
1155 u32 Isr = adapter->IsrCopy[MessageId];
1156 u32 NewIsr = 0;
1157
1158 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "ProcIsr",
1159 adapter, Isr, 0, 0);
1160
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05301161 DBG_ERROR("%s: Entering with %d ISR value\n", __FUNCTION__, Isr);
J.R. Maurob243c4a2008-10-20 19:28:58 -04001162 /* Error */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001163 if (Isr & SXG_ISR_ERR) {
1164 if (Isr & SXG_ISR_PDQF) {
1165 adapter->Stats.PdqFull++;
Harvey Harrisone88bd232008-10-17 14:46:10 -07001166 DBG_ERROR("%s: SXG_ISR_ERR PDQF!!\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001167 }
J.R. Maurob243c4a2008-10-20 19:28:58 -04001168 /* No host buffer */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001169 if (Isr & SXG_ISR_RMISS) {
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05301170 /*
1171 * There is a bunch of code in the SLIC driver which
1172 * attempts to process more receive events per DPC
1173 * if we start to fall behind. We'll probablyd
1174 * need to do something similar here, but hold
1175 * off for now. I don't want to make the code more
1176 * complicated than strictly needed.
1177 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001178 adapter->Stats.RcvNoBuffer++;
1179 if (adapter->Stats.RcvNoBuffer < 5) {
1180 DBG_ERROR("%s: SXG_ISR_ERR RMISS!!\n",
Harvey Harrisone88bd232008-10-17 14:46:10 -07001181 __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001182 }
1183 }
J.R. Maurob243c4a2008-10-20 19:28:58 -04001184 /* Card crash */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001185 if (Isr & SXG_ISR_DEAD) {
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05301186 /*
1187 * Set aside the crash info and set the adapter state
1188 * to RESET
1189 */
1190 adapter->CrashCpu = (unsigned char)
1191 ((Isr & SXG_ISR_CPU) >> SXG_ISR_CPU_SHIFT);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001192 adapter->CrashLocation = (ushort) (Isr & SXG_ISR_CRASH);
1193 adapter->Dead = TRUE;
Harvey Harrisone88bd232008-10-17 14:46:10 -07001194 DBG_ERROR("%s: ISR_DEAD %x, CPU: %d\n", __func__,
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001195 adapter->CrashLocation, adapter->CrashCpu);
1196 }
J.R. Maurob243c4a2008-10-20 19:28:58 -04001197 /* Event ring full */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001198 if (Isr & SXG_ISR_ERFULL) {
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05301199 /*
1200 * Same issue as RMISS, really. This means the
1201 * host is falling behind the card. Need to increase
1202 * event ring size, process more events per interrupt,
1203 * and/or reduce/remove interrupt aggregation.
1204 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001205 adapter->Stats.EventRingFull++;
1206 DBG_ERROR("%s: SXG_ISR_ERR EVENT RING FULL!!\n",
Harvey Harrisone88bd232008-10-17 14:46:10 -07001207 __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001208 }
J.R. Maurob243c4a2008-10-20 19:28:58 -04001209 /* Transmit drop - no DRAM buffers or XMT error */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001210 if (Isr & SXG_ISR_XDROP) {
1211 adapter->Stats.XmtDrops++;
1212 adapter->Stats.XmtErrors++;
Harvey Harrisone88bd232008-10-17 14:46:10 -07001213 DBG_ERROR("%s: SXG_ISR_ERR XDROP!!\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001214 }
1215 }
J.R. Maurob243c4a2008-10-20 19:28:58 -04001216 /* Slowpath send completions */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001217 if (Isr & SXG_ISR_SPSEND) {
1218 sxg_complete_slow_send(adapter);
1219 }
J.R. Maurob243c4a2008-10-20 19:28:58 -04001220 /* Dump */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001221 if (Isr & SXG_ISR_UPC) {
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05301222 /* Maybe change when debug is added.. */
1223 ASSERT(adapter->DumpCmdRunning);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001224 adapter->DumpCmdRunning = FALSE;
1225 }
J.R. Maurob243c4a2008-10-20 19:28:58 -04001226 /* Link event */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001227 if (Isr & SXG_ISR_LINK) {
1228 sxg_link_event(adapter);
1229 }
J.R. Maurob243c4a2008-10-20 19:28:58 -04001230 /* Debug - breakpoint hit */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001231 if (Isr & SXG_ISR_BREAK) {
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05301232 /*
1233 * At the moment AGDB isn't written to support interactive
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05301234 * debug sessions. When it is, this interrupt will be used to
1235 * signal AGDB that it has hit a breakpoint. For now, ASSERT.
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05301236 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001237 ASSERT(0);
1238 }
J.R. Maurob243c4a2008-10-20 19:28:58 -04001239 /* Heartbeat response */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001240 if (Isr & SXG_ISR_PING) {
1241 adapter->PingOutstanding = FALSE;
1242 }
1243 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XProcIsr",
1244 adapter, Isr, NewIsr, 0);
1245
1246 return (NewIsr);
1247}
1248
1249/*
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001250 * sxg_process_event_queue - Process our event queue
1251 *
1252 * Arguments:
1253 * - adapter - Adapter structure
1254 * - RssId - The event queue requiring processing
1255 *
1256 * Return Value:
1257 * None.
1258 */
J.R. Mauro73b07062008-10-28 18:42:02 -04001259static u32 sxg_process_event_queue(struct adapter_t *adapter, u32 RssId)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001260{
Mithlesh Thukral942798b2009-01-05 21:14:34 +05301261 struct sxg_event_ring *EventRing = &adapter->EventRings[RssId];
1262 struct sxg_event *Event = &EventRing->Ring[adapter->NextEvent[RssId]];
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001263 u32 EventsProcessed = 0, Batches = 0;
1264 u32 num_skbs = 0;
1265 struct sk_buff *skb;
1266#ifdef LINUX_HANDLES_RCV_INDICATION_LISTS
1267 struct sk_buff *prev_skb = NULL;
1268 struct sk_buff *IndicationList[SXG_RCV_ARRAYSIZE];
1269 u32 Index;
Mithlesh Thukral942798b2009-01-05 21:14:34 +05301270 struct sxg_rcv_data_buffer_hdr *RcvDataBufferHdr;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001271#endif
1272 u32 ReturnStatus = 0;
1273
1274 ASSERT((adapter->State == SXG_STATE_RUNNING) ||
1275 (adapter->State == SXG_STATE_PAUSING) ||
1276 (adapter->State == SXG_STATE_PAUSED) ||
1277 (adapter->State == SXG_STATE_HALTING));
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05301278 /*
1279 * We may still have unprocessed events on the queue if
1280 * the card crashed. Don't process them.
1281 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001282 if (adapter->Dead) {
1283 return (0);
1284 }
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05301285 /*
1286 * In theory there should only be a single processor that
1287 * accesses this queue, and only at interrupt-DPC time. So/
1288 * we shouldn't need a lock for any of this.
1289 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001290 while (Event->Status & EVENT_STATUS_VALID) {
1291 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "Event",
1292 Event, Event->Code, Event->Status,
1293 adapter->NextEvent);
1294 switch (Event->Code) {
1295 case EVENT_CODE_BUFFERS:
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05301296 /* struct sxg_ring_info Head & Tail == unsigned char */
1297 ASSERT(!(Event->CommandIndex & 0xFF00));
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001298 sxg_complete_descriptor_blocks(adapter,
1299 Event->CommandIndex);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001300 break;
1301 case EVENT_CODE_SLOWRCV:
1302 --adapter->RcvBuffersOnCard;
1303 if ((skb = sxg_slow_receive(adapter, Event))) {
1304 u32 rx_bytes;
1305#ifdef LINUX_HANDLES_RCV_INDICATION_LISTS
J.R. Maurob243c4a2008-10-20 19:28:58 -04001306 /* Add it to our indication list */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001307 SXG_ADD_RCV_PACKET(adapter, skb, prev_skb,
1308 IndicationList, num_skbs);
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05301309 /*
1310 * Linux, we just pass up each skb to the
1311 * protocol above at this point, there is no
1312 * capability of an indication list.
1313 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001314#else
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05301315 /* CHECK skb_pull(skb, INIC_RCVBUF_HEADSIZE); */
1316 /* (rcvbuf->length & IRHDDR_FLEN_MSK); */
1317 rx_bytes = Event->Length;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001318 adapter->stats.rx_packets++;
1319 adapter->stats.rx_bytes += rx_bytes;
1320#if SXG_OFFLOAD_IP_CHECKSUM
1321 skb->ip_summed = CHECKSUM_UNNECESSARY;
1322#endif
1323 skb->dev = adapter->netdev;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001324 netif_rx(skb);
1325#endif
1326 }
1327 break;
1328 default:
1329 DBG_ERROR("%s: ERROR Invalid EventCode %d\n",
Harvey Harrisone88bd232008-10-17 14:46:10 -07001330 __func__, Event->Code);
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05301331 /* ASSERT(0); */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001332 }
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05301333 /*
1334 * See if we need to restock card receive buffers.
1335 * There are two things to note here:
1336 * First - This test is not SMP safe. The
1337 * adapter->BuffersOnCard field is protected via atomic
1338 * interlocked calls, but we do not protect it with respect
1339 * to these tests. The only way to do that is with a lock,
1340 * and I don't want to grab a lock every time we adjust the
1341 * BuffersOnCard count. Instead, we allow the buffer
1342 * replenishment to be off once in a while. The worst that
1343 * can happen is the card is given on more-or-less descriptor
1344 * block than the arbitrary value we've chosen. No big deal
1345 * In short DO NOT ADD A LOCK HERE, OR WHERE RcvBuffersOnCard
1346 * is adjusted.
1347 * Second - We expect this test to rarely
1348 * evaluate to true. We attempt to refill descriptor blocks
1349 * as they are returned to us (sxg_complete_descriptor_blocks)
1350 * so The only time this should evaluate to true is when
1351 * sxg_complete_descriptor_blocks failed to allocate
1352 * receive buffers.
1353 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001354 if (adapter->RcvBuffersOnCard < SXG_RCV_DATA_BUFFERS) {
1355 sxg_stock_rcv_buffers(adapter);
1356 }
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05301357 /*
1358 * It's more efficient to just set this to zero.
1359 * But clearing the top bit saves potential debug info...
1360 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001361 Event->Status &= ~EVENT_STATUS_VALID;
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05301362 /* Advance to the next event */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001363 SXG_ADVANCE_INDEX(adapter->NextEvent[RssId], EVENT_RING_SIZE);
1364 Event = &EventRing->Ring[adapter->NextEvent[RssId]];
1365 EventsProcessed++;
1366 if (EventsProcessed == EVENT_RING_BATCH) {
J.R. Maurob243c4a2008-10-20 19:28:58 -04001367 /* Release a batch of events back to the card */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001368 WRITE_REG(adapter->UcodeRegs[RssId].EventRelease,
1369 EVENT_RING_BATCH, FALSE);
1370 EventsProcessed = 0;
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05301371 /*
1372 * If we've processed our batch limit, break out of the
1373 * loop and return SXG_ISR_EVENT to arrange for us to
1374 * be called again
1375 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001376 if (Batches++ == EVENT_BATCH_LIMIT) {
1377 SXG_TRACE(TRACE_SXG, SxgTraceBuffer,
1378 TRACE_NOISY, "EvtLimit", Batches,
1379 adapter->NextEvent, 0, 0);
1380 ReturnStatus = SXG_ISR_EVENT;
1381 break;
1382 }
1383 }
1384 }
1385#ifdef LINUX_HANDLES_RCV_INDICATION_LISTS
J.R. Maurob243c4a2008-10-20 19:28:58 -04001386 /* Indicate any received dumb-nic frames */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001387 SXG_INDICATE_PACKETS(adapter, IndicationList, num_skbs);
1388#endif
J.R. Maurob243c4a2008-10-20 19:28:58 -04001389 /* Release events back to the card. */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001390 if (EventsProcessed) {
1391 WRITE_REG(adapter->UcodeRegs[RssId].EventRelease,
1392 EventsProcessed, FALSE);
1393 }
1394 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XPrcEvnt",
1395 Batches, EventsProcessed, adapter->NextEvent, num_skbs);
1396
1397 return (ReturnStatus);
1398}
1399
1400/*
1401 * sxg_complete_slow_send - Complete slowpath or dumb-nic sends
1402 *
1403 * Arguments -
1404 * adapter - A pointer to our adapter structure
1405
1406 * Return
1407 * None
1408 */
J.R. Mauro73b07062008-10-28 18:42:02 -04001409static void sxg_complete_slow_send(struct adapter_t *adapter)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001410{
Mithlesh Thukral942798b2009-01-05 21:14:34 +05301411 struct sxg_xmt_ring *XmtRing = &adapter->XmtRings[0];
1412 struct sxg_ring_info *XmtRingInfo = &adapter->XmtRingZeroInfo;
J.R. Mauro5c7514e2008-10-05 20:38:52 -04001413 u32 *ContextType;
Mithlesh Thukral942798b2009-01-05 21:14:34 +05301414 struct sxg_cmd *XmtCmd;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001415
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05301416 /*
1417 * NOTE - This lock is dropped and regrabbed in this loop.
1418 * This means two different processors can both be running/
1419 * through this loop. Be *very* careful.
1420 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001421 spin_lock(&adapter->XmtZeroLock);
1422 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "CmpSnds",
1423 adapter, XmtRingInfo->Head, XmtRingInfo->Tail, 0);
1424
1425 while (XmtRingInfo->Tail != *adapter->XmtRingZeroIndex) {
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05301426 /*
1427 * Locate the current Cmd (ring descriptor entry), and
1428 * associated SGL, and advance the tail
1429 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001430 SXG_RETURN_CMD(XmtRing, XmtRingInfo, XmtCmd, ContextType);
1431 ASSERT(ContextType);
1432 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "CmpSnd",
1433 XmtRingInfo->Head, XmtRingInfo->Tail, XmtCmd, 0);
J.R. Maurob243c4a2008-10-20 19:28:58 -04001434 /* Clear the SGL field. */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001435 XmtCmd->Sgl = 0;
1436
1437 switch (*ContextType) {
1438 case SXG_SGL_DUMB:
1439 {
1440 struct sk_buff *skb;
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05301441 struct sxg_scatter_gather *SxgSgl =
1442 (struct sxg_scatter_gather *)ContextType;
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +05301443
J.R. Maurob243c4a2008-10-20 19:28:58 -04001444 /* Dumb-nic send. Command context is the dumb-nic SGL */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001445 skb = (struct sk_buff *)ContextType;
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +05301446 skb = SxgSgl->DumbPacket;
J.R. Maurob243c4a2008-10-20 19:28:58 -04001447 /* Complete the send */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001448 SXG_TRACE(TRACE_SXG, SxgTraceBuffer,
1449 TRACE_IMPORTANT, "DmSndCmp", skb, 0,
1450 0, 0);
1451 ASSERT(adapter->Stats.XmtQLen);
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05301452 adapter->Stats.XmtQLen--;/* within XmtZeroLock */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001453 adapter->Stats.XmtOk++;
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05301454 /*
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05301455 * Now drop the lock and complete the send
1456 * back to Microsoft. We need to drop the lock
1457 * because Microsoft can come back with a
1458 * chimney send, which results in a double trip
1459 * in SxgTcpOuput
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05301460 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001461 spin_unlock(&adapter->XmtZeroLock);
1462 SXG_COMPLETE_DUMB_SEND(adapter, skb);
J.R. Maurob243c4a2008-10-20 19:28:58 -04001463 /* and reacquire.. */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001464 spin_lock(&adapter->XmtZeroLock);
1465 }
1466 break;
1467 default:
1468 ASSERT(0);
1469 }
1470 }
1471 spin_unlock(&adapter->XmtZeroLock);
1472 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "CmpSnd",
1473 adapter, XmtRingInfo->Head, XmtRingInfo->Tail, 0);
1474}
1475
1476/*
1477 * sxg_slow_receive
1478 *
1479 * Arguments -
1480 * adapter - A pointer to our adapter structure
1481 * Event - Receive event
1482 *
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05301483 * Return - skb
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001484 */
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05301485static struct sk_buff *sxg_slow_receive(struct adapter_t *adapter,
1486 struct sxg_event *Event)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001487{
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05301488 u32 BufferSize = adapter->ReceiveBufferSize;
Mithlesh Thukral942798b2009-01-05 21:14:34 +05301489 struct sxg_rcv_data_buffer_hdr *RcvDataBufferHdr;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001490 struct sk_buff *Packet;
1491
Mithlesh Thukral942798b2009-01-05 21:14:34 +05301492 RcvDataBufferHdr = (struct sxg_rcv_data_buffer_hdr *) Event->HostHandle;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001493 ASSERT(RcvDataBufferHdr);
1494 ASSERT(RcvDataBufferHdr->State == SXG_BUFFER_ONCARD);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001495 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_IMPORTANT, "SlowRcv", Event,
1496 RcvDataBufferHdr, RcvDataBufferHdr->State,
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05301497 /*RcvDataBufferHdr->VirtualAddress*/ 0);
J.R. Maurob243c4a2008-10-20 19:28:58 -04001498 /* Drop rcv frames in non-running state */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001499 switch (adapter->State) {
1500 case SXG_STATE_RUNNING:
1501 break;
1502 case SXG_STATE_PAUSING:
1503 case SXG_STATE_PAUSED:
1504 case SXG_STATE_HALTING:
1505 goto drop;
1506 default:
1507 ASSERT(0);
1508 goto drop;
1509 }
1510
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05301511 /*
1512 * memcpy(SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr),
1513 * RcvDataBufferHdr->VirtualAddress, Event->Length);
1514 */
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +05301515
J.R. Maurob243c4a2008-10-20 19:28:58 -04001516 /* Change buffer state to UPSTREAM */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001517 RcvDataBufferHdr->State = SXG_BUFFER_UPSTREAM;
1518 if (Event->Status & EVENT_STATUS_RCVERR) {
1519 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "RcvError",
1520 Event, Event->Status, Event->HostHandle, 0);
J.R. Maurob243c4a2008-10-20 19:28:58 -04001521 /* XXXTODO - Remove this print later */
J.R. Mauro5c7514e2008-10-05 20:38:52 -04001522 DBG_ERROR("SXG: Receive error %x\n", *(u32 *)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001523 SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr));
J.R. Mauro5c7514e2008-10-05 20:38:52 -04001524 sxg_process_rcv_error(adapter, *(u32 *)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001525 SXG_RECEIVE_DATA_LOCATION
1526 (RcvDataBufferHdr));
1527 goto drop;
1528 }
J.R. Maurob243c4a2008-10-20 19:28:58 -04001529#if XXXTODO /* VLAN stuff */
1530 /* If there's a VLAN tag, extract it and validate it */
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05301531 if (((struct ether_header *)
1532 (SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr)))->EtherType
1533 == ETHERTYPE_VLAN) {
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001534 if (SxgExtractVlanHeader(adapter, RcvDataBufferHdr, Event) !=
1535 STATUS_SUCCESS) {
1536 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY,
1537 "BadVlan", Event,
1538 SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr),
1539 Event->Length, 0);
1540 goto drop;
1541 }
1542 }
1543#endif
J.R. Maurob243c4a2008-10-20 19:28:58 -04001544 /* Dumb-nic frame. See if it passes our mac filter and update stats */
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05301545
1546 /*
1547 * ASK if (!sxg_mac_filter(adapter,
1548 * SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr),
1549 * Event->Length)) {
1550 * SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "RcvFiltr",
1551 * Event, SXG_RECEIVE_DATA_LOCATION(RcvDataBufferHdr),
1552 * Event->Length, 0);
1553 * goto drop;
1554 * }
1555 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001556
1557 Packet = RcvDataBufferHdr->SxgDumbRcvPacket;
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +05301558 SXG_ADJUST_RCV_PACKET(Packet, RcvDataBufferHdr, Event);
1559 Packet->protocol = eth_type_trans(Packet, adapter->netdev);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001560
1561 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_IMPORTANT, "DumbRcv",
1562 RcvDataBufferHdr, Packet, Event->Length, 0);
J.R. Maurob243c4a2008-10-20 19:28:58 -04001563 /* Lastly adjust the receive packet length. */
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +05301564 RcvDataBufferHdr->SxgDumbRcvPacket = NULL;
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05301565 SXG_ALLOCATE_RCV_PACKET(adapter, RcvDataBufferHdr, BufferSize);
1566 if (RcvDataBufferHdr->skb)
1567 {
1568 spin_lock(&adapter->RcvQLock);
1569 SXG_FREE_RCV_DATA_BUFFER(adapter, RcvDataBufferHdr);
1570 adapter->RcvBuffersOnCard ++;
1571 spin_unlock(&adapter->RcvQLock);
1572 }
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001573 return (Packet);
1574
1575 drop:
1576 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DropRcv",
1577 RcvDataBufferHdr, Event->Length, 0, 0);
1578 adapter->Stats.RcvDiscards++;
1579 spin_lock(&adapter->RcvQLock);
1580 SXG_FREE_RCV_DATA_BUFFER(adapter, RcvDataBufferHdr);
1581 spin_unlock(&adapter->RcvQLock);
1582 return (NULL);
1583}
1584
1585/*
1586 * sxg_process_rcv_error - process receive error and update
1587 * stats
1588 *
1589 * Arguments:
1590 * adapter - Adapter structure
1591 * ErrorStatus - 4-byte receive error status
1592 *
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05301593 * Return Value : None
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001594 */
J.R. Mauro73b07062008-10-28 18:42:02 -04001595static void sxg_process_rcv_error(struct adapter_t *adapter, u32 ErrorStatus)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001596{
1597 u32 Error;
1598
1599 adapter->Stats.RcvErrors++;
1600
1601 if (ErrorStatus & SXG_RCV_STATUS_TRANSPORT_ERROR) {
1602 Error = ErrorStatus & SXG_RCV_STATUS_TRANSPORT_MASK;
1603 switch (Error) {
1604 case SXG_RCV_STATUS_TRANSPORT_CSUM:
1605 adapter->Stats.TransportCsum++;
1606 break;
1607 case SXG_RCV_STATUS_TRANSPORT_UFLOW:
1608 adapter->Stats.TransportUflow++;
1609 break;
1610 case SXG_RCV_STATUS_TRANSPORT_HDRLEN:
1611 adapter->Stats.TransportHdrLen++;
1612 break;
1613 }
1614 }
1615 if (ErrorStatus & SXG_RCV_STATUS_NETWORK_ERROR) {
1616 Error = ErrorStatus & SXG_RCV_STATUS_NETWORK_MASK;
1617 switch (Error) {
1618 case SXG_RCV_STATUS_NETWORK_CSUM:
1619 adapter->Stats.NetworkCsum++;
1620 break;
1621 case SXG_RCV_STATUS_NETWORK_UFLOW:
1622 adapter->Stats.NetworkUflow++;
1623 break;
1624 case SXG_RCV_STATUS_NETWORK_HDRLEN:
1625 adapter->Stats.NetworkHdrLen++;
1626 break;
1627 }
1628 }
1629 if (ErrorStatus & SXG_RCV_STATUS_PARITY) {
1630 adapter->Stats.Parity++;
1631 }
1632 if (ErrorStatus & SXG_RCV_STATUS_LINK_ERROR) {
1633 Error = ErrorStatus & SXG_RCV_STATUS_LINK_MASK;
1634 switch (Error) {
1635 case SXG_RCV_STATUS_LINK_PARITY:
1636 adapter->Stats.LinkParity++;
1637 break;
1638 case SXG_RCV_STATUS_LINK_EARLY:
1639 adapter->Stats.LinkEarly++;
1640 break;
1641 case SXG_RCV_STATUS_LINK_BUFOFLOW:
1642 adapter->Stats.LinkBufOflow++;
1643 break;
1644 case SXG_RCV_STATUS_LINK_CODE:
1645 adapter->Stats.LinkCode++;
1646 break;
1647 case SXG_RCV_STATUS_LINK_DRIBBLE:
1648 adapter->Stats.LinkDribble++;
1649 break;
1650 case SXG_RCV_STATUS_LINK_CRC:
1651 adapter->Stats.LinkCrc++;
1652 break;
1653 case SXG_RCV_STATUS_LINK_OFLOW:
1654 adapter->Stats.LinkOflow++;
1655 break;
1656 case SXG_RCV_STATUS_LINK_UFLOW:
1657 adapter->Stats.LinkUflow++;
1658 break;
1659 }
1660 }
1661}
1662
1663/*
1664 * sxg_mac_filter
1665 *
1666 * Arguments:
1667 * adapter - Adapter structure
1668 * pether - Ethernet header
1669 * length - Frame length
1670 *
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05301671 * Return Value : TRUE if the frame is to be allowed
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001672 */
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05301673static bool sxg_mac_filter(struct adapter_t *adapter,
1674 struct ether_header *EtherHdr, ushort length)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001675{
1676 bool EqualAddr;
1677
1678 if (SXG_MULTICAST_PACKET(EtherHdr)) {
1679 if (SXG_BROADCAST_PACKET(EtherHdr)) {
J.R. Maurob243c4a2008-10-20 19:28:58 -04001680 /* broadcast */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001681 if (adapter->MacFilter & MAC_BCAST) {
1682 adapter->Stats.DumbRcvBcastPkts++;
1683 adapter->Stats.DumbRcvBcastBytes += length;
1684 adapter->Stats.DumbRcvPkts++;
1685 adapter->Stats.DumbRcvBytes += length;
1686 return (TRUE);
1687 }
1688 } else {
J.R. Maurob243c4a2008-10-20 19:28:58 -04001689 /* multicast */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001690 if (adapter->MacFilter & MAC_ALLMCAST) {
1691 adapter->Stats.DumbRcvMcastPkts++;
1692 adapter->Stats.DumbRcvMcastBytes += length;
1693 adapter->Stats.DumbRcvPkts++;
1694 adapter->Stats.DumbRcvBytes += length;
1695 return (TRUE);
1696 }
1697 if (adapter->MacFilter & MAC_MCAST) {
Mithlesh Thukral942798b2009-01-05 21:14:34 +05301698 struct sxg_multicast_address *MulticastAddrs =
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001699 adapter->MulticastAddrs;
1700 while (MulticastAddrs) {
1701 ETHER_EQ_ADDR(MulticastAddrs->Address,
1702 EtherHdr->ether_dhost,
1703 EqualAddr);
1704 if (EqualAddr) {
1705 adapter->Stats.
1706 DumbRcvMcastPkts++;
1707 adapter->Stats.
1708 DumbRcvMcastBytes += length;
1709 adapter->Stats.DumbRcvPkts++;
1710 adapter->Stats.DumbRcvBytes +=
1711 length;
1712 return (TRUE);
1713 }
1714 MulticastAddrs = MulticastAddrs->Next;
1715 }
1716 }
1717 }
1718 } else if (adapter->MacFilter & MAC_DIRECTED) {
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05301719 /*
1720 * Not broadcast or multicast. Must be directed at us or
1721 * the card is in promiscuous mode. Either way, consider it
1722 * ours if MAC_DIRECTED is set
1723 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001724 adapter->Stats.DumbRcvUcastPkts++;
1725 adapter->Stats.DumbRcvUcastBytes += length;
1726 adapter->Stats.DumbRcvPkts++;
1727 adapter->Stats.DumbRcvBytes += length;
1728 return (TRUE);
1729 }
1730 if (adapter->MacFilter & MAC_PROMISC) {
J.R. Maurob243c4a2008-10-20 19:28:58 -04001731 /* Whatever it is, keep it. */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001732 adapter->Stats.DumbRcvPkts++;
1733 adapter->Stats.DumbRcvBytes += length;
1734 return (TRUE);
1735 }
1736 adapter->Stats.RcvDiscards++;
1737 return (FALSE);
1738}
1739
J.R. Mauro73b07062008-10-28 18:42:02 -04001740static int sxg_register_interrupt(struct adapter_t *adapter)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001741{
1742 if (!adapter->intrregistered) {
1743 int retval;
1744
1745 DBG_ERROR
1746 ("sxg: %s AllocAdaptRsrcs adapter[%p] dev->irq[%x] %x\n",
Harvey Harrisone88bd232008-10-17 14:46:10 -07001747 __func__, adapter, adapter->netdev->irq, NR_IRQS);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001748
J.R. Mauro5c7514e2008-10-05 20:38:52 -04001749 spin_unlock_irqrestore(&sxg_global.driver_lock,
1750 sxg_global.flags);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001751
1752 retval = request_irq(adapter->netdev->irq,
1753 &sxg_isr,
1754 IRQF_SHARED,
1755 adapter->netdev->name, adapter->netdev);
1756
1757 spin_lock_irqsave(&sxg_global.driver_lock, sxg_global.flags);
1758
1759 if (retval) {
1760 DBG_ERROR("sxg: request_irq (%s) FAILED [%x]\n",
1761 adapter->netdev->name, retval);
1762 return (retval);
1763 }
1764 adapter->intrregistered = 1;
1765 adapter->IntRegistered = TRUE;
J.R. Maurob243c4a2008-10-20 19:28:58 -04001766 /* Disable RSS with line-based interrupts */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001767 adapter->MsiEnabled = FALSE;
1768 adapter->RssEnabled = FALSE;
1769 DBG_ERROR("sxg: %s AllocAdaptRsrcs adapter[%p] dev->irq[%x]\n",
Harvey Harrisone88bd232008-10-17 14:46:10 -07001770 __func__, adapter, adapter->netdev->irq);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001771 }
1772 return (STATUS_SUCCESS);
1773}
1774
J.R. Mauro73b07062008-10-28 18:42:02 -04001775static void sxg_deregister_interrupt(struct adapter_t *adapter)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001776{
Harvey Harrisone88bd232008-10-17 14:46:10 -07001777 DBG_ERROR("sxg: %s ENTER adapter[%p]\n", __func__, adapter);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001778#if XXXTODO
1779 slic_init_cleanup(adapter);
1780#endif
1781 memset(&adapter->stats, 0, sizeof(struct net_device_stats));
1782 adapter->error_interrupts = 0;
1783 adapter->rcv_interrupts = 0;
1784 adapter->xmit_interrupts = 0;
1785 adapter->linkevent_interrupts = 0;
1786 adapter->upr_interrupts = 0;
1787 adapter->num_isrs = 0;
1788 adapter->xmit_completes = 0;
1789 adapter->rcv_broadcasts = 0;
1790 adapter->rcv_multicasts = 0;
1791 adapter->rcv_unicasts = 0;
Harvey Harrisone88bd232008-10-17 14:46:10 -07001792 DBG_ERROR("sxg: %s EXIT\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001793}
1794
1795/*
1796 * sxg_if_init
1797 *
1798 * Perform initialization of our slic interface.
1799 *
1800 */
J.R. Mauro73b07062008-10-28 18:42:02 -04001801static int sxg_if_init(struct adapter_t *adapter)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001802{
Mithlesh Thukral942798b2009-01-05 21:14:34 +05301803 struct net_device *dev = adapter->netdev;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001804 int status = 0;
1805
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +05301806 DBG_ERROR("sxg: %s (%s) ENTER states[%d:%d] flags[%x]\n",
Harvey Harrisone88bd232008-10-17 14:46:10 -07001807 __func__, adapter->netdev->name,
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +05301808 adapter->state,
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001809 adapter->linkstate, dev->flags);
1810
1811 /* adapter should be down at this point */
1812 if (adapter->state != ADAPT_DOWN) {
1813 DBG_ERROR("sxg_if_init adapter->state != ADAPT_DOWN\n");
1814 return (-EIO);
1815 }
1816 ASSERT(adapter->linkstate == LINK_DOWN);
1817
1818 adapter->devflags_prev = dev->flags;
1819 adapter->macopts = MAC_DIRECTED;
1820 if (dev->flags) {
Harvey Harrisone88bd232008-10-17 14:46:10 -07001821 DBG_ERROR("sxg: %s (%s) Set MAC options: ", __func__,
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001822 adapter->netdev->name);
1823 if (dev->flags & IFF_BROADCAST) {
1824 adapter->macopts |= MAC_BCAST;
1825 DBG_ERROR("BCAST ");
1826 }
1827 if (dev->flags & IFF_PROMISC) {
1828 adapter->macopts |= MAC_PROMISC;
1829 DBG_ERROR("PROMISC ");
1830 }
1831 if (dev->flags & IFF_ALLMULTI) {
1832 adapter->macopts |= MAC_ALLMCAST;
1833 DBG_ERROR("ALL_MCAST ");
1834 }
1835 if (dev->flags & IFF_MULTICAST) {
1836 adapter->macopts |= MAC_MCAST;
1837 DBG_ERROR("MCAST ");
1838 }
1839 DBG_ERROR("\n");
1840 }
1841 status = sxg_register_interrupt(adapter);
1842 if (status != STATUS_SUCCESS) {
1843 DBG_ERROR("sxg_if_init: sxg_register_interrupt FAILED %x\n",
1844 status);
1845 sxg_deregister_interrupt(adapter);
1846 return (status);
1847 }
1848
1849 adapter->state = ADAPT_UP;
1850
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05301851 /* clear any pending events, then enable interrupts */
Harvey Harrisone88bd232008-10-17 14:46:10 -07001852 DBG_ERROR("sxg: %s ENABLE interrupts(slic)\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001853
1854 return (STATUS_SUCCESS);
1855}
1856
Mithlesh Thukral942798b2009-01-05 21:14:34 +05301857static int sxg_entry_open(struct net_device *dev)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001858{
J.R. Mauro73b07062008-10-28 18:42:02 -04001859 struct adapter_t *adapter = (struct adapter_t *) netdev_priv(dev);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001860 int status;
1861
1862 ASSERT(adapter);
Harvey Harrisone88bd232008-10-17 14:46:10 -07001863 DBG_ERROR("sxg: %s adapter->activated[%d]\n", __func__,
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001864 adapter->activated);
1865 DBG_ERROR
1866 ("sxg: %s (%s): [jiffies[%lx] cpu %d] dev[%p] adapt[%p] port[%d]\n",
Harvey Harrisone88bd232008-10-17 14:46:10 -07001867 __func__, adapter->netdev->name, jiffies, smp_processor_id(),
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001868 adapter->netdev, adapter, adapter->port);
1869
1870 netif_stop_queue(adapter->netdev);
1871
1872 spin_lock_irqsave(&sxg_global.driver_lock, sxg_global.flags);
1873 if (!adapter->activated) {
1874 sxg_global.num_sxg_ports_active++;
1875 adapter->activated = 1;
1876 }
J.R. Maurob243c4a2008-10-20 19:28:58 -04001877 /* Initialize the adapter */
Harvey Harrisone88bd232008-10-17 14:46:10 -07001878 DBG_ERROR("sxg: %s ENTER sxg_initialize_adapter\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001879 status = sxg_initialize_adapter(adapter);
1880 DBG_ERROR("sxg: %s EXIT sxg_initialize_adapter status[%x]\n",
Harvey Harrisone88bd232008-10-17 14:46:10 -07001881 __func__, status);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001882
1883 if (status == STATUS_SUCCESS) {
Harvey Harrisone88bd232008-10-17 14:46:10 -07001884 DBG_ERROR("sxg: %s ENTER sxg_if_init\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001885 status = sxg_if_init(adapter);
Harvey Harrisone88bd232008-10-17 14:46:10 -07001886 DBG_ERROR("sxg: %s EXIT sxg_if_init status[%x]\n", __func__,
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001887 status);
1888 }
1889
1890 if (status != STATUS_SUCCESS) {
1891 if (adapter->activated) {
1892 sxg_global.num_sxg_ports_active--;
1893 adapter->activated = 0;
1894 }
1895 spin_unlock_irqrestore(&sxg_global.driver_lock,
1896 sxg_global.flags);
1897 return (status);
1898 }
Harvey Harrisone88bd232008-10-17 14:46:10 -07001899 DBG_ERROR("sxg: %s ENABLE ALL INTERRUPTS\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001900
J.R. Maurob243c4a2008-10-20 19:28:58 -04001901 /* Enable interrupts */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001902 SXG_ENABLE_ALL_INTERRUPTS(adapter);
1903
Harvey Harrisone88bd232008-10-17 14:46:10 -07001904 DBG_ERROR("sxg: %s EXIT\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001905
1906 spin_unlock_irqrestore(&sxg_global.driver_lock, sxg_global.flags);
1907 return STATUS_SUCCESS;
1908}
1909
1910static void __devexit sxg_entry_remove(struct pci_dev *pcidev)
1911{
Mithlesh Thukral942798b2009-01-05 21:14:34 +05301912 struct net_device *dev = pci_get_drvdata(pcidev);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001913 u32 mmio_start = 0;
1914 unsigned int mmio_len = 0;
J.R. Mauro73b07062008-10-28 18:42:02 -04001915 struct adapter_t *adapter = (struct adapter_t *) netdev_priv(dev);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001916
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05301917 set_bit(ADAPT_DOWN, &adapter->state);
1918 flush_scheduled_work();
1919
1920 /* Deallocate Resources */
1921
1922 SxgFreeResources(adapter);
1923
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001924 ASSERT(adapter);
Harvey Harrisone88bd232008-10-17 14:46:10 -07001925 DBG_ERROR("sxg: %s ENTER dev[%p] adapter[%p]\n", __func__, dev,
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001926 adapter);
1927 sxg_deregister_interrupt(adapter);
1928 sxg_unmap_mmio_space(adapter);
Harvey Harrisone88bd232008-10-17 14:46:10 -07001929 DBG_ERROR("sxg: %s unregister_netdev\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001930
1931 mmio_start = pci_resource_start(pcidev, 0);
1932 mmio_len = pci_resource_len(pcidev, 0);
1933
Harvey Harrisone88bd232008-10-17 14:46:10 -07001934 DBG_ERROR("sxg: %s rel_region(0) start[%x] len[%x]\n", __func__,
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001935 mmio_start, mmio_len);
1936 release_mem_region(mmio_start, mmio_len);
1937
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05301938/*
Harvey Harrisone88bd232008-10-17 14:46:10 -07001939 DBG_ERROR("sxg: %s iounmap dev->base_addr[%x]\n", __func__,
J.R. Mauro5c7514e2008-10-05 20:38:52 -04001940 (unsigned int)dev->base_addr);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001941 iounmap((char *)dev->base_addr);
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05301942*/
1943 mmio_start = pci_resource_start(pcidev, 2);
1944 mmio_len = pci_resource_len(pcidev, 2);
1945
1946 DBG_ERROR("sxg: %s rel_region(2) start[%x] len[%x]\n", __FUNCTION__,
1947 mmio_start, mmio_len);
1948 release_mem_region(mmio_start, mmio_len);
1949
1950 iounmap((char *)dev->base_addr);
1951 unregister_netdev(dev);
1952 //pci_release_regions(pcidev);
1953 //free_netdev(dev);
1954 pci_disable_device(pcidev);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001955
Harvey Harrisone88bd232008-10-17 14:46:10 -07001956 DBG_ERROR("sxg: %s deallocate device\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001957 kfree(dev);
Harvey Harrisone88bd232008-10-17 14:46:10 -07001958 DBG_ERROR("sxg: %s EXIT\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001959}
1960
Mithlesh Thukral942798b2009-01-05 21:14:34 +05301961static int sxg_entry_halt(struct net_device *dev)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001962{
J.R. Mauro73b07062008-10-28 18:42:02 -04001963 struct adapter_t *adapter = (struct adapter_t *) netdev_priv(dev);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001964
1965 spin_lock_irqsave(&sxg_global.driver_lock, sxg_global.flags);
Harvey Harrisone88bd232008-10-17 14:46:10 -07001966 DBG_ERROR("sxg: %s (%s) ENTER\n", __func__, dev->name);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001967
1968 netif_stop_queue(adapter->netdev);
1969 adapter->state = ADAPT_DOWN;
1970 adapter->linkstate = LINK_DOWN;
1971 adapter->devflags_prev = 0;
1972 DBG_ERROR("sxg: %s (%s) set adapter[%p] state to ADAPT_DOWN(%d)\n",
Harvey Harrisone88bd232008-10-17 14:46:10 -07001973 __func__, dev->name, adapter, adapter->state);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001974
Harvey Harrisone88bd232008-10-17 14:46:10 -07001975 DBG_ERROR("sxg: %s (%s) EXIT\n", __func__, dev->name);
1976 DBG_ERROR("sxg: %s EXIT\n", __func__);
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05301977
1978 /* Disable interrupts */
1979 SXG_DISABLE_ALL_INTERRUPTS(adapter);
1980
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001981 spin_unlock_irqrestore(&sxg_global.driver_lock, sxg_global.flags);
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05301982
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001983 return (STATUS_SUCCESS);
1984}
1985
Mithlesh Thukral942798b2009-01-05 21:14:34 +05301986static int sxg_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001987{
1988 ASSERT(rq);
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05301989/* DBG_ERROR("sxg: %s cmd[%x] rq[%p] dev[%p]\n", __func__, cmd, rq, dev);*/
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001990 switch (cmd) {
1991 case SIOCSLICSETINTAGG:
1992 {
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05301993 /* struct adapter_t *adapter = (struct adapter_t *)
1994 * netdev_priv(dev);
1995 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07001996 u32 data[7];
1997 u32 intagg;
1998
1999 if (copy_from_user(data, rq->ifr_data, 28)) {
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302000 DBG_ERROR("copy_from_user FAILED getting \
2001 initial params\n");
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002002 return -EFAULT;
2003 }
2004 intagg = data[0];
2005 printk(KERN_EMERG
2006 "%s: set interrupt aggregation to %d\n",
Harvey Harrisone88bd232008-10-17 14:46:10 -07002007 __func__, intagg);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002008 return 0;
2009 }
2010
2011 default:
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302012 /* DBG_ERROR("sxg: %s UNSUPPORTED[%x]\n", __func__, cmd); */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002013 return -EOPNOTSUPP;
2014 }
2015 return 0;
2016}
2017
2018#define NORMAL_ETHFRAME 0
2019
2020/*
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002021 * sxg_send_packets - Send a skb packet
2022 *
2023 * Arguments:
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302024 * skb - The packet to send
2025 * dev - Our linux net device that refs our adapter
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002026 *
2027 * Return:
2028 * 0 regardless of outcome XXXTODO refer to e1000 driver
2029 */
Mithlesh Thukral942798b2009-01-05 21:14:34 +05302030static int sxg_send_packets(struct sk_buff *skb, struct net_device *dev)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002031{
J.R. Mauro73b07062008-10-28 18:42:02 -04002032 struct adapter_t *adapter = (struct adapter_t *) netdev_priv(dev);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002033 u32 status = STATUS_SUCCESS;
2034
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05302035 /*
2036 * DBG_ERROR("sxg: %s ENTER sxg_send_packets skb[%p]\n", __FUNCTION__,
2037 * skb);
2038 */
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +05302039 printk("ASK:sxg_send_packets: skb[%p]\n", skb);
2040
J.R. Maurob243c4a2008-10-20 19:28:58 -04002041 /* Check the adapter state */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002042 switch (adapter->State) {
2043 case SXG_STATE_INITIALIZING:
2044 case SXG_STATE_HALTED:
2045 case SXG_STATE_SHUTDOWN:
J.R. Maurob243c4a2008-10-20 19:28:58 -04002046 ASSERT(0); /* unexpected */
2047 /* fall through */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002048 case SXG_STATE_RESETTING:
2049 case SXG_STATE_SLEEP:
2050 case SXG_STATE_BOOTDIAG:
2051 case SXG_STATE_DIAG:
2052 case SXG_STATE_HALTING:
2053 status = STATUS_FAILURE;
2054 break;
2055 case SXG_STATE_RUNNING:
2056 if (adapter->LinkState != SXG_LINK_UP) {
2057 status = STATUS_FAILURE;
2058 }
2059 break;
2060 default:
2061 ASSERT(0);
2062 status = STATUS_FAILURE;
2063 }
2064 if (status != STATUS_SUCCESS) {
2065 goto xmit_fail;
2066 }
J.R. Maurob243c4a2008-10-20 19:28:58 -04002067 /* send a packet */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002068 status = sxg_transmit_packet(adapter, skb);
2069 if (status == STATUS_SUCCESS) {
2070 goto xmit_done;
2071 }
2072
2073 xmit_fail:
J.R. Maurob243c4a2008-10-20 19:28:58 -04002074 /* reject & complete all the packets if they cant be sent */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002075 if (status != STATUS_SUCCESS) {
2076#if XXXTODO
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302077 /* sxg_send_packets_fail(adapter, skb, status); */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002078#else
2079 SXG_DROP_DUMB_SEND(adapter, skb);
2080 adapter->stats.tx_dropped++;
2081#endif
2082 }
Harvey Harrisone88bd232008-10-17 14:46:10 -07002083 DBG_ERROR("sxg: %s EXIT sxg_send_packets status[%x]\n", __func__,
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002084 status);
2085
2086 xmit_done:
2087 return 0;
2088}
2089
2090/*
2091 * sxg_transmit_packet
2092 *
2093 * This function transmits a single packet.
2094 *
2095 * Arguments -
2096 * adapter - Pointer to our adapter structure
2097 * skb - The packet to be sent
2098 *
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302099 * Return - STATUS of send
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002100 */
J.R. Mauro73b07062008-10-28 18:42:02 -04002101static int sxg_transmit_packet(struct adapter_t *adapter, struct sk_buff *skb)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002102{
Mithlesh Thukral942798b2009-01-05 21:14:34 +05302103 struct sxg_x64_sgl *pSgl;
2104 struct sxg_scatter_gather *SxgSgl;
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05302105 /* void *SglBuffer; */
2106 /* u32 SglBufferLength; */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002107
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05302108 /*
2109 * The vast majority of work is done in the shared
2110 * sxg_dumb_sgl routine.
2111 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002112 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DumbSend",
2113 adapter, skb, 0, 0);
2114
J.R. Maurob243c4a2008-10-20 19:28:58 -04002115 /* Allocate a SGL buffer */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002116 SXG_GET_SGL_BUFFER(adapter, SxgSgl);
2117 if (!SxgSgl) {
2118 adapter->Stats.NoSglBuf++;
2119 adapter->Stats.XmtErrors++;
2120 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "SndPktF1",
2121 adapter, skb, 0, 0);
2122 return (STATUS_RESOURCES);
2123 }
2124 ASSERT(SxgSgl->adapter == adapter);
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05302125 /*SglBuffer = SXG_SGL_BUFFER(SxgSgl);
2126 SglBufferLength = SXG_SGL_BUF_SIZE; */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002127 SxgSgl->VlanTag.VlanTci = 0;
2128 SxgSgl->VlanTag.VlanTpid = 0;
2129 SxgSgl->Type = SXG_SGL_DUMB;
2130 SxgSgl->DumbPacket = skb;
2131 pSgl = NULL;
2132
J.R. Maurob243c4a2008-10-20 19:28:58 -04002133 /* Call the common sxg_dumb_sgl routine to complete the send. */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002134 sxg_dumb_sgl(pSgl, SxgSgl);
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302135 /* Return success sxg_dumb_sgl (or something later) will complete it.*/
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002136 return (STATUS_SUCCESS);
2137}
2138
2139/*
2140 * sxg_dumb_sgl
2141 *
2142 * Arguments:
2143 * pSgl -
Mithlesh Thukral942798b2009-01-05 21:14:34 +05302144 * SxgSgl - struct sxg_scatter_gather
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002145 *
2146 * Return Value:
2147 * None.
2148 */
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302149static void sxg_dumb_sgl(struct sxg_x64_sgl *pSgl,
2150 struct sxg_scatter_gather *SxgSgl)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002151{
J.R. Mauro73b07062008-10-28 18:42:02 -04002152 struct adapter_t *adapter = SxgSgl->adapter;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002153 struct sk_buff *skb = SxgSgl->DumbPacket;
J.R. Maurob243c4a2008-10-20 19:28:58 -04002154 /* For now, all dumb-nic sends go on RSS queue zero */
Mithlesh Thukral942798b2009-01-05 21:14:34 +05302155 struct sxg_xmt_ring *XmtRing = &adapter->XmtRings[0];
2156 struct sxg_ring_info *XmtRingInfo = &adapter->XmtRingZeroInfo;
2157 struct sxg_cmd *XmtCmd = NULL;
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302158 /* u32 Index = 0; */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002159 u32 DataLength = skb->len;
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302160 /* unsigned int BufLen; */
2161 /* u32 SglOffset; */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002162 u64 phys_addr;
2163
2164 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DumbSgl",
2165 pSgl, SxgSgl, 0, 0);
2166
J.R. Maurob243c4a2008-10-20 19:28:58 -04002167 /* Set aside a pointer to the sgl */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002168 SxgSgl->pSgl = pSgl;
2169
J.R. Maurob243c4a2008-10-20 19:28:58 -04002170 /* Sanity check that our SGL format is as we expect. */
Mithlesh Thukral942798b2009-01-05 21:14:34 +05302171 ASSERT(sizeof(struct sxg_x64_sge) == sizeof(struct sxg_x64_sge));
J.R. Maurob243c4a2008-10-20 19:28:58 -04002172 /* Shouldn't be a vlan tag on this frame */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002173 ASSERT(SxgSgl->VlanTag.VlanTci == 0);
2174 ASSERT(SxgSgl->VlanTag.VlanTpid == 0);
2175
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05302176 /*
2177 * From here below we work with the SGL placed in our
2178 * buffer.
2179 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002180
2181 SxgSgl->Sgl.NumberOfElements = 1;
2182
J.R. Maurob243c4a2008-10-20 19:28:58 -04002183 /* Grab the spinlock and acquire a command */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002184 spin_lock(&adapter->XmtZeroLock);
2185 SXG_GET_CMD(XmtRing, XmtRingInfo, XmtCmd, SxgSgl);
2186 if (XmtCmd == NULL) {
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05302187 /*
2188 * Call sxg_complete_slow_send to see if we can
2189 * free up any XmtRingZero entries and then try again
2190 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002191 spin_unlock(&adapter->XmtZeroLock);
2192 sxg_complete_slow_send(adapter);
2193 spin_lock(&adapter->XmtZeroLock);
2194 SXG_GET_CMD(XmtRing, XmtRingInfo, XmtCmd, SxgSgl);
2195 if (XmtCmd == NULL) {
2196 adapter->Stats.XmtZeroFull++;
2197 goto abortcmd;
2198 }
2199 }
2200 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DumbCmd",
2201 XmtCmd, XmtRingInfo->Head, XmtRingInfo->Tail, 0);
J.R. Maurob243c4a2008-10-20 19:28:58 -04002202 /* Update stats */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002203 adapter->Stats.DumbXmtPkts++;
2204 adapter->Stats.DumbXmtBytes += DataLength;
J.R. Maurob243c4a2008-10-20 19:28:58 -04002205#if XXXTODO /* Stats stuff */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002206 if (SXG_MULTICAST_PACKET(EtherHdr)) {
2207 if (SXG_BROADCAST_PACKET(EtherHdr)) {
2208 adapter->Stats.DumbXmtBcastPkts++;
2209 adapter->Stats.DumbXmtBcastBytes += DataLength;
2210 } else {
2211 adapter->Stats.DumbXmtMcastPkts++;
2212 adapter->Stats.DumbXmtMcastBytes += DataLength;
2213 }
2214 } else {
2215 adapter->Stats.DumbXmtUcastPkts++;
2216 adapter->Stats.DumbXmtUcastBytes += DataLength;
2217 }
2218#endif
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05302219 /*
2220 * Fill in the command
2221 * Copy out the first SGE to the command and adjust for offset
2222 */
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302223 phys_addr = pci_map_single(adapter->pcidev, skb->data, skb->len,
J.R. Mauro5c7514e2008-10-05 20:38:52 -04002224 PCI_DMA_TODEVICE);
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +05302225 memset(XmtCmd, '\0', sizeof(*XmtCmd));
2226 XmtCmd->Buffer.FirstSgeAddress = phys_addr;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002227 XmtCmd->Buffer.FirstSgeLength = DataLength;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002228 XmtCmd->Buffer.SgeOffset = 0;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002229 XmtCmd->Buffer.TotalLength = DataLength;
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +05302230 XmtCmd->SgEntries = 1;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002231 XmtCmd->Flags = 0;
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05302232 /*
2233 * Advance transmit cmd descripter by 1.
2234 * NOTE - See comments in SxgTcpOutput where we write
2235 * to the XmtCmd register regarding CPU ID values and/or
2236 * multiple commands.
2237 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002238 WRITE_REG(adapter->UcodeRegs[0].XmtCmd, 1, TRUE);
J.R. Maurob243c4a2008-10-20 19:28:58 -04002239 adapter->Stats.XmtQLen++; /* Stats within lock */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002240 spin_unlock(&adapter->XmtZeroLock);
2241 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XDumSgl2",
2242 XmtCmd, pSgl, SxgSgl, 0);
2243 return;
2244
2245 abortcmd:
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05302246 /*
2247 * NOTE - Only jump to this label AFTER grabbing the
2248 * XmtZeroLock, and DO NOT DROP IT between the
2249 * command allocation and the following abort.
2250 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002251 if (XmtCmd) {
2252 SXG_ABORT_CMD(XmtRingInfo);
2253 }
2254 spin_unlock(&adapter->XmtZeroLock);
2255
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05302256/*
2257 * failsgl:
2258 * Jump to this label if failure occurs before the
2259 * XmtZeroLock is grabbed
2260 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002261 adapter->Stats.XmtErrors++;
2262 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_IMPORTANT, "DumSGFal",
2263 pSgl, SxgSgl, XmtRingInfo->Head, XmtRingInfo->Tail);
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302264 /* SxgSgl->DumbPacket is the skb */
2265 SXG_COMPLETE_DUMB_SEND(adapter, SxgSgl->DumbPacket);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002266}
2267
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002268/*
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05302269 * Link management functions
2270 *
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002271 * sxg_initialize_link - Initialize the link stuff
2272 *
2273 * Arguments -
2274 * adapter - A pointer to our adapter structure
2275 *
2276 * Return
2277 * status
2278 */
J.R. Mauro73b07062008-10-28 18:42:02 -04002279static int sxg_initialize_link(struct adapter_t *adapter)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002280{
Mithlesh Thukral942798b2009-01-05 21:14:34 +05302281 struct sxg_hw_regs *HwRegs = adapter->HwRegs;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002282 u32 Value;
2283 u32 ConfigData;
2284 u32 MaxFrame;
2285 int status;
2286
2287 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "InitLink",
2288 adapter, 0, 0, 0);
2289
J.R. Maurob243c4a2008-10-20 19:28:58 -04002290 /* Reset PHY and XGXS module */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002291 WRITE_REG(HwRegs->LinkStatus, LS_SERDES_POWER_DOWN, TRUE);
2292
J.R. Maurob243c4a2008-10-20 19:28:58 -04002293 /* Reset transmit configuration register */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002294 WRITE_REG(HwRegs->XmtConfig, XMT_CONFIG_RESET, TRUE);
2295
J.R. Maurob243c4a2008-10-20 19:28:58 -04002296 /* Reset receive configuration register */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002297 WRITE_REG(HwRegs->RcvConfig, RCV_CONFIG_RESET, TRUE);
2298
J.R. Maurob243c4a2008-10-20 19:28:58 -04002299 /* Reset all MAC modules */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002300 WRITE_REG(HwRegs->MacConfig0, AXGMAC_CFG0_SUB_RESET, TRUE);
2301
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05302302 /*
2303 * Link address 0
2304 * XXXTODO - This assumes the MAC address (0a:0b:0c:0d:0e:0f)
2305 * is stored with the first nibble (0a) in the byte 0
2306 * of the Mac address. Possibly reverse?
2307 */
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +05302308 Value = *(u32 *) adapter->macaddr;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002309 WRITE_REG(HwRegs->LinkAddress0Low, Value, TRUE);
J.R. Maurob243c4a2008-10-20 19:28:58 -04002310 /* also write the MAC address to the MAC. Endian is reversed. */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002311 WRITE_REG(HwRegs->MacAddressLow, ntohl(Value), TRUE);
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +05302312 Value = (*(u16 *) & adapter->macaddr[4] & 0x0000FFFF);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002313 WRITE_REG(HwRegs->LinkAddress0High, Value | LINK_ADDRESS_ENABLE, TRUE);
J.R. Maurob243c4a2008-10-20 19:28:58 -04002314 /* endian swap for the MAC (put high bytes in bits [31:16], swapped) */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002315 Value = ntohl(Value);
2316 WRITE_REG(HwRegs->MacAddressHigh, Value, TRUE);
J.R. Maurob243c4a2008-10-20 19:28:58 -04002317 /* Link address 1 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002318 WRITE_REG(HwRegs->LinkAddress1Low, 0, TRUE);
2319 WRITE_REG(HwRegs->LinkAddress1High, 0, TRUE);
J.R. Maurob243c4a2008-10-20 19:28:58 -04002320 /* Link address 2 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002321 WRITE_REG(HwRegs->LinkAddress2Low, 0, TRUE);
2322 WRITE_REG(HwRegs->LinkAddress2High, 0, TRUE);
J.R. Maurob243c4a2008-10-20 19:28:58 -04002323 /* Link address 3 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002324 WRITE_REG(HwRegs->LinkAddress3Low, 0, TRUE);
2325 WRITE_REG(HwRegs->LinkAddress3High, 0, TRUE);
2326
J.R. Maurob243c4a2008-10-20 19:28:58 -04002327 /* Enable MAC modules */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002328 WRITE_REG(HwRegs->MacConfig0, 0, TRUE);
2329
J.R. Maurob243c4a2008-10-20 19:28:58 -04002330 /* Configure MAC */
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302331 WRITE_REG(HwRegs->MacConfig1, (
2332 /* Allow sending of pause */
2333 AXGMAC_CFG1_XMT_PAUSE |
2334 /* Enable XMT */
2335 AXGMAC_CFG1_XMT_EN |
2336 /* Enable detection of pause */
2337 AXGMAC_CFG1_RCV_PAUSE |
2338 /* Enable receive */
2339 AXGMAC_CFG1_RCV_EN |
2340 /* short frame detection */
2341 AXGMAC_CFG1_SHORT_ASSERT |
2342 /* Verify frame length */
2343 AXGMAC_CFG1_CHECK_LEN |
2344 /* Generate FCS */
2345 AXGMAC_CFG1_GEN_FCS |
2346 /* Pad frames to 64 bytes */
2347 AXGMAC_CFG1_PAD_64),
2348 TRUE);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002349
J.R. Maurob243c4a2008-10-20 19:28:58 -04002350 /* Set AXGMAC max frame length if jumbo. Not needed for standard MTU */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002351 if (adapter->JumboEnabled) {
2352 WRITE_REG(HwRegs->MacMaxFrameLen, AXGMAC_MAXFRAME_JUMBO, TRUE);
2353 }
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05302354 /*
2355 * AMIIM Configuration Register -
2356 * The value placed in the AXGMAC_AMIIM_CFG_HALF_CLOCK portion
2357 * (bottom bits) of this register is used to determine the MDC frequency
2358 * as specified in the A-XGMAC Design Document. This value must not be
2359 * zero. The following value (62 or 0x3E) is based on our MAC transmit
2360 * clock frequency (MTCLK) of 312.5 MHz. Given a maximum MDIO clock
2361 * frequency of 2.5 MHz (see the PHY spec), we get:
2362 * 312.5/(2*(X+1)) < 2.5 ==> X = 62.
2363 * This value happens to be the default value for this register, so we
2364 * really don't have to do this.
2365 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002366 WRITE_REG(HwRegs->MacAmiimConfig, 0x0000003E, TRUE);
2367
J.R. Maurob243c4a2008-10-20 19:28:58 -04002368 /* Power up and enable PHY and XAUI/XGXS/Serdes logic */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002369 WRITE_REG(HwRegs->LinkStatus,
2370 (LS_PHY_CLR_RESET |
2371 LS_XGXS_ENABLE |
2372 LS_XGXS_CTL | LS_PHY_CLK_EN | LS_ATTN_ALARM), TRUE);
2373 DBG_ERROR("After Power Up and enable PHY in sxg_initialize_link\n");
2374
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05302375 /*
2376 * Per information given by Aeluros, wait 100 ms after removing reset.
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302377 * It's not enough to wait for the self-clearing reset bit in reg 0 to
2378 * clear.
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05302379 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002380 mdelay(100);
2381
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302382 /* Verify the PHY has come up by checking that the Reset bit has
2383 * cleared.
2384 */
2385 status = sxg_read_mdio_reg(adapter,
2386 MIIM_DEV_PHY_PMA, /* PHY PMA/PMD module */
2387 PHY_PMA_CONTROL1, /* PMA/PMD control register */
2388 &Value);
2389 DBG_ERROR("After sxg_read_mdio_reg Value[%x] fail=%x\n", Value,
2390 (Value & PMA_CONTROL1_RESET));
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002391 if (status != STATUS_SUCCESS)
2392 return (STATUS_FAILURE);
J.R. Maurob243c4a2008-10-20 19:28:58 -04002393 if (Value & PMA_CONTROL1_RESET) /* reset complete if bit is 0 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002394 return (STATUS_FAILURE);
2395
J.R. Maurob243c4a2008-10-20 19:28:58 -04002396 /* The SERDES should be initialized by now - confirm */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002397 READ_REG(HwRegs->LinkStatus, Value);
J.R. Maurob243c4a2008-10-20 19:28:58 -04002398 if (Value & LS_SERDES_DOWN) /* verify SERDES is initialized */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002399 return (STATUS_FAILURE);
2400
J.R. Maurob243c4a2008-10-20 19:28:58 -04002401 /* The XAUI link should also be up - confirm */
2402 if (!(Value & LS_XAUI_LINK_UP)) /* verify XAUI link is up */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002403 return (STATUS_FAILURE);
2404
J.R. Maurob243c4a2008-10-20 19:28:58 -04002405 /* Initialize the PHY */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002406 status = sxg_phy_init(adapter);
2407 if (status != STATUS_SUCCESS)
2408 return (STATUS_FAILURE);
2409
J.R. Maurob243c4a2008-10-20 19:28:58 -04002410 /* Enable the Link Alarm */
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302411
2412 /* MIIM_DEV_PHY_PMA - PHY PMA/PMD module
2413 * LASI_CONTROL - LASI control register
2414 * LASI_CTL_LS_ALARM_ENABLE - enable link alarm bit
2415 */
2416 status = sxg_write_mdio_reg(adapter, MIIM_DEV_PHY_PMA,
2417 LASI_CONTROL,
2418 LASI_CTL_LS_ALARM_ENABLE);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002419 if (status != STATUS_SUCCESS)
2420 return (STATUS_FAILURE);
2421
J.R. Maurob243c4a2008-10-20 19:28:58 -04002422 /* XXXTODO - temporary - verify bit is set */
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302423
2424 /* MIIM_DEV_PHY_PMA - PHY PMA/PMD module
2425 * LASI_CONTROL - LASI control register
2426 */
2427 status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA,
2428 LASI_CONTROL,
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002429 &Value);
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302430
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002431 if (status != STATUS_SUCCESS)
2432 return (STATUS_FAILURE);
2433 if (!(Value & LASI_CTL_LS_ALARM_ENABLE)) {
2434 DBG_ERROR("Error! LASI Control Alarm Enable bit not set!\n");
2435 }
J.R. Maurob243c4a2008-10-20 19:28:58 -04002436 /* Enable receive */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002437 MaxFrame = adapter->JumboEnabled ? JUMBOMAXFRAME : ETHERMAXFRAME;
2438 ConfigData = (RCV_CONFIG_ENABLE |
2439 RCV_CONFIG_ENPARSE |
2440 RCV_CONFIG_RCVBAD |
2441 RCV_CONFIG_RCVPAUSE |
2442 RCV_CONFIG_TZIPV6 |
2443 RCV_CONFIG_TZIPV4 |
2444 RCV_CONFIG_HASH_16 |
2445 RCV_CONFIG_SOCKET | RCV_CONFIG_BUFSIZE(MaxFrame));
2446 WRITE_REG(HwRegs->RcvConfig, ConfigData, TRUE);
2447
2448 WRITE_REG(HwRegs->XmtConfig, XMT_CONFIG_ENABLE, TRUE);
2449
J.R. Maurob243c4a2008-10-20 19:28:58 -04002450 /* Mark the link as down. We'll get a link event when it comes up. */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002451 sxg_link_state(adapter, SXG_LINK_DOWN);
2452
2453 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XInitLnk",
2454 adapter, 0, 0, 0);
2455 return (STATUS_SUCCESS);
2456}
2457
2458/*
2459 * sxg_phy_init - Initialize the PHY
2460 *
2461 * Arguments -
2462 * adapter - A pointer to our adapter structure
2463 *
2464 * Return
2465 * status
2466 */
J.R. Mauro73b07062008-10-28 18:42:02 -04002467static int sxg_phy_init(struct adapter_t *adapter)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002468{
2469 u32 Value;
Mithlesh Thukral942798b2009-01-05 21:14:34 +05302470 struct phy_ucode *p;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002471 int status;
2472
Harvey Harrisone88bd232008-10-17 14:46:10 -07002473 DBG_ERROR("ENTER %s\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002474
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302475 /* MIIM_DEV_PHY_PMA - PHY PMA/PMD module
2476 * 0xC205 - PHY ID register (?)
2477 * &Value - XXXTODO - add def
2478 */
2479 status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA,
2480 0xC205,
2481 &Value);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002482 if (status != STATUS_SUCCESS)
2483 return (STATUS_FAILURE);
2484
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302485 if (Value == 0x0012) {
2486 /* 0x0012 == AEL2005C PHY(?) - XXXTODO - add def */
2487 DBG_ERROR("AEL2005C PHY detected. Downloading PHY \
2488 microcode.\n");
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002489
J.R. Maurob243c4a2008-10-20 19:28:58 -04002490 /* Initialize AEL2005C PHY and download PHY microcode */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002491 for (p = PhyUcode; p->Addr != 0xFFFF; p++) {
2492 if (p->Addr == 0) {
J.R. Maurob243c4a2008-10-20 19:28:58 -04002493 /* if address == 0, data == sleep time in ms */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002494 mdelay(p->Data);
2495 } else {
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302496 /* write the given data to the specified address */
2497 status = sxg_write_mdio_reg(adapter,
2498 MIIM_DEV_PHY_PMA,
2499 /* PHY address */
2500 p->Addr,
2501 /* PHY data */
2502 p->Data);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002503 if (status != STATUS_SUCCESS)
2504 return (STATUS_FAILURE);
2505 }
2506 }
2507 }
Harvey Harrisone88bd232008-10-17 14:46:10 -07002508 DBG_ERROR("EXIT %s\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002509
2510 return (STATUS_SUCCESS);
2511}
2512
2513/*
2514 * sxg_link_event - Process a link event notification from the card
2515 *
2516 * Arguments -
2517 * adapter - A pointer to our adapter structure
2518 *
2519 * Return
2520 * None
2521 */
J.R. Mauro73b07062008-10-28 18:42:02 -04002522static void sxg_link_event(struct adapter_t *adapter)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002523{
Mithlesh Thukral942798b2009-01-05 21:14:34 +05302524 struct sxg_hw_regs *HwRegs = adapter->HwRegs;
J.R. Mauro73b07062008-10-28 18:42:02 -04002525 enum SXG_LINK_STATE LinkState;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002526 int status;
2527 u32 Value;
2528
2529 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "LinkEvnt",
2530 adapter, 0, 0, 0);
Harvey Harrisone88bd232008-10-17 14:46:10 -07002531 DBG_ERROR("ENTER %s\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002532
J.R. Maurob243c4a2008-10-20 19:28:58 -04002533 /* Check the Link Status register. We should have a Link Alarm. */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002534 READ_REG(HwRegs->LinkStatus, Value);
2535 if (Value & LS_LINK_ALARM) {
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05302536 /*
2537 * We got a Link Status alarm. First, pause to let the
2538 * link state settle (it can bounce a number of times)
2539 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002540 mdelay(10);
2541
J.R. Maurob243c4a2008-10-20 19:28:58 -04002542 /* Now clear the alarm by reading the LASI status register. */
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302543 /* MIIM_DEV_PHY_PMA - PHY PMA/PMD module */
2544 status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA,
2545 /* LASI status register */
2546 LASI_STATUS,
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002547 &Value);
2548 if (status != STATUS_SUCCESS) {
2549 DBG_ERROR("Error reading LASI Status MDIO register!\n");
2550 sxg_link_state(adapter, SXG_LINK_DOWN);
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302551 /* ASSERT(0); */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002552 }
2553 ASSERT(Value & LASI_STATUS_LS_ALARM);
2554
J.R. Maurob243c4a2008-10-20 19:28:58 -04002555 /* Now get and set the link state */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002556 LinkState = sxg_get_link_state(adapter);
2557 sxg_link_state(adapter, LinkState);
2558 DBG_ERROR("SXG: Link Alarm occurred. Link is %s\n",
2559 ((LinkState == SXG_LINK_UP) ? "UP" : "DOWN"));
2560 } else {
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05302561 /*
2562 * XXXTODO - Assuming Link Attention is only being generated
2563 * for the Link Alarm pin (and not for a XAUI Link Status change)
2564 * , then it's impossible to get here. Yet we've gotten here
2565 * twice (under extreme conditions - bouncing the link up and
2566 * down many times a second). Needs further investigation.
2567 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002568 DBG_ERROR("SXG: sxg_link_event: Can't get here!\n");
2569 DBG_ERROR("SXG: Link Status == 0x%08X.\n", Value);
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302570 /* ASSERT(0); */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002571 }
Harvey Harrisone88bd232008-10-17 14:46:10 -07002572 DBG_ERROR("EXIT %s\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002573
2574}
2575
2576/*
2577 * sxg_get_link_state - Determine if the link is up or down
2578 *
2579 * Arguments -
2580 * adapter - A pointer to our adapter structure
2581 *
2582 * Return
2583 * Link State
2584 */
J.R. Mauro73b07062008-10-28 18:42:02 -04002585static enum SXG_LINK_STATE sxg_get_link_state(struct adapter_t *adapter)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002586{
2587 int status;
2588 u32 Value;
2589
Harvey Harrisone88bd232008-10-17 14:46:10 -07002590 DBG_ERROR("ENTER %s\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002591
2592 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "GetLink",
2593 adapter, 0, 0, 0);
2594
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05302595 /*
2596 * Per the Xenpak spec (and the IEEE 10Gb spec?), the link is up if
2597 * the following 3 bits (from 3 different MDIO registers) are all true.
2598 */
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302599
2600 /* MIIM_DEV_PHY_PMA - PHY PMA/PMD module */
2601 status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PMA,
2602 /* PMA/PMD Receive Signal Detect register */
2603 PHY_PMA_RCV_DET,
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002604 &Value);
2605 if (status != STATUS_SUCCESS)
2606 goto bad;
2607
J.R. Maurob243c4a2008-10-20 19:28:58 -04002608 /* If PMA/PMD receive signal detect is 0, then the link is down */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002609 if (!(Value & PMA_RCV_DETECT))
2610 return (SXG_LINK_DOWN);
2611
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302612 /* MIIM_DEV_PHY_PCS - PHY PCS module */
2613 status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_PCS,
2614 /* PCS 10GBASE-R Status 1 register */
2615 PHY_PCS_10G_STATUS1,
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002616 &Value);
2617 if (status != STATUS_SUCCESS)
2618 goto bad;
2619
J.R. Maurob243c4a2008-10-20 19:28:58 -04002620 /* If PCS is not locked to receive blocks, then the link is down */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002621 if (!(Value & PCS_10B_BLOCK_LOCK))
2622 return (SXG_LINK_DOWN);
2623
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302624 status = sxg_read_mdio_reg(adapter, MIIM_DEV_PHY_XS,/* PHY XS module */
2625 /* XS Lane Status register */
2626 PHY_XS_LANE_STATUS,
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002627 &Value);
2628 if (status != STATUS_SUCCESS)
2629 goto bad;
2630
J.R. Maurob243c4a2008-10-20 19:28:58 -04002631 /* If XS transmit lanes are not aligned, then the link is down */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002632 if (!(Value & XS_LANE_ALIGN))
2633 return (SXG_LINK_DOWN);
2634
J.R. Maurob243c4a2008-10-20 19:28:58 -04002635 /* All 3 bits are true, so the link is up */
Harvey Harrisone88bd232008-10-17 14:46:10 -07002636 DBG_ERROR("EXIT %s\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002637
2638 return (SXG_LINK_UP);
2639
2640 bad:
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302641 /* An error occurred reading an MDIO register. This shouldn't happen. */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002642 DBG_ERROR("Error reading an MDIO register!\n");
2643 ASSERT(0);
2644 return (SXG_LINK_DOWN);
2645}
2646
J.R. Mauro73b07062008-10-28 18:42:02 -04002647static void sxg_indicate_link_state(struct adapter_t *adapter,
2648 enum SXG_LINK_STATE LinkState)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002649{
2650 if (adapter->LinkState == SXG_LINK_UP) {
2651 DBG_ERROR("%s: LINK now UP, call netif_start_queue\n",
Harvey Harrisone88bd232008-10-17 14:46:10 -07002652 __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002653 netif_start_queue(adapter->netdev);
2654 } else {
2655 DBG_ERROR("%s: LINK now DOWN, call netif_stop_queue\n",
Harvey Harrisone88bd232008-10-17 14:46:10 -07002656 __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002657 netif_stop_queue(adapter->netdev);
2658 }
2659}
2660
2661/*
2662 * sxg_link_state - Set the link state and if necessary, indicate.
2663 * This routine the central point of processing for all link state changes.
2664 * Nothing else in the driver should alter the link state or perform
2665 * link state indications
2666 *
2667 * Arguments -
2668 * adapter - A pointer to our adapter structure
2669 * LinkState - The link state
2670 *
2671 * Return
2672 * None
2673 */
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302674static void sxg_link_state(struct adapter_t *adapter,
2675 enum SXG_LINK_STATE LinkState)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002676{
2677 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_IMPORTANT, "LnkINDCT",
2678 adapter, LinkState, adapter->LinkState, adapter->State);
2679
Harvey Harrisone88bd232008-10-17 14:46:10 -07002680 DBG_ERROR("ENTER %s\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002681
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05302682 /*
2683 * Hold the adapter lock during this routine. Maybe move
2684 * the lock to the caller.
2685 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002686 spin_lock(&adapter->AdapterLock);
2687 if (LinkState == adapter->LinkState) {
J.R. Maurob243c4a2008-10-20 19:28:58 -04002688 /* Nothing changed.. */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002689 spin_unlock(&adapter->AdapterLock);
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302690 DBG_ERROR("EXIT #0 %s. Link status = %d\n",
2691 __func__, LinkState);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002692 return;
2693 }
J.R. Maurob243c4a2008-10-20 19:28:58 -04002694 /* Save the adapter state */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002695 adapter->LinkState = LinkState;
2696
J.R. Maurob243c4a2008-10-20 19:28:58 -04002697 /* Drop the lock and indicate link state */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002698 spin_unlock(&adapter->AdapterLock);
Harvey Harrisone88bd232008-10-17 14:46:10 -07002699 DBG_ERROR("EXIT #1 %s\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002700
2701 sxg_indicate_link_state(adapter, LinkState);
2702}
2703
2704/*
2705 * sxg_write_mdio_reg - Write to a register on the MDIO bus
2706 *
2707 * Arguments -
2708 * adapter - A pointer to our adapter structure
2709 * DevAddr - MDIO device number being addressed
2710 * RegAddr - register address for the specified MDIO device
2711 * Value - value to write to the MDIO register
2712 *
2713 * Return
2714 * status
2715 */
J.R. Mauro73b07062008-10-28 18:42:02 -04002716static int sxg_write_mdio_reg(struct adapter_t *adapter,
J.R. Mauro5c7514e2008-10-05 20:38:52 -04002717 u32 DevAddr, u32 RegAddr, u32 Value)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002718{
Mithlesh Thukral942798b2009-01-05 21:14:34 +05302719 struct sxg_hw_regs *HwRegs = adapter->HwRegs;
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302720 /* Address operation (written to MIIM field reg) */
2721 u32 AddrOp;
2722 /* Write operation (written to MIIM field reg) */
2723 u32 WriteOp;
2724 u32 Cmd;/* Command (written to MIIM command reg) */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002725 u32 ValueRead;
2726 u32 Timeout;
2727
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302728 /* DBG_ERROR("ENTER %s\n", __func__); */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002729
2730 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "WrtMDIO",
2731 adapter, 0, 0, 0);
2732
J.R. Maurob243c4a2008-10-20 19:28:58 -04002733 /* Ensure values don't exceed field width */
2734 DevAddr &= 0x001F; /* 5-bit field */
2735 RegAddr &= 0xFFFF; /* 16-bit field */
2736 Value &= 0xFFFF; /* 16-bit field */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002737
J.R. Maurob243c4a2008-10-20 19:28:58 -04002738 /* Set MIIM field register bits for an MIIM address operation */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002739 AddrOp = (MIIM_PORT_NUM << AXGMAC_AMIIM_FIELD_PORT_SHIFT) |
2740 (DevAddr << AXGMAC_AMIIM_FIELD_DEV_SHIFT) |
2741 (MIIM_TA_10GB << AXGMAC_AMIIM_FIELD_TA_SHIFT) |
2742 (MIIM_OP_ADDR << AXGMAC_AMIIM_FIELD_OP_SHIFT) | RegAddr;
2743
J.R. Maurob243c4a2008-10-20 19:28:58 -04002744 /* Set MIIM field register bits for an MIIM write operation */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002745 WriteOp = (MIIM_PORT_NUM << AXGMAC_AMIIM_FIELD_PORT_SHIFT) |
2746 (DevAddr << AXGMAC_AMIIM_FIELD_DEV_SHIFT) |
2747 (MIIM_TA_10GB << AXGMAC_AMIIM_FIELD_TA_SHIFT) |
2748 (MIIM_OP_WRITE << AXGMAC_AMIIM_FIELD_OP_SHIFT) | Value;
2749
J.R. Maurob243c4a2008-10-20 19:28:58 -04002750 /* Set MIIM command register bits to execute an MIIM command */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002751 Cmd = AXGMAC_AMIIM_CMD_START | AXGMAC_AMIIM_CMD_10G_OPERATION;
2752
J.R. Maurob243c4a2008-10-20 19:28:58 -04002753 /* Reset the command register command bit (in case it's not 0) */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002754 WRITE_REG(HwRegs->MacAmiimCmd, 0, TRUE);
2755
J.R. Maurob243c4a2008-10-20 19:28:58 -04002756 /* MIIM write to set the address of the specified MDIO register */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002757 WRITE_REG(HwRegs->MacAmiimField, AddrOp, TRUE);
2758
J.R. Maurob243c4a2008-10-20 19:28:58 -04002759 /* Write to MIIM Command Register to execute to address operation */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002760 WRITE_REG(HwRegs->MacAmiimCmd, Cmd, TRUE);
2761
J.R. Maurob243c4a2008-10-20 19:28:58 -04002762 /* Poll AMIIM Indicator register to wait for completion */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002763 Timeout = SXG_LINK_TIMEOUT;
2764 do {
J.R. Maurob243c4a2008-10-20 19:28:58 -04002765 udelay(100); /* Timeout in 100us units */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002766 READ_REG(HwRegs->MacAmiimIndicator, ValueRead);
2767 if (--Timeout == 0) {
2768 return (STATUS_FAILURE);
2769 }
2770 } while (ValueRead & AXGMAC_AMIIM_INDC_BUSY);
2771
J.R. Maurob243c4a2008-10-20 19:28:58 -04002772 /* Reset the command register command bit */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002773 WRITE_REG(HwRegs->MacAmiimCmd, 0, TRUE);
2774
J.R. Maurob243c4a2008-10-20 19:28:58 -04002775 /* MIIM write to set up an MDIO write operation */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002776 WRITE_REG(HwRegs->MacAmiimField, WriteOp, TRUE);
2777
J.R. Maurob243c4a2008-10-20 19:28:58 -04002778 /* Write to MIIM Command Register to execute the write operation */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002779 WRITE_REG(HwRegs->MacAmiimCmd, Cmd, TRUE);
2780
J.R. Maurob243c4a2008-10-20 19:28:58 -04002781 /* Poll AMIIM Indicator register to wait for completion */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002782 Timeout = SXG_LINK_TIMEOUT;
2783 do {
J.R. Maurob243c4a2008-10-20 19:28:58 -04002784 udelay(100); /* Timeout in 100us units */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002785 READ_REG(HwRegs->MacAmiimIndicator, ValueRead);
2786 if (--Timeout == 0) {
2787 return (STATUS_FAILURE);
2788 }
2789 } while (ValueRead & AXGMAC_AMIIM_INDC_BUSY);
2790
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302791 /* DBG_ERROR("EXIT %s\n", __func__); */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002792
2793 return (STATUS_SUCCESS);
2794}
2795
2796/*
2797 * sxg_read_mdio_reg - Read a register on the MDIO bus
2798 *
2799 * Arguments -
2800 * adapter - A pointer to our adapter structure
2801 * DevAddr - MDIO device number being addressed
2802 * RegAddr - register address for the specified MDIO device
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302803 * pValue - pointer to where to put data read from the MDIO register
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002804 *
2805 * Return
2806 * status
2807 */
J.R. Mauro73b07062008-10-28 18:42:02 -04002808static int sxg_read_mdio_reg(struct adapter_t *adapter,
J.R. Mauro5c7514e2008-10-05 20:38:52 -04002809 u32 DevAddr, u32 RegAddr, u32 *pValue)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002810{
Mithlesh Thukral942798b2009-01-05 21:14:34 +05302811 struct sxg_hw_regs *HwRegs = adapter->HwRegs;
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302812 u32 AddrOp; /* Address operation (written to MIIM field reg) */
2813 u32 ReadOp; /* Read operation (written to MIIM field reg) */
2814 u32 Cmd; /* Command (written to MIIM command reg) */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002815 u32 ValueRead;
2816 u32 Timeout;
2817
2818 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "WrtMDIO",
2819 adapter, 0, 0, 0);
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302820 DBG_ERROR("ENTER %s\n", __FUNCTION__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002821
J.R. Maurob243c4a2008-10-20 19:28:58 -04002822 /* Ensure values don't exceed field width */
2823 DevAddr &= 0x001F; /* 5-bit field */
2824 RegAddr &= 0xFFFF; /* 16-bit field */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002825
J.R. Maurob243c4a2008-10-20 19:28:58 -04002826 /* Set MIIM field register bits for an MIIM address operation */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002827 AddrOp = (MIIM_PORT_NUM << AXGMAC_AMIIM_FIELD_PORT_SHIFT) |
2828 (DevAddr << AXGMAC_AMIIM_FIELD_DEV_SHIFT) |
2829 (MIIM_TA_10GB << AXGMAC_AMIIM_FIELD_TA_SHIFT) |
2830 (MIIM_OP_ADDR << AXGMAC_AMIIM_FIELD_OP_SHIFT) | RegAddr;
2831
J.R. Maurob243c4a2008-10-20 19:28:58 -04002832 /* Set MIIM field register bits for an MIIM read operation */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002833 ReadOp = (MIIM_PORT_NUM << AXGMAC_AMIIM_FIELD_PORT_SHIFT) |
2834 (DevAddr << AXGMAC_AMIIM_FIELD_DEV_SHIFT) |
2835 (MIIM_TA_10GB << AXGMAC_AMIIM_FIELD_TA_SHIFT) |
2836 (MIIM_OP_READ << AXGMAC_AMIIM_FIELD_OP_SHIFT);
2837
J.R. Maurob243c4a2008-10-20 19:28:58 -04002838 /* Set MIIM command register bits to execute an MIIM command */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002839 Cmd = AXGMAC_AMIIM_CMD_START | AXGMAC_AMIIM_CMD_10G_OPERATION;
2840
J.R. Maurob243c4a2008-10-20 19:28:58 -04002841 /* Reset the command register command bit (in case it's not 0) */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002842 WRITE_REG(HwRegs->MacAmiimCmd, 0, TRUE);
2843
J.R. Maurob243c4a2008-10-20 19:28:58 -04002844 /* MIIM write to set the address of the specified MDIO register */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002845 WRITE_REG(HwRegs->MacAmiimField, AddrOp, TRUE);
2846
J.R. Maurob243c4a2008-10-20 19:28:58 -04002847 /* Write to MIIM Command Register to execute to address operation */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002848 WRITE_REG(HwRegs->MacAmiimCmd, Cmd, TRUE);
2849
J.R. Maurob243c4a2008-10-20 19:28:58 -04002850 /* Poll AMIIM Indicator register to wait for completion */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002851 Timeout = SXG_LINK_TIMEOUT;
2852 do {
J.R. Maurob243c4a2008-10-20 19:28:58 -04002853 udelay(100); /* Timeout in 100us units */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002854 READ_REG(HwRegs->MacAmiimIndicator, ValueRead);
2855 if (--Timeout == 0) {
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +05302856 DBG_ERROR("EXIT %s with STATUS_FAILURE 1\n", __FUNCTION__);
2857
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002858 return (STATUS_FAILURE);
2859 }
2860 } while (ValueRead & AXGMAC_AMIIM_INDC_BUSY);
2861
J.R. Maurob243c4a2008-10-20 19:28:58 -04002862 /* Reset the command register command bit */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002863 WRITE_REG(HwRegs->MacAmiimCmd, 0, TRUE);
2864
J.R. Maurob243c4a2008-10-20 19:28:58 -04002865 /* MIIM write to set up an MDIO register read operation */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002866 WRITE_REG(HwRegs->MacAmiimField, ReadOp, TRUE);
2867
J.R. Maurob243c4a2008-10-20 19:28:58 -04002868 /* Write to MIIM Command Register to execute the read operation */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002869 WRITE_REG(HwRegs->MacAmiimCmd, Cmd, TRUE);
2870
J.R. Maurob243c4a2008-10-20 19:28:58 -04002871 /* Poll AMIIM Indicator register to wait for completion */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002872 Timeout = SXG_LINK_TIMEOUT;
2873 do {
J.R. Maurob243c4a2008-10-20 19:28:58 -04002874 udelay(100); /* Timeout in 100us units */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002875 READ_REG(HwRegs->MacAmiimIndicator, ValueRead);
2876 if (--Timeout == 0) {
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +05302877 DBG_ERROR("EXIT %s with STATUS_FAILURE 2\n", __FUNCTION__);
2878
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002879 return (STATUS_FAILURE);
2880 }
2881 } while (ValueRead & AXGMAC_AMIIM_INDC_BUSY);
2882
J.R. Maurob243c4a2008-10-20 19:28:58 -04002883 /* Read the MDIO register data back from the field register */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002884 READ_REG(HwRegs->MacAmiimField, *pValue);
J.R. Maurob243c4a2008-10-20 19:28:58 -04002885 *pValue &= 0xFFFF; /* data is in the lower 16 bits */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002886
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302887 DBG_ERROR("EXIT %s\n", __FUNCTION__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002888
2889 return (STATUS_SUCCESS);
2890}
2891
2892/*
Greg Kroah-Hartmanc6c25ed2008-10-21 10:41:45 -07002893 * Functions to obtain the CRC corresponding to the destination mac address.
2894 * This is a standard ethernet CRC in that it is a 32-bit, reflected CRC using
2895 * the polynomial:
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302896 * x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5
2897 * + x^4 + x^2 + x^1.
Greg Kroah-Hartmanc6c25ed2008-10-21 10:41:45 -07002898 *
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302899 * After the CRC for the 6 bytes is generated (but before the value is
2900 * complemented), we must then transpose the value and return bits 30-23.
Greg Kroah-Hartmanc6c25ed2008-10-21 10:41:45 -07002901 */
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302902static u32 sxg_crc_table[256];/* Table of CRC's for all possible byte values */
2903static u32 sxg_crc_init; /* Is table initialized */
Greg Kroah-Hartmanc6c25ed2008-10-21 10:41:45 -07002904
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302905/* Contruct the CRC32 table */
Greg Kroah-Hartmanc6c25ed2008-10-21 10:41:45 -07002906static void sxg_mcast_init_crc32(void)
2907{
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302908 u32 c; /* CRC shit reg */
2909 u32 e = 0; /* Poly X-or pattern */
2910 int i; /* counter */
Greg Kroah-Hartmanc6c25ed2008-10-21 10:41:45 -07002911 int k; /* byte being shifted into crc */
2912
2913 static int p[] = { 0, 1, 2, 4, 5, 7, 8, 10, 11, 12, 16, 22, 23, 26 };
2914
2915 for (i = 0; i < sizeof(p) / sizeof(int); i++) {
2916 e |= 1L << (31 - p[i]);
2917 }
2918
2919 for (i = 1; i < 256; i++) {
2920 c = i;
2921 for (k = 8; k; k--) {
2922 c = c & 1 ? (c >> 1) ^ e : c >> 1;
2923 }
2924 sxg_crc_table[i] = c;
2925 }
2926}
2927
Greg Kroah-Hartmanc6c25ed2008-10-21 10:41:45 -07002928/*
2929 * Return the MAC hast as described above.
2930 */
2931static unsigned char sxg_mcast_get_mac_hash(char *macaddr)
2932{
2933 u32 crc;
2934 char *p;
2935 int i;
2936 unsigned char machash = 0;
2937
2938 if (!sxg_crc_init) {
2939 sxg_mcast_init_crc32();
2940 sxg_crc_init = 1;
2941 }
2942
2943 crc = 0xFFFFFFFF; /* Preload shift register, per crc-32 spec */
2944 for (i = 0, p = macaddr; i < 6; ++p, ++i) {
2945 crc = (crc >> 8) ^ sxg_crc_table[(crc ^ *p) & 0xFF];
2946 }
2947
2948 /* Return bits 1-8, transposed */
2949 for (i = 1; i < 9; i++) {
2950 machash |= (((crc >> i) & 1) << (8 - i));
2951 }
2952
2953 return (machash);
2954}
2955
J.R. Mauro73b07062008-10-28 18:42:02 -04002956static void sxg_mcast_set_mask(struct adapter_t *adapter)
Greg Kroah-Hartmanc6c25ed2008-10-21 10:41:45 -07002957{
Mithlesh Thukral942798b2009-01-05 21:14:34 +05302958 struct sxg_ucode_regs *sxg_regs = adapter->UcodeRegs;
Greg Kroah-Hartmanc6c25ed2008-10-21 10:41:45 -07002959
2960 DBG_ERROR("%s ENTER (%s) macopts[%x] mask[%llx]\n", __func__,
2961 adapter->netdev->name, (unsigned int)adapter->MacFilter,
2962 adapter->MulticastMask);
2963
2964 if (adapter->MacFilter & (MAC_ALLMCAST | MAC_PROMISC)) {
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05302965 /*
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302966 * Turn on all multicast addresses. We have to do this for
2967 * promiscuous mode as well as ALLMCAST mode. It saves the
2968 * Microcode from having keep state about the MAC configuration
Greg Kroah-Hartmanc6c25ed2008-10-21 10:41:45 -07002969 */
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302970 /* DBG_ERROR("sxg: %s macopts = MAC_ALLMCAST | MAC_PROMISC\n
2971 * SLUT MODE!!!\n",__func__);
2972 */
Greg Kroah-Hartmanc6c25ed2008-10-21 10:41:45 -07002973 WRITE_REG(sxg_regs->McastLow, 0xFFFFFFFF, FLUSH);
2974 WRITE_REG(sxg_regs->McastHigh, 0xFFFFFFFF, FLUSH);
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302975 /* DBG_ERROR("%s (%s) WRITE to slic_regs slic_mcastlow&high \
2976 * 0xFFFFFFFF\n",__func__, adapter->netdev->name);
2977 */
Greg Kroah-Hartmanc6c25ed2008-10-21 10:41:45 -07002978
2979 } else {
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05302980 /*
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05302981 * Commit our multicast mast to the SLIC by writing to the
2982 * multicast address mask registers
Greg Kroah-Hartmanc6c25ed2008-10-21 10:41:45 -07002983 */
2984 DBG_ERROR("%s (%s) WRITE mcastlow[%lx] mcasthigh[%lx]\n",
2985 __func__, adapter->netdev->name,
2986 ((ulong) (adapter->MulticastMask & 0xFFFFFFFF)),
2987 ((ulong)
2988 ((adapter->MulticastMask >> 32) & 0xFFFFFFFF)));
2989
2990 WRITE_REG(sxg_regs->McastLow,
2991 (u32) (adapter->MulticastMask & 0xFFFFFFFF), FLUSH);
2992 WRITE_REG(sxg_regs->McastHigh,
2993 (u32) ((adapter->
2994 MulticastMask >> 32) & 0xFFFFFFFF), FLUSH);
2995 }
2996}
2997
2998/*
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07002999 * Allocate a mcast_address structure to hold the multicast address.
3000 * Link it in.
3001 */
J.R. Mauro73b07062008-10-28 18:42:02 -04003002static int sxg_mcast_add_list(struct adapter_t *adapter, char *address)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003003{
Mithlesh Thukral942798b2009-01-05 21:14:34 +05303004 struct mcast_address *mcaddr, *mlist;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003005 bool equaladdr;
3006
3007 /* Check to see if it already exists */
3008 mlist = adapter->mcastaddrs;
3009 while (mlist) {
3010 ETHER_EQ_ADDR(mlist->address, address, equaladdr);
3011 if (equaladdr) {
3012 return (STATUS_SUCCESS);
3013 }
3014 mlist = mlist->next;
3015 }
3016
3017 /* Doesn't already exist. Allocate a structure to hold it */
Mithlesh Thukral942798b2009-01-05 21:14:34 +05303018 mcaddr = kmalloc(sizeof(struct mcast_address), GFP_ATOMIC);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003019 if (mcaddr == NULL)
3020 return 1;
3021
3022 memcpy(mcaddr->address, address, 6);
3023
3024 mcaddr->next = adapter->mcastaddrs;
3025 adapter->mcastaddrs = mcaddr;
3026
3027 return (STATUS_SUCCESS);
3028}
3029
J.R. Mauro73b07062008-10-28 18:42:02 -04003030static void sxg_mcast_set_bit(struct adapter_t *adapter, char *address)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003031{
3032 unsigned char crcpoly;
3033
3034 /* Get the CRC polynomial for the mac address */
3035 crcpoly = sxg_mcast_get_mac_hash(address);
3036
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05303037 /*
3038 * We only have space on the SLIC for 64 entries. Lop
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003039 * off the top two bits. (2^6 = 64)
3040 */
3041 crcpoly &= 0x3F;
3042
3043 /* OR in the new bit into our 64 bit mask. */
3044 adapter->MulticastMask |= (u64) 1 << crcpoly;
3045}
3046
Mithlesh Thukral942798b2009-01-05 21:14:34 +05303047static void sxg_mcast_set_list(struct net_device *dev)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003048{
J.R. Mauro73b07062008-10-28 18:42:02 -04003049 struct adapter_t *adapter = (struct adapter_t *) netdev_priv(dev);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003050
3051 ASSERT(adapter);
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +05303052 if (dev->flags & IFF_PROMISC) {
3053 adapter->MacFilter |= MAC_PROMISC;
3054 }
3055 //XXX handle other flags as well
3056 sxg_mcast_set_mask(adapter);
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +05303057}
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003058
J.R. Mauro73b07062008-10-28 18:42:02 -04003059static void sxg_unmap_mmio_space(struct adapter_t *adapter)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003060{
3061#if LINUX_FREES_ADAPTER_RESOURCES
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05303062/*
3063 * if (adapter->Regs) {
3064 * iounmap(adapter->Regs);
3065 * }
3066 * adapter->slic_regs = NULL;
3067 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003068#endif
3069}
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303070/*
3071void SxgFreeRcvBlocks(struct adapter_t *adapter)
3072{
3073 u32 i;
3074 struct list_entry *ple;
3075 struct sxg_rcv_block_hdr *Hdr;
3076 struct sxg_rcv_data_buffer_hdr *RcvDataBufferHdr;
3077 u32 FreeBuffers = 0, FreeBlocks = 0;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003078
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303079 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "FrRcvBlk",
3080 adapter, 0, 0, 0);
3081
3082 ASSERT((adapter->State == SXG_STATE_INITIALIZING) ||
3083 (pAdapt->State == SXG_STATE_HALTING));
3084
3085 for(i = 0; i < SXG_MAX_CPU; i++) {
3086 FreeBuffers += pAdapt->PerCpuResources[i].FreeReceiveBuffers.Count;
3087 FreeBlocks += pAdapt->PerCpuResources[i].FreeReceiveBlocks.Count;
3088 pAdapt->PerCpuResources[i].FreeReceiveBuffers.Count = 0;
3089 pAdapt->PerCpuResources[i].FreeReceiveBuffers.FreeList = NULL;
3090 pAdapt->PerCpuResources[i].FreeReceiveBlocks.Count = 0;
3091 pAdapt->PerCpuResources[i].FreeReceiveBlocks.FreeList = NULL;
3092 }
3093 FreeBuffers += pAdapt->GlobalResources.FreeReceiveBuffers.Count;
3094 FreeBlocks += pAdapt->GlobalResources.FreeReceiveBlocks.Count;
3095 pAdapt->GlobalResources.FreeReceiveBuffers.Count = 0;
3096 pAdapt->GlobalResources.FreeReceiveBuffers.FreeList = NULL;
3097 pAdapt->GlobalResources.FreeReceiveBlocks.Count = 0;
3098 pAdapt->GlobalResources.FreeReceiveBlocks.FreeList = NULL;
3099 ASSERT(FreeBlocks == pAdapt->AllRcvBlockCount); // See SXG_RCV_BLOCK
3100 ASSERT(FreeBuffers ==
3101 (pAdapt->AllRcvBlockCount * SXG_RCV_DESCRIPTORS_PER_BLOCK)); // See SXG_RCV_BLOCK
3102
3103 while(!(IsListEmpty(&pAdapt->AllRcvBlocks))) {
3104 ple = RemoveHeadList(&pAdapt->AllRcvBlocks);
3105 Hdr = CONTAINING_RECORD(ple, SXG_RCV_BLOCK_HDR, AllList);
3106 NdisMFreeSharedMemory(pAdapt->MiniportHandle,
3107 SXG_RCV_BLOCK_SIZE(pAdapt->ReceiveBufferSize),
3108 TRUE,
3109 Hdr->VirtualAddress,
3110 Hdr->PhysicalAddress);
3111 pAdapt->AllRcvBlockCount--;
3112 }
3113 ASSERT(pAdapt->AllRcvBlockCount == 0);
3114 SLIC_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XFrRBlk",
3115 pAdapt, 0, 0, 0);
3116}
3117*/
3118//#if XXXTODO
3119
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003120/*
3121 * SxgFreeResources - Free everything allocated in SxgAllocateResources
3122 *
3123 * Arguments -
3124 * adapter - A pointer to our adapter structure
3125 *
3126 * Return
3127 * none
3128 */
J.R. Mauro73b07062008-10-28 18:42:02 -04003129void SxgFreeResources(struct adapter_t *adapter)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003130{
3131 u32 RssIds, IsrCount;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003132 u32 i;
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303133/*
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003134 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "FreeRes",
3135 adapter, adapter->MaxTcbs, 0, 0);
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303136*/
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003137 RssIds = SXG_RSS_CPU_COUNT(adapter);
3138 IsrCount = adapter->MsiEnabled ? RssIds : 1;
3139
3140 if (adapter->BasicAllocations == FALSE) {
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05303141 /*
3142 * No allocations have been made, including spinlocks,
3143 * or listhead initializations. Return.
3144 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003145 return;
3146 }
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303147/*
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003148 if (!(IsListEmpty(&adapter->AllRcvBlocks))) {
3149 SxgFreeRcvBlocks(adapter);
3150 }
3151 if (!(IsListEmpty(&adapter->AllSglBuffers))) {
3152 SxgFreeSglBuffers(adapter);
3153 }
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303154*/
3155
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003156 if (adapter->XmtRingZeroIndex) {
3157 pci_free_consistent(adapter->pcidev,
3158 sizeof(u32),
3159 adapter->XmtRingZeroIndex,
3160 adapter->PXmtRingZeroIndex);
3161 }
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303162 printk("VSS Free Isr\n");
3163 if (adapter->Isr) {
3164 pci_free_consistent(adapter->pcidev,
3165 sizeof(u32) * IsrCount,
3166 adapter->Isr, adapter->PIsr);
3167 }
3168
3169 printk("VSS Free EventRings\n");
3170 if (adapter->EventRings) {
3171 pci_free_consistent(adapter->pcidev,
3172 sizeof(struct sxg_event_ring) * RssIds,
3173 adapter->EventRings, adapter->PEventRings);
3174 }
3175/*
3176 printk("VSS Free RcvRings\n");
3177 if (adapter->RcvRings) {
3178 pci_free_consistent(adapter->pcidev,
3179 sizeof(struct sxg_rcv_ring) * 4096,
3180 adapter->RcvRings,
3181 adapter->PRcvRings);
3182 adapter->RcvRings = NULL;
3183 }
3184
3185 printk("VSS Free XmtRings\n");
3186 if(adapter->XmtRings) {
3187 pci_free_consistent(adapter->pcidev,
3188 sizeof(struct sxg_xmt_ring) * 4096,
3189 adapter->XmtRings,
3190 adapter->PXmtRings);
3191 adapter->XmtRings = NULL;
3192 }
3193
3194*/
3195
3196/*
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003197
3198 SXG_FREE_PACKET_POOL(adapter->PacketPoolHandle);
3199 SXG_FREE_BUFFER_POOL(adapter->BufferPoolHandle);
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303200*/
J.R. Maurob243c4a2008-10-20 19:28:58 -04003201 /* Unmap register spaces */
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303202 // SxgUnmapResources(adapter);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003203
J.R. Maurob243c4a2008-10-20 19:28:58 -04003204 /* Deregister DMA */
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303205/* if (adapter->DmaHandle) {
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003206 SXG_DEREGISTER_DMA(adapter->DmaHandle);
3207 }
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303208*/ /* Deregister interrupt */
3209 // SxgDeregisterInterrupt(adapter);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003210
J.R. Maurob243c4a2008-10-20 19:28:58 -04003211 /* Possibly free system info (5.2 only) */
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303212 // SXG_RELEASE_SYSTEM_INFO(adapter);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003213
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303214 //SxgDiagFreeResources(adapter);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003215
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303216 // SxgFreeMCastAddrs(adapter);
3217/*
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003218 if (SXG_TIMER_ALLOCATED(adapter->ResetTimer)) {
3219 SXG_CANCEL_TIMER(adapter->ResetTimer, TimerCancelled);
3220 SXG_FREE_TIMER(adapter->ResetTimer);
3221 }
3222 if (SXG_TIMER_ALLOCATED(adapter->RssTimer)) {
3223 SXG_CANCEL_TIMER(adapter->RssTimer, TimerCancelled);
3224 SXG_FREE_TIMER(adapter->RssTimer);
3225 }
3226 if (SXG_TIMER_ALLOCATED(adapter->OffloadTimer)) {
3227 SXG_CANCEL_TIMER(adapter->OffloadTimer, TimerCancelled);
3228 SXG_FREE_TIMER(adapter->OffloadTimer);
3229 }
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303230*/
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003231 adapter->BasicAllocations = FALSE;
3232
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303233/* SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XFreeRes",
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003234 adapter, adapter->MaxTcbs, 0, 0);
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303235*/
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003236}
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303237// #endif
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003238
3239/*
3240 * sxg_allocate_complete -
3241 *
3242 * This routine is called when a memory allocation has completed.
3243 *
3244 * Arguments -
J.R. Mauro73b07062008-10-28 18:42:02 -04003245 * struct adapter_t * - Our adapter structure
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003246 * VirtualAddress - Memory virtual address
3247 * PhysicalAddress - Memory physical address
3248 * Length - Length of memory allocated (or 0)
3249 * Context - The type of buffer allocated
3250 *
3251 * Return
3252 * None.
3253 */
J.R. Mauro73b07062008-10-28 18:42:02 -04003254static void sxg_allocate_complete(struct adapter_t *adapter,
J.R. Mauro5c7514e2008-10-05 20:38:52 -04003255 void *VirtualAddress,
3256 dma_addr_t PhysicalAddress,
Mithlesh Thukral942798b2009-01-05 21:14:34 +05303257 u32 Length, enum sxg_buffer_type Context)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003258{
3259 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "AllocCmp",
3260 adapter, VirtualAddress, Length, Context);
3261 ASSERT(adapter->AllocationsPending);
3262 --adapter->AllocationsPending;
3263
3264 switch (Context) {
3265
3266 case SXG_BUFFER_TYPE_RCV:
3267 sxg_allocate_rcvblock_complete(adapter,
3268 VirtualAddress,
3269 PhysicalAddress, Length);
3270 break;
3271 case SXG_BUFFER_TYPE_SGL:
Mithlesh Thukral942798b2009-01-05 21:14:34 +05303272 sxg_allocate_sgl_buffer_complete(adapter, (struct sxg_scatter_gather *)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003273 VirtualAddress,
3274 PhysicalAddress, Length);
3275 break;
3276 }
3277 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAlocCmp",
3278 adapter, VirtualAddress, Length, Context);
3279}
3280
3281/*
3282 * sxg_allocate_buffer_memory - Shared memory allocation routine used for
3283 * synchronous and asynchronous buffer allocations
3284 *
3285 * Arguments -
3286 * adapter - A pointer to our adapter structure
3287 * Size - block size to allocate
3288 * BufferType - Type of buffer to allocate
3289 *
3290 * Return
3291 * int
3292 */
J.R. Mauro73b07062008-10-28 18:42:02 -04003293static int sxg_allocate_buffer_memory(struct adapter_t *adapter,
Mithlesh Thukral942798b2009-01-05 21:14:34 +05303294 u32 Size, enum sxg_buffer_type BufferType)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003295{
3296 int status;
J.R. Mauro5c7514e2008-10-05 20:38:52 -04003297 void *Buffer;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003298 dma_addr_t pBuffer;
3299
3300 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "AllocMem",
3301 adapter, Size, BufferType, 0);
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05303302 /*
3303 * Grab the adapter lock and check the state. If we're in anything other
3304 * than INITIALIZING or RUNNING state, fail. This is to prevent
3305 * allocations in an improper driver state
3306 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003307 spin_lock(&adapter->AdapterLock);
3308
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05303309 /*
3310 * Increment the AllocationsPending count while holding
3311 * the lock. Pause processing relies on this
3312 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003313 ++adapter->AllocationsPending;
3314 spin_unlock(&adapter->AdapterLock);
3315
J.R. Maurob243c4a2008-10-20 19:28:58 -04003316 /* At initialization time allocate resources synchronously. */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003317 Buffer = pci_alloc_consistent(adapter->pcidev, Size, &pBuffer);
3318 if (Buffer == NULL) {
3319 spin_lock(&adapter->AdapterLock);
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05303320 /*
3321 * Decrement the AllocationsPending count while holding
3322 * the lock. Pause processing relies on this
3323 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003324 --adapter->AllocationsPending;
3325 spin_unlock(&adapter->AdapterLock);
3326 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "AlcMemF1",
3327 adapter, Size, BufferType, 0);
3328 return (STATUS_RESOURCES);
3329 }
3330 sxg_allocate_complete(adapter, Buffer, pBuffer, Size, BufferType);
3331 status = STATUS_SUCCESS;
3332
3333 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAlocMem",
3334 adapter, Size, BufferType, status);
3335 return (status);
3336}
3337
3338/*
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05303339 * sxg_allocate_rcvblock_complete - Complete a receive descriptor
3340 * block allocation
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003341 *
3342 * Arguments -
3343 * adapter - A pointer to our adapter structure
3344 * RcvBlock - receive block virtual address
3345 * PhysicalAddress - Physical address
3346 * Length - Memory length
3347 *
3348 * Return
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003349 */
J.R. Mauro73b07062008-10-28 18:42:02 -04003350static void sxg_allocate_rcvblock_complete(struct adapter_t *adapter,
J.R. Mauro5c7514e2008-10-05 20:38:52 -04003351 void *RcvBlock,
3352 dma_addr_t PhysicalAddress,
3353 u32 Length)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003354{
3355 u32 i;
3356 u32 BufferSize = adapter->ReceiveBufferSize;
3357 u64 Paddr;
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303358 void *temp_RcvBlock;
Mithlesh Thukral942798b2009-01-05 21:14:34 +05303359 struct sxg_rcv_block_hdr *RcvBlockHdr;
Mithlesh Thukral942798b2009-01-05 21:14:34 +05303360 struct sxg_rcv_data_buffer_hdr *RcvDataBufferHdr;
3361 struct sxg_rcv_descriptor_block *RcvDescriptorBlock;
3362 struct sxg_rcv_descriptor_block_hdr *RcvDescriptorBlockHdr;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003363
3364 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "AlRcvBlk",
3365 adapter, RcvBlock, Length, 0);
3366 if (RcvBlock == NULL) {
3367 goto fail;
3368 }
3369 memset(RcvBlock, 0, Length);
3370 ASSERT((BufferSize == SXG_RCV_DATA_BUFFER_SIZE) ||
3371 (BufferSize == SXG_RCV_JUMBO_BUFFER_SIZE));
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303372 ASSERT(Length == SXG_RCV_BLOCK_SIZE(SXG_RCV_DATA_HDR_SIZE));
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05303373 /*
3374 * First, initialize the contained pool of receive data buffers.
3375 * This initialization requires NBL/NB/MDL allocations, if any of them
3376 * fail, free the block and return without queueing the shared memory
3377 */
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303378 //RcvDataBuffer = RcvBlock;
3379 temp_RcvBlock = RcvBlock;
3380 for (i = 0; i < SXG_RCV_DESCRIPTORS_PER_BLOCK;
3381 i++, temp_RcvBlock += SXG_RCV_DATA_HDR_SIZE) {
3382 RcvDataBufferHdr = (struct sxg_rcv_data_buffer_hdr *)
3383 temp_RcvBlock;
3384 /* For FREE macro assertion */
3385 RcvDataBufferHdr->State = SXG_BUFFER_UPSTREAM;
3386 SXG_ALLOCATE_RCV_PACKET(adapter, RcvDataBufferHdr, BufferSize);
3387 if (RcvDataBufferHdr->SxgDumbRcvPacket == NULL)
3388 goto fail;
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05303389
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303390 }
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003391
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05303392 /*
3393 * Place this entire block of memory on the AllRcvBlocks queue so it
3394 * can be free later
3395 */
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303396
3397 RcvBlockHdr = (struct sxg_rcv_block_hdr *) ((unsigned char *)RcvBlock +
3398 SXG_RCV_BLOCK_HDR_OFFSET(SXG_RCV_DATA_HDR_SIZE));
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003399 RcvBlockHdr->VirtualAddress = RcvBlock;
3400 RcvBlockHdr->PhysicalAddress = PhysicalAddress;
3401 spin_lock(&adapter->RcvQLock);
3402 adapter->AllRcvBlockCount++;
3403 InsertTailList(&adapter->AllRcvBlocks, &RcvBlockHdr->AllList);
3404 spin_unlock(&adapter->RcvQLock);
3405
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05303406 /* Now free the contained receive data buffers that we
3407 * initialized above */
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303408 temp_RcvBlock = RcvBlock;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003409 for (i = 0, Paddr = PhysicalAddress;
3410 i < SXG_RCV_DESCRIPTORS_PER_BLOCK;
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303411 i++, Paddr += SXG_RCV_DATA_HDR_SIZE,
3412 temp_RcvBlock += SXG_RCV_DATA_HDR_SIZE) {
3413 RcvDataBufferHdr =
3414 (struct sxg_rcv_data_buffer_hdr *)temp_RcvBlock;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003415 spin_lock(&adapter->RcvQLock);
3416 SXG_FREE_RCV_DATA_BUFFER(adapter, RcvDataBufferHdr);
3417 spin_unlock(&adapter->RcvQLock);
3418 }
3419
J.R. Maurob243c4a2008-10-20 19:28:58 -04003420 /* Locate the descriptor block and put it on a separate free queue */
J.R. Mauro5c7514e2008-10-05 20:38:52 -04003421 RcvDescriptorBlock =
Mithlesh Thukral942798b2009-01-05 21:14:34 +05303422 (struct sxg_rcv_descriptor_block *) ((unsigned char *)RcvBlock +
J.R. Mauro5c7514e2008-10-05 20:38:52 -04003423 SXG_RCV_DESCRIPTOR_BLOCK_OFFSET
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303424 (SXG_RCV_DATA_HDR_SIZE));
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003425 RcvDescriptorBlockHdr =
Mithlesh Thukral942798b2009-01-05 21:14:34 +05303426 (struct sxg_rcv_descriptor_block_hdr *) ((unsigned char *)RcvBlock +
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003427 SXG_RCV_DESCRIPTOR_BLOCK_HDR_OFFSET
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303428 (SXG_RCV_DATA_HDR_SIZE));
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003429 RcvDescriptorBlockHdr->VirtualAddress = RcvDescriptorBlock;
3430 RcvDescriptorBlockHdr->PhysicalAddress = Paddr;
3431 spin_lock(&adapter->RcvQLock);
3432 SXG_FREE_RCV_DESCRIPTOR_BLOCK(adapter, RcvDescriptorBlockHdr);
3433 spin_unlock(&adapter->RcvQLock);
3434 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAlRBlk",
3435 adapter, RcvBlock, Length, 0);
3436 return;
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05303437fail:
J.R. Maurob243c4a2008-10-20 19:28:58 -04003438 /* Free any allocated resources */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003439 if (RcvBlock) {
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303440 temp_RcvBlock = RcvBlock;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003441 for (i = 0; i < SXG_RCV_DESCRIPTORS_PER_BLOCK;
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303442 i++, temp_RcvBlock += SXG_RCV_DATA_HDR_SIZE) {
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003443 RcvDataBufferHdr =
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303444 (struct sxg_rcv_data_buffer_hdr *)temp_RcvBlock;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003445 SXG_FREE_RCV_PACKET(RcvDataBufferHdr);
3446 }
3447 pci_free_consistent(adapter->pcidev,
3448 Length, RcvBlock, PhysicalAddress);
3449 }
Harvey Harrisone88bd232008-10-17 14:46:10 -07003450 DBG_ERROR("%s: OUT OF RESOURCES\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003451 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_IMPORTANT, "RcvAFail",
3452 adapter, adapter->FreeRcvBufferCount,
3453 adapter->FreeRcvBlockCount, adapter->AllRcvBlockCount);
3454 adapter->Stats.NoMem++;
3455}
3456
3457/*
3458 * sxg_allocate_sgl_buffer_complete - Complete a SGL buffer allocation
3459 *
3460 * Arguments -
3461 * adapter - A pointer to our adapter structure
Mithlesh Thukral942798b2009-01-05 21:14:34 +05303462 * SxgSgl - struct sxg_scatter_gather buffer
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003463 * PhysicalAddress - Physical address
3464 * Length - Memory length
3465 *
3466 * Return
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003467 */
J.R. Mauro73b07062008-10-28 18:42:02 -04003468static void sxg_allocate_sgl_buffer_complete(struct adapter_t *adapter,
Mithlesh Thukral942798b2009-01-05 21:14:34 +05303469 struct sxg_scatter_gather *SxgSgl,
J.R. Mauro5c7514e2008-10-05 20:38:52 -04003470 dma_addr_t PhysicalAddress,
3471 u32 Length)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003472{
3473 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "AlSglCmp",
3474 adapter, SxgSgl, Length, 0);
3475 spin_lock(&adapter->SglQLock);
3476 adapter->AllSglBufferCount++;
Mithlesh Thukral942798b2009-01-05 21:14:34 +05303477 memset(SxgSgl, 0, sizeof(struct sxg_scatter_gather));
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05303478 /* *PhysicalAddress; */
3479 SxgSgl->PhysicalAddress = PhysicalAddress;
3480 /* Initialize backpointer once */
3481 SxgSgl->adapter = adapter;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003482 InsertTailList(&adapter->AllSglBuffers, &SxgSgl->AllList);
3483 spin_unlock(&adapter->SglQLock);
3484 SxgSgl->State = SXG_BUFFER_BUSY;
3485 SXG_FREE_SGL_BUFFER(adapter, SxgSgl, NULL);
3486 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XAlSgl",
3487 adapter, SxgSgl, Length, 0);
3488}
3489
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003490
J.R. Mauro73b07062008-10-28 18:42:02 -04003491static void sxg_adapter_set_hwaddr(struct adapter_t *adapter)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003492{
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05303493 /*
3494 * DBG_ERROR ("%s ENTER card->config_set[%x] port[%d] physport[%d] \
3495 * funct#[%d]\n", __func__, card->config_set,
3496 * adapter->port, adapter->physport, adapter->functionnumber);
3497 *
3498 * sxg_dbg_macaddrs(adapter);
3499 */
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05303500 /* DBG_ERROR ("%s AFTER copying from config.macinfo into currmacaddr\n",
3501 * __FUNCTION__);
3502 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003503
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05303504 /* sxg_dbg_macaddrs(adapter); */
3505
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003506 if (!(adapter->currmacaddr[0] ||
3507 adapter->currmacaddr[1] ||
3508 adapter->currmacaddr[2] ||
3509 adapter->currmacaddr[3] ||
3510 adapter->currmacaddr[4] || adapter->currmacaddr[5])) {
3511 memcpy(adapter->currmacaddr, adapter->macaddr, 6);
3512 }
3513 if (adapter->netdev) {
3514 memcpy(adapter->netdev->dev_addr, adapter->currmacaddr, 6);
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +05303515 memcpy(adapter->netdev->perm_addr, adapter->currmacaddr, 6);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003516 }
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05303517 /* DBG_ERROR ("%s EXIT port %d\n", __func__, adapter->port); */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003518 sxg_dbg_macaddrs(adapter);
3519
3520}
3521
Greg Kroah-Hartmanc6c25ed2008-10-21 10:41:45 -07003522#if XXXTODO
Mithlesh Thukral942798b2009-01-05 21:14:34 +05303523static int sxg_mac_set_address(struct net_device *dev, void *ptr)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003524{
J.R. Mauro73b07062008-10-28 18:42:02 -04003525 struct adapter_t *adapter = (struct adapter_t *) netdev_priv(dev);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003526 struct sockaddr *addr = ptr;
3527
Harvey Harrisone88bd232008-10-17 14:46:10 -07003528 DBG_ERROR("%s ENTER (%s)\n", __func__, adapter->netdev->name);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003529
3530 if (netif_running(dev)) {
3531 return -EBUSY;
3532 }
3533 if (!adapter) {
3534 return -EBUSY;
3535 }
3536 DBG_ERROR("sxg: %s (%s) curr %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
Harvey Harrisone88bd232008-10-17 14:46:10 -07003537 __func__, adapter->netdev->name, adapter->currmacaddr[0],
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003538 adapter->currmacaddr[1], adapter->currmacaddr[2],
3539 adapter->currmacaddr[3], adapter->currmacaddr[4],
3540 adapter->currmacaddr[5]);
3541 memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
3542 memcpy(adapter->currmacaddr, addr->sa_data, dev->addr_len);
3543 DBG_ERROR("sxg: %s (%s) new %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
Harvey Harrisone88bd232008-10-17 14:46:10 -07003544 __func__, adapter->netdev->name, adapter->currmacaddr[0],
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003545 adapter->currmacaddr[1], adapter->currmacaddr[2],
3546 adapter->currmacaddr[3], adapter->currmacaddr[4],
3547 adapter->currmacaddr[5]);
3548
3549 sxg_config_set(adapter, TRUE);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003550 return 0;
3551}
Greg Kroah-Hartmanc6c25ed2008-10-21 10:41:45 -07003552#endif
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003553
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003554/*
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05303555 * SXG DRIVER FUNCTIONS (below)
3556 *
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003557 * sxg_initialize_adapter - Initialize adapter
3558 *
3559 * Arguments -
3560 * adapter - A pointer to our adapter structure
3561 *
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05303562 * Return - int
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003563 */
J.R. Mauro73b07062008-10-28 18:42:02 -04003564static int sxg_initialize_adapter(struct adapter_t *adapter)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003565{
3566 u32 RssIds, IsrCount;
3567 u32 i;
3568 int status;
3569
3570 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "InitAdpt",
3571 adapter, 0, 0, 0);
3572
J.R. Maurob243c4a2008-10-20 19:28:58 -04003573 RssIds = 1; /* XXXTODO SXG_RSS_CPU_COUNT(adapter); */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003574 IsrCount = adapter->MsiEnabled ? RssIds : 1;
3575
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05303576 /*
3577 * Sanity check SXG_UCODE_REGS structure definition to
3578 * make sure the length is correct
3579 */
Mithlesh Thukral942798b2009-01-05 21:14:34 +05303580 ASSERT(sizeof(struct sxg_ucode_regs) == SXG_REGISTER_SIZE_PER_CPU);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003581
J.R. Maurob243c4a2008-10-20 19:28:58 -04003582 /* Disable interrupts */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003583 SXG_DISABLE_ALL_INTERRUPTS(adapter);
3584
J.R. Maurob243c4a2008-10-20 19:28:58 -04003585 /* Set MTU */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003586 ASSERT((adapter->FrameSize == ETHERMAXFRAME) ||
3587 (adapter->FrameSize == JUMBOMAXFRAME));
3588 WRITE_REG(adapter->UcodeRegs[0].LinkMtu, adapter->FrameSize, TRUE);
3589
J.R. Maurob243c4a2008-10-20 19:28:58 -04003590 /* Set event ring base address and size */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003591 WRITE_REG64(adapter,
3592 adapter->UcodeRegs[0].EventBase, adapter->PEventRings, 0);
3593 WRITE_REG(adapter->UcodeRegs[0].EventSize, EVENT_RING_SIZE, TRUE);
3594
J.R. Maurob243c4a2008-10-20 19:28:58 -04003595 /* Per-ISR initialization */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003596 for (i = 0; i < IsrCount; i++) {
3597 u64 Addr;
J.R. Maurob243c4a2008-10-20 19:28:58 -04003598 /* Set interrupt status pointer */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003599 Addr = adapter->PIsr + (i * sizeof(u32));
3600 WRITE_REG64(adapter, adapter->UcodeRegs[i].Isp, Addr, i);
3601 }
3602
J.R. Maurob243c4a2008-10-20 19:28:58 -04003603 /* XMT ring zero index */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003604 WRITE_REG64(adapter,
3605 adapter->UcodeRegs[0].SPSendIndex,
3606 adapter->PXmtRingZeroIndex, 0);
3607
J.R. Maurob243c4a2008-10-20 19:28:58 -04003608 /* Per-RSS initialization */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003609 for (i = 0; i < RssIds; i++) {
J.R. Maurob243c4a2008-10-20 19:28:58 -04003610 /* Release all event ring entries to the Microcode */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003611 WRITE_REG(adapter->UcodeRegs[i].EventRelease, EVENT_RING_SIZE,
3612 TRUE);
3613 }
3614
J.R. Maurob243c4a2008-10-20 19:28:58 -04003615 /* Transmit ring base and size */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003616 WRITE_REG64(adapter,
3617 adapter->UcodeRegs[0].XmtBase, adapter->PXmtRings, 0);
3618 WRITE_REG(adapter->UcodeRegs[0].XmtSize, SXG_XMT_RING_SIZE, TRUE);
3619
J.R. Maurob243c4a2008-10-20 19:28:58 -04003620 /* Receive ring base and size */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003621 WRITE_REG64(adapter,
3622 adapter->UcodeRegs[0].RcvBase, adapter->PRcvRings, 0);
3623 WRITE_REG(adapter->UcodeRegs[0].RcvSize, SXG_RCV_RING_SIZE, TRUE);
3624
J.R. Maurob243c4a2008-10-20 19:28:58 -04003625 /* Populate the card with receive buffers */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003626 sxg_stock_rcv_buffers(adapter);
3627
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05303628 /*
3629 * Initialize checksum offload capabilities. At the moment we always
3630 * enable IP and TCP receive checksums on the card. Depending on the
3631 * checksum configuration specified by the user, we can choose to
3632 * report or ignore the checksum information provided by the card.
3633 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003634 WRITE_REG(adapter->UcodeRegs[0].ReceiveChecksum,
3635 SXG_RCV_TCP_CSUM_ENABLED | SXG_RCV_IP_CSUM_ENABLED, TRUE);
3636
J.R. Maurob243c4a2008-10-20 19:28:58 -04003637 /* Initialize the MAC, XAUI */
Harvey Harrisone88bd232008-10-17 14:46:10 -07003638 DBG_ERROR("sxg: %s ENTER sxg_initialize_link\n", __func__);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003639 status = sxg_initialize_link(adapter);
Harvey Harrisone88bd232008-10-17 14:46:10 -07003640 DBG_ERROR("sxg: %s EXIT sxg_initialize_link status[%x]\n", __func__,
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003641 status);
3642 if (status != STATUS_SUCCESS) {
3643 return (status);
3644 }
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05303645 /*
3646 * Initialize Dead to FALSE.
3647 * SlicCheckForHang or SlicDumpThread will take it from here.
3648 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003649 adapter->Dead = FALSE;
3650 adapter->PingOutstanding = FALSE;
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +05303651 adapter->State = SXG_STATE_RUNNING;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003652
3653 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XInit",
3654 adapter, 0, 0, 0);
3655 return (STATUS_SUCCESS);
3656}
3657
3658/*
3659 * sxg_fill_descriptor_block - Populate a descriptor block and give it to
3660 * the card. The caller should hold the RcvQLock
3661 *
3662 * Arguments -
3663 * adapter - A pointer to our adapter structure
3664 * RcvDescriptorBlockHdr - Descriptor block to fill
3665 *
3666 * Return
3667 * status
3668 */
J.R. Mauro73b07062008-10-28 18:42:02 -04003669static int sxg_fill_descriptor_block(struct adapter_t *adapter,
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05303670 struct sxg_rcv_descriptor_block_hdr *RcvDescriptorBlockHdr)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003671{
3672 u32 i;
Mithlesh Thukral942798b2009-01-05 21:14:34 +05303673 struct sxg_ring_info *RcvRingInfo = &adapter->RcvRingZeroInfo;
3674 struct sxg_rcv_data_buffer_hdr *RcvDataBufferHdr;
3675 struct sxg_rcv_descriptor_block *RcvDescriptorBlock;
3676 struct sxg_cmd *RingDescriptorCmd;
3677 struct sxg_rcv_ring *RingZero = &adapter->RcvRings[0];
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003678
3679 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "FilBlk",
3680 adapter, adapter->RcvBuffersOnCard,
3681 adapter->FreeRcvBufferCount, adapter->AllRcvBlockCount);
3682
3683 ASSERT(RcvDescriptorBlockHdr);
3684
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05303685 /*
3686 * If we don't have the resources to fill the descriptor block,
3687 * return failure
3688 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003689 if ((adapter->FreeRcvBufferCount < SXG_RCV_DESCRIPTORS_PER_BLOCK) ||
3690 SXG_RING_FULL(RcvRingInfo)) {
3691 adapter->Stats.NoMem++;
3692 return (STATUS_FAILURE);
3693 }
J.R. Maurob243c4a2008-10-20 19:28:58 -04003694 /* Get a ring descriptor command */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003695 SXG_GET_CMD(RingZero,
3696 RcvRingInfo, RingDescriptorCmd, RcvDescriptorBlockHdr);
3697 ASSERT(RingDescriptorCmd);
3698 RcvDescriptorBlockHdr->State = SXG_BUFFER_ONCARD;
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05303699 RcvDescriptorBlock = (struct sxg_rcv_descriptor_block *)
3700 RcvDescriptorBlockHdr->VirtualAddress;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003701
J.R. Maurob243c4a2008-10-20 19:28:58 -04003702 /* Fill in the descriptor block */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003703 for (i = 0; i < SXG_RCV_DESCRIPTORS_PER_BLOCK; i++) {
3704 SXG_GET_RCV_DATA_BUFFER(adapter, RcvDataBufferHdr);
3705 ASSERT(RcvDataBufferHdr);
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +05303706 ASSERT(RcvDataBufferHdr->SxgDumbRcvPacket);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003707 SXG_REINIATIALIZE_PACKET(RcvDataBufferHdr->SxgDumbRcvPacket);
3708 RcvDataBufferHdr->State = SXG_BUFFER_ONCARD;
J.R. Mauro5c7514e2008-10-05 20:38:52 -04003709 RcvDescriptorBlock->Descriptors[i].VirtualAddress =
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05303710 (void *)RcvDataBufferHdr;
Mithlesh Thukral1323e5f2009-01-05 21:13:23 +05303711
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003712 RcvDescriptorBlock->Descriptors[i].PhysicalAddress =
3713 RcvDataBufferHdr->PhysicalAddress;
3714 }
J.R. Maurob243c4a2008-10-20 19:28:58 -04003715 /* Add the descriptor block to receive descriptor ring 0 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003716 RingDescriptorCmd->Sgl = RcvDescriptorBlockHdr->PhysicalAddress;
3717
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05303718 /*
3719 * RcvBuffersOnCard is not protected via the receive lock (see
3720 * sxg_process_event_queue) We don't want to grap a lock every time a
3721 * buffer is returned to us, so we use atomic interlocked functions
3722 * instead.
3723 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003724 adapter->RcvBuffersOnCard += SXG_RCV_DESCRIPTORS_PER_BLOCK;
3725
3726 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "DscBlk",
3727 RcvDescriptorBlockHdr,
3728 RingDescriptorCmd, RcvRingInfo->Head, RcvRingInfo->Tail);
3729
3730 WRITE_REG(adapter->UcodeRegs[0].RcvCmd, 1, true);
3731 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XFilBlk",
3732 adapter, adapter->RcvBuffersOnCard,
3733 adapter->FreeRcvBufferCount, adapter->AllRcvBlockCount);
3734 return (STATUS_SUCCESS);
3735}
3736
3737/*
3738 * sxg_stock_rcv_buffers - Stock the card with receive buffers
3739 *
3740 * Arguments -
3741 * adapter - A pointer to our adapter structure
3742 *
3743 * Return
3744 * None
3745 */
J.R. Mauro73b07062008-10-28 18:42:02 -04003746static void sxg_stock_rcv_buffers(struct adapter_t *adapter)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003747{
Mithlesh Thukral942798b2009-01-05 21:14:34 +05303748 struct sxg_rcv_descriptor_block_hdr *RcvDescriptorBlockHdr;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003749
3750 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "StockBuf",
3751 adapter, adapter->RcvBuffersOnCard,
3752 adapter->FreeRcvBufferCount, adapter->AllRcvBlockCount);
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05303753 /*
3754 * First, see if we've got less than our minimum threshold of
3755 * receive buffers, there isn't an allocation in progress, and
3756 * we haven't exceeded our maximum.. get another block of buffers
3757 * None of this needs to be SMP safe. It's round numbers.
3758 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003759 if ((adapter->FreeRcvBufferCount < SXG_MIN_RCV_DATA_BUFFERS) &&
3760 (adapter->AllRcvBlockCount < SXG_MAX_RCV_BLOCKS) &&
3761 (adapter->AllocationsPending == 0)) {
3762 sxg_allocate_buffer_memory(adapter,
Mithlesh Thukrald0128aa2009-01-05 21:18:04 +05303763 SXG_RCV_BLOCK_SIZE
3764 (SXG_RCV_DATA_HDR_SIZE),
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003765 SXG_BUFFER_TYPE_RCV);
3766 }
J.R. Maurob243c4a2008-10-20 19:28:58 -04003767 /* Now grab the RcvQLock lock and proceed */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003768 spin_lock(&adapter->RcvQLock);
3769 while (adapter->RcvBuffersOnCard < SXG_RCV_DATA_BUFFERS) {
Mithlesh Thukral942798b2009-01-05 21:14:34 +05303770 struct list_entry *_ple;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003771
J.R. Maurob243c4a2008-10-20 19:28:58 -04003772 /* Get a descriptor block */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003773 RcvDescriptorBlockHdr = NULL;
3774 if (adapter->FreeRcvBlockCount) {
3775 _ple = RemoveHeadList(&adapter->FreeRcvBlocks);
J.R. Mauro5c7514e2008-10-05 20:38:52 -04003776 RcvDescriptorBlockHdr =
Mithlesh Thukral942798b2009-01-05 21:14:34 +05303777 container_of(_ple, struct sxg_rcv_descriptor_block_hdr,
J.R. Mauro5c7514e2008-10-05 20:38:52 -04003778 FreeList);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003779 adapter->FreeRcvBlockCount--;
3780 RcvDescriptorBlockHdr->State = SXG_BUFFER_BUSY;
3781 }
3782
3783 if (RcvDescriptorBlockHdr == NULL) {
J.R. Maurob243c4a2008-10-20 19:28:58 -04003784 /* Bail out.. */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003785 adapter->Stats.NoMem++;
3786 break;
3787 }
J.R. Maurob243c4a2008-10-20 19:28:58 -04003788 /* Fill in the descriptor block and give it to the card */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003789 if (sxg_fill_descriptor_block(adapter, RcvDescriptorBlockHdr) ==
3790 STATUS_FAILURE) {
J.R. Maurob243c4a2008-10-20 19:28:58 -04003791 /* Free the descriptor block */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003792 SXG_FREE_RCV_DESCRIPTOR_BLOCK(adapter,
3793 RcvDescriptorBlockHdr);
3794 break;
3795 }
3796 }
3797 spin_unlock(&adapter->RcvQLock);
3798 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XFilBlks",
3799 adapter, adapter->RcvBuffersOnCard,
3800 adapter->FreeRcvBufferCount, adapter->AllRcvBlockCount);
3801}
3802
3803/*
3804 * sxg_complete_descriptor_blocks - Return descriptor blocks that have been
3805 * completed by the microcode
3806 *
3807 * Arguments -
3808 * adapter - A pointer to our adapter structure
3809 * Index - Where the microcode is up to
3810 *
3811 * Return
3812 * None
3813 */
J.R. Mauro73b07062008-10-28 18:42:02 -04003814static void sxg_complete_descriptor_blocks(struct adapter_t *adapter,
J.R. Mauro5c7514e2008-10-05 20:38:52 -04003815 unsigned char Index)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003816{
Mithlesh Thukral942798b2009-01-05 21:14:34 +05303817 struct sxg_rcv_ring *RingZero = &adapter->RcvRings[0];
3818 struct sxg_ring_info *RcvRingInfo = &adapter->RcvRingZeroInfo;
3819 struct sxg_rcv_descriptor_block_hdr *RcvDescriptorBlockHdr;
3820 struct sxg_cmd *RingDescriptorCmd;
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003821
3822 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "CmpRBlks",
3823 adapter, Index, RcvRingInfo->Head, RcvRingInfo->Tail);
3824
J.R. Maurob243c4a2008-10-20 19:28:58 -04003825 /* Now grab the RcvQLock lock and proceed */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003826 spin_lock(&adapter->RcvQLock);
3827 ASSERT(Index != RcvRingInfo->Tail);
3828 while (RcvRingInfo->Tail != Index) {
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05303829 /*
3830 * Locate the current Cmd (ring descriptor entry), and
3831 * associated receive descriptor block, and advance
3832 * the tail
3833 */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003834 SXG_RETURN_CMD(RingZero,
3835 RcvRingInfo,
3836 RingDescriptorCmd, RcvDescriptorBlockHdr);
3837 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "CmpRBlk",
3838 RcvRingInfo->Head, RcvRingInfo->Tail,
3839 RingDescriptorCmd, RcvDescriptorBlockHdr);
3840
J.R. Maurob243c4a2008-10-20 19:28:58 -04003841 /* Clear the SGL field */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003842 RingDescriptorCmd->Sgl = 0;
Mithlesh Thukralddd6f0a2009-01-05 21:15:29 +05303843 /*
3844 * Attempt to refill it and hand it right back to the
3845 * card. If we fail to refill it, free the descriptor block
3846 * header. The card will be restocked later via the
3847 * RcvBuffersOnCard test
3848 */
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05303849 if (sxg_fill_descriptor_block(adapter,
3850 RcvDescriptorBlockHdr) == STATUS_FAILURE)
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003851 SXG_FREE_RCV_DESCRIPTOR_BLOCK(adapter,
3852 RcvDescriptorBlockHdr);
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003853 }
3854 spin_unlock(&adapter->RcvQLock);
3855 SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "XCRBlks",
3856 adapter, Index, RcvRingInfo->Head, RcvRingInfo->Tail);
3857}
3858
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003859static struct pci_driver sxg_driver = {
3860 .name = DRV_NAME,
3861 .id_table = sxg_pci_tbl,
3862 .probe = sxg_entry_probe,
3863 .remove = sxg_entry_remove,
3864#if SXG_POWER_MANAGEMENT_ENABLED
3865 .suspend = sxgpm_suspend,
3866 .resume = sxgpm_resume,
3867#endif
Mithlesh Thukralcb636fe2009-01-05 21:16:56 +05303868 /* .shutdown = slic_shutdown, MOOK_INVESTIGATE */
Greg Kroah-Hartman5db6b772008-08-21 14:04:55 -07003869};
3870
3871static int __init sxg_module_init(void)
3872{
3873 sxg_init_driver();
3874
3875 if (debug >= 0)
3876 sxg_debug = debug;
3877
3878 return pci_register_driver(&sxg_driver);
3879}
3880
3881static void __exit sxg_module_cleanup(void)
3882{
3883 pci_unregister_driver(&sxg_driver);
3884}
3885
3886module_init(sxg_module_init);
3887module_exit(sxg_module_cleanup);