X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Fsk98lin%2Fskge.c;h=92d11b961db88bd81133ce89eb7fec03365f1f40;hb=refs%2Fheads%2Fvserver;hp=53da4816349689b5ef720892ee4da13735664197;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index 53da48163..92d11b961 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c @@ -72,8 +72,8 @@ * * * + * * - * * * * @@ -101,19 +101,20 @@ * "h/skgeinit.h" * "h/skaddr.h" * "h/skgesirq.h" - * "h/skcsum.h" * "h/skrlmt.h" * ******************************************************************************/ #include "h/skversion.h" +#include #include +#include #include - -#ifdef CONFIG_PROC_FS -#include -#endif +#include +#include +#include +#include #include "h/skdrv1st.h" #include "h/skdrv2nd.h" @@ -197,8 +198,8 @@ static SK_BOOL BoardAllocMem(SK_AC *pAC); static void BoardFreeMem(SK_AC *pAC); static void BoardInitMem(SK_AC *pAC); static void SetupRing(SK_AC*, void*, uintptr_t, RXD**, RXD**, RXD**, int*, SK_BOOL); -static SkIsrRetVar SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs); -static SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs); +static SkIsrRetVar SkGeIsr(int irq, void *dev_id); +static SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id); 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); @@ -207,7 +208,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*); @@ -236,17 +236,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 = NULL; -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*); @@ -255,302 +249,33 @@ static void DumpLong(char*, int); #endif /* global variables *********************************************************/ -static const char *BootString = BOOT_STRING; -struct SK_NET_DEVICE *SkGeRootDev = NULL; -static int probed __initdata = 0; static SK_BOOL DoPrintInterfaceChange = SK_TRUE; +extern const 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}; - -#ifdef CONFIG_PROC_FS -static struct proc_dir_entry *pSkRootDir; -#endif - - - /***************************************************************************** * - * skge_probe - find all SK-98xx adapters + * SkPciWriteCfgDWord - write a 32 bit value to pci config space * * Description: - * This function scans the PCI bus for SK-98xx adapters. Resources for - * each adapter are allocated and the adapter is brought into Init 1 - * state. + * This routine writes a 32 bit value to the pci configuration + * space. * * Returns: - * 0, if everything is ok - * !=0, on error + * 0 - indicate everything worked ok. + * != 0 - error indication */ -static int __init skge_probe (void) +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 */ { - int boards_found = 0; - int vendor_flag = SK_FALSE; - SK_AC *pAC; - DEV_NET *pNet = NULL; - struct pci_dev *pdev = NULL; - struct SK_NET_DEVICE *dev = NULL; - SK_BOOL DeviceFound = SK_FALSE; - SK_BOOL BootStringCount = SK_FALSE; - int retval; -#ifdef CONFIG_PROC_FS - struct proc_dir_entry *pProcFile; -#endif - - if (probed) - return -ENODEV; - probed++; - - - while((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pdev))) { - - if (pci_enable_device(pdev)) { - continue; - } - dev = NULL; - pNet = NULL; - - /* Don't handle Yukon2 cards at the moment */ - /* 12-feb-2004 ---- mlindner@syskonnect.de */ - if (pdev->vendor == 0x11ab) { - if ( (pdev->device == 0x4360) || (pdev->device == 0x4361) ) - continue; - } - - SK_PCI_ISCOMPLIANT(vendor_flag, pdev); - if (!vendor_flag) - continue; - - /* Configure DMA attributes. */ - if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL) && - pci_set_dma_mask(pdev, (u64) 0xffffffff)) - continue; - - - if ((dev = alloc_etherdev(sizeof(DEV_NET))) == NULL) { - printk(KERN_ERR "Unable to allocate etherdev " - "structure!\n"); - break; - } - - pNet = dev->priv; - pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL); - if (pNet->pAC == NULL){ - free_netdev(dev); - printk(KERN_ERR "Unable to allocate adapter " - "structure!\n"); - 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->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; - retval = SkGeInitPCI(pAC); - if (retval) { - printk("SKGE: PCI setup failed: %i\n", retval); - free_netdev(dev); - continue; - } - - SET_MODULE_OWNER(dev); - dev->open = &SkGeOpen; - dev->stop = &SkGeClose; - dev->hard_start_xmit = &SkGeXmit; - dev->get_stats = &SkGeStats; - dev->last_stats = &SkGeStats; - dev->set_multicast_list = &SkGeSetRxMode; - dev->set_mac_address = &SkGeSetMacAddr; - dev->do_ioctl = &SkGeIoctl; - dev->change_mtu = &SkGeChangeMtu; - dev->flags &= ~IFF_RUNNING; - SET_NETDEV_DEV(dev, &pdev->dev); - -#ifdef SK_ZEROCOPY -#ifdef USE_SK_TX_CHECKSUM - - if (pAC->ChipsetType) { - /* Use only if yukon hardware */ - /* SK and ZEROCOPY - fly baby... */ - dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; - } -#endif -#endif - - pAC->Index = boards_found; - - if (SkGeBoardInit(dev, pAC)) { - free_netdev(dev); - continue; - } - - /* Register net device */ - if (register_netdev(dev)) { - printk(KERN_ERR "SKGE: Could not register device.\n"); - FreeResources(dev); - free_netdev(dev); - continue; - } - - /* Print adapter specific string from vpd */ - ProductStr(pAC); - printk("%s: %s\n", dev->name, pAC->DeviceStr); - - /* Print configuration settings */ - printk(" PrefPort:%c RlmtMode:%s\n", - 'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber, - (pAC->RlmtMode==0) ? "Check Link State" : - ((pAC->RlmtMode==1) ? "Check Link State" : - ((pAC->RlmtMode==3) ? "Check Local Port" : - ((pAC->RlmtMode==7) ? "Check Segmentation" : - ((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error"))))); - - SkGeYellowLED(pAC, pAC->IoBase, 1); - - - memcpy((caddr_t) &dev->dev_addr, - (caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6); - - /* First adapter... Create proc and print message */ -#ifdef CONFIG_PROC_FS - if (!DeviceFound) { - DeviceFound = SK_TRUE; - SK_MEMCPY(&SK_Root_Dir_entry, BootString, - sizeof(SK_Root_Dir_entry) - 1); - - /*Create proc (directory)*/ - if(!pSkRootDir) { - pSkRootDir = proc_mkdir(SK_Root_Dir_entry, proc_net); - if (!pSkRootDir) { - printk(KERN_WARNING "%s: Unable to create /proc/net/%s", - dev->name, SK_Root_Dir_entry); - } else { - pSkRootDir->owner = THIS_MODULE; - } - } - } - - /* Create proc file */ - if (pSkRootDir && - (pProcFile = create_proc_entry(dev->name, S_IRUGO, - pSkRootDir))) { - pProcFile->proc_fops = &sk_proc_fops; - pProcFile->data = dev; - } - -#endif - - pNet->PortNr = 0; - pNet->NetNr = 0; - - boards_found++; - - /* 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 " - "structure!\n"); - break; - } - - pAC->dev[1] = dev; - pNet = dev->priv; - pNet->PortNr = 1; - pNet->NetNr = 1; - pNet->pAC = pAC; - pNet->Mtu = 1500; - pNet->Up = 0; - - dev->open = &SkGeOpen; - dev->stop = &SkGeClose; - dev->hard_start_xmit = &SkGeXmit; - dev->get_stats = &SkGeStats; - dev->last_stats = &SkGeStats; - dev->set_multicast_list = &SkGeSetRxMode; - dev->set_mac_address = &SkGeSetMacAddr; - dev->do_ioctl = &SkGeIoctl; - dev->change_mtu = &SkGeChangeMtu; - dev->flags &= ~IFF_RUNNING; - -#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; - } -#endif -#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 - if (pSkRootDir - && (pProcFile = create_proc_entry(dev->name, - S_IRUGO, pSkRootDir))) { - pProcFile->proc_fops = &sk_proc_fops; - pProcFile->data = dev; - } -#endif - - 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); - - /* Set driver globals */ - pAC->Pnmi.pDriverFileName = DRIVER_FILE_NAME; - pAC->Pnmi.pDriverReleaseDate = DRIVER_REL_DATE; - - SK_MEMSET(&(pAC->PnmiBackup), 0, sizeof(SK_PNMI_STRUCT_DATA)); - SK_MEMCPY(&(pAC->PnmiBackup), &(pAC->PnmiStruct), - sizeof(SK_PNMI_STRUCT_DATA)); - - /* - * This is bollocks, but we need to tell the net-init - * code that it shall go for the next device. - */ -#ifndef MODULE - dev->base_addr = 0; -#endif - } - - /* - * If we're at this point we're going through skge_probe() for - * the first time. Return success (0) if we've initialized 1 - * or more boards. Otherwise, return failure (-ENODEV). - */ - - return boards_found; -} /* skge_probe */ - + pci_write_config_dword(pAC->PciDev, PciAddr, Val); + return(0); +} /* SkPciWriteCfgDWord */ /***************************************************************************** * @@ -559,26 +284,22 @@ static int __init skge_probe (void) * 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 /* @@ -596,10 +317,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; } @@ -607,8 +327,7 @@ int SkGeInitPCI(SK_AC *pAC) out_release: pci_release_regions(pdev); - out_disable: - pci_disable_device(pdev); + out: return retval; } @@ -630,22 +349,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 */ @@ -653,29 +370,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"); -/* not used, just there because every driver should have them: */ -MODULE_PARM(options, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "i"); -MODULE_PARM(debug, "i"); -/* 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; @@ -755,122 +449,31 @@ static char *RlmtMode[SK_MAX_CARD_PARAM] = RLMT_MODE; static char *RlmtMode[SK_MAX_CARD_PARAM] = {"", }; #endif -static int debug = 0; /* not used */ -static int options[SK_MAX_CARD_PARAM] = {0, }; /* not used */ - static int IntsPerSec[SK_MAX_CARD_PARAM]; static char *Moderation[SK_MAX_CARD_PARAM]; static char *ModerationMask[SK_MAX_CARD_PARAM]; static char *AutoSizing[SK_MAX_CARD_PARAM]; static char *Stats[SK_MAX_CARD_PARAM]; - -/***************************************************************************** - * - * skge_init_module - module initialization function - * - * Description: - * Very simple, only call skge_probe and return approriate result. - * - * Returns: - * 0, if everything is ok - * !=0, on error - */ -static int __init skge_init_module(void) -{ - int cards; - SkGeRootDev = NULL; - - /* just to avoid warnings ... */ - debug = 0; - options[0] = 0; - - cards = skge_probe(); - if (cards == 0) { - printk("sk98lin: No adapter found.\n"); - } - return cards ? 0 : -ENODEV; -} /* skge_init_module */ - - -/***************************************************************************** - * - * skge_cleanup_module - module unload function - * - * Description: - * Disable adapter if it is still running, free resources, - * free device struct. - * - * Returns: N/A - */ -static void __exit skge_cleanup_module(void) -{ -DEV_NET *pNet; -SK_AC *pAC; -struct SK_NET_DEVICE *next; -unsigned long Flags; -SK_EVPARA EvPara; - - while (SkGeRootDev) { - pNet = (DEV_NET*) SkGeRootDev->priv; - pAC = pNet->pAC; - next = pAC->Next; - - netif_stop_queue(SkGeRootDev); - SkGeYellowLED(pAC, pAC->IoBase, 0); - - if(pAC->BoardLevel == SK_INIT_RUN) { - /* board is still alive */ - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - EvPara.Para32[0] = 0; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - EvPara.Para32[0] = 1; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - SkEventDispatcher(pAC, pAC->IoBase); - /* disable interrupts */ - SK_OUT32(pAC->IoBase, B0_IMSK, 0); - SkGeDeInit(pAC, pAC->IoBase); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - pAC->BoardLevel = SK_INIT_DATA; - /* We do NOT check here, if IRQ was pending, of course*/ - } - - if(pAC->BoardLevel == SK_INIT_IO) { - /* board is still alive */ - SkGeDeInit(pAC, pAC->IoBase); - pAC->BoardLevel = SK_INIT_DATA; - } - - if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 2){ - unregister_netdev(pAC->dev[1]); - free_netdev(pAC->dev[1]); - } - - FreeResources(SkGeRootDev); - - SkGeRootDev->get_stats = NULL; - /* - * otherwise unregister_netdev calls get_stats with - * invalid IO ... :-( - */ - unregister_netdev(SkGeRootDev); - free_netdev(SkGeRootDev); - kfree(pAC); - SkGeRootDev = next; - } - -#ifdef CONFIG_PROC_FS - /* clear proc-dir */ - remove_proc_entry(pSkRootDir->name, proc_net); -#endif - -} /* skge_cleanup_module */ - -module_init(skge_init_module); -module_exit(skge_cleanup_module); - +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); /***************************************************************************** * @@ -885,7 +488,7 @@ module_exit(skge_cleanup_module); * 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; @@ -910,6 +513,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); @@ -917,7 +525,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); @@ -939,7 +547,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); @@ -964,34 +572,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, IRQF_SHARED, "sk98lin", dev); } else if (pAC->GIni.GIMacsFound == 1) { - Ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ, - pAC->Name, dev); + Ret = request_irq(dev->irq, SkGeIsrOnePort, IRQF_SHARED, + "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; @@ -1005,15 +608,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 */ @@ -1032,8 +629,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 */ @@ -1126,8 +722,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*/ @@ -1215,7 +810,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; @@ -1287,14 +882,14 @@ int PortIndex) /* index of the port for which to re-init */ * Returns: N/A * */ -static SkIsrRetVar SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs) +static SkIsrRetVar SkGeIsr(int irq, void *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 */ - pNet = (DEV_NET*) dev->priv; + pNet = netdev_priv(dev); pAC = pNet->pAC; /* @@ -1436,14 +1031,14 @@ SK_U32 IntSrc; /* interrupts source register contents */ * Returns: N/A * */ -static SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs) +static SkIsrRetVar SkGeIsrOnePort(int irq, void *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 */ - pNet = (DEV_NET*) dev->priv; + pNet = netdev_priv(dev); pAC = pNet->pAC; /* @@ -1533,6 +1128,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); + enable_irq(dev->irq); +} +#endif /**************************************************************************** * @@ -1559,7 +1172,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, @@ -1573,10 +1186,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; @@ -1584,7 +1193,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); } @@ -1600,7 +1208,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); } @@ -1650,7 +1257,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, @@ -1686,19 +1292,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 { @@ -1781,9 +1386,7 @@ struct SK_NET_DEVICE *dev) sizeof(SK_PNMI_STRUCT_DATA)); pAC->MaxPorts--; - pNet->Up = 0; - module_put(THIS_MODULE); return (0); } /* SkGeClose */ @@ -1809,7 +1412,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) || @@ -1887,8 +1490,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")); @@ -1926,7 +1527,8 @@ struct sk_buff *pMessage) /* pointer to send-message */ ** This is to resolve faulty padding by the HW with 0xaa bytes. */ if (BytesSend < C_LEN_ETHERNET_MINSIZE) { - if ((pMessage = skb_padto(pMessage, C_LEN_ETHERNET_MINSIZE)) == NULL) { + if (skb_padto(pMessage, C_LEN_ETHERNET_MINSIZE)) { + spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); return 0; } pMessage->len = C_LEN_ETHERNET_MINSIZE; @@ -1959,9 +1561,11 @@ struct sk_buff *pMessage) /* pointer to send-message */ pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32); pTxd->pMBuf = pMessage; - if (pMessage->ip_summed == CHECKSUM_HW) { - Protocol = ((SK_U8)pMessage->data[C_OFFSET_IPPROTO] & 0xff); - if ((Protocol == C_PROTO_ID_UDP) && + if (pMessage->ip_summed == CHECKSUM_PARTIAL) { + u16 hdrlen = pMessage->h.raw - pMessage->data; + u16 offset = hdrlen + pMessage->csum_offset; + + if ((pMessage->h.ipiph->protocol == IPPROTO_UDP ) && (pAC->GIni.GIChipRev == 0) && (pAC->GIni.GIChipId == CHIP_ID_YUKON)) { pTxd->TBControl = BMU_TCP_CHECK; @@ -1969,14 +1573,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 | @@ -2039,11 +1638,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 @@ -2066,7 +1664,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 @@ -2083,33 +1680,32 @@ 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); + if (pMessage->ip_summed == CHECKSUM_PARTIAL) { + u16 hdrlen = pMessage->h.raw - pMessage->data; + u16 offset = hdrlen + pMessage->csum_offset; + + 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--; @@ -2133,40 +1729,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; @@ -2413,7 +1987,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 */ @@ -2426,10 +1999,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: @@ -2558,8 +2127,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, @@ -2587,69 +2156,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_COMPLETE; #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 @@ -2904,7 +2419,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; @@ -2961,7 +2476,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; @@ -3024,7 +2539,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; @@ -3033,7 +2548,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)) { @@ -3054,11 +2569,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; @@ -3093,8 +2608,7 @@ SK_EVPARA EvPara; SkEventDispatcher(pAC, pAC->IoBase); for (i=0; iGIni.GIMacsFound; i++) { - spin_lock_irqsave( - &pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock, Flags); + spin_lock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock); netif_stop_queue(pAC->dev[i]); } @@ -3221,7 +2735,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); } @@ -3262,7 +2777,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 */ @@ -3295,7 +2810,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 - @@ -3330,6 +2845,56 @@ unsigned long Flags; /* for spin lock */ return(&pAC->stats); } /* SkGeStats */ +/* + * Basic MII register access + */ +static int SkGeMiiIoctl(struct net_device *dev, + struct mii_ioctl_data *data, int cmd) +{ + DEV_NET *pNet = netdev_priv(dev); + SK_AC *pAC = pNet->pAC; + SK_IOC IoC = pAC->IoBase; + int Port = pNet->PortNr; + SK_GEPORT *pPrt = &pAC->GIni.GP[Port]; + unsigned long Flags; + int err = 0; + int reg = data->reg_num & 0x1f; + SK_U16 val = data->val_in; + + if (!netif_running(dev)) + return -ENODEV; /* Phy still in reset */ + + spin_lock_irqsave(&pAC->SlowPathLock, Flags); + switch(cmd) { + case SIOCGMIIPHY: + data->phy_id = pPrt->PhyAddr; + + /* fallthru */ + case SIOCGMIIREG: + if (pAC->GIni.GIGenesis) + SkXmPhyRead(pAC, IoC, Port, reg, &val); + else + SkGmPhyRead(pAC, IoC, Port, reg, &val); + + data->val_out = val; + break; + + case SIOCSMIIREG: + if (!capable(CAP_NET_ADMIN)) + err = -EPERM; + + else if (pAC->GIni.GIGenesis) + SkXmPhyWrite(pAC, IoC, Port, reg, val); + else + SkGmPhyWrite(pAC, IoC, Port, reg, val); + break; + default: + err = -EOPNOTSUPP; + } + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + return err; +} + /***************************************************************************** * @@ -3338,7 +2903,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 @@ -3360,9 +2925,12 @@ 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 (cmd == SIOCGMIIPHY || cmd == SIOCSMIIREG || cmd == SIOCGMIIREG) + return SkGeMiiIoctl(dev, if_mii(rq), cmd); + if(copy_from_user(&Ioctl, rq->ifr_data, sizeof(SK_GE_IOCTL))) { return -EFAULT; } @@ -3441,7 +3009,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; @@ -4246,25 +3814,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 */ /***************************************************************************** @@ -4465,28 +4029,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 @@ -4595,7 +4137,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); @@ -4625,6 +4167,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, @@ -4708,22 +4251,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; @@ -4738,9 +4271,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, @@ -4751,7 +4284,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, @@ -4773,12 +4306,10 @@ SK_BOOL DualNet; spin_lock_irqsave( &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, Flags); - spin_lock_irqsave( - &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags); + spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock); SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST); SkGeStopPort(pAC, IoC, ToPort, SK_STOP_ALL, SK_SOFT_RST); - spin_unlock_irqrestore( - &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags); + spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock); spin_unlock_irqrestore( &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, Flags); @@ -4791,8 +4322,7 @@ SK_BOOL DualNet; spin_lock_irqsave( &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, Flags); - spin_lock_irqsave( - &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags); + spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock); pAC->ActivePort = ToPort; #if 0 SetQueueSizes(pAC); @@ -4807,8 +4337,7 @@ SK_BOOL DualNet; pAC, pAC->ActivePort, DualNet)) { - spin_unlock_irqrestore( - &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags); + spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock); spin_unlock_irqrestore( &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, Flags); @@ -4834,8 +4363,7 @@ SK_BOOL DualNet; SkGePollTxD(pAC, IoC, ToPort, SK_TRUE); ClearAndStartRx(pAC, FromPort); ClearAndStartRx(pAC, ToPort); - spin_unlock_irqrestore( - &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags); + spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock); spin_unlock_irqrestore( &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, Flags); @@ -4951,18 +4479,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; @@ -4970,9 +4495,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; @@ -5093,20 +4618,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); @@ -5135,17 +4651,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); } /* @@ -5310,8 +4815,386 @@ int l; #endif -/******************************************************************************* - * - * End of file - * - ******************************************************************************/ +static int __devinit skge_probe_one(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + SK_AC *pAC; + DEV_NET *pNet = NULL; + struct net_device *dev = NULL; + 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 (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; + } + } + + 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 = netdev_priv(dev); + pNet->pAC = kzalloc(sizeof(SK_AC), GFP_KERNEL); + if (!pNet->pAC) { + printk(KERN_ERR "sk98lin: unable to allocate adapter " + "structure!\n"); + goto out_free_netdev; + } + + pAC = pNet->pAC; + pAC->PciDev = pdev; + + pAC->dev[0] = dev; + pAC->dev[1] = dev; + pAC->CheckQueue = SK_FALSE; + + dev->irq = pdev->irq; + + error = SkGeInitPCI(pAC); + if (error) { + printk(KERN_ERR "sk98lin: PCI setup failed: %i\n", error); + goto out_free_netdev; + } + + SET_MODULE_OWNER(dev); + dev->open = &SkGeOpen; + dev->stop = &SkGeClose; + dev->hard_start_xmit = &SkGeXmit; + dev->get_stats = &SkGeStats; + dev->set_multicast_list = &SkGeSetRxMode; + dev->set_mac_address = &SkGeSetMacAddr; + dev->do_ioctl = &SkGeIoctl; + dev->change_mtu = &SkGeChangeMtu; +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = &SkGePollController; +#endif + SET_NETDEV_DEV(dev, &pdev->dev); + SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps); + + /* Use only if yukon hardware */ + if (pAC->ChipsetType) { +#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++; + + 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 */ + 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 */ + printk("%s: %s\n", dev->name, DeviceStr); + + /* Print configuration settings */ + printk(" PrefPort:%c RlmtMode:%s\n", + 'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber, + (pAC->RlmtMode==0) ? "Check Link State" : + ((pAC->RlmtMode==1) ? "Check Link State" : + ((pAC->RlmtMode==3) ? "Check Local Port" : + ((pAC->RlmtMode==7) ? "Check Segmentation" : + ((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error"))))); + + SkGeYellowLED(pAC, pAC->IoBase, 1); + + memcpy(&dev->dev_addr, &pAC->Addr.Net[0].CurrentMacAddress, 6); + 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)) { + dev = alloc_etherdev(sizeof(DEV_NET)); + if (!dev) { + printk(KERN_ERR "sk98lin: unable to allocate etherdev " + "structure!\n"); + goto single_port; + } + + pNet = netdev_priv(dev); + pNet->PortNr = 1; + pNet->NetNr = 1; + pNet->pAC = pAC; + + dev->open = &SkGeOpen; + dev->stop = &SkGeClose; + dev->hard_start_xmit = &SkGeXmit; + dev->get_stats = &SkGeStats; + dev->set_multicast_list = &SkGeSetRxMode; + dev->set_mac_address = &SkGeSetMacAddr; + dev->do_ioctl = &SkGeIoctl; + dev->change_mtu = &SkGeChangeMtu; + SET_NETDEV_DEV(dev, &pdev->dev); + SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps); + + if (pAC->ChipsetType) { +#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[1].RxCsum = 1; +#endif + } + + 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); + + /* Set driver globals */ + pAC->Pnmi.pDriverFileName = DRIVER_FILE_NAME; + pAC->Pnmi.pDriverReleaseDate = DRIVER_REL_DATE; + + memset(&pAC->PnmiBackup, 0, sizeof(SK_PNMI_STRUCT_DATA)); + memcpy(&pAC->PnmiBackup, &pAC->PnmiStruct, sizeof(SK_PNMI_STRUCT_DATA)); + + return 0; + + out_free_resources: + FreeResources(dev); + out_free_netdev: + free_netdev(dev); + out_disable_device: + pci_disable_device(pdev); + out: + return error; +} + +static void __devexit skge_remove_one(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]; + + unregister_netdev(dev); + + SkGeYellowLED(pAC, pAC->IoBase, 0); + + if (pAC->BoardLevel == SK_INIT_RUN) { + SK_EVPARA EvPara; + unsigned long Flags; + + /* board is still alive */ + spin_lock_irqsave(&pAC->SlowPathLock, Flags); + EvPara.Para32[0] = 0; + EvPara.Para32[1] = -1; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); + EvPara.Para32[0] = 1; + EvPara.Para32[1] = -1; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); + SkEventDispatcher(pAC, pAC->IoBase); + /* disable interrupts */ + SK_OUT32(pAC->IoBase, B0_IMSK, 0); + SkGeDeInit(pAC, pAC->IoBase); + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + pAC->BoardLevel = SK_INIT_DATA; + /* We do NOT check here, if IRQ was pending, of course*/ + } + + if (pAC->BoardLevel == SK_INIT_IO) { + /* board is still alive */ + SkGeDeInit(pAC, pAC->IoBase); + pAC->BoardLevel = SK_INIT_DATA; + } + + FreeResources(dev); + free_netdev(dev); + 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, IRQF_SHARED, "sk98lin", dev); + else + ret = request_irq(dev->irq, SkGeIsrOnePort, IRQF_SHARED, "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 }, +/* 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 }, + { 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, 0x0015, }, + { PCI_VENDOR_ID_LINKSYS, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { 0 } +}; + +MODULE_DEVICE_TABLE(pci, skge_pci_tbl); + +static struct pci_driver skge_driver = { + .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) +{ + return pci_register_driver(&skge_driver); +} + +static void __exit skge_exit(void) +{ + pci_unregister_driver(&skge_driver); +} + +module_init(skge_init); +module_exit(skge_exit);