public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Nigel Cunningham <ncunningham@cyclades.com>
To: Prakash Punnoor <prakash@punnoor.de>
Cc: linux-kernel <linux-kernel@vger.kernel.org>, jgarzik@pobox.com
Subject: Re: Issues with uli526x networking module
Date: Wed, 29 Mar 2006 07:47:32 +1000	[thread overview]
Message-ID: <200603290747.38402.ncunningham@cyclades.com> (raw)
In-Reply-To: <200603281930.53859.prakash@punnoor.de>


[-- Attachment #1.1: Type: text/plain, Size: 706 bytes --]

Hi.

On Wednesday 29 March 2006 03:30, Prakash Punnoor wrote:
> Hi, I am just wondering whether you found out what the issue is with the
> link problem. If you have some patch ready (even if it is hackish) I would
> be happy to use it.
>
> Anyways, I know you are busy with swsusp2. ;-)
>
> Cheers,

Yes, I do have a patch. It is hackish at the moment because as you've rightly 
guessed, I haven't gotten around to finishing it. It also doesn't work 
perfectly - I sometimes need to rmmod and insmod after booting a new kernel 
to get the link to come up. But, apart from that, it works fine. Attached. 
(Jeff, I'm sure it doesn't need saying, but please don't apply!)

Regards,

Nigel

[-- Attachment #1.2: 180-uli-power-manaagement.patch --]
[-- Type: text/x-diff, Size: 19428 bytes --]

 uli526x.c |  335 +++++++++++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 255 insertions(+), 80 deletions(-)
diff -ruNp 180-uli-power-manaagement.patch-old/drivers/net/tulip/uli526x.c 180-uli-power-manaagement.patch-new/drivers/net/tulip/uli526x.c
--- 180-uli-power-manaagement.patch-old/drivers/net/tulip/uli526x.c	2006-03-13 10:02:46.000000000 +1000
+++ 180-uli-power-manaagement.patch-new/drivers/net/tulip/uli526x.c	2006-03-15 09:35:15.000000000 +1000
@@ -13,8 +13,8 @@
 */
 
 #define DRV_NAME	"uli526x"
-#define DRV_VERSION	"0.9.3"
-#define DRV_RELDATE	"2005-7-29"
+#define DRV_VERSION	"0.9.4"
+#define DRV_RELDATE	"2006-1-17"
 
 #include <linux/module.h>
 
@@ -248,6 +248,68 @@ static void uli526x_set_phyxcer(struct u
 
 /* ULI526X network board routine ---------------------------- */
 
+static void uli526x_free_resources(struct uli526x_board_info *db)
+{
+	if(db->desc_pool_ptr) {
+		pci_free_consistent(db->pdev, sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20,
+			db->desc_pool_ptr, db->desc_pool_dma_ptr);
+		db->desc_pool_ptr = NULL;
+	}
+			
+	if(db->buf_pool_ptr != NULL) {
+		pci_free_consistent(db->pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4,
+			db->buf_pool_ptr, db->buf_pool_dma_ptr);
+		db->buf_pool_ptr = NULL;
+	}
+}
+
+static int uli526x_get_resources(struct uli526x_board_info *db)
+{
+	/* Allocate Tx/Rx descriptor memory */
+	db->desc_pool_ptr = pci_alloc_consistent(db->pdev, sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20, &db->desc_pool_dma_ptr);
+	if(!db->desc_pool_ptr)
+		return -ENOMEM;
+
+	db->buf_pool_ptr = pci_alloc_consistent(db->pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4, &db->buf_pool_dma_ptr);
+	return db->buf_pool_ptr ? 0 : -ENOMEM;
+}
+
+static void do_reset(struct net_device *dev)
+{
+	struct uli526x_board_info *db = netdev_priv(dev);
+	int i;
+
+	printk("Do_reset\n");
+
+	/* read 64 word srom data */
+	for (i = 0; i < 64; i++)
+		((u16 *) db->srom)[i] = cpu_to_le16(read_srom_word(db->ioaddr, i));
+
+	/* Set Node address */
+	if(((u16 *) db->srom)[0] == 0xffff || ((u16 *) db->srom)[0] == 0)		/* SROM absent, so read MAC address from ID Table */
+	{
+		outl(0x10000, db->ioaddr + DCR0);	//Diagnosis mode
+		outl(0x1c0, db->ioaddr + DCR13);	//Reset dianostic pointer port
+		outl(0, db->ioaddr + DCR14);		//Clear reset port
+		outl(0x10, db->ioaddr + DCR14);		//Reset ID Table pointer
+		outl(0, db->ioaddr + DCR14);		//Clear reset port
+		outl(0, db->ioaddr + DCR13);		//Clear CR13
+		outl(0x1b0, db->ioaddr + DCR13);	//Select ID Table access port
+		//Read MAC address from CR14
+		for (i = 0; i < 6; i++)
+			dev->dev_addr[i] = inl(db->ioaddr + DCR14);
+		//Read end
+		outl(0, db->ioaddr + DCR13);	//Clear CR13
+		outl(0, db->ioaddr + DCR0);		//Clear CR0
+		udelay(10);
+	}
+	else		/*Exist SROM*/
+	{
+		for (i = 0; i < 6; i++)
+			dev->dev_addr[i] = db->srom[20 + i];
+	}
+}
+
 /*
  *	Search ULI526X board, allocate space and register it
  */
@@ -256,18 +318,30 @@ static int __devinit uli526x_init_one (s
 				    const struct pci_device_id *ent)
 {
 	struct uli526x_board_info *db;	/* board information structure */
-	struct net_device *dev;
+	struct net_device *dev = NULL;
 	int i, err;
 	
 	ULI526X_DBUG(0, "uli526x_init_one()", 0);
+	printk("uli526x_init_one()\n");
 
 	if (!printed_version++)
 		printk(version);
 
+
+	/* Enable Master/IO access, Disable memory access */
+	err = pci_enable_device(pdev);
+	if (err)
+		goto err_out_free;
+
+	pci_set_power_state(pdev, PCI_D0);
+
 	/* Init network device */
 	dev = alloc_etherdev(sizeof(*db));
-	if (dev == NULL)
-		return -ENOMEM;
+	if (dev == NULL) {
+		err = -ENOMEM;
+		goto err_out_disable;
+	}
+
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
@@ -277,11 +351,6 @@ static int __devinit uli526x_init_one (s
 		goto err_out_free;
 	}
 
-	/* Enable Master/IO access, Disable memory access */
-	err = pci_enable_device(pdev);
-	if (err)
-		goto err_out_free;
-
 	if (!pci_resource_start(pdev, 0)) {
 		printk(KERN_ERR DRV_NAME ": I/O base is zero\n");
 		err = -ENODEV;
@@ -303,19 +372,9 @@ static int __devinit uli526x_init_one (s
 	/* Init system & device */
 	db = netdev_priv(dev);
 
-	/* Allocate Tx/Rx descriptor memory */
-	db->desc_pool_ptr = pci_alloc_consistent(pdev, sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20, &db->desc_pool_dma_ptr);
-	if(db->desc_pool_ptr == NULL)
-	{
-		err = -ENOMEM;
-		goto err_out_nomem;
-	}
-	db->buf_pool_ptr = pci_alloc_consistent(pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4, &db->buf_pool_dma_ptr);
-	if(db->buf_pool_ptr == NULL)
-	{
-		err = -ENOMEM;
+	err = uli526x_get_resources(db);
+	if (err)
 		goto err_out_nomem;
-	}
 	
 	db->first_tx_desc = (struct tx_desc *) db->desc_pool_ptr;
 	db->first_tx_desc_dma = db->desc_pool_dma_ptr;
@@ -341,34 +400,8 @@ static int __devinit uli526x_init_one (s
 	dev->ethtool_ops = &netdev_ethtool_ops;
 	spin_lock_init(&db->lock);
 
-		
-	/* read 64 word srom data */
-	for (i = 0; i < 64; i++)
-		((u16 *) db->srom)[i] = cpu_to_le16(read_srom_word(db->ioaddr, i));
+	do_reset(dev);
 
-	/* Set Node address */
-	if(((u16 *) db->srom)[0] == 0xffff || ((u16 *) db->srom)[0] == 0)		/* SROM absent, so read MAC address from ID Table */
-	{
-		outl(0x10000, db->ioaddr + DCR0);	//Diagnosis mode
-		outl(0x1c0, db->ioaddr + DCR13);	//Reset dianostic pointer port
-		outl(0, db->ioaddr + DCR14);		//Clear reset port
-		outl(0x10, db->ioaddr + DCR14);		//Reset ID Table pointer
-		outl(0, db->ioaddr + DCR14);		//Clear reset port
-		outl(0, db->ioaddr + DCR13);		//Clear CR13
-		outl(0x1b0, db->ioaddr + DCR13);	//Select ID Table access port
-		//Read MAC address from CR14
-		for (i = 0; i < 6; i++)
-			dev->dev_addr[i] = inl(db->ioaddr + DCR14);
-		//Read end
-		outl(0, db->ioaddr + DCR13);	//Clear CR13
-		outl(0, db->ioaddr + DCR0);		//Clear CR0
-		udelay(10);
-	}
-	else		/*Exist SROM*/
-	{
-		for (i = 0; i < 6; i++)
-			dev->dev_addr[i] = db->srom[20 + i];
-	}
 	err = register_netdev (dev);
 	if (err)
 		goto err_out_res;
@@ -379,25 +412,34 @@ static int __devinit uli526x_init_one (s
 		printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]);
 	printk(", irq %d.\n", dev->irq);
 
+	pci_set_power_state(pdev, PCI_D0);
+
 	pci_set_master(pdev);
 
+	printk("Register 0 is %x.\n", inl(db->ioaddr));
+	printk("Register 3 is %x.\n", inl(db->ioaddr + 0x18));
+	printk("Register 4 is %x.\n", inl(db->ioaddr + 0x20));
+	printk("Register 5 is %x.\n", inl(db->ioaddr + 0x28));
+	printk("Register 6 is %x.\n", inl(db->ioaddr + 0x30));
+	printk("Register 7 is %x.\n", inl(db->ioaddr + 0x38));
+	printk("Register 8 is %x.\n", inl(db->ioaddr + 0x40));
+	printk("Register 9 is %x.\n", inl(db->ioaddr + 0x48));
+	printk("Register 10 is %x.\n", inl(db->ioaddr + 0x50));
+	printk("Register 11 is %x.\n", inl(db->ioaddr + 0x58));
+	printk("Register 12 is %x.\n", inl(db->ioaddr + 0x60));
+	printk("Register 15 is %x.\n", inl(db->ioaddr + 0x78));
 	return 0;
 
 err_out_res:
 	pci_release_regions(pdev);
 err_out_nomem:
-	if(db->desc_pool_ptr)
-		pci_free_consistent(pdev, sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20,
-			db->desc_pool_ptr, db->desc_pool_dma_ptr);
-			
-	if(db->buf_pool_ptr != NULL)
-		pci_free_consistent(pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4,
-			db->buf_pool_ptr, db->buf_pool_dma_ptr);
+	uli526x_free_resources(db);
 err_out_disable:
 	pci_disable_device(pdev);
 err_out_free:
 	pci_set_drvdata(pdev, NULL);
-	free_netdev(dev);
+	if (dev)
+		free_netdev(dev);
 
 	return err;
 }
@@ -410,15 +452,19 @@ static void __devexit uli526x_remove_one
 
 	ULI526X_DBUG(0, "uli526x_remove_one()", 0);
 
-	pci_free_consistent(db->pdev, sizeof(struct tx_desc) *
-				DESC_ALL_CNT + 0x20, db->desc_pool_ptr,
- 				db->desc_pool_dma_ptr);
-	pci_free_consistent(db->pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4,
-				db->buf_pool_ptr, db->buf_pool_dma_ptr);
+	//20060306 - Uncommented
+	//netif_poll_disable(dev);
+	
+	//netif_stop_queue(dev);
 	unregister_netdev(dev);
-	pci_release_regions(pdev);
+	uli526x_free_resources(db);
 	free_netdev(dev);	/* free board information */
+	
+	//20060306 - Uncommented
+	//pci_iounmap(pdev, (void *) dev->base_addr);
+	pci_release_regions(pdev);
 	pci_set_drvdata(pdev, NULL);
+	pci_set_power_state(pdev, PCI_D3hot);
 	pci_disable_device(pdev);
 	ULI526X_DBUG(0, "uli526x_remove_one() exit", 0);
 }
@@ -435,6 +481,7 @@ static int uli526x_open(struct net_devic
 	struct uli526x_board_info *db = netdev_priv(dev);
 	
 	ULI526X_DBUG(0, "uli526x_open", 0);
+	printk("uli526x_open\n");
 
 	ret = request_irq(dev->irq, &uli526x_interrupt, SA_SHIRQ, dev->name, dev);
 	if (ret)
@@ -443,6 +490,7 @@ static int uli526x_open(struct net_devic
 	/* system variable init */
 	db->cr6_data = CR6_DEFAULT | uli526x_cr6_user_set;
 	db->tx_packet_cnt = 0;
+	//ULI526X_DBUG(0, "db->tx_packet_cnt reset to %d.", db->tx_packet_cnt);
 	db->rx_avail_cnt = 0;
 	db->link_failed = 1;
 	netif_carrier_off(dev);
@@ -488,6 +536,7 @@ static void uli526x_init(struct net_devi
 	u16 phy_reg_reset;
 
 	ULI526X_DBUG(0, "uli526x_init()", 0);
+	printk("uli526x_init\n");
 
 	/* Reset M526x MAC controller */
 	outl(ULI526X_RESET, ioaddr + DCR0);	/* RESET MAC */
@@ -557,7 +606,7 @@ static int uli526x_start_xmit(struct sk_
 	struct tx_desc *txptr;
 	unsigned long flags;
 
-	ULI526X_DBUG(0, "uli526x_start_xmit", 0);
+	//ULI526X_DBUG(0, "uli526x_start_xmit", 0);
 
 	/* Resource flag check */
 	netif_stop_queue(dev);
@@ -593,6 +642,7 @@ static int uli526x_start_xmit(struct sk_
 	if ( (db->tx_packet_cnt < TX_DESC_CNT) ) {
 		txptr->tdes0 = cpu_to_le32(0x80000000);	/* Set owner bit */
 		db->tx_packet_cnt++;			/* Ready to send */
+		//ULI526X_DBUG(0, "db->tx_packet_cnt = %d.", db->tx_packet_cnt);
 		outl(0x1, dev->base_addr + DCR1);	/* Issue Tx polling */
 		dev->trans_start = jiffies;		/* saved time stamp */
 	}
@@ -638,6 +688,8 @@ static int uli526x_stop(struct net_devic
 	/* free interrupt */
 	free_irq(dev->irq, dev);
 
+	netif_carrier_off(dev);
+
 	/* free allocated rx buffer */
 	uli526x_free_rxbuffer(db);
 
@@ -678,6 +730,7 @@ static irqreturn_t uli526x_interrupt(int
 	db->cr5_data = inl(ioaddr + DCR5);
 	outl(db->cr5_data, ioaddr + DCR5);
 	if ( !(db->cr5_data & 0x180c1) ) {
+		ULI526X_DBUG(1, "Earlier return. CR5=", db->cr5_data);
 		spin_unlock_irqrestore(&db->lock, flags);
 		outl(db->cr7_data, ioaddr + DCR7);
 		return IRQ_HANDLED;
@@ -698,7 +751,7 @@ static irqreturn_t uli526x_interrupt(int
 		uli526x_rx_packet(dev, db);
 
 	/* reallocate rx descriptor buffer */
-	if (db->rx_avail_cnt<RX_DESC_CNT)
+	if (db->rx_avail_cnt < RX_DESC_CNT)
 		allocate_rx_buffer(db);
 
 	/* Free the transmitted descriptor */
@@ -729,8 +782,10 @@ static void uli526x_free_tx_pkt(struct n
 		if (tdes0 & 0x80000000)
 			break;
 
+		//ULI526X_DBUG(0, "Free tx pkt.\n", NULL);
 		/* A packet sent completed */
 		db->tx_packet_cnt--;
+		//ULI526X_DBUG(0, "db->tx_packet_cnt = %d.", db->tx_packet_cnt);
 		db->stats.tx_packets++;
 
 		/* Transmit statistic counter */
@@ -788,10 +843,9 @@ static void uli526x_rx_packet(struct net
 	while(db->rx_avail_cnt) {
 		rdes0 = le32_to_cpu(rxptr->rdes0);
 		if (rdes0 & 0x80000000)	/* packet owner check */
-		{
 			break;
-		}
 
+		//ULI526X_DBUG(0, "rx pkt.", NULL);
 		db->rx_avail_cnt--;
 		db->interval_rx_cnt++;
 
@@ -799,7 +853,7 @@ static void uli526x_rx_packet(struct net
 		if ( (rdes0 & 0x300) != 0x300) {
 			/* A packet without First/Last flag */
 			/* reuse this SKB */
-			ULI526X_DBUG(0, "Reuse SK buffer, rdes0", rdes0);
+			//ULI526X_DBUG(0, "Reuse SK buffer, rdes0", rdes0);
 			uli526x_reuse_skb(db, rxptr->rx_skb_ptr);
 		} else {
 			/* A packet with First/Last flag */
@@ -808,7 +862,7 @@ static void uli526x_rx_packet(struct net
 			/* error summary bit check */
 			if (rdes0 & 0x8000) {
 				/* This is a error packet */
-				//printk(DRV_NAME ": rdes0: %lx\n", rdes0);
+				printk(DRV_NAME ": rdes0: %x\n", rdes0);
 				db->stats.rx_errors++;
 				if (rdes0 & 1)
 					db->stats.rx_fifo_errors++;
@@ -844,7 +898,7 @@ static void uli526x_rx_packet(struct net
 				
 			} else {
 				/* Reuse SKB buffer when the packet is error */
-				ULI526X_DBUG(0, "Reuse SK buffer, rdes0", rdes0);
+				//ULI526X_DBUG(0, "Reuse SK buffer, rdes0", rdes0);
 				uli526x_reuse_skb(db, rxptr->rx_skb_ptr);
 			}
 		}
@@ -864,7 +918,7 @@ static struct net_device_stats * uli526x
 {
 	struct uli526x_board_info *db = netdev_priv(dev);
 
-	ULI526X_DBUG(0, "uli526x_get_stats", 0);
+	//ULI526X_DBUG(0, "uli526x_get_stats", 0);
 	return &db->stats;
 }
 
@@ -878,11 +932,11 @@ static void uli526x_set_filter_mode(stru
 	struct uli526x_board_info *db = dev->priv;
 	unsigned long flags;
 
-	ULI526X_DBUG(0, "uli526x_set_filter_mode()", 0);
+	//ULI526X_DBUG(0, "uli526x_set_filter_mode()", 0);
 	spin_lock_irqsave(&db->lock, flags);
 
 	if (dev->flags & IFF_PROMISC) {
-		ULI526X_DBUG(0, "Enable PROM Mode", 0);
+		//ULI526X_DBUG(0, "Enable PROM Mode", 0);
 		db->cr6_data |= CR6_PM | CR6_PBF;
 		update_cr6(db->cr6_data, db->ioaddr);
 		spin_unlock_irqrestore(&db->lock, flags);
@@ -890,14 +944,14 @@ static void uli526x_set_filter_mode(stru
 	}
 
 	if (dev->flags & IFF_ALLMULTI || dev->mc_count > ULI5261_MAX_MULTICAST) {
-		ULI526X_DBUG(0, "Pass all multicast address", dev->mc_count);
+		//ULI526X_DBUG(0, "Pass all multicast address", dev->mc_count);
 		db->cr6_data &= ~(CR6_PM | CR6_PBF);
 		db->cr6_data |= CR6_PAM;
 		spin_unlock_irqrestore(&db->lock, flags);
 		return;
 	}
 
-	ULI526X_DBUG(0, "Set multicast address", dev->mc_count);
+	//ULI526X_DBUG(0, "Set multicast address", dev->mc_count);
 	send_filter_frame(dev, dev->mc_count); 	/* M5261/M5263 */
 	spin_unlock_irqrestore(&db->lock, flags);
 }
@@ -1005,6 +1059,7 @@ static void uli526x_timer(unsigned long 
 	struct uli526x_board_info *db = netdev_priv(dev);
  	unsigned long flags;
 	u8 TmpSpeed=10;
+	int link_status = 0;
 	
 	//ULI526X_DBUG(0, "uli526x_timer()", 0);
 	spin_lock_irqsave(&db->lock, flags);
@@ -1023,6 +1078,7 @@ static void uli526x_timer(unsigned long 
 	     time_after(jiffies, dev->trans_start + ULI526X_TX_KICK) ) {
 		outl(0x1, dev->base_addr + DCR1);   // Tx polling again 
 
+		//ULI526X_DBUG(0, "db->tx_packet_cnt = %d.", db->tx_packet_cnt);
 		// TX Timeout 
 		if ( time_after(jiffies, dev->trans_start + ULI526X_TX_TIMEOUT) ) {
 			db->reset_TXtimeout++;
@@ -1043,7 +1099,9 @@ static void uli526x_timer(unsigned long 
 	}
 
 	/* Link status check, Dynamic media type change */
-	if((phy_read(db->ioaddr, db->phy_addr, 5, db->chip_id) & 0x01e0)!=0)
+	link_status = phy_read(db->ioaddr, db->phy_addr, 5, db->chip_id);
+	//ULI526X_DBUG(0, "Link status is ", link_status);
+	if (link_status & 0x1e0)
 		tmp_cr12 = 3;
 
 	if ( !(tmp_cr12 & 0x3) && !db->link_failed ) {
@@ -1065,7 +1123,7 @@ static void uli526x_timer(unsigned long 
 		}
 	} else
 		if ((tmp_cr12 & 0x3) && db->link_failed) {
-			ULI526X_DBUG(0, "Link link OK", tmp_cr12);
+			//ULI526X_DBUG(0, "Link link OK", tmp_cr12);
 			db->link_failed = 0;
 
 			/* Auto Sense Speed */
@@ -1137,6 +1195,7 @@ static void uli526x_dynamic_reset(struct
 
 	/* system variable init */
 	db->tx_packet_cnt = 0;
+	ULI526X_DBUG(0, "db->tx_packet_cnt reset to ", db->tx_packet_cnt);
 	db->rx_avail_cnt = 0;
 	db->link_failed = 1;
 	db->init=1;
@@ -1156,11 +1215,12 @@ static void uli526x_dynamic_reset(struct
 
 static void uli526x_free_rxbuffer(struct uli526x_board_info * db)
 {
-	ULI526X_DBUG(0, "uli526x_free_rxbuffer()", 0);
+	//ULI526X_DBUG(0, "uli526x_free_rxbuffer()", 0);
 
 	/* free allocated rx buffer */
 	while (db->rx_avail_cnt) {
-		dev_kfree_skb(db->rx_ready_ptr->rx_skb_ptr);
+		if (db->rx_ready_ptr->rx_skb_ptr)
+			dev_kfree_skb(db->rx_ready_ptr->rx_skb_ptr);
 		db->rx_ready_ptr = db->rx_ready_ptr->next_rx_desc;
 		db->rx_avail_cnt--;
 	}
@@ -1277,7 +1337,7 @@ static void send_filter_frame(struct net
 	u32 * suptr;
 	int i;
 
-	ULI526X_DBUG(0, "send_filter_frame()", 0);
+	//ULI526X_DBUG(0, "send_filter_frame()", 0);
 
 	txptr = db->tx_insert_ptr;
 	suptr = (u32 *) txptr->tx_buf_ptr;
@@ -1669,6 +1729,117 @@ static u16 phy_read_1bit(unsigned long i
 	return phy_data;
 }
 
+#ifdef CONFIG_PM
+
+#if 0
+static void uli526x_set_power_state (
+		struct uli526x_board_info *deb,
+		   int sleep, int snooze)
+{
+	if (tp->flags & HAS_ACPI) {
+		u32 tmp, newtmp;
+		pci_read_config_dword (tp->pdev, CFDD, &tmp);
+		newtmp = tmp & ~(CFDD_Sleep | CFDD_Snooze);
+		if (sleep)
+			newtmp |= CFDD_Sleep;
+		else if (snooze)
+			newtmp |= CFDD_Snooze;
+		if (tmp != newtmp)
+			pci_write_config_dword (tp->pdev, CFDD, newtmp);
+	}
+
+}
+#endif
+
+static u32 *dcr_save;
+
+static int uli526x_suspend (struct pci_dev *pdev, pm_message_t state)
+{
+	struct net_device *dev = pci_get_drvdata (pdev);
+	struct uli526x_board_info *db = netdev_priv(dev);
+	unsigned long ioaddr = db->ioaddr;
+	unsigned long flags;
+	int i;
+
+	if (!dev)
+	       return -EINVAL;
+
+	if (netif_running(dev))
+		netif_stop_queue(dev);
+	
+	netif_device_detach(dev);
+
+	spin_lock_irqsave(&db->lock, flags);
+
+	/* Disable interrupts, stop Tx and Rx. */
+	outl(0, ioaddr + DCR7);
+	db->cr6_data &= ~(CR6_RXSC | CR6_TXSC);
+	update_cr6(db->cr6_data, ioaddr);
+
+	dcr_save = kmalloc(sizeof(u32) * 16, GFP_ATOMIC);
+	for (i=0; i<16; i++)
+		dcr_save[i] = inl(ioaddr + i);
+
+	//phy_write_1bit(ioaddr, PHY_POWER_DOWN, chip_id);
+
+	spin_unlock_irqrestore(&db->lock, flags);
+
+	pci_save_state(pdev);
+
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev,
+		pci_choose_state(pdev, state));
+
+	return 0;
+}
+
+
+static int uli526x_resume (struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata (pdev);
+	struct uli526x_board_info *db = netdev_priv(dev);
+	unsigned long ioaddr = db->ioaddr;
+	u32 val;
+	int i;
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	pci_enable_device(pdev);
+
+	netif_device_attach(dev);
+
+	if (!netif_running(dev))
+		return 0;
+
+	pci_set_master(pdev);
+	
+	pci_read_config_dword(pdev, 0x40, &val);
+	if ((val & 0x0000ff00) != 0)
+		pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+	
+	for (i=0; i<16; i++)
+		outl(ioaddr+i, dcr_save[i]);
+
+	kfree(dcr_save);
+	dcr_save = NULL;
+
+	db->tx_packet_cnt = 0;
+	db->first_tx_desc = (struct tx_desc *) db->desc_pool_ptr;
+	db->first_tx_desc_dma = db->desc_pool_dma_ptr;
+	db->buf_pool_start = db->buf_pool_ptr;
+	db->buf_pool_dma_start = db->buf_pool_dma_ptr;
+
+	do_reset(dev);
+
+	uli526x_get_resources(db);
+	
+	uli526x_init(dev);
+
+	return 0;
+}
+
+#endif /* CONFIG_PM */
+
 
 static struct pci_device_id uli526x_pci_tbl[] = {
 	{ 0x10B9, 0x5261, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PCI_ULI5261_ID },
@@ -1683,6 +1854,10 @@ static struct pci_driver uli526x_driver 
 	.id_table	= uli526x_pci_tbl,
 	.probe		= uli526x_init_one,
 	.remove		= __devexit_p(uli526x_remove_one),
+#ifdef CONFIG_PM
+	.suspend	= uli526x_suspend,
+	.resume		= uli526x_resume,
+#endif /* CONFIG_PM */
 };
 
 MODULE_AUTHOR("Peer Chen, peer.chen@uli.com.tw");

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

  reply	other threads:[~2006-03-28 21:49 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-01-26  8:00 Issues with uli526x networking module Prakash Punnoor
2006-01-26 11:10 ` Nigel Cunningham
2006-03-28 17:30   ` Prakash Punnoor
2006-03-28 21:47     ` Nigel Cunningham [this message]
2006-04-04 14:15       ` Prakash Punnoor
2006-04-06  3:24         ` Nigel Cunningham

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200603290747.38402.ncunningham@cyclades.com \
    --to=ncunningham@cyclades.com \
    --cc=jgarzik@pobox.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=prakash@punnoor.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox