patch-2.4.21 linux-2.4.21/drivers/net/sk98lin/skge.c
Next file: linux-2.4.21/drivers/net/sk98lin/skgehwt.c
Previous file: linux-2.4.21/drivers/net/sk98lin/skcsum.c
Back to the patch index
Back to the overall index
- Lines: 2327
- Date:
2003-06-13 07:51:35.000000000 -0700
- Orig file:
linux-2.4.20/drivers/net/sk98lin/skge.c
- Orig date:
2002-11-28 15:53:14.000000000 -0800
diff -urN linux-2.4.20/drivers/net/sk98lin/skge.c linux-2.4.21/drivers/net/sk98lin/skge.c
@@ -2,18 +2,20 @@
*
* Name: skge.c
* Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.29.2.6 $
- * Date: $Date: 2001/05/21 07:59:29 $
+ * Version: $Revision: 1.43 $
+ * Date: $Date: 2002/11/29 08:42:41 $
* Purpose: The main driver source module
*
******************************************************************************/
/******************************************************************************
*
- * (C)Copyright 1998-2001 SysKonnect GmbH.
+ * (C)Copyright 1998-2002 SysKonnect GmbH.
*
* Driver for SysKonnect Gigabit Ethernet Server Adapters:
*
+ * SK-9871 (single link 1000Base-ZX)
+ * SK-9872 (dual link 1000Base-ZX)
* SK-9861 (single link 1000Base-SX, VF45 Volition Plug)
* SK-9862 (dual link 1000Base-SX, VF45 Volition Plug)
* SK-9841 (single link 1000Base-LX)
@@ -22,6 +24,12 @@
* SK-9844 (dual link 1000Base-SX)
* SK-9821 (single link 1000Base-T)
* SK-9822 (dual link 1000Base-T)
+ * SK-9881 (single link 1000Base-SX V2 LC)
+ * SK-9871 (single link 1000Base-ZX V2)
+ * SK-9861 (single link 1000Base-SX V2, VF45 Volition Plug)
+ * SK-9841 (single link 1000Base-LX V2)
+ * SK-9843 (single link 1000Base-SX V2)
+ * SK-9821 (single link 1000Base-T V2)
*
* Created 10-Feb-1999, based on Linux' acenic.c, 3c59x.c and
* SysKonnects GEnesis Solaris driver
@@ -48,6 +56,62 @@
* History:
*
* $Log: skge.c,v $
+ * Revision 1.43 2002/11/29 08:42:41 mlindner
+ * Fix: Boot message
+ *
+ * Revision 1.42 2002/11/28 13:30:23 mlindner
+ * Add: New frame check
+ *
+ * Revision 1.41 2002/11/27 13:55:18 mlindner
+ * Fix: Drop wrong csum packets
+ * Fix: Initialize proc_entry after hw check
+ *
+ * Revision 1.40 2002/10/31 07:50:37 tschilli
+ * Function SkGeInitAssignRamToQueues() from common module inserted.
+ * Autonegotiation is set to ON for all adapters.
+ * LinkSpeedUsed is used in link up status report.
+ * Role parameter will show up for 1000 Mbps links only.
+ * GetConfiguration() inserted after init level 1 in SkGeChangeMtu().
+ * All return values of SkGeInit() and SkGeInitPort() are checked.
+ *
+ * Revision 1.39 2002/10/02 12:56:05 mlindner
+ * Add: Support for Yukon
+ * Add: Support for ZEROCOPY, scatter-gather and hw checksum
+ * Add: New transmit ring function (use SG and TCP/UDP hardware checksumming)
+ * Add: New init function
+ * Add: Speed check and setup
+ * Add: Merge source for kernel 2.2.x and 2.4.x
+ * Add: Opcode check for tcp
+ * Add: Frame length check
+ * Fix: Transmit complete interrupt
+ * Fix: Interrupt moderation
+ *
+ * Revision 1.29.2.13 2002/01/14 12:44:52 mlindner
+ * Fix: Rlmt modes
+ *
+ * Revision 1.29.2.12 2001/12/07 12:06:18 mlindner
+ * Fix: malloc -> slab changes
+ *
+ * Revision 1.29.2.11 2001/12/06 15:19:20 mlindner
+ * Add: DMA attributes
+ * Fix: Module initialisation
+ * Fix: pci_map_single and pci_unmap_single replaced
+ *
+ * Revision 1.29.2.10 2001/12/06 09:56:50 mlindner
+ * Corrected some printk's
+ *
+ * Revision 1.29.2.9 2001/09/05 12:15:34 mlindner
+ * Add: LBFO Changes
+ * Fix: Counter Errors (Jumbo == to long errors)
+ * Fix: Changed pAC->PciDev declaration
+ * Fix: too short counters
+ *
+ * Revision 1.29.2.8 2001/06/25 12:10:44 mlindner
+ * fix: ReceiveIrq() changed.
+ *
+ * Revision 1.29.2.7 2001/06/25 08:07:05 mlindner
+ * fix: RLMT locking in ReceiveIrq() changed.
+ *
* Revision 1.29.2.6 2001/05/21 07:59:29 mlindner
* fix: MTU init problems
*
@@ -266,24 +330,26 @@
******************************************************************************/
#include "h/skversion.h"
-
#include <linux/module.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
-
#include "h/skdrv1st.h"
#include "h/skdrv2nd.h"
+
/* defines ******************************************************************/
/* for debuging on x86 only */
/* #define BREAKPOINT() asm(" int $3"); */
+/* use the scatter-gather functionality with sendfile() */
+#define SK_ZEROCOPY
+
/* use of a transmit complete interrupt */
#define USE_TX_COMPLETE
/* use interrupt moderation (for tx complete only) */
-// #define USE_INT_MOD
-#define INTS_PER_SEC 1000
+#define USE_INT_MOD
+#define INTS_PER_SEC 1800
/*
* threshold for copying small receive frames
@@ -294,10 +360,13 @@
/* number of adapters that can be configured via command line params */
#define SK_MAX_CARD_PARAM 16
+
/*
* use those defines for a compile-in version of the driver instead
* of command line parameters
*/
+// #define LINK_SPEED_A {"Auto", }
+// #define LINK_SPEED_B {"Auto", }
// #define AUTO_NEG_A {"Sense", }
// #define AUTO_NEG_B {"Sense", }
// #define DUP_CAP_A {"Both", }
@@ -314,10 +383,8 @@
#define DEV_KFREE_SKB_ANY(skb) dev_kfree_skb_any(skb)
/* function prototypes ******************************************************/
-static void FreeResources(struct net_device *dev);
-int init_module(void);
-void cleanup_module(void);
-static int SkGeBoardInit(struct net_device *dev, SK_AC *pAC);
+static void FreeResources(struct SK_NET_DEVICE *dev);
+static int SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC);
static SK_BOOL BoardAllocMem(SK_AC *pAC);
static void BoardFreeMem(SK_AC *pAC);
static void BoardInitMem(SK_AC *pAC);
@@ -326,66 +393,62 @@
static void SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs);
static void SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs);
-static int SkGeOpen(struct net_device *dev);
-static int SkGeClose(struct net_device *dev);
-static int SkGeXmit(struct sk_buff *skb, struct net_device *dev);
-static int SkGeSetMacAddr(struct net_device *dev, void *p);
-static void SkGeSetRxMode(struct net_device *dev);
-static struct net_device_stats *SkGeStats(struct net_device *dev);
-static int SkGeIoctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static int SkGeOpen(struct SK_NET_DEVICE *dev);
+static int SkGeClose(struct SK_NET_DEVICE *dev);
+static int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev);
+static int SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p);
+static void SkGeSetRxMode(struct SK_NET_DEVICE *dev);
+static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev);
+static int SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd);
static void GetConfiguration(SK_AC*);
static void ProductStr(SK_AC*);
static int XmitFrame(SK_AC*, TX_PORT*, struct sk_buff*);
static void FreeTxDescriptors(SK_AC*pAC, TX_PORT*);
static void FillRxRing(SK_AC*, RX_PORT*);
static SK_BOOL FillRxDescriptor(SK_AC*, RX_PORT*);
-static void ReceiveIrq(SK_AC*, RX_PORT*);
-static void ClearAndStartRx(SK_AC*, int);
+static void ReceiveIrq(SK_AC*, RX_PORT*, SK_BOOL);
+static void ClearAndStartRx(SK_AC*, int);
static void ClearTxIrq(SK_AC*, int, int);
static void ClearRxRing(SK_AC*, RX_PORT*);
static void ClearTxRing(SK_AC*, TX_PORT*);
static void SetQueueSizes(SK_AC *pAC);
-static int SkGeChangeMtu(struct net_device *dev, int new_mtu);
+static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int new_mtu);
static void PortReInitBmu(SK_AC*, int);
static int SkGeIocMib(DEV_NET*, unsigned int, int);
-
+static int XmitFrameSG(SK_AC*, TX_PORT*, struct sk_buff*);
/*Extern */
-extern struct proc_dir_entry *pSkRootDir;
-
-//extern struct proc_dir_entry Our_Proc_Dir;
-extern int proc_read(char *buffer, char **buffer_location,
- off_t offset, int buffer_length, int *eof, void *data);
-
+/* external Proc function */
+extern int proc_read(
+ char *buffer,
+ char **buffer_location,
+ off_t offset,
+ int buffer_length,
+ int *eof,
+ void *data);
#ifdef DEBUG
static void DumpMsg(struct sk_buff*, char*);
static void DumpData(char*, int);
static void DumpLong(char*, int);
#endif
-
+void dump_frag( SK_U8 *data, int length);
/* global variables *********************************************************/
static const char *BootString = BOOT_STRING;
-struct net_device *sk98lin_root_dev = NULL;
+struct SK_NET_DEVICE *SkGeRootDev = NULL;
static int probed __initdata = 0;
-struct inode_operations SkInodeOps;
-//static struct file_operations SkFileOps; /* with open/relase */
/* local variables **********************************************************/
static uintptr_t TxQueueAddr[SK_MAX_MACS][2] = {{0x680, 0x600},{0x780, 0x700}};
static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480};
+/* local variables **********************************************************/
+const char SK_Root_Dir_entry[8];
-void proc_fill_inode(struct inode *inode, int fill)
-{
- if (fill)
- MOD_INC_USE_COUNT;
- else
- MOD_DEC_USE_COUNT;
-}
+static struct proc_dir_entry *pSkRootDir;
@@ -405,51 +468,53 @@
static int __init skge_probe (void)
{
int proc_root_initialized = 0;
- int boards_found = 0;
- int version_disp = 0;
- SK_AC *pAC;
- DEV_NET *pNet = NULL;
- struct pci_dev *pdev = NULL;
- unsigned long base_address;
- struct net_device *dev = NULL;
+ int boards_found = 0;
+ SK_AC *pAC;
+ DEV_NET *pNet = NULL;
struct proc_dir_entry *pProcFile;
+ struct pci_dev *pdev = NULL;
+ unsigned long base_address;
+ struct SK_NET_DEVICE *dev = NULL;
+ SK_BOOL DeviceFound = SK_FALSE;
+ SK_BOOL BootStringCount = SK_FALSE;
if (probed)
return -ENODEV;
probed++;
-
- /* display driver info */
- if (!version_disp)
- {
- /* set display flag to TRUE so that */
- /* we only display this string ONCE */
- version_disp = 1;
- printk("%s\n", BootString);
- }
if (!pci_present()) /* is PCI support present? */
return -ENODEV;
- while((pdev = pci_find_device(PCI_VENDOR_ID_SYSKONNECT,
- PCI_DEVICE_ID_SYSKONNECT_GE, pdev)) != NULL) {
+ while((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pdev)))
+ {
dev = NULL;
pNet = NULL;
- if (pci_enable_device(pdev))
+ if ((pdev->vendor != PCI_VENDOR_ID_SYSKONNECT) &&
+ ((pdev->device != PCI_DEVICE_ID_SYSKONNECT_GE) ||
+ (pdev->device != PCI_DEVICE_ID_SYSKONNECT_YU))){
continue;
+ }
/* Configure DMA attributes. */
if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffff) &&
- pci_set_dma_mask(pdev, (u64) 0xffffffff))
- continue;
+ pci_set_dma_mask(pdev, (u64) 0xffffffff))
+ continue;
+
- if ((dev = init_etherdev(dev, sizeof(DEV_NET))) == 0) {
+ if ((dev = init_etherdev(dev, sizeof(DEV_NET))) == NULL) {
printk(KERN_ERR "Unable to allocate etherdev "
"structure!\n");
break;
}
+ if (dev->priv == NULL) {
+ printk(KERN_ERR "Unable to allocate adapter "
+ "structure!\n");
+ break;
+ }
+
pNet = dev->priv;
pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL);
if (pNet->pAC == NULL){
@@ -459,15 +524,23 @@
break;
}
+ /* Print message */
+ if (!BootStringCount) {
+ /* set display flag to TRUE so that */
+ /* we only display this string ONCE */
+ BootStringCount = SK_TRUE;
+ printk("%s\n", BootString);
+ }
+
memset(pNet->pAC, 0, sizeof(SK_AC));
pAC = pNet->pAC;
- pAC->PciDev = *pdev;
+ pAC->PciDev = pdev;
pAC->PciDevId = pdev->device;
pAC->dev[0] = dev;
pAC->dev[1] = dev;
sprintf(pAC->Name, "SysKonnect SK-98xx");
pAC->CheckQueue = SK_FALSE;
-
+
pNet->Mtu = 1500;
pNet->Up = 0;
dev->irq = pdev->irq;
@@ -480,28 +553,23 @@
dev->set_mac_address = &SkGeSetMacAddr;
dev->do_ioctl = &SkGeIoctl;
dev->change_mtu = &SkGeChangeMtu;
+ dev->flags &= ~IFF_RUNNING;
- if(!proc_root_initialized) {
- pSkRootDir = create_proc_entry("sk98lin",
- S_IFDIR | S_IWUSR | S_IRUGO | S_IXUGO, proc_net);
- pSkRootDir->owner = THIS_MODULE;
-
- proc_root_initialized = 1;
+#ifdef SK_ZEROCOPY
+ if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
+ /* Use only if yukon hardware */
+ /* SK and ZEROCOPY - fly baby... */
+ dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
}
-
- pProcFile = create_proc_entry(dev->name,
- S_IFREG | 0444, pSkRootDir);
- pProcFile->read_proc = proc_read;
- pProcFile->write_proc = NULL;
- pProcFile->nlink = 1;
- pProcFile->size = sizeof(dev->name+1);
- pProcFile->data = (void*)pProcFile;
+#endif
/*
* Dummy value.
*/
dev->base_addr = 42;
pci_set_master(pdev);
+
+ pci_set_master(pdev);
base_address = pci_resource_start (pdev, 0);
#ifdef SK_BIG_ENDIAN
@@ -515,13 +583,13 @@
our2 |= PCI_REV_DESC;
SkPciWriteCfgDWord(pAC, PCI_OUR_REG_2, our2);
}
-#endif /* BIG ENDIAN */
+#endif
/*
* Remap the regs into kernel space.
*/
-
pAC->IoBase = (char*)ioremap(base_address, 0x4000);
+
if (!pAC->IoBase){
printk(KERN_ERR "%s: Unable to map I/O register, "
"SK 98xx No. %i will be disabled.\n",
@@ -529,8 +597,8 @@
kfree(dev);
break;
}
- pAC->Index = boards_found;
+ pAC->Index = boards_found;
if (SkGeBoardInit(dev, pAC)) {
FreeResources(dev);
kfree(dev);
@@ -540,9 +608,46 @@
memcpy((caddr_t) &dev->dev_addr,
(caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6);
+ /* First adapter... Create proc and print message */
+ if (!DeviceFound) {
+ DeviceFound = SK_TRUE;
+ SK_MEMCPY(&SK_Root_Dir_entry, BootString,
+ sizeof(SK_Root_Dir_entry) - 1);
+
+ /*Create proc (directory)*/
+ if(!proc_root_initialized) {
+ pSkRootDir = create_proc_entry(SK_Root_Dir_entry,
+ S_IFDIR | S_IWUSR | S_IRUGO | S_IXUGO, proc_net);
+ proc_root_initialized = 1;
+ }
+
+ pSkRootDir->owner = THIS_MODULE;
+ }
+
+
+
+ /* Create proc file */
+ pProcFile = create_proc_entry(dev->name,
+ S_IFREG | S_IXUSR | S_IWGRP | S_IROTH,
+ pSkRootDir);
+
+
+ pProcFile->read_proc = proc_read;
+ pProcFile->write_proc = NULL;
+ pProcFile->nlink = 1;
+ pProcFile->size = sizeof(dev->name + 1);
+ pProcFile->data = (void *)pProcFile;
+
pNet->PortNr = 0;
pNet->NetNr = 0;
+#ifdef SK_ZEROCOPY
+ if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
+ /* SG and ZEROCOPY - fly baby... */
+ dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+ }
+#endif
+
boards_found++;
/* More then one port found */
@@ -569,24 +674,39 @@
dev->set_mac_address = &SkGeSetMacAddr;
dev->do_ioctl = &SkGeIoctl;
dev->change_mtu = &SkGeChangeMtu;
+ dev->flags &= ~IFF_RUNNING;
- pProcFile = create_proc_entry(dev->name,
- S_IFREG | 0444, pSkRootDir);
+#ifdef SK_ZEROCOPY
+ if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
+ /* SG and ZEROCOPY - fly baby... */
+ dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+ }
+#endif
+
+ pProcFile = create_proc_entry(dev->name,
+ S_IFREG | S_IXUSR | S_IWGRP | S_IROTH,
+ pSkRootDir);
+
+
pProcFile->read_proc = proc_read;
pProcFile->write_proc = NULL;
pProcFile->nlink = 1;
- pProcFile->size = sizeof(dev->name+1);
- pProcFile->data = (void*)pProcFile;
+ pProcFile->size = sizeof(dev->name + 1);
+ pProcFile->data = (void *)pProcFile;
memcpy((caddr_t) &dev->dev_addr,
(caddr_t) &pAC->Addr.Net[1].CurrentMacAddress, 6);
printk("%s: %s\n", dev->name, pAC->DeviceStr);
printk(" PrefPort:B RlmtMode:Dual Check Link State\n");
-
+
}
+ /* Save the hardware revision */
+ pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) +
+ (pAC->GIni.GIPciHwRev & 0x0F);
+
/*
* This is bollocks, but we need to tell the net-init
* code that it shall go for the next device.
@@ -617,7 +737,7 @@
* Returns: N/A
*
*/
-static void FreeResources(struct net_device *dev)
+static void FreeResources(struct SK_NET_DEVICE *dev)
{
SK_U32 AllocFlag;
DEV_NET *pNet;
@@ -640,17 +760,19 @@
} /* FreeResources */
-MODULE_AUTHOR("Christoph Goos <cgoos@syskonnect.de>");
+MODULE_AUTHOR("Mirko Lindner <mlindner@syskonnect.de>");
MODULE_DESCRIPTION("SysKonnect SK-NET Gigabit Ethernet SK-98xx driver");
MODULE_LICENSE("GPL");
+MODULE_PARM(Speed_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+MODULE_PARM(Speed_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
MODULE_PARM(AutoNeg_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
MODULE_PARM(AutoNeg_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
MODULE_PARM(DupCap_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
MODULE_PARM(DupCap_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
MODULE_PARM(FlowCtrl_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
MODULE_PARM(FlowCtrl_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
-MODULE_PARM(Role_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
-MODULE_PARM(Role_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+MODULE_PARM(Role_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+MODULE_PARM(Role_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
MODULE_PARM(PrefPort, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
MODULE_PARM(RlmtMode, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
/* not used, just there because every driver should have them: */
@@ -658,6 +780,18 @@
MODULE_PARM(debug, "i");
+#ifdef LINK_SPEED_A
+static char *Speed_A[SK_MAX_CARD_PARAM] = LINK_SPEED;
+#else
+static char *Speed_A[SK_MAX_CARD_PARAM] = {"", };
+#endif
+
+#ifdef LINK_SPEED_B
+static char *Speed_B[SK_MAX_CARD_PARAM] = LINK_SPEED;
+#else
+static char *Speed_B[SK_MAX_CARD_PARAM] = {"", };
+#endif
+
#ifdef AUTO_NEG_A
static char *AutoNeg_A[SK_MAX_CARD_PARAM] = AUTO_NEG_A;
#else
@@ -718,7 +852,6 @@
static char *RlmtMode[SK_MAX_CARD_PARAM] = {"", };
#endif
-
static int debug = 0; /* not used */
static int options[SK_MAX_CARD_PARAM] = {0, }; /* not used */
@@ -737,7 +870,7 @@
static int __init skge_init_module(void)
{
int cards;
- sk98lin_root_dev = NULL;
+ SkGeRootDev = NULL;
/* just to avoid warnings ... */
debug = 0;
@@ -745,7 +878,7 @@
cards = skge_probe();
if (cards == 0) {
- printk("No adapter found\n");
+ printk("No adapter found.\n");
}
return cards ? 0 : -ENODEV;
} /* skge_init_module */
@@ -765,16 +898,16 @@
{
DEV_NET *pNet;
SK_AC *pAC;
-struct net_device *next;
+struct SK_NET_DEVICE *next;
unsigned long Flags;
SK_EVPARA EvPara;
- while (sk98lin_root_dev) {
- pNet = (DEV_NET*) sk98lin_root_dev->priv;
+ while (SkGeRootDev) {
+ pNet = (DEV_NET*) SkGeRootDev->priv;
pAC = pNet->pAC;
next = pAC->Next;
- netif_stop_queue(sk98lin_root_dev);
+ netif_stop_queue(SkGeRootDev);
SkGeYellowLED(pAC, pAC->IoBase, 0);
if(pAC->BoardLevel == 2) {
@@ -806,17 +939,17 @@
kfree(pAC->dev[1]);
}
- FreeResources(sk98lin_root_dev);
+ FreeResources(SkGeRootDev);
- sk98lin_root_dev->get_stats = NULL;
+ SkGeRootDev->get_stats = NULL;
/*
* otherwise unregister_netdev calls get_stats with
* invalid IO ... :-(
*/
- unregister_netdev(sk98lin_root_dev);
- kfree(sk98lin_root_dev);
+ unregister_netdev(SkGeRootDev);
+ kfree(SkGeRootDev);
kfree(pAC);
- sk98lin_root_dev = next;
+ SkGeRootDev = next;
}
/* clear proc-dir */
@@ -840,13 +973,14 @@
* 0, if everything is ok
* !=0, on error
*/
-static int __init SkGeBoardInit(struct net_device *dev, SK_AC *pAC)
+static int __init SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC)
{
short i;
unsigned long Flags;
char *DescrString = "sk98lin: Driver for Linux"; /* this is given to PNMI */
char *VerStr = VER_STRING;
int Ret; /* return code of request_irq */
+SK_BOOL DualNet;
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
("IoBase: %08lX\n", (unsigned long)pAC->IoBase));
@@ -858,7 +992,6 @@
}
/* Initialize the mutexes */
-
for (i=0; i<SK_MAX_MACS; i++) {
spin_lock_init(&pAC->TxPort[i][0].TxDesRingLock);
spin_lock_init(&pAC->RxPort[i].RxDesRingLock);
@@ -908,7 +1041,6 @@
pAC->GIni.GIPortUsage = SK_MUL_LINK;
}
-
pAC->BoardLevel = 1;
spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
@@ -918,12 +1050,13 @@
Ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ,
pAC->Name, dev);
} else {
- printk(KERN_WARNING "%s: illegal number of ports: %d\n",
+ printk(KERN_WARNING "%s: Illegal number of ports: %d\n",
dev->name, pAC->GIni.GIMacsFound);
return -EAGAIN;
}
+
if (Ret) {
- printk(KERN_WARNING "%s: Requested IRQ %d is busy\n",
+ printk(KERN_WARNING "%s: Requested IRQ %d is busy.\n",
dev->name, dev->irq);
return -EAGAIN;
}
@@ -931,7 +1064,7 @@
/* Alloc memory for this board (Mem for RxD/TxD) : */
if(!BoardAllocMem(pAC)) {
- printk("No memory for descriptor rings\n");
+ printk("No memory for descriptor rings.\n");
return(-EAGAIN);
}
@@ -941,8 +1074,24 @@
pAC->CsOfs = (pAC->CsOfs2 << 16) | pAC->CsOfs1;
BoardInitMem(pAC);
-
+#if 0
SetQueueSizes(pAC);
+#else
+ /* tschilling: New common function with minimum size check. */
+ DualNet = SK_FALSE;
+ if (pAC->RlmtNets == 2) {
+ DualNet = SK_TRUE;
+ }
+
+ if (SkGeInitAssignRamToQueues(
+ pAC,
+ pAC->ActivePort,
+ DualNet)) {
+ BoardFreeMem(pAC);
+ printk("SkGeInitAssignRamToQueues failed.\n");
+ return(-EAGAIN);
+ }
+#endif
/* Print adapter specific string from vpd */
ProductStr(pAC);
@@ -957,14 +1106,13 @@
((pAC->RlmtMode==7) ? "Check Segmentation" :
((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error")))));
-
SkGeYellowLED(pAC, pAC->IoBase, 1);
/*
* Register the device here
*/
- pAC->Next = sk98lin_root_dev;
- sk98lin_root_dev = dev;
+ pAC->Next = SkGeRootDev;
+ SkGeRootDev = dev;
return (0);
} /* SkGeBoardInit */
@@ -1001,17 +1149,19 @@
AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound
+ RX_RING_SIZE + 8;
#endif
- pDescrMem = pci_alloc_consistent(&pAC->PciDev, AllocLength,
+
+ pDescrMem = pci_alloc_consistent(pAC->PciDev, AllocLength,
&pAC->pDescrMemDMA);
+
if (pDescrMem == NULL) {
return (SK_FALSE);
}
pAC->pDescrMem = pDescrMem;
+ BusAddr = (unsigned long) pAC->pDescrMemDMA;
/* Descriptors need 8 byte alignment, and this is ensured
* by pci_alloc_consistent.
*/
- BusAddr = (unsigned long) pAC->pDescrMemDMA;
for (i=0; i<pAC->GIni.GIMacsFound; i++) {
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
("TX%d/A: pDescrMem: %lX, PhysDescrMem: %lX\n",
@@ -1059,7 +1209,8 @@
AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound
+ RX_RING_SIZE + 8;
#endif
- pci_free_consistent(&pAC->PciDev, AllocLength,
+
+ pci_free_consistent(pAC->PciDev, AllocLength,
pAC->pDescrMem, pAC->pDescrMemDMA);
pAC->pDescrMem = NULL;
} /* BoardFreeMem */
@@ -1146,8 +1297,7 @@
DescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) *
DESCR_ALIGN;
DescrNum = TX_RING_SIZE / DescrSize;
- }
- else {
+ } else {
DescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) *
DESCR_ALIGN;
DescrNum = RX_RING_SIZE / DescrSize;
@@ -1156,7 +1306,7 @@
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
("Descriptor size: %d Descriptor Number: %d\n",
DescrSize,DescrNum));
-
+
pDescr = (RXD*) pMemArea;
pPrevDescr = NULL;
pNextDescr = (RXD*) (((char*)pDescr) + DescrSize);
@@ -1166,7 +1316,8 @@
pDescr->VNextRxd = VNextDescr & 0xffffffffULL;
pDescr->pNextRxd = pNextDescr;
pDescr->TcpSumStarts = pAC->CsOfs;
- /* advance on step */
+
+ /* advance one step */
pPrevDescr = pDescr;
pDescr = pNextDescr;
pNextDescr = (RXD*) (((char*)pDescr) + DescrSize);
@@ -1240,8 +1391,7 @@
*/
static void SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs)
{
-struct net_device *dev = (struct net_device *)dev_id;
-
+struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id;
DEV_NET *pNet;
SK_AC *pAC;
SK_U32 IntSrc; /* interrupts source register contents */
@@ -1269,22 +1419,22 @@
SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
SK_DBGCAT_DRV_INT_SRC,
("EOF RX1 IRQ\n"));
- ReceiveIrq(pAC, &pAC->RxPort[0]);
- SK_PNMI_CNT_RX_INTR(pAC,0);
+ ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
+ SK_PNMI_CNT_RX_INTR(pAC, 0);
}
if (IntSrc & IRQ_EOF_RX2) {
SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
SK_DBGCAT_DRV_INT_SRC,
("EOF RX2 IRQ\n"));
- ReceiveIrq(pAC, &pAC->RxPort[1]);
- SK_PNMI_CNT_RX_INTR(pAC,1);
+ ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE);
+ SK_PNMI_CNT_RX_INTR(pAC, 1);
}
#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
if (IntSrc & IRQ_EOF_AS_TX1) {
SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
SK_DBGCAT_DRV_INT_SRC,
("EOF AS TX1 IRQ\n"));
- SK_PNMI_CNT_TX_INTR(pAC,0);
+ SK_PNMI_CNT_TX_INTR(pAC, 0);
spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
@@ -1293,7 +1443,7 @@
SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
SK_DBGCAT_DRV_INT_SRC,
("EOF AS TX2 IRQ\n"));
- SK_PNMI_CNT_TX_INTR(pAC,1);
+ SK_PNMI_CNT_TX_INTR(pAC, 1);
spin_lock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
FreeTxDescriptors(pAC, &pAC->TxPort[1][TX_PRIO_LOW]);
spin_unlock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
@@ -1303,7 +1453,7 @@
SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
SK_DBGCAT_DRV_INT_SRC,
("EOF SY TX1 IRQ\n"));
- SK_PNMI_CNT_TX_INTR(pAC,0);
+ SK_PNMI_CNT_TX_INTR(pAC, 1);
spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);
spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
@@ -1313,14 +1463,14 @@
SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
SK_DBGCAT_DRV_INT_SRC,
("EOF SY TX2 IRQ\n"));
- SK_PNMI_CNT_TX_INTR(pAC,1);
+ SK_PNMI_CNT_TX_INTR(pAC, 1);
spin_lock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);
FreeTxDescriptors(pAC, 1, TX_PRIO_HIGH);
spin_unlock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);
ClearTxIrq(pAC, 1, TX_PRIO_HIGH);
}
-#endif /* 0 */
-#endif /* USE_TX_COMPLETE */
+#endif
+#endif
/* do all IO at once */
if (IntSrc & IRQ_EOF_RX1)
@@ -1338,11 +1488,12 @@
if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) {
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
- ("SPECIAL IRQ\n"));
+ ("SPECIAL IRQ DP-Cards => %x\n", IntSrc));
pAC->CheckQueue = SK_FALSE;
spin_lock(&pAC->SlowPathLock);
if (IntSrc & SPECIAL_IRQS)
SkGeSirqIsr(pAC, pAC->IoBase, IntSrc);
+
SkEventDispatcher(pAC, pAC->IoBase);
spin_unlock(&pAC->SlowPathLock);
}
@@ -1351,33 +1502,17 @@
* came in after handling the ring (OUTs may be delayed
* in hardware buffers, but are through after IN)
*/
- // ReceiveIrq(pAC, &pAC->RxPort[pAC->ActivePort]);
- ReceiveIrq(pAC, &pAC->RxPort[0]);
- ReceiveIrq(pAC, &pAC->RxPort[1]);
-
+ ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
+ ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE);
+ if (pAC->CheckQueue) {
+ pAC->CheckQueue = SK_FALSE;
+ spin_lock(&pAC->SlowPathLock);
+ SkEventDispatcher(pAC, pAC->IoBase);
+ spin_unlock(&pAC->SlowPathLock);
+ }
-#if 0
-// #ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
- spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
- FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
- spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
-
- spin_lock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
- FreeTxDescriptors(pAC, &pAC->TxPort[1][TX_PRIO_LOW]);
- spin_unlock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
-
-#if 0 /* only if sync. queues used */
- spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
- FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);
- spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
-
- spin_lock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);
- FreeTxDescriptors(pAC, 1, TX_PRIO_HIGH);
- spin_unlock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);
-#endif /* 0 */
-#endif /* USE_TX_COMPLETE */
/* IRQ is processed - Enable IRQs again*/
SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK);
@@ -1401,7 +1536,7 @@
*/
static void SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs)
{
-struct net_device *dev = (struct net_device *)dev_id;
+struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id;
DEV_NET *pNet;
SK_AC *pAC;
SK_U32 IntSrc; /* interrupts source register contents */
@@ -1416,7 +1551,7 @@
if (IntSrc == 0) {
return;
}
-
+
while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) {
#if 0 /* software irq currently not used */
if (IntSrc & IRQ_SW) {
@@ -1429,15 +1564,15 @@
SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
SK_DBGCAT_DRV_INT_SRC,
("EOF RX1 IRQ\n"));
- ReceiveIrq(pAC, &pAC->RxPort[0]);
- SK_PNMI_CNT_RX_INTR(pAC,0);
+ ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
+ SK_PNMI_CNT_RX_INTR(pAC, 0);
}
#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
if (IntSrc & IRQ_EOF_AS_TX1) {
SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
SK_DBGCAT_DRV_INT_SRC,
("EOF AS TX1 IRQ\n"));
- SK_PNMI_CNT_TX_INTR(pAC,0);
+ SK_PNMI_CNT_TX_INTR(pAC, 0);
spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
@@ -1447,14 +1582,14 @@
SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
SK_DBGCAT_DRV_INT_SRC,
("EOF SY TX1 IRQ\n"));
- SK_PNMI_CNT_TX_INTR(pAC,1);
+ SK_PNMI_CNT_TX_INTR(pAC, 0);
spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);
spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
ClearTxIrq(pAC, 0, TX_PRIO_HIGH);
}
-#endif /* 0 */
-#endif /* USE_TX_COMPLETE */
+#endif
+#endif
/* do all IO at once */
if (IntSrc & IRQ_EOF_RX1)
@@ -1468,11 +1603,12 @@
if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) {
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
- ("SPECIAL IRQ\n"));
+ ("SPECIAL IRQ SP-Cards => %x\n", IntSrc));
pAC->CheckQueue = SK_FALSE;
spin_lock(&pAC->SlowPathLock);
if (IntSrc & SPECIAL_IRQS)
SkGeSirqIsr(pAC, pAC->IoBase, IntSrc);
+
SkEventDispatcher(pAC, pAC->IoBase);
spin_unlock(&pAC->SlowPathLock);
}
@@ -1481,21 +1617,7 @@
* came in after handling the ring (OUTs may be delayed
* in hardware buffers, but are through after IN)
*/
- ReceiveIrq(pAC, &pAC->RxPort[0]);
-
-#if 0
-// #ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
- spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
- FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
- spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
-
-#if 0 /* only if sync. queues used */
- spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
- FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);
- spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
-
-#endif /* 0 */
-#endif /* USE_TX_COMPLETE */
+ ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
/* IRQ is processed - Enable IRQs again*/
SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK);
@@ -1521,13 +1643,13 @@
* != 0 on error
*/
static int SkGeOpen(
-struct net_device *dev)
+struct SK_NET_DEVICE *dev)
{
-DEV_NET *pNet;
-SK_AC *pAC;
-unsigned long Flags; /* for spin lock */
-int i;
-SK_EVPARA EvPara; /* an event parameter union */
+ DEV_NET *pNet;
+ SK_AC *pAC;
+ unsigned long Flags; /* for spin lock */
+ int i;
+ SK_EVPARA EvPara; /* an event parameter union */
pNet = (DEV_NET*) dev->priv;
pAC = pNet->pAC;
@@ -1538,7 +1660,7 @@
if (pAC->BoardLevel == 0) {
/* level 1 init common modules here */
if (SkGeInit(pAC, pAC->IoBase, 1) != 0) {
- printk("%s: HWInit(1) failed\n", pAC->dev[pNet->PortNr]->name);
+ printk("%s: HWInit (1) failed.\n", pAC->dev[pNet->PortNr]->name);
return (-1);
}
SkI2cInit (pAC, pAC->IoBase, 1);
@@ -1551,8 +1673,11 @@
}
if (pAC->BoardLevel != 2) {
- /* level 2 init modules here */
- SkGeInit (pAC, pAC->IoBase, 2);
+ /* tschilling: Level 2 init modules here, check return value. */
+ if (SkGeInit(pAC, pAC->IoBase, 2) != 0) {
+ printk("%s: HWInit (2) failed.\n", pAC->dev[pNet->PortNr]->name);
+ return (-1);
+ }
SkI2cInit (pAC, pAC->IoBase, 2);
SkEventInit (pAC, pAC->IoBase, 2);
SkPnmiInit (pAC, pAC->IoBase, 2);
@@ -1561,6 +1686,7 @@
SkTimerInit (pAC, pAC->IoBase, 2);
pAC->BoardLevel = 2;
}
+
for (i=0; i<pAC->GIni.GIMacsFound; i++) {
/* Enable transmit descriptor polling. */
SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE);
@@ -1627,18 +1753,17 @@
* error code - on error
*/
static int SkGeClose(
-struct net_device *dev)
+struct SK_NET_DEVICE *dev)
{
-DEV_NET *pNet;
-SK_AC *pAC;
+ DEV_NET *pNet;
+ SK_AC *pAC;
-unsigned long Flags; /* for spin lock */
-int i;
-int PortIdx;
-SK_EVPARA EvPara;
+ unsigned long Flags; /* for spin lock */
+ int i;
+ int PortIdx;
+ SK_EVPARA EvPara;
netif_stop_queue(dev);
-
pNet = (DEV_NET*) dev->priv;
pAC = pNet->pAC;
@@ -1653,7 +1778,6 @@
/*
* Clear multicast table, promiscuous mode ....
*/
-
SkAddrMcClear(pAC, pAC->IoBase, PortIdx, 0);
SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
SK_PROM_MODE_NONE);
@@ -1688,16 +1812,17 @@
spin_unlock_irqrestore(&pAC->TxPort[pNet->PortNr]
[TX_PRIO_LOW].TxDesRingLock, Flags);
}
+
if (pAC->RlmtNets == 1) {
/* clear all descriptor rings */
for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- ReceiveIrq(pAC, &pAC->RxPort[i]);
+ ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE);
ClearRxRing(pAC, &pAC->RxPort[i]);
ClearTxRing(pAC, &pAC->TxPort[i][TX_PRIO_LOW]);
}
} else {
/* clear port descriptor rings */
- ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr]);
+ ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE);
ClearRxRing(pAC, &pAC->RxPort[pNet->PortNr]);
ClearTxRing(pAC, &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW]);
}
@@ -1712,6 +1837,7 @@
return (0);
} /* SkGeClose */
+
/*****************************************************************************
*
* SkGeXmit - Linux frame transmit function
@@ -1727,23 +1853,47 @@
* WARNING: returning 1 in 'tbusy' case caused system crashes (double
* allocated skb's) !!!
*/
-static int SkGeXmit(struct sk_buff *skb, struct net_device *dev)
+static int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev)
{
DEV_NET *pNet;
SK_AC *pAC;
int Rc; /* return code of XmitFrame */
-
+
pNet = (DEV_NET*) dev->priv;
pAC = pNet->pAC;
- if (pAC->RlmtNets == 2)
- Rc = XmitFrame(pAC, &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW], skb);
- else
- Rc = XmitFrame(pAC, &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW], skb);
+ if ((!skb_shinfo(skb)->nr_frags) ||
+ (pAC->GIni.GIChipId == CHIP_ID_GENESIS)) {
+ /* Don't activate scatter-gather and hardware checksum */
+
+ if (pAC->RlmtNets == 2)
+ Rc = XmitFrame(
+ pAC,
+ &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW],
+ skb);
+ else
+ Rc = XmitFrame(
+ pAC,
+ &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW],
+ skb);
+ } else {
+ /* scatter-gather and hardware TCP checksumming anabled*/
+ if (pAC->RlmtNets == 2)
+ Rc = XmitFrameSG(
+ pAC,
+ &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW],
+ skb);
+ else
+ Rc = XmitFrameSG(
+ pAC,
+ &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW],
+ skb);
+ }
/* Transmitter out of resources? */
- if (Rc <= 0)
+ if (Rc <= 0) {
netif_stop_queue(dev);
+ }
/* If not taken, give buffer ownership back to the
* queueing layer.
@@ -1773,10 +1923,10 @@
* if necessary.
*
* Returns:
- * > 0 - on succes: the number of bytes in the message
- * = 0 - on resource shortage: this frame sent or dropped, now
- * the ring is full ( -> set tbusy)
- * < 0 - on failure: other problems ( -> return failure to upper layers)
+ * > 0 - on succes: the number of bytes in the message
+ * = 0 - on resource shortage: this frame sent or dropped, now
+ * the ring is full ( -> set tbusy)
+ * < 0 - on failure: other problems ( -> return failure to upper layers)
*/
static int XmitFrame(
SK_AC *pAC, /* pointer to adapter context */
@@ -1792,7 +1942,9 @@
("X"));
spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
-
+#ifndef USE_TX_COMPLETE
+ FreeTxDescriptors(pAC, pTxPort);
+#endif
if (pTxPort->TxdRingFree == 0) {
/* no enough free descriptors in ring at the moment */
FreeTxDescriptors(pAC, pTxPort);
@@ -1803,6 +1955,8 @@
SK_DBGCAT_DRV_TX_PROGRESS,
("XmitFrame failed\n"));
/* this message can not be sent now */
+ /* Because tbusy seems to be set, the message should not be freed here */
+ /* It will be used by the scheduler of the ethernet handler */
return (-1);
}
}
@@ -1821,12 +1975,12 @@
#endif
/* set up descriptor and CONTROL dword */
- PhysAddr = (SK_U64) pci_map_page(&pAC->PciDev,
- virt_to_page(pMessage->data),
- ((unsigned long) pMessage->data &
- ~PAGE_MASK),
- pMessage->len,
- PCI_DMA_TODEVICE);
+ PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
+ virt_to_page(pMessage->data),
+ ((unsigned long) pMessage->data &
+ ~PAGE_MASK),
+ pMessage->len,
+ PCI_DMA_TODEVICE);
pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff);
pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
pTxd->pMBuf = pMessage;
@@ -1847,18 +2001,200 @@
BytesSend = pMessage->len;
+ spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
/* after releasing the lock, the skb may be immidiately freed */
- if (pTxPort->TxdRingFree != 0) {
- spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
+ if (pTxPort->TxdRingFree != 0)
return (BytesSend);
- }
- else {
- /* ring full: set tbusy on return */
- spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
+ else
return (0);
- }
+
} /* XmitFrame */
+/*****************************************************************************
+ *
+ * XmitFrameSG - fill one socket buffer into the transmit ring
+ * (use SG and TCP/UDP hardware checksumming)
+ *
+ * Description:
+ * This function puts a message into the transmit descriptor ring
+ * if there is a descriptors left.
+ *
+ * Returns:
+ * > 0 - on succes: the number of bytes in the message
+ * = 0 - on resource shortage: this frame sent or dropped, now
+ * the ring is full ( -> set tbusy)
+ * < 0 - on failure: other problems ( -> return failure to upper layers)
+ */
+static int XmitFrameSG(
+SK_AC *pAC, /* pointer to adapter context */
+TX_PORT *pTxPort, /* pointer to struct of port to send to */
+struct sk_buff *pMessage) /* pointer to send-message */
+{
+
+ int i;
+ int BytesSend;
+ int hlength;
+ int protocol;
+ skb_frag_t *sk_frag;
+ TXD *pTxd;
+ TXD *pTxdFst;
+ TXD *pTxdLst;
+ SK_U64 PhysAddr;
+ unsigned long Flags;
+
+ spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
+#ifndef USE_TX_COMPLETE
+ FreeTxDescriptors(pAC, pTxPort);
+#endif
+ if ((skb_shinfo(pMessage)->nr_frags +1) > pTxPort->TxdRingFree) {
+ FreeTxDescriptors(pAC, pTxPort);
+ if ((skb_shinfo(pMessage)->nr_frags + 1) > pTxPort->TxdRingFree) {
+ spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
+ SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex);
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+ SK_DBGCAT_DRV_TX_PROGRESS,
+ ("XmitFrameSG failed - Ring full\n"));
+ /* this message can not be sent now */
+ return(-1);
+ }
+ }
+
+
+ pTxd = pTxPort->pTxdRingHead;
+ pTxdFst = pTxd;
+ pTxdLst = pTxd;
+ BytesSend = 0;
+ protocol = 0;
+
+ /* map first fragment (header) */
+ PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
+ virt_to_page(pMessage->data),
+ ((unsigned long) pMessage->data & ~PAGE_MASK),
+ skb_headlen(pMessage),
+ PCI_DMA_TODEVICE);
+
+ pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff);
+ pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
+
+ /* HW checksum? */
+ if (pMessage->ip_summed == CHECKSUM_HW) {
+ pTxd->TBControl = TX_CTRL_STF |
+ TX_CTRL_ST_FWD |
+ skb_headlen(pMessage);
+
+ /* We have to use the opcode for tcp here because the opcode for
+ udp is not working in the hardware yet (revision 2.0)*/
+ protocol = ((SK_U8)pMessage->data[23] & 0xf);
+ if ((protocol == 17) && (pAC->GIni.GIChipRev != 0))
+ pTxd->TBControl |= BMU_UDP_CHECK;
+ else
+ pTxd->TBControl |= BMU_TCP_CHECK ;
+
+ hlength = ((SK_U8)pMessage->data[14] & 0xf) * 4;
+ pTxd->TcpSumOfs = 0; /* PH-Checksum already claculated */
+ pTxd->TcpSumSt = 14+hlength+16;
+ pTxd->TcpSumWr = 14+hlength;
+
+ } else {
+ pTxd->TBControl = TX_CTRL_CHECK_DEFAULT |
+ TX_CTRL_SOFTWARE |
+ TX_CTRL_STF |
+ skb_headlen(pMessage);
+ }
+
+ pTxd = pTxd->pNextTxd;
+ pTxPort->TxdRingFree--;
+ BytesSend += skb_headlen(pMessage);
+
+
+ /* Map SG fragments */
+ for (i = 0; i < skb_shinfo(pMessage)->nr_frags; i++) {
+ sk_frag = &skb_shinfo(pMessage)->frags[i];
+
+ /* we already have the proper value in entry */
+ PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
+ sk_frag->page,
+ sk_frag->page_offset,
+ sk_frag->size,
+ PCI_DMA_TODEVICE);
+
+ pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff);
+ pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
+ pTxd->pMBuf = pMessage;
+
+ /* HW checksum */
+ if (pMessage->ip_summed == CHECKSUM_HW) {
+ pTxd->TBControl = TX_CTRL_OWN_BMU |
+ TX_CTRL_SOFTWARE |
+ TX_CTRL_ST_FWD;
+
+ /* We have to use the opcode for tcp here because the opcode for
+ udp is not working in the hardware yet (revision 2.0)*/
+ if ((protocol == 17) && (pAC->GIni.GIChipRev != 0))
+ pTxd->TBControl |= BMU_UDP_CHECK ;
+ else
+ pTxd->TBControl |= BMU_TCP_CHECK ;
+
+ } else {
+ pTxd->TBControl = TX_CTRL_CHECK_DEFAULT |
+ TX_CTRL_SOFTWARE |
+ TX_CTRL_OWN_BMU;
+ }
+
+ /* Last fragment */
+ if( (i+1) == skb_shinfo(pMessage)->nr_frags ) {
+#ifdef USE_TX_COMPLETE
+ pTxd->TBControl |= TX_CTRL_EOF |
+ TX_CTRL_EOF_IRQ |
+ sk_frag->size;
+#else
+ pTxd->TBControl |= TX_CTRL_EOF |
+ sk_frag->size;
+#endif
+ pTxdFst->TBControl |= TX_CTRL_OWN_BMU |
+ TX_CTRL_SOFTWARE;
+
+ } else {
+ pTxd->TBControl |= sk_frag->size;
+ }
+ pTxdLst = pTxd;
+ pTxd = pTxd->pNextTxd;
+ pTxPort->TxdRingFree--;
+ BytesSend += sk_frag->size;
+ }
+
+ if ((pTxPort->pTxdRingPrev->TBControl & TX_CTRL_OWN_BMU) == 0) {
+ /* previous descriptor already done, so give tx start cmd */
+ /* StartTx(pAC, pTxPort->HwAddr); */
+ SK_OUT8(pTxPort->HwAddr, TX_Q_CTRL, TX_Q_CTRL_START);
+ }
+
+ pTxPort->pTxdRingPrev = pTxdLst;
+ pTxPort->pTxdRingHead = pTxd;
+
+ spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
+
+ if (pTxPort->TxdRingFree > 0)
+ return (BytesSend);
+ else
+ return (0);
+}
+
+
+void dump_frag( SK_U8 *data, int length)
+{
+ int i;
+
+ printk("Length: %d\n", length);
+ for( i=0; i < length; i++ ) {
+ printk(" %02x", (SK_U8)*(data + i) );
+ if( !((i+1) % 20) )
+ printk("\n");
+ }
+ printk("\n\n");
+
+}
+
/*****************************************************************************
*
@@ -1889,7 +2225,6 @@
pNewTail = pTxPort->pTxdRingTail;
pTxd = pNewTail;
-
/*
* loop forever; exits if TX_CTRL_SOFTWARE bit not set in start frame
* or TX_CTRL_OWN_BMU bit set in any frame
@@ -1918,19 +2253,19 @@
/* release the DMA mapping */
PhysAddr = ((SK_U64) pTxd->VDataHigh) << (SK_U64) 32;
PhysAddr |= (SK_U64) pTxd->VDataLow;
- pci_unmap_page(&pAC->PciDev, PhysAddr,
- pTxd->pMBuf->len,
- PCI_DMA_TODEVICE);
+ pci_unmap_page(pAC->PciDev, PhysAddr,
+ pTxd->pMBuf->len,
+ PCI_DMA_TODEVICE);
+
+ if (Control & TX_CTRL_EOF)
+ DEV_KFREE_SKB_ANY(pTxd->pMBuf); /* free message */
- /* free message */
- DEV_KFREE_SKB_ANY(pTxd->pMBuf);
pTxPort->TxdRingFree++;
pTxd->TBControl &= ~TX_CTRL_SOFTWARE;
pTxd = pTxd->pNextTxd; /* point behind fragment with EOF */
} /* while(forever) */
} /* FreeTxDescriptors */
-
/*****************************************************************************
*
* FillRxRing - fill the receive ring with valid descriptors
@@ -1999,12 +2334,12 @@
pRxPort->pRxdRingTail = pRxd->pNextRxd;
pRxPort->RxdRingFree--;
Length = pAC->RxBufSize;
- PhysAddr = (SK_U64) pci_map_page(&pAC->PciDev,
- virt_to_page(pMsgBlock->data),
- ((unsigned long) pMsgBlock->data &
- ~PAGE_MASK),
- pAC->RxBufSize - 2,
- PCI_DMA_FROMDEVICE);
+ PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
+ virt_to_page(pMsgBlock->data),
+ ((unsigned long) pMsgBlock->data &
+ ~PAGE_MASK),
+ pAC->RxBufSize - 2,
+ PCI_DMA_FROMDEVICE);
pRxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff);
pRxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
pRxd->pMBuf = pMsgBlock;
@@ -2061,28 +2396,32 @@
* Returns: N/A
*/
static void ReceiveIrq(
-SK_AC *pAC, /* pointer to adapter context */
-RX_PORT *pRxPort) /* pointer to receive port struct */
-{
-RXD *pRxd; /* pointer to receive descriptors */
-SK_U32 Control; /* control field of descriptor */
-struct sk_buff *pMsg; /* pointer to message holding frame */
-struct sk_buff *pNewMsg; /* pointer to a new message for copying frame */
-int FrameLength; /* total length of received frame */
-SK_MBUF *pRlmtMbuf; /* ptr to a buffer for giving a frame to rlmt */
-SK_EVPARA EvPara; /* an event parameter union */
-int PortIndex = pRxPort->PortIndex;
+ SK_AC *pAC, /* pointer to adapter context */
+ RX_PORT *pRxPort, /* pointer to receive port struct */
+ SK_BOOL SlowPathLock) /* indicates if SlowPathLock is needed */
+{
+RXD *pRxd; /* pointer to receive descriptors */
+SK_U32 Control; /* control field of descriptor */
+struct sk_buff *pMsg; /* pointer to message holding frame */
+struct sk_buff *pNewMsg; /* pointer to a new message for copying frame */
+int FrameLength; /* total length of received frame */
+SK_MBUF *pRlmtMbuf; /* ptr to a buffer for giving a frame to rlmt */
+SK_EVPARA EvPara; /* an event parameter union */
+unsigned long Flags; /* for spin lock */
+int PortIndex = pRxPort->PortIndex;
unsigned int Offset;
unsigned int NumBytes;
unsigned int ForRlmt;
-SK_BOOL IsBc;
-SK_BOOL IsMc;
-SK_U32 FrameStat;
+SK_BOOL IsBc;
+SK_BOOL IsMc;
+SK_BOOL IsBadFrame; /* Bad frame */
+
+SK_U32 FrameStat;
unsigned short Csum1;
unsigned short Csum2;
unsigned short Type;
-int Result;
-SK_U64 PhysAddr;
+int Result;
+SK_U64 PhysAddr;
rx_start:
/* do forever; exit if RX_CTRL_OWN_BMU found */
@@ -2124,33 +2463,75 @@
(RX_CTRL_STF | RX_CTRL_EOF)) {
goto rx_failed;
}
-
+
/* here we have a complete frame in the ring */
pMsg = pRxd->pMBuf;
FrameStat = pRxd->FrameStat;
+
+ /* check for frame length mismatch */
+#define XMR_FS_LEN_SHIFT 18
+#define GMR_FS_LEN_SHIFT 16
+ if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+ if (FrameLength != (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)) {
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+ SK_DBGCAT_DRV_RX_PROGRESS,
+ ("skge: Frame length mismatch (%u/%u).\n",
+ FrameLength,
+ (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)));
+ goto rx_failed;
+ }
+ }
+ else {
+ if (FrameLength != (SK_U32) (FrameStat >> GMR_FS_LEN_SHIFT)) {
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+ SK_DBGCAT_DRV_RX_PROGRESS,
+ ("skge: Frame length mismatch (%u/%u).\n",
+ FrameLength,
+ (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)));
+ goto rx_failed;
+ }
+ }
+
+ /* Set Rx Status */
+ if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+ IsBc = (FrameStat & XMR_FS_BC) != 0;
+ IsMc = (FrameStat & XMR_FS_MC) != 0;
+ IsBadFrame = (FrameStat &
+ (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0;
+ } else {
+ IsBc = (FrameStat & GMR_FS_BC) != 0;
+ IsMc = (FrameStat & GMR_FS_MC) != 0;
+ IsBadFrame = (((FrameStat & GMR_FS_ANY_ERR) != 0) ||
+ ((FrameStat & GMR_FS_RX_OK) == 0));
+ }
+
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0,
("Received frame of length %d on port %d\n",
FrameLength, PortIndex));
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0,
("Number of free rx descriptors: %d\n",
pRxPort->RxdRingFree));
- /*DumpMsg(pMsg, "Rx"); */
-
+/* DumpMsg(pMsg, "Rx"); */
+
if ((Control & RX_CTRL_STAT_VALID) != RX_CTRL_STAT_VALID ||
+ (IsBadFrame)) {
+#if 0
(FrameStat & (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0) {
+#endif
/* there is a receive error in this frame */
SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
SK_DBGCAT_DRV_RX_PROGRESS,
("skge: Error in received frame, dropped!\n"
"Control: %x\nRxStat: %x\n",
Control, FrameStat));
+
PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
PhysAddr |= (SK_U64) pRxd->VDataLow;
- pci_dma_sync_single(&pAC->PciDev,
- (dma_addr_t) PhysAddr,
- FrameLength,
- PCI_DMA_FROMDEVICE);
+ pci_dma_sync_single(pAC->PciDev,
+ (dma_addr_t) PhysAddr,
+ FrameLength,
+ PCI_DMA_FROMDEVICE);
ReQueueRxBuffer(pAC, pRxPort, pMsg,
pRxd->VDataHigh, pRxd->VDataLow);
@@ -2165,16 +2546,16 @@
/*
* Short frame detected and allocation successfull
*/
- PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
- PhysAddr |= (SK_U64) pRxd->VDataLow;
-
/* use new skb and copy data */
skb_reserve(pNewMsg, 2);
skb_put(pNewMsg, FrameLength);
- pci_dma_sync_single(&pAC->PciDev,
- (dma_addr_t) PhysAddr,
- FrameLength,
- PCI_DMA_FROMDEVICE);
+ PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
+ PhysAddr |= (SK_U64) pRxd->VDataLow;
+
+ pci_dma_sync_single(pAC->PciDev,
+ (dma_addr_t) PhysAddr,
+ FrameLength,
+ PCI_DMA_FROMDEVICE);
eth_copy_and_sum(pNewMsg, pMsg->data,
FrameLength, 0);
ReQueueRxBuffer(pAC, pRxPort, pMsg,
@@ -2192,10 +2573,10 @@
PhysAddr |= (SK_U64) pRxd->VDataLow;
/* release the DMA mapping */
- pci_unmap_page(&pAC->PciDev,
- PhysAddr,
- pAC->RxBufSize - 2,
- PCI_DMA_FROMDEVICE);
+ pci_unmap_single(pAC->PciDev,
+ PhysAddr,
+ pAC->RxBufSize - 2,
+ PCI_DMA_FROMDEVICE);
/* set length in message */
skb_put(pMsg, FrameLength);
@@ -2204,11 +2585,13 @@
if (Type == 0x800) {
Csum1=le16_to_cpu(pRxd->TcpSums & 0xffff);
Csum2=le16_to_cpu((pRxd->TcpSums >> 16) & 0xffff);
- if ((Csum1 & 0xfffe) && (Csum2 & 0xfffe)) {
+ if ((((Csum1 & 0xfffe) && (Csum2 & 0xfffe)) &&
+ (pAC->GIni.GIChipId == CHIP_ID_GENESIS)) ||
+ (pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
Result = SkCsGetReceiveInfo(pAC,
&pMsg->data[14],
Csum1, Csum2, pRxPort->PortIndex);
- if (Result ==
+ if (Result ==
SKCS_STATUS_IP_FRAGMENT ||
Result ==
SKCS_STATUS_IP_CSUM_OK ||
@@ -2216,20 +2599,29 @@
SKCS_STATUS_TCP_CSUM_OK ||
Result ==
SKCS_STATUS_UDP_CSUM_OK) {
- pMsg->ip_summed =
- CHECKSUM_UNNECESSARY;
+ pMsg->ip_summed =
+ CHECKSUM_UNNECESSARY;
+ } else {
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+ SK_DBGCAT_DRV_RX_PROGRESS,
+ ("skge: CRC error. Frame dropped!\n"));
+ goto rx_failed;
}
- } /* checksum calculation valid */
+ }/* checksumControl calculation valid */
} /* IP frame */
} /* frame > SK_COPY_TRESHOLD */
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("V"));
ForRlmt = SK_RLMT_RX_PROTOCOL;
+#if 0
IsBc = (FrameStat & XMR_FS_BC)==XMR_FS_BC;
+#endif
SK_RLMT_PRE_LOOKAHEAD(pAC, PortIndex, FrameLength,
IsBc, &Offset, &NumBytes);
if (NumBytes != 0) {
+#if 0
IsMc = (FrameStat & XMR_FS_MC)==XMR_FS_MC;
+#endif
SK_RLMT_LOOKAHEAD(pAC, PortIndex,
&pMsg->data[Offset],
IsBc, IsMc, &ForRlmt);
@@ -2276,10 +2668,22 @@
memcpy((char*)(pRlmtMbuf->pData),
(char*)(pMsg->data),
FrameLength);
- SkEventQueue(pAC, SKGE_RLMT,
- SK_RLMT_PACKET_RECEIVED,
- EvPara);
- pAC->CheckQueue = SK_TRUE;
+
+ /* SlowPathLock needed? */
+ if (SlowPathLock == SK_TRUE) {
+ spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+ SkEventQueue(pAC, SKGE_RLMT,
+ SK_RLMT_PACKET_RECEIVED,
+ EvPara);
+ pAC->CheckQueue = SK_TRUE;
+ spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+ } else {
+ SkEventQueue(pAC, SKGE_RLMT,
+ SK_RLMT_PACKET_RECEIVED,
+ EvPara);
+ pAC->CheckQueue = SK_TRUE;
+ }
+
SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
SK_DBGCAT_DRV_RX_PROGRESS,
("Q"));
@@ -2315,12 +2719,13 @@
("Schrottdescriptor, length: 0x%x\n", FrameLength));
/* release the DMA mapping */
+
PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
PhysAddr |= (SK_U64) pRxd->VDataLow;
- pci_unmap_page(&pAC->PciDev,
- PhysAddr,
- pAC->RxBufSize - 2,
- PCI_DMA_FROMDEVICE);
+ pci_unmap_page(pAC->PciDev,
+ PhysAddr,
+ pAC->RxBufSize - 2,
+ PCI_DMA_FROMDEVICE);
DEV_KFREE_SKB_IRQ(pRxd->pMBuf);
pRxd->pMBuf = NULL;
pRxPort->RxdRingFree++;
@@ -2386,7 +2791,7 @@
{
RXD *pRxd; /* pointer to the current descriptor */
unsigned long Flags;
- SK_U64 PhysAddr;
+SK_U64 PhysAddr;
if (pRxPort->RxdRingFree == pAC->RxDescrPerRing) {
return;
@@ -2395,12 +2800,13 @@
pRxd = pRxPort->pRxdRingHead;
do {
if (pRxd->pMBuf != NULL) {
+
PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
PhysAddr |= (SK_U64) pRxd->VDataLow;
- pci_unmap_page(&pAC->PciDev,
- PhysAddr,
- pAC->RxBufSize - 2,
- PCI_DMA_FROMDEVICE);
+ pci_unmap_page(pAC->PciDev,
+ PhysAddr,
+ pAC->RxBufSize - 2,
+ PCI_DMA_FROMDEVICE);
DEV_KFREE_SKB(pRxd->pMBuf);
pRxd->pMBuf = NULL;
}
@@ -2549,7 +2955,7 @@
* 0, if everything is ok
* !=0, on error
*/
-static int SkGeSetMacAddr(struct net_device *dev, void *p)
+static int SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p)
{
DEV_NET *pNet = (DEV_NET*) dev->priv;
@@ -2557,12 +2963,12 @@
struct sockaddr *addr = p;
unsigned long Flags;
-
+
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
("SkGeSetMacAddr starts now...\n"));
- if(netif_running(dev)) {
+ if(netif_running(dev))
return -EBUSY;
- }
+
memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
spin_lock_irqsave(&pAC->SlowPathLock, Flags);
@@ -2595,7 +3001,7 @@
* 0, if everything is ok
* !=0, on error
*/
-static void SkGeSetRxMode(struct net_device *dev)
+static void SkGeSetRxMode(struct SK_NET_DEVICE *dev)
{
DEV_NET *pNet;
@@ -2649,7 +3055,6 @@
pMcList->dmi_addr[5]));
}
SkAddrMcUpdate(pAC, pAC->IoBase, PortIdx);
-
}
spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
@@ -2670,7 +3075,7 @@
* 0, if everything is ok
* !=0, on error
*/
-static int SkGeChangeMtu(struct net_device *dev, int NewMtu)
+static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int NewMtu)
{
DEV_NET *pNet;
DEV_NET *pOtherNet;
@@ -2689,6 +3094,10 @@
return -EINVAL;
}
+ if(pAC->BoardLevel != 2) {
+ return -EINVAL;
+ }
+
pNet->Mtu = NewMtu;
pOtherNet = (DEV_NET*)pAC->dev[1 - pNet->NetNr]->priv;
if ((pOtherNet->Mtu > 1500) && (NewMtu <= 1500) && (pOtherNet->Up==1)) {
@@ -2704,10 +3113,6 @@
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
("New MTU: %d\n", NewMtu));
- if(pAC->BoardLevel != 2) {
- return 0;
- }
-
/* prevent reconfiguration while changing the MTU */
/* disable interrupts */
@@ -2732,6 +3137,7 @@
spin_lock_irqsave(
&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock, Flags);
netif_stop_queue(pAC->dev[i]);
+
}
/*
@@ -2756,7 +3162,7 @@
}
}
else {
- /* use normal anoumt of rx buffers */
+ /* use normal amount of rx buffers */
for (i=0; i<pAC->GIni.GIMacsFound; i++) {
/* Found more than one port */
if ((pAC->GIni.GIMacsFound == 2 ) &&
@@ -2780,10 +3186,6 @@
if (NewMtu > 1500) {
// pAC->JumboActivated = SK_TRUE; /* is never set back !!! */
pAC->GIni.GIPortUsage = SK_JUMBO_LINK;
- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- pAC->GIni.GP[i].PRxCmd =
- XM_RX_STRIP_FCS | XM_RX_LENERR_OK;
- }
}
else {
if ((pAC->GIni.GIMacsFound == 2 ) &&
@@ -2792,9 +3194,6 @@
} else {
pAC->GIni.GIPortUsage = SK_RED_LINK;
}
- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- pAC->GIni.GP[i].PRxCmd = XM_RX_STRIP_FCS;
- }
}
SkGeInit( pAC, pAC->IoBase, 1);
@@ -2805,6 +3204,12 @@
SkRlmtInit( pAC, pAC->IoBase, 1);
SkTimerInit(pAC, pAC->IoBase, 1);
+ /*
+ * tschilling:
+ * Speed and others are set back to default in level 1 init!
+ */
+ GetConfiguration(pAC);
+
SkGeInit( pAC, pAC->IoBase, 2);
SkI2cInit( pAC, pAC->IoBase, 2);
SkEventInit(pAC, pAC->IoBase, 2);
@@ -2817,7 +3222,7 @@
* clear and reinit the rx rings here
*/
for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- ReceiveIrq(pAC, &pAC->RxPort[i]);
+ ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE);
ClearRxRing(pAC, &pAC->RxPort[i]);
FillRxRing(pAC, &pAC->RxPort[i]);
@@ -2891,12 +3296,13 @@
* Returns:
* pointer to the statistic structure.
*/
-static struct net_device_stats *SkGeStats(struct net_device *dev)
+static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev)
{
DEV_NET *pNet = (DEV_NET*) dev->priv;
SK_AC *pAC = pNet->pAC;
SK_PNMI_STRUCT_DATA *pPnmiStruct; /* structure for all Pnmi-Data */
-SK_PNMI_STAT *pPnmiStat; /* pointer to virtual XMAC stat. data */SK_PNMI_CONF *pPnmiConf; /* pointer to virtual link config. */
+SK_PNMI_STAT *pPnmiStat; /* pointer to virtual XMAC stat. data */
+SK_PNMI_CONF *pPnmiConf; /* pointer to virtual link config. */
unsigned int Size; /* size of pnmi struct */
unsigned long Flags; /* for spin lock */
@@ -2915,7 +3321,18 @@
pAC->stats.tx_packets = (SK_U32) pPnmiStat->StatTxOkCts & 0xFFFFFFFF;
pAC->stats.rx_bytes = (SK_U32) pPnmiStruct->RxOctetsDeliveredCts;
pAC->stats.tx_bytes = (SK_U32) pPnmiStat->StatTxOctetsOkCts;
- pAC->stats.rx_errors = (SK_U32) pPnmiStruct->InErrorsCts & 0xFFFFFFFF;
+
+ if (pNet->Mtu <= 1500) {
+ pAC->stats.rx_errors = (SK_U32) pPnmiStruct->InErrorsCts & 0xFFFFFFFF;
+ } else {
+ pAC->stats.rx_errors = (SK_U32) ((pPnmiStruct->InErrorsCts -
+ pPnmiStat->StatRxTooLongCts) & 0xFFFFFFFF);
+ }
+
+
+ if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC && pAC->HWRevision < 12)
+ pAC->stats.rx_errors = pAC->stats.rx_errors - pPnmiStat->StatRxShortsCts;
+
pAC->stats.tx_errors = (SK_U32) pPnmiStat->StatTxSingleCollisionCts & 0xFFFFFFFF;
pAC->stats.rx_dropped = (SK_U32) pPnmiStruct->RxNoBufCts & 0xFFFFFFFF;
pAC->stats.tx_dropped = (SK_U32) pPnmiStruct->TxNoBufCts & 0xFFFFFFFF;
@@ -2954,7 +3371,7 @@
* 0, if everything is ok
* !=0, on error
*/
-static int SkGeIoctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd)
{
DEV_NET *pNet;
SK_AC *pAC;
@@ -3068,6 +3485,7 @@
SK_AC *pAC) /* pointer to the adapter context structure */
{
SK_I32 Port; /* preferred port */
+int LinkSpeed; /* Link speed */
int AutoNeg; /* auto negotiation off (0) or on (1) */
int DuplexCap; /* duplex capabilities (0=both, 1=full, 2=half */
int MSMode; /* master / slave mode selection */
@@ -3097,7 +3515,44 @@
#define AN_SENS 2
/* settings for port A */
- AutoNeg = AN_SENS; /* default: do auto Sense */
+ /* settings link speed */
+ LinkSpeed = SK_LSPEED_AUTO; /* default: do auto select */
+ if (Speed_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+ Speed_A[pAC->Index] != NULL) {
+ if (strcmp(Speed_A[pAC->Index],"")==0) {
+ LinkSpeed = SK_LSPEED_AUTO;
+ }
+ else if (strcmp(Speed_A[pAC->Index],"Auto")==0) {
+ LinkSpeed = SK_LSPEED_AUTO;
+ }
+ else if (strcmp(Speed_A[pAC->Index],"10")==0) {
+ LinkSpeed = SK_LSPEED_10MBPS;
+ }
+ else if (strcmp(Speed_A[pAC->Index],"100")==0) {
+ LinkSpeed = SK_LSPEED_100MBPS;
+ }
+ else if (strcmp(Speed_A[pAC->Index],"1000")==0) {
+ LinkSpeed = SK_LSPEED_1000MBPS;
+ }
+ else printk("%s: Illegal value for Speed_A\n",
+ pAC->dev[0]->name);
+ }
+
+ /* Check speed parameter */
+ /* Only copper type adapter and GE V2 cards */
+ if (((pAC->GIni.GIChipId != CHIP_ID_YUKON) ||
+ (pAC->GIni.GICopperType != SK_TRUE)) &&
+ ((LinkSpeed != SK_LSPEED_AUTO) &&
+ (LinkSpeed != SK_LSPEED_1000MBPS))) {
+ printk("%s: Illegal value for Speed_A. "
+ "Not a copper card or GE V2 card\n Using "
+ "speed 1000\n", pAC->dev[0]->name);
+ LinkSpeed = SK_LSPEED_1000MBPS;
+ }
+ pAC->GIni.GP[0].PLinkSpeed = LinkSpeed;
+
+ /* Autonegotiation */
+ AutoNeg = AN_ON; /* tschilling: Default: Autonegotiation on! */
AutoSet = SK_FALSE;
if (AutoNeg_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
AutoNeg_A[pAC->Index] != NULL) {
@@ -3219,6 +3674,43 @@
/* settings for port B */
+ /* settings link speed */
+ LinkSpeed = SK_LSPEED_AUTO; /* default: do auto select */
+ if (Speed_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+ Speed_B[pAC->Index] != NULL) {
+ if (strcmp(Speed_B[pAC->Index],"")==0) {
+ LinkSpeed = SK_LSPEED_AUTO;
+ }
+ else if (strcmp(Speed_B[pAC->Index],"Auto")==0) {
+ LinkSpeed = SK_LSPEED_AUTO;
+ }
+ else if (strcmp(Speed_B[pAC->Index],"10")==0) {
+ LinkSpeed = SK_LSPEED_10MBPS;
+ }
+ else if (strcmp(Speed_B[pAC->Index],"100")==0) {
+ LinkSpeed = SK_LSPEED_100MBPS;
+ }
+ else if (strcmp(Speed_B[pAC->Index],"1000")==0) {
+ LinkSpeed = SK_LSPEED_1000MBPS;
+ }
+ else printk("%s: Illegal value for Speed_B\n",
+ pAC->dev[1]->name);
+ }
+
+ /* Check speed parameter */
+ /* Only copper type adapter and GE V2 cards */
+ if (((pAC->GIni.GIChipId != CHIP_ID_YUKON) ||
+ (pAC->GIni.GICopperType != SK_TRUE)) &&
+ ((LinkSpeed != SK_LSPEED_AUTO) &&
+ (LinkSpeed != SK_LSPEED_1000MBPS))) {
+ printk("%s: Illegal value for Speed_B. "
+ "Not a copper card or GE V2 card\n Using "
+ "speed 1000\n", pAC->dev[1]->name);
+ LinkSpeed = SK_LSPEED_1000MBPS;
+ }
+ pAC->GIni.GP[1].PLinkSpeed = LinkSpeed;
+
+ /* Auto negotiation */
AutoNeg = AN_SENS; /* default: do auto Sense */
AutoSet = SK_FALSE;
if (AutoNeg_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
@@ -3370,7 +3862,7 @@
}
pAC->RlmtNets = 1;
-
+
if (RlmtMode != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
RlmtMode[pAC->Index] != NULL) {
if (strcmp(RlmtMode[pAC->Index], "") == 0) {
@@ -3396,10 +3888,6 @@
else {
printk("%s: Illegal value for"
" RlmtMode, using default\n", pAC->dev[0]->name);
-
-printk("MacFound = %d\nRlmtMode = %s", pAC->GIni.GIMacsFound, RlmtMode[pAC->Index]);
-
-
pAC->RlmtMode = 0;
}
}
@@ -3551,7 +4039,7 @@
int PciAddr, /* PCI register address */
SK_U32 *pVal) /* pointer to store the read value */
{
- pci_read_config_dword(&pAC->PciDev, PciAddr, pVal);
+ pci_read_config_dword(pAC->PciDev, PciAddr, pVal);
return(0);
} /* SkPciReadCfgDWord */
@@ -3573,7 +4061,7 @@
int PciAddr, /* PCI register address */
SK_U16 *pVal) /* pointer to store the read value */
{
- pci_read_config_word(&pAC->PciDev, PciAddr, pVal);
+ pci_read_config_word(pAC->PciDev, PciAddr, pVal);
return(0);
} /* SkPciReadCfgWord */
@@ -3595,7 +4083,7 @@
int PciAddr, /* PCI register address */
SK_U8 *pVal) /* pointer to store the read value */
{
- pci_read_config_byte(&pAC->PciDev, PciAddr, pVal);
+ pci_read_config_byte(pAC->PciDev, PciAddr, pVal);
return(0);
} /* SkPciReadCfgByte */
@@ -3617,7 +4105,7 @@
int PciAddr, /* PCI register address */
SK_U32 Val) /* pointer to store the read value */
{
- pci_write_config_dword(&pAC->PciDev, PciAddr, Val);
+ pci_write_config_dword(pAC->PciDev, PciAddr, Val);
return(0);
} /* SkPciWriteCfgDWord */
@@ -3640,7 +4128,7 @@
int PciAddr, /* PCI register address */
SK_U16 Val) /* pointer to store the read value */
{
- pci_write_config_word(&pAC->PciDev, PciAddr, Val);
+ pci_write_config_word(pAC->PciDev, PciAddr, Val);
return(0);
} /* SkPciWriteCfgWord */
@@ -3663,7 +4151,7 @@
int PciAddr, /* PCI register address */
SK_U8 Val) /* pointer to store the read value */
{
- pci_write_config_byte(&pAC->PciDev, PciAddr, Val);
+ pci_write_config_byte(pAC->PciDev, PciAddr, Val);
return(0);
} /* SkPciWriteCfgByte */
@@ -3696,6 +4184,7 @@
SK_EVPARA NewPara; /* parameter for further events */
int Stat;
unsigned long Flags;
+SK_BOOL DualNet;
switch (Event) {
case SK_DRV_ADAP_FAIL:
@@ -3728,18 +4217,27 @@
&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
Flags);
SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST);
+ pAC->dev[Param.Para32[0]]->flags &= ~IFF_RUNNING;
spin_unlock_irqrestore(
&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
Flags);
/* clear rx ring from received frames */
- ReceiveIrq(pAC, &pAC->RxPort[FromPort]);
+ ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE);
ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]);
spin_lock_irqsave(
&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
Flags);
- SkGeInitPort(pAC, IoC, FromPort);
+
+ /* tschilling: Handling of return value inserted. */
+ if (SkGeInitPort(pAC, IoC, FromPort)) {
+ if (FromPort == 0) {
+ printk("%s: SkGeInitPort A failed.\n", pAC->dev[0]->name);
+ } else {
+ printk("%s: SkGeInitPort B failed.\n", pAC->dev[1]->name);
+ }
+ }
SkAddrMcUpdate(pAC,IoC, FromPort);
PortReInitBmu(pAC, FromPort);
SkGePollTxD(pAC, IoC, FromPort, SK_TRUE);
@@ -3755,7 +4253,19 @@
("NET UP EVENT, Port: %d ", Param.Para32[0]));
printk("%s: network connection up using"
" port %c\n", pAC->dev[Param.Para32[0]]->name, 'A'+Param.Para32[0]);
- printk(" speed: 1000\n");
+
+ /* tschilling: Values changed according to LinkSpeedUsed. */
+ Stat = pAC->GIni.GP[FromPort].PLinkSpeedUsed;
+ if (Stat == SK_LSPEED_STAT_10MBPS) {
+ printk(" speed: 10\n");
+ } else if (Stat == SK_LSPEED_STAT_100MBPS) {
+ printk(" speed: 100\n");
+ } else if (Stat == SK_LSPEED_STAT_1000MBPS) {
+ printk(" speed: 1000\n");
+ } else {
+ printk(" speed: unknown\n");
+ }
+
Stat = pAC->GIni.GP[FromPort].PLinkModeStatus;
if (Stat == SK_LMODE_STAT_AUTOHALF ||
Stat == SK_LMODE_STAT_AUTOFULL) {
@@ -3784,8 +4294,12 @@
else {
printk(" flowctrl: none\n");
}
- if (pAC->GIni.GP[FromPort].PhyType != SK_PHY_XMAC) {
- Stat = pAC->GIni.GP[FromPort].PMSStatus;
+
+ /* tschilling: Check against CopperType now. */
+ if ((pAC->GIni.GICopperType == SK_TRUE) &&
+ (pAC->GIni.GP[FromPort].PLinkSpeedUsed ==
+ SK_LSPEED_STAT_1000MBPS)) {
+ Stat = pAC->GIni.GP[FromPort].PMSStatus;
if (Stat == SK_MS_STAT_MASTER ) {
printk(" role: master\n");
}
@@ -3796,6 +4310,16 @@
printk(" role: ???\n");
}
}
+
+#ifdef SK_ZEROCOPY
+ if (pAC->GIni.GIChipId == CHIP_ID_YUKON)
+ printk(" scatter-gather: enabled\n");
+ else
+ printk(" scatter-gather: disabled\n");
+
+#else
+ printk(" scatter-gather: disabled\n");
+#endif
if ((Param.Para32[0] != pAC->ActivePort) &&
(pAC->RlmtNets == 1)) {
@@ -3804,12 +4328,17 @@
SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_INTERN,
NewPara);
}
+
+ /* Inform the world that link protocol is up. */
+ pAC->dev[Param.Para32[0]]->flags |= IFF_RUNNING;
+
break;
case SK_DRV_NET_DOWN: /* SK_U32 Reason */
/* action list 7 */
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
("NET DOWN EVENT "));
printk("%s: network connection down\n", pAC->dev[Param.Para32[1]]->name);
+ pAC->dev[Param.Para32[1]]->flags &= ~IFF_RUNNING;
break;
case SK_DRV_SWITCH_HARD: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
@@ -3841,8 +4370,8 @@
&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
Flags);
- ReceiveIrq(pAC, &pAC->RxPort[FromPort]); /* clears rx ring */
- ReceiveIrq(pAC, &pAC->RxPort[ToPort]); /* clears rx ring */
+ ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); /* clears rx ring */
+ ReceiveIrq(pAC, &pAC->RxPort[ToPort], SK_FALSE); /* clears rx ring */
ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]);
ClearTxRing(pAC, &pAC->TxPort[ToPort][TX_PRIO_LOW]);
@@ -3852,13 +4381,37 @@
spin_lock_irqsave(
&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags);
pAC->ActivePort = ToPort;
+#if 0
SetQueueSizes(pAC);
- SkGeInitPort(pAC, IoC, FromPort);
- SkGeInitPort(pAC, IoC, ToPort);
+#else
+ /* tschilling: New common function with minimum size check. */
+ DualNet = SK_FALSE;
+ if (pAC->RlmtNets == 2) {
+ DualNet = SK_TRUE;
+ }
+
+ if (SkGeInitAssignRamToQueues(
+ pAC,
+ pAC->ActivePort,
+ DualNet)) {
+ spin_unlock_irqrestore(
+ &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags);
+ spin_unlock_irqrestore(
+ &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+ Flags);
+ printk("SkGeInitAssignRamToQueues failed.\n");
+ break;
+ }
+#endif
+ /* tschilling: Handling of return values inserted. */
+ if (SkGeInitPort(pAC, IoC, FromPort) ||
+ SkGeInitPort(pAC, IoC, ToPort)) {
+ printk("%s: SkGeInitPort failed.\n", pAC->dev[0]->name);
+ }
if (Event == SK_DRV_SWITCH_SOFT) {
- SkXmRxTxEnable(pAC, IoC, FromPort);
+ SkMacRxTxEnable(pAC, IoC, FromPort);
}
- SkXmRxTxEnable(pAC, IoC, ToPort);
+ SkMacRxTxEnable(pAC, IoC, ToPort);
SkAddrSwap(pAC, IoC, FromPort, ToPort);
SkAddrMcUpdate(pAC, IoC, FromPort);
SkAddrMcUpdate(pAC, IoC, ToPort);
@@ -3881,7 +4434,8 @@
pMsg = (struct sk_buff*) pRlmtMbuf->pOs;
skb_put(pMsg, pRlmtMbuf->Length);
if (XmitFrame(pAC, &pAC->TxPort[pRlmtMbuf->PortIdx][TX_PRIO_LOW],
- pMsg) < 0)
+ pMsg) < 0)
+
DEV_KFREE_SKB_ANY(pMsg);
break;
default:
@@ -3943,7 +4497,8 @@
} /* SkErrorLog */
-#ifdef DEBUG /***************************************************************/
+#ifdef DEBUG
+/****************************************************************************/
/* "debug only" section *****************************************************/
/****************************************************************************/
@@ -4090,7 +4645,7 @@
printk("------------------------\n");
} /* DumpLong */
-#endif /* DEBUG */
+#endif
/*
* Local variables:
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)