Commit 4a493b70 authored by Daniele Venzano's avatar Daniele Venzano Committed by Jeff Garzik

[netdrvr sis900] add suspend/resume support

The attached patch adds support for suspend/resume to the sis900 driver.
With this patch on resume the NIC is fully configured and operational,
before a module reload was needed because of the complete lack of
suspend/resume callbacks.

I added two functions, sis900_suspend and sis900_resume, with their
pointers in struct pci_driver. A vector of 16 u32 was then needed to the
to keep PCI data during suspend. I added it in struct sis900_private.
I updated the revision number to reflect my changes. 
Looking at the code I also killed three typos.

The patch doesn't touch any other code.

Since I don't know anything on ethernet drivers the rule 'works for me'
is fully valid.


parent 3a8d5347
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
preliminary Rev. 1.0 Jan. 18, 1998 preliminary Rev. 1.0 Jan. 18, 1998
http://www.sis.com.tw/support/databook.htm http://www.sis.com.tw/support/databook.htm
Rev 1.08.07 Nov. 2 2003 Daniele Venzano <webvenza@libero.it> add suspend/resume support
Rev 1.08.06 Sep. 24 2002 Mufasa Yang bug fix for Tx timeout & add SiS963 support Rev 1.08.06 Sep. 24 2002 Mufasa Yang bug fix for Tx timeout & add SiS963 support
Rev 1.08.05 Jun. 6 2002 Mufasa Yang bug fix for read_eeprom & Tx descriptor over-boundary Rev 1.08.05 Jun. 6 2002 Mufasa Yang bug fix for read_eeprom & Tx descriptor over-boundary
Rev 1.08.04 Apr. 25 2002 Mufasa Yang <mufasa@sis.com.tw> added SiS962 support Rev 1.08.04 Apr. 25 2002 Mufasa Yang <mufasa@sis.com.tw> added SiS962 support
...@@ -72,7 +73,7 @@ ...@@ -72,7 +73,7 @@
#include "sis900.h" #include "sis900.h"
#define SIS900_MODULE_NAME "sis900" #define SIS900_MODULE_NAME "sis900"
#define SIS900_DRV_VERSION "v1.08.06 9/24/2002" #define SIS900_DRV_VERSION "v1.08.07 11/02/2003"
static char version[] __devinitdata = static char version[] __devinitdata =
KERN_INFO "sis900.c: " SIS900_DRV_VERSION "\n"; KERN_INFO "sis900.c: " SIS900_DRV_VERSION "\n";
...@@ -169,6 +170,7 @@ struct sis900_private { ...@@ -169,6 +170,7 @@ struct sis900_private {
unsigned int tx_full; /* The Tx queue is full. */ unsigned int tx_full; /* The Tx queue is full. */
u8 host_bridge_rev; u8 host_bridge_rev;
u32 pci_state[16];
}; };
MODULE_AUTHOR("Jim Huang <cmhuang@sis.com.tw>, Ollie Lho <ollie@sis.com.tw>"); MODULE_AUTHOR("Jim Huang <cmhuang@sis.com.tw>, Ollie Lho <ollie@sis.com.tw>");
...@@ -305,7 +307,7 @@ static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev, struct net_de ...@@ -305,7 +307,7 @@ static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev, struct net_de
*( ((u16 *)net_dev->dev_addr) + i) = inw(ioaddr + rfdr); *( ((u16 *)net_dev->dev_addr) + i) = inw(ioaddr + rfdr);
} }
/* enable packet filitering */ /* enable packet filtering */
outl(rfcrSave | RFEN, rfcr + ioaddr); outl(rfcrSave | RFEN, rfcr + ioaddr);
return 1; return 1;
...@@ -994,7 +996,7 @@ sis900_init_rxfilter (struct net_device * net_dev) ...@@ -994,7 +996,7 @@ sis900_init_rxfilter (struct net_device * net_dev)
} }
} }
/* enable packet filitering */ /* enable packet filtering */
outl(rfcrSave | RFEN, rfcr + ioaddr); outl(rfcrSave | RFEN, rfcr + ioaddr);
} }
...@@ -1466,7 +1468,7 @@ static void sis900_tx_timeout(struct net_device *net_dev) ...@@ -1466,7 +1468,7 @@ static void sis900_tx_timeout(struct net_device *net_dev)
* @net_dev: the net device to transmit with * @net_dev: the net device to transmit with
* *
* Set the transmit buffer descriptor, * Set the transmit buffer descriptor,
* and write TxENA to enable transimt state machine. * and write TxENA to enable transmit state machine.
* tell upper layer if the buffer is full * tell upper layer if the buffer is full
*/ */
...@@ -2184,11 +2186,72 @@ static void __devexit sis900_remove(struct pci_dev *pci_dev) ...@@ -2184,11 +2186,72 @@ static void __devexit sis900_remove(struct pci_dev *pci_dev)
pci_set_drvdata(pci_dev, NULL); pci_set_drvdata(pci_dev, NULL);
} }
#ifdef CONFIG_PM
static int sis900_suspend(struct pci_dev *pci_dev, u32 state)
{
struct net_device *net_dev = pci_get_drvdata(pci_dev);
struct sis900_private *sis_priv = net_dev->priv;
long ioaddr = net_dev->base_addr;
if(!netif_running(net_dev))
return 0;
netif_stop_queue(net_dev);
/* Stop the chip's Tx and Rx Status Machine */
outl(RxDIS | TxDIS | inl(ioaddr + cr), ioaddr + cr);
pci_set_power_state(pci_dev, 3);
pci_save_state(pci_dev, sis_priv->pci_state);
return 0;
}
static int sis900_resume(struct pci_dev *pci_dev)
{
struct net_device *net_dev = pci_get_drvdata(pci_dev);
struct sis900_private *sis_priv = net_dev->priv;
long ioaddr = net_dev->base_addr;
if(!netif_running(net_dev))
return 0;
pci_restore_state(pci_dev, sis_priv->pci_state);
pci_set_power_state(pci_dev, 0);
sis900_init_rxfilter(net_dev);
sis900_init_tx_ring(net_dev);
sis900_init_rx_ring(net_dev);
set_rx_mode(net_dev);
netif_device_attach(net_dev);
netif_start_queue(net_dev);
/* Workaround for EDB */
sis900_set_mode(ioaddr, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED);
/* Enable all known interrupts by setting the interrupt mask. */
outl((RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxIDLE), ioaddr + imr);
outl(RxENA | inl(ioaddr + cr), ioaddr + cr);
outl(IE, ioaddr + ier);
sis900_check_mode(net_dev, sis_priv->mii);
return 0;
}
#endif /* CONFIG_PM */
static struct pci_driver sis900_pci_driver = { static struct pci_driver sis900_pci_driver = {
.name = SIS900_MODULE_NAME, .name = SIS900_MODULE_NAME,
.id_table = sis900_pci_tbl, .id_table = sis900_pci_tbl,
.probe = sis900_probe, .probe = sis900_probe,
.remove = __devexit_p(sis900_remove), .remove = __devexit_p(sis900_remove),
#ifdef CONFIG_PM
.suspend = sis900_suspend,
.resume = sis900_resume,
#endif /* CONFIG_PM */
}; };
static int __init sis900_init_module(void) static int __init sis900_init_module(void)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment