X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Fsk98lin%2Fskge.c;h=38a26df4095f33976dc05bca3b405fe3cf9c64dc;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=6cb5342a40acdc6a0463338c4bd6b85b8d3036d1;hpb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;p=linux-2.6.git diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index 6cb5342a4..38a26df40 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c @@ -72,8 +72,8 @@ * * * + * * - * * * * @@ -101,16 +101,18 @@ * "h/skgeinit.h" * "h/skaddr.h" * "h/skgesirq.h" - * "h/skcsum.h" * "h/skrlmt.h" * ******************************************************************************/ #include "h/skversion.h" +#include #include +#include #include -#include +#include +#include #include "h/skdrv1st.h" #include "h/skdrv2nd.h" @@ -204,7 +206,6 @@ 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*); @@ -233,17 +234,11 @@ static int SkDrvDeInitAdapter(SK_AC *pAC, int devNbr); * Extern Function Prototypes * ******************************************************************************/ - -#ifdef CONFIG_PROC_FS -static const char SK_Root_Dir_entry[] = "sk98lin"; -static struct proc_dir_entry *pSkRootDir; -extern struct file_operations sk_proc_fops; -#endif - extern void SkDimEnableModerationIfNeeded(SK_AC *pAC); extern void SkDimDisplayModerationSettings(SK_AC *pAC); extern void SkDimStartModerationTimer(SK_AC *pAC); extern void SkDimModerate(SK_AC *pAC); +extern void SkGeBlinkTimer(unsigned long data); #ifdef DEBUG static void DumpMsg(struct sk_buff*, char*); @@ -252,13 +247,34 @@ static void DumpLong(char*, int); #endif /* global variables *********************************************************/ -struct SK_NET_DEVICE *SkGeRootDev = NULL; static SK_BOOL DoPrintInterfaceChange = SK_TRUE; +extern struct ethtool_ops SkGeEthtoolOps; /* local variables **********************************************************/ static uintptr_t TxQueueAddr[SK_MAX_MACS][2] = {{0x680, 0x600},{0x780, 0x700}}; static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480}; +/***************************************************************************** + * + * SkPciWriteCfgDWord - write a 32 bit value to pci config space + * + * Description: + * This routine writes a 32 bit value to the pci configuration + * space. + * + * Returns: + * 0 - indicate everything worked ok. + * != 0 - error indication + */ +static inline int SkPciWriteCfgDWord( +SK_AC *pAC, /* Adapter Control structure pointer */ +int PciAddr, /* PCI register address */ +SK_U32 Val) /* pointer to store the read value */ +{ + pci_write_config_dword(pAC->PciDev, PciAddr, Val); + return(0); +} /* SkPciWriteCfgDWord */ + /***************************************************************************** * * SkGeInitPCI - Init the PCI resources @@ -266,26 +282,22 @@ static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480}; * Description: * This function initialize the PCI resources and IO * - * Returns: N/A - * + * Returns: + * 0 - indicate everything worked ok. + * != 0 - error indication */ -int SkGeInitPCI(SK_AC *pAC) +static __devinit int SkGeInitPCI(SK_AC *pAC) { struct SK_NET_DEVICE *dev = pAC->dev[0]; struct pci_dev *pdev = pAC->PciDev; int retval; - if (pci_enable_device(pdev) != 0) { - return 1; - } - dev->mem_start = pci_resource_start (pdev, 0); pci_set_master(pdev); - if (pci_request_regions(pdev, pAC->Name) != 0) { - retval = 2; - goto out_disable; - } + retval = pci_request_regions(pdev, "sk98lin"); + if (retval) + goto out; #ifdef SK_BIG_ENDIAN /* @@ -303,10 +315,9 @@ int SkGeInitPCI(SK_AC *pAC) /* * Remap the regs into kernel space. */ - pAC->IoBase = (char*)ioremap_nocache(dev->mem_start, 0x4000); - - if (!pAC->IoBase){ - retval = 3; + pAC->IoBase = ioremap_nocache(dev->mem_start, 0x4000); + if (!pAC->IoBase) { + retval = -EIO; goto out_release; } @@ -314,8 +325,7 @@ int SkGeInitPCI(SK_AC *pAC) out_release: pci_release_regions(pdev); - out_disable: - pci_disable_device(pdev); + out: return retval; } @@ -337,22 +347,20 @@ SK_U32 AllocFlag; DEV_NET *pNet; SK_AC *pAC; - if (dev->priv) { - pNet = (DEV_NET*) dev->priv; - pAC = pNet->pAC; - AllocFlag = pAC->AllocFlag; - if (pAC->PciDev) { - pci_release_regions(pAC->PciDev); - } - if (AllocFlag & SK_ALLOC_IRQ) { - free_irq(dev->irq, dev); - } - if (pAC->IoBase) { - iounmap(pAC->IoBase); - } - if (pAC->pDescrMem) { - BoardFreeMem(pAC); - } + pNet = netdev_priv(dev); + pAC = pNet->pAC; + AllocFlag = pAC->AllocFlag; + if (pAC->PciDev) { + pci_release_regions(pAC->PciDev); + } + if (AllocFlag & SK_ALLOC_IRQ) { + free_irq(dev->irq, dev); + } + if (pAC->IoBase) { + iounmap(pAC->IoBase); + } + if (pAC->pDescrMem) { + BoardFreeMem(pAC); } } /* FreeResources */ @@ -360,26 +368,6 @@ SK_AC *pAC; MODULE_AUTHOR("Mirko Lindner "); 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(ConType, "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"); -/* used for interrupt moderation */ -MODULE_PARM(IntsPerSec, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "i"); -MODULE_PARM(Moderation, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); -MODULE_PARM(Stats, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); -MODULE_PARM(ModerationMask, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); -MODULE_PARM(AutoSizing, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s"); - #ifdef LINK_SPEED_A static char *Speed_A[SK_MAX_CARD_PARAM] = LINK_SPEED; @@ -465,6 +453,26 @@ static char *ModerationMask[SK_MAX_CARD_PARAM]; static char *AutoSizing[SK_MAX_CARD_PARAM]; static char *Stats[SK_MAX_CARD_PARAM]; +module_param_array(Speed_A, charp, NULL, 0); +module_param_array(Speed_B, charp, NULL, 0); +module_param_array(AutoNeg_A, charp, NULL, 0); +module_param_array(AutoNeg_B, charp, NULL, 0); +module_param_array(DupCap_A, charp, NULL, 0); +module_param_array(DupCap_B, charp, NULL, 0); +module_param_array(FlowCtrl_A, charp, NULL, 0); +module_param_array(FlowCtrl_B, charp, NULL, 0); +module_param_array(Role_A, charp, NULL, 0); +module_param_array(Role_B, charp, NULL, 0); +module_param_array(ConType, charp, NULL, 0); +module_param_array(PrefPort, charp, NULL, 0); +module_param_array(RlmtMode, charp, NULL, 0); +/* used for interrupt moderation */ +module_param_array(IntsPerSec, int, NULL, 0); +module_param_array(Moderation, charp, NULL, 0); +module_param_array(Stats, charp, NULL, 0); +module_param_array(ModerationMask, charp, NULL, 0); +module_param_array(AutoSizing, charp, NULL, 0); + /***************************************************************************** * * SkGeBoardInit - do level 0 and 1 initialization @@ -478,7 +486,7 @@ static char *Stats[SK_MAX_CARD_PARAM]; * 0, if everything is ok * !=0, on error */ -static int __init SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC) +static int __devinit SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC) { short i; unsigned long Flags; @@ -503,6 +511,11 @@ SK_BOOL DualNet; } spin_lock_init(&pAC->SlowPathLock); + /* setup phy_id blink timer */ + pAC->BlinkTimer.function = SkGeBlinkTimer; + pAC->BlinkTimer.data = (unsigned long) dev; + init_timer(&pAC->BlinkTimer); + /* level 0 init common modules here */ spin_lock_irqsave(&pAC->SlowPathLock, Flags); @@ -510,7 +523,7 @@ SK_BOOL DualNet; if (SkGeInit(pAC, pAC->IoBase, SK_INIT_DATA) != 0) { printk("HWInit (0) failed.\n"); spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - return(-EAGAIN); + return -EIO; } SkI2cInit( pAC, pAC->IoBase, SK_INIT_DATA); SkEventInit(pAC, pAC->IoBase, SK_INIT_DATA); @@ -532,7 +545,7 @@ SK_BOOL DualNet; if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) { printk("sk98lin: HWInit (1) failed.\n"); spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - return(-EAGAIN); + return -EIO; } SkI2cInit( pAC, pAC->IoBase, SK_INIT_IO); SkEventInit(pAC, pAC->IoBase, SK_INIT_IO); @@ -557,34 +570,29 @@ SK_BOOL DualNet; spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); if (pAC->GIni.GIMacsFound == 2) { - Ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, pAC->Name, dev); + Ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, "sk98lin", dev); } else if (pAC->GIni.GIMacsFound == 1) { Ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ, - pAC->Name, dev); + "sk98lin", dev); } else { printk(KERN_WARNING "sk98lin: Illegal number of ports: %d\n", pAC->GIni.GIMacsFound); - return -EAGAIN; + return -EIO; } if (Ret) { printk(KERN_WARNING "sk98lin: Requested IRQ %d is busy.\n", dev->irq); - return -EAGAIN; + return Ret; } pAC->AllocFlag |= SK_ALLOC_IRQ; /* Alloc memory for this board (Mem for RxD/TxD) : */ if(!BoardAllocMem(pAC)) { printk("No memory for descriptor rings.\n"); - return(-EAGAIN); + return -ENOMEM; } - SkCsSetReceiveFlags(pAC, - SKCS_PROTO_IP | SKCS_PROTO_TCP | SKCS_PROTO_UDP, - &pAC->CsOfs1, &pAC->CsOfs2, 0); - pAC->CsOfs = (pAC->CsOfs2 << 16) | pAC->CsOfs1; - BoardInitMem(pAC); /* tschilling: New common function with minimum size check. */ DualNet = SK_FALSE; @@ -598,15 +606,9 @@ SK_BOOL DualNet; DualNet)) { BoardFreeMem(pAC); printk("sk98lin: SkGeInitAssignRamToQueues failed.\n"); - return(-EAGAIN); + return -EIO; } - /* - * Register the device here - */ - pAC->Next = SkGeRootDev; - SkGeRootDev = dev; - return (0); } /* SkGeBoardInit */ @@ -625,8 +627,7 @@ SK_BOOL DualNet; * SK_TRUE, if all memory could be allocated * SK_FALSE, if not */ -static SK_BOOL BoardAllocMem( -SK_AC *pAC) +static __devinit SK_BOOL BoardAllocMem(SK_AC *pAC) { caddr_t pDescrMem; /* pointer to descriptor memory area */ size_t AllocLength; /* length of complete descriptor area */ @@ -719,8 +720,7 @@ size_t AllocLength; /* length of complete descriptor area */ * * Returns: N/A */ -static void BoardInitMem( -SK_AC *pAC) /* pointer to adapter context */ +static __devinit void BoardInitMem(SK_AC *pAC) { int i; /* loop counter */ int RxDescrSize; /* the size of a rx descriptor rounded up to alignment*/ @@ -808,7 +808,7 @@ uintptr_t VNextDescr; /* the virtual bus address of the next descriptor */ /* set the pointers right */ pDescr->VNextRxd = VNextDescr & 0xffffffffULL; pDescr->pNextRxd = pNextDescr; - pDescr->TcpSumStarts = pAC->CsOfs; + if (!IsTx) pDescr->TcpSumStarts = ETH_HLEN << 16 | ETH_HLEN; /* advance one step */ pPrevDescr = pDescr; @@ -887,7 +887,7 @@ DEV_NET *pNet; SK_AC *pAC; SK_U32 IntSrc; /* interrupts source register contents */ - pNet = (DEV_NET*) dev->priv; + pNet = netdev_priv(dev); pAC = pNet->pAC; /* @@ -1036,7 +1036,7 @@ DEV_NET *pNet; SK_AC *pAC; SK_U32 IntSrc; /* interrupts source register contents */ - pNet = (DEV_NET*) dev->priv; + pNet = netdev_priv(dev); pAC = pNet->pAC; /* @@ -1126,6 +1126,24 @@ SK_U32 IntSrc; /* interrupts source register contents */ return SkIsrRetHandled; } /* SkGeIsrOnePort */ +#ifdef CONFIG_NET_POLL_CONTROLLER +/**************************************************************************** + * + * SkGePollController - polling receive, for netconsole + * + * Description: + * Polling receive - used by netconsole and other diagnostic tools + * to allow network i/o with interrupts disabled. + * + * Returns: N/A + */ +static void SkGePollController(struct net_device *dev) +{ + disable_irq(dev->irq); + SkGeIsr(dev->irq, dev, NULL); + enable_irq(dev->irq); +} +#endif /**************************************************************************** * @@ -1152,7 +1170,7 @@ struct SK_NET_DEVICE *dev) int i; SK_EVPARA EvPara; /* an event parameter union */ - pNet = (DEV_NET*) dev->priv; + pNet = netdev_priv(dev); pAC = pNet->pAC; SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, @@ -1166,10 +1184,6 @@ struct SK_NET_DEVICE *dev) } #endif - if (!try_module_get(THIS_MODULE)) { - return (-1); /* increase of usage count not possible */ - } - /* Set blink mode */ if ((pAC->PciDev->vendor == 0x1186) || (pAC->PciDev->vendor == 0x11ab )) pAC->GIni.GILedBlinkCtrl = OEM_CONFIG_VALUE; @@ -1177,7 +1191,6 @@ struct SK_NET_DEVICE *dev) if (pAC->BoardLevel == SK_INIT_DATA) { /* level 1 init common modules here */ if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) { - module_put(THIS_MODULE); /* decrease usage count */ printk("%s: HWInit (1) failed.\n", pAC->dev[pNet->PortNr]->name); return (-1); } @@ -1193,7 +1206,6 @@ struct SK_NET_DEVICE *dev) if (pAC->BoardLevel != SK_INIT_RUN) { /* tschilling: Level 2 init modules here, check return value. */ if (SkGeInit(pAC, pAC->IoBase, SK_INIT_RUN) != 0) { - module_put(THIS_MODULE); /* decrease usage count */ printk("%s: HWInit (2) failed.\n", pAC->dev[pNet->PortNr]->name); return (-1); } @@ -1243,7 +1255,6 @@ struct SK_NET_DEVICE *dev) spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); pAC->MaxPorts++; - pNet->Up = 1; SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, @@ -1279,19 +1290,18 @@ struct SK_NET_DEVICE *dev) SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("SkGeClose: pAC=0x%lX ", (unsigned long)pAC)); - pNet = (DEV_NET*) dev->priv; + pNet = netdev_priv(dev); pAC = pNet->pAC; #ifdef SK_DIAG_SUPPORT if (pAC->DiagModeActive == DIAG_ACTIVE) { if (pAC->DiagFlowCtrl == SK_FALSE) { - module_put(THIS_MODULE); /* ** notify that the interface which has been closed ** by operator interaction must not be started up ** again when the DIAG has finished. */ - newPtrNet = (DEV_NET *) pAC->dev[0]->priv; + newPtrNet = netdev_priv(pAC->dev[0]); if (newPtrNet == pNet) { pAC->WasIfUp[0] = SK_FALSE; } else { @@ -1374,9 +1384,7 @@ struct SK_NET_DEVICE *dev) sizeof(SK_PNMI_STRUCT_DATA)); pAC->MaxPorts--; - pNet->Up = 0; - module_put(THIS_MODULE); return (0); } /* SkGeClose */ @@ -1402,7 +1410,7 @@ DEV_NET *pNet; SK_AC *pAC; int Rc; /* return code of XmitFrame */ - pNet = (DEV_NET*) dev->priv; + pNet = netdev_priv(dev); pAC = pNet->pAC; if ((!skb_shinfo(skb)->nr_frags) || @@ -1480,8 +1488,6 @@ struct sk_buff *pMessage) /* pointer to send-message */ TXD *pOldTxd; unsigned long Flags; SK_U64 PhysAddr; - int Protocol; - int IpHeaderLength; int BytesSend = pMessage->len; SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("X")); @@ -1554,8 +1560,10 @@ struct sk_buff *pMessage) /* pointer to send-message */ pTxd->pMBuf = pMessage; if (pMessage->ip_summed == CHECKSUM_HW) { - Protocol = ((SK_U8)pMessage->data[C_OFFSET_IPPROTO] & 0xff); - if ((Protocol == C_PROTO_ID_UDP) && + u16 hdrlen = pMessage->h.raw - pMessage->data; + u16 offset = hdrlen + pMessage->csum; + + if ((pMessage->h.ipiph->protocol == IPPROTO_UDP ) && (pAC->GIni.GIChipRev == 0) && (pAC->GIni.GIChipId == CHIP_ID_YUKON)) { pTxd->TBControl = BMU_TCP_CHECK; @@ -1563,14 +1571,9 @@ struct sk_buff *pMessage) /* pointer to send-message */ pTxd->TBControl = BMU_UDP_CHECK; } - IpHeaderLength = (SK_U8)pMessage->data[C_OFFSET_IPHEADER]; - IpHeaderLength = (IpHeaderLength & 0xf) * 4; - pTxd->TcpSumOfs = 0; /* PH-Checksum already calculated */ - pTxd->TcpSumSt = C_LEN_ETHERMAC_HEADER + IpHeaderLength + - (Protocol == C_PROTO_ID_UDP ? - C_OFFSET_UDPHEADER_UDPCS : - C_OFFSET_TCPHEADER_TCPCS); - pTxd->TcpSumWr = C_LEN_ETHERMAC_HEADER + IpHeaderLength; + pTxd->TcpSumOfs = 0; + pTxd->TcpSumSt = hdrlen; + pTxd->TcpSumWr = offset; pTxd->TBControl |= BMU_OWN | BMU_STF | BMU_SW | BMU_EOF | @@ -1633,11 +1636,10 @@ struct sk_buff *pMessage) /* pointer to send-message */ TXD *pTxdLst; int CurrFrag; int BytesSend; - int IpHeaderLength; - int Protocol; skb_frag_t *sk_frag; SK_U64 PhysAddr; unsigned long Flags; + SK_U32 Control; spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags); #ifndef USE_TX_COMPLETE @@ -1660,7 +1662,6 @@ struct sk_buff *pMessage) /* pointer to send-message */ pTxdFst = pTxd; pTxdLst = pTxd; BytesSend = 0; - Protocol = 0; /* ** Map the first fragment (header) into the DMA-space @@ -1678,32 +1679,31 @@ struct sk_buff *pMessage) /* pointer to send-message */ ** Does the HW need to evaluate checksum for TCP or UDP packets? */ if (pMessage->ip_summed == CHECKSUM_HW) { - pTxd->TBControl = BMU_STF | BMU_STFWD | skb_headlen(pMessage); + u16 hdrlen = pMessage->h.raw - pMessage->data; + u16 offset = hdrlen + pMessage->csum; + + Control = BMU_STFWD; + /* ** 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[C_OFFSET_IPPROTO] & 0xff); - if ((Protocol == C_PROTO_ID_UDP) && + if ((pMessage->h.ipiph->protocol == IPPROTO_UDP ) && (pAC->GIni.GIChipRev == 0) && (pAC->GIni.GIChipId == CHIP_ID_YUKON)) { - pTxd->TBControl |= BMU_TCP_CHECK; + Control |= BMU_TCP_CHECK; } else { - pTxd->TBControl |= BMU_UDP_CHECK; + Control |= BMU_UDP_CHECK; } - IpHeaderLength = ((SK_U8)pMessage->data[C_OFFSET_IPHEADER] & 0xf)*4; - pTxd->TcpSumOfs = 0; /* PH-Checksum already claculated */ - pTxd->TcpSumSt = C_LEN_ETHERMAC_HEADER + IpHeaderLength + - (Protocol == C_PROTO_ID_UDP ? - C_OFFSET_UDPHEADER_UDPCS : - C_OFFSET_TCPHEADER_TCPCS); - pTxd->TcpSumWr = C_LEN_ETHERMAC_HEADER + IpHeaderLength; - } else { - pTxd->TBControl = BMU_CHECK | BMU_SW | BMU_STF | - skb_headlen(pMessage); - } + pTxd->TcpSumOfs = 0; + pTxd->TcpSumSt = hdrlen; + pTxd->TcpSumWr = offset; + } else + Control = BMU_CHECK | BMU_SW; + + pTxd->TBControl = BMU_STF | Control | skb_headlen(pMessage); pTxd = pTxd->pNextTxd; pTxPort->TxdRingFree--; @@ -1727,40 +1727,18 @@ struct sk_buff *pMessage) /* pointer to send-message */ pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32); pTxd->pMBuf = pMessage; - /* - ** Does the HW need to evaluate checksum for TCP or UDP packets? - */ - if (pMessage->ip_summed == CHECKSUM_HW) { - pTxd->TBControl = BMU_OWN | BMU_SW | BMU_STFWD; - /* - ** 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 == C_PROTO_ID_UDP) && - (pAC->GIni.GIChipRev == 0) && - (pAC->GIni.GIChipId == CHIP_ID_YUKON)) { - pTxd->TBControl |= BMU_TCP_CHECK; - } else { - pTxd->TBControl |= BMU_UDP_CHECK; - } - } else { - pTxd->TBControl = BMU_CHECK | BMU_SW | BMU_OWN; - } + pTxd->TBControl = Control | BMU_OWN | sk_frag->size; /* ** Do we have the last fragment? */ if( (CurrFrag+1) == skb_shinfo(pMessage)->nr_frags ) { #ifdef USE_TX_COMPLETE - pTxd->TBControl |= BMU_EOF | BMU_IRQ_EOF | sk_frag->size; + pTxd->TBControl |= BMU_EOF | BMU_IRQ_EOF; #else - pTxd->TBControl |= BMU_EOF | sk_frag->size; + pTxd->TBControl |= BMU_EOF; #endif pTxdFst->TBControl |= BMU_OWN | BMU_SW; - - } else { - pTxd->TBControl |= sk_frag->size; } pTxdLst = pTxd; pTxd = pTxd->pNextTxd; @@ -2007,7 +1985,6 @@ 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 */ -int IpFrameLength; 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 */ @@ -2020,10 +1997,6 @@ 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; rx_start: @@ -2152,8 +2125,8 @@ rx_start: (dma_addr_t) PhysAddr, FrameLength, PCI_DMA_FROMDEVICE); - eth_copy_and_sum(pNewMsg, pMsg->data, - FrameLength, 0); + memcpy(pNewMsg->data, pMsg, FrameLength); + pci_dma_sync_single_for_device(pAC->PciDev, (dma_addr_t) PhysAddr, FrameLength, @@ -2181,69 +2154,15 @@ rx_start: /* set length in message */ skb_put(pMsg, FrameLength); - /* hardware checksum */ - Type = ntohs(*((short*)&pMsg->data[12])); + } /* frame > SK_COPY_TRESHOLD */ #ifdef USE_SK_RX_CHECKSUM - if (Type == 0x800) { - Csum1=le16_to_cpu(pRxd->TcpSums & 0xffff); - Csum2=le16_to_cpu((pRxd->TcpSums >> 16) & 0xffff); - IpFrameLength = (int) ntohs((unsigned short) - ((unsigned short *) pMsg->data)[8]); - - /* - * Test: If frame is padded, a check is not possible! - * Frame not padded? Length difference must be 14 (0xe)! - */ - if ((FrameLength - IpFrameLength) != 0xe) { - /* Frame padded => TCP offload not possible! */ - pMsg->ip_summed = CHECKSUM_NONE; - } else { - /* Frame not padded => TCP offload! */ - if ((((Csum1 & 0xfffe) && (Csum2 & 0xfffe)) && - (pAC->GIni.GIChipId == CHIP_ID_GENESIS)) || - (pAC->ChipsetType)) { - Result = SkCsGetReceiveInfo(pAC, - &pMsg->data[14], - Csum1, Csum2, pRxPort->PortIndex); - if (Result == - SKCS_STATUS_IP_FRAGMENT || - Result == - SKCS_STATUS_IP_CSUM_OK || - Result == - SKCS_STATUS_TCP_CSUM_OK || - Result == - SKCS_STATUS_UDP_CSUM_OK) { - pMsg->ip_summed = - CHECKSUM_UNNECESSARY; - } - else if (Result == - SKCS_STATUS_TCP_CSUM_ERROR || - Result == - SKCS_STATUS_UDP_CSUM_ERROR || - Result == - SKCS_STATUS_IP_CSUM_ERROR_UDP || - Result == - SKCS_STATUS_IP_CSUM_ERROR_TCP || - Result == - SKCS_STATUS_IP_CSUM_ERROR ) { - /* HW Checksum error */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_RX_PROGRESS, - ("skge: CRC error. Frame dropped!\n")); - goto rx_failed; - } else { - pMsg->ip_summed = - CHECKSUM_NONE; - } - }/* checksumControl calculation valid */ - } /* Frame length check */ - } /* IP frame */ + pMsg->csum = pRxd->TcpSums & 0xffff; + pMsg->ip_summed = CHECKSUM_HW; #else - pMsg->ip_summed = CHECKSUM_NONE; + pMsg->ip_summed = CHECKSUM_NONE; #endif - } /* frame > SK_COPY_TRESHOLD */ - + SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("V")); ForRlmt = SK_RLMT_RX_PROTOCOL; #if 0 @@ -2498,7 +2417,7 @@ unsigned long Flags; static int SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p) { -DEV_NET *pNet = (DEV_NET*) dev->priv; +DEV_NET *pNet = netdev_priv(dev); SK_AC *pAC = pNet->pAC; struct sockaddr *addr = p; @@ -2555,7 +2474,7 @@ unsigned long Flags; SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("SkGeSetRxMode starts now... ")); - pNet = (DEV_NET*) dev->priv; + pNet = netdev_priv(dev); pAC = pNet->pAC; if (pAC->RlmtNets == 1) PortIdx = pAC->ActivePort; @@ -2618,7 +2537,7 @@ unsigned long Flags; static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int NewMtu) { DEV_NET *pNet; -DEV_NET *pOtherNet; +struct net_device *pOtherDev; SK_AC *pAC; unsigned long Flags; int i; @@ -2627,7 +2546,7 @@ SK_EVPARA EvPara; SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("SkGeChangeMtu starts now...\n")); - pNet = (DEV_NET*) dev->priv; + pNet = netdev_priv(dev); pAC = pNet->pAC; if ((NewMtu < 68) || (NewMtu > SK_JUMBO_MTU)) { @@ -2648,11 +2567,11 @@ SK_EVPARA EvPara; } #endif - pNet->Mtu = NewMtu; - pOtherNet = (DEV_NET*)pAC->dev[1 - pNet->NetNr]->priv; - if ((pOtherNet->Mtu>1500) && (NewMtu<=1500) && (pOtherNet->Up==1)) { - return(0); - } + pOtherDev = pAC->dev[1 - pNet->NetNr]; + + if ( netif_running(pOtherDev) && (pOtherDev->mtu > 1500) + && (NewMtu <= 1500)) + return 0; pAC->RxBufSize = NewMtu + 32; dev->mtu = NewMtu; @@ -2814,7 +2733,8 @@ SK_EVPARA EvPara; EvPara.Para32[1] = -1; SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara); - if (pOtherNet->Up) { + if (netif_running(pOtherDev)) { + DEV_NET *pOtherNet = netdev_priv(pOtherDev); EvPara.Para32[0] = pOtherNet->PortNr; SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara); } @@ -2855,7 +2775,7 @@ SK_EVPARA EvPara; */ static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev) { -DEV_NET *pNet = (DEV_NET*) dev->priv; +DEV_NET *pNet = netdev_priv(dev); 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 */ @@ -2888,7 +2808,7 @@ unsigned long Flags; /* for spin lock */ pAC->stats.rx_bytes = (SK_U32) pPnmiStruct->RxOctetsDeliveredCts; pAC->stats.tx_bytes = (SK_U32) pPnmiStat->StatTxOctetsOkCts; - if (pNet->Mtu <= 1500) { + if (dev->mtu <= 1500) { pAC->stats.rx_errors = (SK_U32) pPnmiStruct->InErrorsCts & 0xFFFFFFFF; } else { pAC->stats.rx_errors = (SK_U32) ((pPnmiStruct->InErrorsCts - @@ -2931,7 +2851,7 @@ unsigned long Flags; /* for spin lock */ * Description: * This function is called if an ioctl is issued on the device. * There are three subfunction for reading, writing and test-writing - * the private MIB data structure (usefull for SysKonnect-internal tools). + * the private MIB data structure (useful for SysKonnect-internal tools). * * Returns: * 0, if everything is ok @@ -2953,7 +2873,7 @@ int HeaderLength = sizeof(SK_U32) + sizeof(SK_U32); SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("SkGeIoctl starts now...\n")); - pNet = (DEV_NET*) dev->priv; + pNet = netdev_priv(dev); pAC = pNet->pAC; if(copy_from_user(&Ioctl, rq->ifr_data, sizeof(SK_GE_IOCTL))) { @@ -3034,7 +2954,7 @@ fault_gen: */ * ((SK_U32 *)pMemBuf) = 0; * ((SK_U32 *)pMemBuf + 1) = pdev->bus->number; - * ((SK_U32 *)pMemBuf + 2) = ParseDeviceNbrFromSlotName(pdev->slot_name); + * ((SK_U32 *)pMemBuf + 2) = ParseDeviceNbrFromSlotName(pci_name(pdev)); if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) { Err = -EFAULT; goto fault_diag; @@ -3839,25 +3759,21 @@ int Capabilities[3][3] = * * Returns: N/A */ -static void ProductStr( -SK_AC *pAC /* pointer to adapter context */ +static inline int ProductStr( + SK_AC *pAC, /* pointer to adapter context */ + char *DeviceStr, /* result string */ + int StrLen /* length of the string */ ) { -int StrLen = 80; /* length of the string, defined in SK_AC */ char Keyword[] = VPD_NAME; /* vpd productname identifier */ int ReturnCode; /* return code from vpd_read */ unsigned long Flags; spin_lock_irqsave(&pAC->SlowPathLock, Flags); - ReturnCode = VpdRead(pAC, pAC->IoBase, Keyword, pAC->DeviceStr, - &StrLen); + ReturnCode = VpdRead(pAC, pAC->IoBase, Keyword, DeviceStr, &StrLen); spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - if (ReturnCode != 0) { - /* there was an error reading the vpd data */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ERROR, - ("Error reading VPD data: %d\n", ReturnCode)); - pAC->DeviceStr[0] = '\0'; - } + + return ReturnCode; } /* ProductStr */ /***************************************************************************** @@ -4058,28 +3974,6 @@ SK_U8 *pVal) /* pointer to store the read value */ } /* SkPciReadCfgByte */ -/***************************************************************************** - * - * SkPciWriteCfgDWord - write a 32 bit value to pci config space - * - * Description: - * This routine writes a 32 bit value to the pci configuration - * space. - * - * Returns: - * 0 - indicate everything worked ok. - * != 0 - error indication - */ -int SkPciWriteCfgDWord( -SK_AC *pAC, /* Adapter Control structure pointer */ -int PciAddr, /* PCI register address */ -SK_U32 Val) /* pointer to store the read value */ -{ - pci_write_config_dword(pAC->PciDev, PciAddr, Val); - return(0); -} /* SkPciWriteCfgDWord */ - - /***************************************************************************** * * SkPciWriteCfgWord - write a 16 bit value to pci config space @@ -4188,7 +4082,7 @@ SK_BOOL DualNet; Flags); SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST); - pAC->dev[Param.Para32[0]]->flags &= ~IFF_RUNNING; + netif_carrier_off(pAC->dev[Param.Para32[0]]); spin_unlock_irqrestore( &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, Flags); @@ -4218,6 +4112,7 @@ SK_BOOL DualNet; Flags); break; case SK_DRV_NET_UP: /* SK_U32 PortIdx */ + { struct net_device *dev = pAC->dev[Param.Para32[0]]; /* action list 5 */ FromPort = Param.Para32[0]; SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, @@ -4301,22 +4196,12 @@ SK_BOOL DualNet; printk(" irq moderation: disabled\n"); -#ifdef SK_ZEROCOPY - if (pAC->ChipsetType) -#ifdef USE_SK_TX_CHECKSUM - printk(" scatter-gather: enabled\n"); -#else - printk(" tx-checksum: disabled\n"); -#endif - else - printk(" scatter-gather: disabled\n"); -#else - printk(" scatter-gather: disabled\n"); -#endif - -#ifndef USE_SK_RX_CHECKSUM - printk(" rx-checksum: disabled\n"); -#endif + printk(" scatter-gather: %s\n", + (dev->features & NETIF_F_SG) ? "enabled" : "disabled"); + printk(" tx-checksum: %s\n", + (dev->features & NETIF_F_IP_CSUM) ? "enabled" : "disabled"); + printk(" rx-checksum: %s\n", + pAC->RxPort[Param.Para32[0]].RxCsum ? "enabled" : "disabled"); } else { DoPrintInterfaceChange = SK_TRUE; @@ -4331,9 +4216,9 @@ SK_BOOL DualNet; } /* Inform the world that link protocol is up. */ - pAC->dev[Param.Para32[0]]->flags |= IFF_RUNNING; - + netif_carrier_on(dev); break; + } case SK_DRV_NET_DOWN: /* SK_U32 Reason */ /* action list 7 */ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, @@ -4344,7 +4229,7 @@ SK_BOOL DualNet; } else { DoPrintInterfaceChange = SK_TRUE; } - pAC->dev[Param.Para32[1]]->flags &= ~IFF_RUNNING; + netif_carrier_off(pAC->dev[Param.Para32[1]]); break; case SK_DRV_SWITCH_HARD: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, @@ -4539,18 +4424,15 @@ char ClassStr[80]; int SkDrvEnterDiagMode( SK_AC *pAc) /* pointer to adapter context */ { - SK_AC *pAC = NULL; - DEV_NET *pNet = NULL; - - pNet = (DEV_NET *) pAc->dev[0]->priv; - pAC = pNet->pAC; + DEV_NET *pNet = netdev_priv(pAc->dev[0]); + SK_AC *pAC = pNet->pAC; SK_MEMCPY(&(pAc->PnmiBackup), &(pAc->PnmiStruct), sizeof(SK_PNMI_STRUCT_DATA)); pAC->DiagModeActive = DIAG_ACTIVE; if (pAC->BoardLevel > SK_INIT_DATA) { - if (pNet->Up) { + if (netif_running(pAC->dev[0])) { pAC->WasIfUp[0] = SK_TRUE; pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */ DoPrintInterfaceChange = SK_FALSE; @@ -4558,9 +4440,9 @@ SK_AC *pAc) /* pointer to adapter context */ } else { pAC->WasIfUp[0] = SK_FALSE; } - if (pNet != (DEV_NET *) pAc->dev[1]->priv) { - pNet = (DEV_NET *) pAc->dev[1]->priv; - if (pNet->Up) { + if (pNet != netdev_priv(pAC->dev[1])) { + pNet = netdev_priv(pAC->dev[1]); + if (netif_running(pAC->dev[1])) { pAC->WasIfUp[1] = SK_TRUE; pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */ DoPrintInterfaceChange = SK_FALSE; @@ -4681,20 +4563,11 @@ int devNbr) /* what device is to be handled */ dev = pAC->dev[devNbr]; - /* - ** Function SkGeClose() uses MOD_DEC_USE_COUNT (2.2/2.4) - ** or module_put() (2.6) to decrease the number of users for - ** a device, but if a device is to be put under control of - ** the DIAG, that count is OK already and does not need to - ** be adapted! Hence the opposite MOD_INC_USE_COUNT or - ** try_module_get() needs to be used again to correct that. + /* On Linux 2.6 the network driver does NOT mess with reference + ** counts. The driver MUST be able to be unloaded at any time + ** due to the possibility of hotplug. */ - if (!try_module_get(THIS_MODULE)) { - return (-1); - } - if (SkGeClose(dev) != 0) { - module_put(THIS_MODULE); return (-1); } return (0); @@ -4723,17 +4596,6 @@ int devNbr) /* what device is to be handled */ if (SkGeOpen(dev) != 0) { return (-1); - } else { - /* - ** Function SkGeOpen() uses MOD_INC_USE_COUNT (2.2/2.4) - ** or try_module_get() (2.6) to increase the number of - ** users for a device, but if a device was just under - ** control of the DIAG, that count is OK already and - ** does not need to be adapted! Hence the opposite - ** MOD_DEC_USE_COUNT or module_put() needs to be used - ** again to correct that. - */ - module_put(THIS_MODULE); } /* @@ -4904,50 +4766,61 @@ static int __devinit skge_probe_one(struct pci_dev *pdev, SK_AC *pAC; DEV_NET *pNet = NULL; struct net_device *dev = NULL; -#ifdef CONFIG_PROC_FS - struct proc_dir_entry *pProcFile; -#endif static int boards_found = 0; int error = -ENODEV; + int using_dac = 0; + char DeviceStr[80]; if (pci_enable_device(pdev)) goto out; /* Configure DMA attributes. */ - if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL) && - pci_set_dma_mask(pdev, (u64) 0xffffffff)) - goto out_disable_device; - + if (sizeof(dma_addr_t) > sizeof(u32) && + !(error = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) { + using_dac = 1; + error = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); + if (error < 0) { + printk(KERN_ERR "sk98lin %s unable to obtain 64 bit DMA " + "for consistent allocations\n", pci_name(pdev)); + goto out_disable_device; + } + } else { + error = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + if (error) { + printk(KERN_ERR "sk98lin %s no usable DMA configuration\n", + pci_name(pdev)); + goto out_disable_device; + } + } - if ((dev = alloc_etherdev(sizeof(DEV_NET))) == NULL) { - printk(KERN_ERR "Unable to allocate etherdev " + error = -ENOMEM; + dev = alloc_etherdev(sizeof(DEV_NET)); + if (!dev) { + printk(KERN_ERR "sk98lin: unable to allocate etherdev " "structure!\n"); goto out_disable_device; } - pNet = dev->priv; - pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL); + pNet = netdev_priv(dev); + pNet->pAC = kzalloc(sizeof(SK_AC), GFP_KERNEL); if (!pNet->pAC) { - printk(KERN_ERR "Unable to allocate adapter " + printk(KERN_ERR "sk98lin: unable to allocate adapter " "structure!\n"); goto out_free_netdev; } - memset(pNet->pAC, 0, sizeof(SK_AC)); pAC = pNet->pAC; 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; + error = SkGeInitPCI(pAC); if (error) { - printk("SKGE: PCI setup failed: %i\n", error); + printk(KERN_ERR "sk98lin: PCI setup failed: %i\n", error); goto out_free_netdev; } @@ -4960,33 +4833,50 @@ static int __devinit skge_probe_one(struct pci_dev *pdev, dev->set_mac_address = &SkGeSetMacAddr; dev->do_ioctl = &SkGeIoctl; dev->change_mtu = &SkGeChangeMtu; - dev->flags &= ~IFF_RUNNING; +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = &SkGePollController; +#endif SET_NETDEV_DEV(dev, &pdev->dev); + SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps); -#ifdef SK_ZEROCOPY -#ifdef USE_SK_TX_CHECKSUM + /* Use only if yukon hardware */ if (pAC->ChipsetType) { - /* Use only if yukon hardware */ - /* SK and ZEROCOPY - fly baby... */ - dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; - } +#ifdef USE_SK_TX_CHECKSUM + dev->features |= NETIF_F_IP_CSUM; #endif +#ifdef SK_ZEROCOPY + dev->features |= NETIF_F_SG; #endif +#ifdef USE_SK_RX_CHECKSUM + pAC->RxPort[0].RxCsum = 1; +#endif + } + + if (using_dac) + dev->features |= NETIF_F_HIGHDMA; pAC->Index = boards_found++; - if (SkGeBoardInit(dev, pAC)) + error = SkGeBoardInit(dev, pAC); + if (error) goto out_free_netdev; + /* Read Adapter name from VPD */ + if (ProductStr(pAC, DeviceStr, sizeof(DeviceStr)) != 0) { + error = -EIO; + printk(KERN_ERR "sk98lin: Could not read VPD data.\n"); + goto out_free_resources; + } + /* Register net device */ - if (register_netdev(dev)) { - printk(KERN_ERR "SKGE: Could not register device.\n"); + error = register_netdev(dev); + if (error) { + printk(KERN_ERR "sk98lin: Could not register device.\n"); goto out_free_resources; } /* Print adapter specific string from vpd */ - ProductStr(pAC); - printk("%s: %s\n", dev->name, pAC->DeviceStr); + printk("%s: %s\n", dev->name, DeviceStr); /* Print configuration settings */ printk(" PrefPort:%c RlmtMode:%s\n", @@ -4999,38 +4889,29 @@ static int __devinit skge_probe_one(struct pci_dev *pdev, SkGeYellowLED(pAC, pAC->IoBase, 1); - memcpy(&dev->dev_addr, &pAC->Addr.Net[0].CurrentMacAddress, 6); - -#ifdef CONFIG_PROC_FS - pProcFile = create_proc_entry(dev->name, S_IRUGO, pSkRootDir); - if (pProcFile) { - pProcFile->proc_fops = &sk_proc_fops; - pProcFile->data = dev; - pProcFile->owner = THIS_MODULE; - } -#endif + memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); pNet->PortNr = 0; pNet->NetNr = 0; boards_found++; + pci_set_drvdata(pdev, dev); + /* More then one port found */ if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) { - if ((dev = alloc_etherdev(sizeof(DEV_NET))) == 0) { - printk(KERN_ERR "Unable to allocate etherdev " + dev = alloc_etherdev(sizeof(DEV_NET)); + if (!dev) { + printk(KERN_ERR "sk98lin: unable to allocate etherdev " "structure!\n"); - goto out; + goto single_port; } - pAC->dev[1] = dev; - pNet = dev->priv; + pNet = netdev_priv(dev); pNet->PortNr = 1; pNet->NetNr = 1; pNet->pAC = pAC; - pNet->Mtu = 1500; - pNet->Up = 0; dev->open = &SkGeOpen; dev->stop = &SkGeClose; @@ -5040,40 +4921,43 @@ static int __devinit skge_probe_one(struct pci_dev *pdev, dev->set_mac_address = &SkGeSetMacAddr; dev->do_ioctl = &SkGeIoctl; dev->change_mtu = &SkGeChangeMtu; - dev->flags &= ~IFF_RUNNING; + SET_NETDEV_DEV(dev, &pdev->dev); + SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps); -#ifdef SK_ZEROCOPY -#ifdef USE_SK_TX_CHECKSUM if (pAC->ChipsetType) { - /* SG and ZEROCOPY - fly baby... */ - dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; - } +#ifdef USE_SK_TX_CHECKSUM + dev->features |= NETIF_F_IP_CSUM; #endif +#ifdef SK_ZEROCOPY + dev->features |= NETIF_F_SG; #endif - - if (register_netdev(dev)) { - printk(KERN_ERR "SKGE: Could not register device.\n"); - free_netdev(dev); - pAC->dev[1] = pAC->dev[0]; - } else { -#ifdef CONFIG_PROC_FS - pProcFile = create_proc_entry(dev->name, S_IRUGO, - pSkRootDir); - if (pProcFile) { - pProcFile->proc_fops = &sk_proc_fops; - pProcFile->data = dev; - pProcFile->owner = THIS_MODULE; - } +#ifdef USE_SK_RX_CHECKSUM + pAC->RxPort[1].RxCsum = 1; #endif + } - memcpy(&dev->dev_addr, - &pAC->Addr.Net[1].CurrentMacAddress, 6); - - printk("%s: %s\n", dev->name, pAC->DeviceStr); - printk(" PrefPort:B RlmtMode:Dual Check Link State\n"); + if (using_dac) + dev->features |= NETIF_F_HIGHDMA; + + error = register_netdev(dev); + if (error) { + printk(KERN_ERR "sk98lin: Could not register device" + " for second port. (%d)\n", error); + free_netdev(dev); + goto single_port; } + + pAC->dev[1] = dev; + memcpy(&dev->dev_addr, + &pAC->Addr.Net[1].CurrentMacAddress, 6); + memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); + + printk("%s: %s\n", dev->name, DeviceStr); + printk(" PrefPort:B RlmtMode:Dual Check Link State\n"); } +single_port: + /* Save the hardware revision */ pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) + (pAC->GIni.GIPciHwRev & 0x0F); @@ -5085,7 +4969,6 @@ static int __devinit skge_probe_one(struct pci_dev *pdev, memset(&pAC->PnmiBackup, 0, sizeof(SK_PNMI_STRUCT_DATA)); memcpy(&pAC->PnmiBackup, &pAC->PnmiStruct, sizeof(SK_PNMI_STRUCT_DATA)); - pci_set_drvdata(pdev, dev); return 0; out_free_resources: @@ -5101,19 +4984,11 @@ static int __devinit skge_probe_one(struct pci_dev *pdev, static void __devexit skge_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - DEV_NET *pNet = (DEV_NET *) dev->priv; + DEV_NET *pNet = netdev_priv(dev); SK_AC *pAC = pNet->pAC; - int have_second_mac = 0; - - if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 2) - have_second_mac = 1; + struct net_device *otherdev = pAC->dev[1]; - remove_proc_entry(dev->name, pSkRootDir); unregister_netdev(dev); - if (have_second_mac) { - remove_proc_entry(pAC->dev[1]->name, pSkRootDir); - unregister_netdev(pAC->dev[1]); - } SkGeYellowLED(pAC, pAC->IoBase, 0); @@ -5146,68 +5021,124 @@ static void __devexit skge_remove_one(struct pci_dev *pdev) FreeResources(dev); free_netdev(dev); - if (have_second_mac) - free_netdev(pAC->dev[1]); + if (otherdev != dev) + free_netdev(otherdev); kfree(pAC); } +#ifdef CONFIG_PM +static int skge_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct net_device *dev = pci_get_drvdata(pdev); + DEV_NET *pNet = netdev_priv(dev); + SK_AC *pAC = pNet->pAC; + struct net_device *otherdev = pAC->dev[1]; + + if (netif_running(dev)) { + netif_carrier_off(dev); + DoPrintInterfaceChange = SK_FALSE; + SkDrvDeInitAdapter(pAC, 0); /* performs SkGeClose */ + netif_device_detach(dev); + } + if (otherdev != dev) { + if (netif_running(otherdev)) { + netif_carrier_off(otherdev); + DoPrintInterfaceChange = SK_FALSE; + SkDrvDeInitAdapter(pAC, 1); /* performs SkGeClose */ + netif_device_detach(otherdev); + } + } + + pci_save_state(pdev); + pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); + if (pAC->AllocFlag & SK_ALLOC_IRQ) { + free_irq(dev->irq, dev); + } + pci_disable_device(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + + return 0; +} + +static int skge_resume(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + DEV_NET *pNet = netdev_priv(dev); + SK_AC *pAC = pNet->pAC; + struct net_device *otherdev = pAC->dev[1]; + int ret; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + pci_enable_device(pdev); + pci_set_master(pdev); + if (pAC->GIni.GIMacsFound == 2) + ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, "sk98lin", dev); + else + ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ, "sk98lin", dev); + if (ret) { + printk(KERN_WARNING "sk98lin: unable to acquire IRQ %d\n", dev->irq); + pAC->AllocFlag &= ~SK_ALLOC_IRQ; + dev->irq = 0; + pci_disable_device(pdev); + return -EBUSY; + } + + netif_device_attach(dev); + if (netif_running(dev)) { + DoPrintInterfaceChange = SK_FALSE; + SkDrvInitAdapter(pAC, 0); /* first device */ + } + if (otherdev != dev) { + netif_device_attach(otherdev); + if (netif_running(otherdev)) { + DoPrintInterfaceChange = SK_FALSE; + SkDrvInitAdapter(pAC, 1); /* second device */ + } + } + + return 0; +} +#else +#define skge_suspend NULL +#define skge_resume NULL +#endif + static struct pci_device_id skge_pci_tbl[] = { { PCI_VENDOR_ID_3COM, 0x1700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_SYSKONNECT, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_SYSKONNECT, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, +/* DLink card does not have valid VPD so this driver gags + * { PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + */ { PCI_VENDOR_ID_MARVELL, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, -#if 0 /* don't handle Yukon2 cards at the moment -- mlindner@syskonnect.de */ - { PCI_VENDOR_ID_MARVELL, 0x4360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_MARVELL, 0x4361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, -#endif { PCI_VENDOR_ID_MARVELL, 0x5005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_CNET, 0x434e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015, }, { PCI_VENDOR_ID_LINKSYS, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { 0, } + { 0 } }; +MODULE_DEVICE_TABLE(pci, skge_pci_tbl); + static struct pci_driver skge_driver = { - .name = "skge", + .name = "sk98lin", .id_table = skge_pci_tbl, .probe = skge_probe_one, .remove = __devexit_p(skge_remove_one), + .suspend = skge_suspend, + .resume = skge_resume, }; static int __init skge_init(void) { - int error; - -#ifdef CONFIG_PROC_FS - memcpy(&SK_Root_Dir_entry, BOOT_STRING, sizeof(SK_Root_Dir_entry) - 1); - - pSkRootDir = proc_mkdir(SK_Root_Dir_entry, proc_net); - if (!pSkRootDir) { - printk(KERN_WARNING "Unable to create /proc/net/%s", - SK_Root_Dir_entry); - return -ENOMEM; - } - pSkRootDir->owner = THIS_MODULE; -#endif - - error = pci_module_init(&skge_driver); - if (error) { -#ifdef CONFIG_PROC_FS - remove_proc_entry(pSkRootDir->name, proc_net); -#endif - } - - return error; + return pci_module_init(&skge_driver); } static void __exit skge_exit(void) { - pci_unregister_driver(&skge_driver); -#ifdef CONFIG_PROC_FS - remove_proc_entry(pSkRootDir->name, proc_net); -#endif + pci_unregister_driver(&skge_driver); } module_init(skge_init);