patch-2.4.7 linux/drivers/net/sis900.c

Next file: linux/drivers/net/sis900.h
Previous file: linux/drivers/net/setup.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.6/linux/drivers/net/sis900.c linux/drivers/net/sis900.c
@@ -150,8 +150,11 @@
 	/* The saved address of a sent/receive-in-place packet buffer */
 	struct sk_buff *tx_skbuff[NUM_TX_DESC];
 	struct sk_buff *rx_skbuff[NUM_RX_DESC];
-	BufferDesc tx_ring[NUM_TX_DESC];
-	BufferDesc rx_ring[NUM_RX_DESC];
+	BufferDesc *tx_ring;
+	BufferDesc *rx_ring;
+
+	dma_addr_t tx_ring_dma;
+	dma_addr_t rx_ring_dma;
 
 	unsigned int tx_full;			/* The Tx queue is full.    */
 };
@@ -309,6 +312,8 @@
 {
 	struct sis900_private *sis_priv;
 	struct net_device *net_dev;
+	dma_addr_t ring_dma;
+	void *ring_space;
 	long ioaddr;
 	int i, ret;
 	u8 revision;
@@ -353,6 +358,22 @@
 
 	pci_set_drvdata(pci_dev, net_dev);
 
+	ring_space = pci_alloc_consistent(pci_dev, TX_TOTAL_SIZE, &ring_dma);
+	if (!ring_space) {
+		ret = -ENOMEM;
+		goto err_out_cleardev;
+	}
+	sis_priv->tx_ring = (BufferDesc *)ring_space;
+	sis_priv->tx_ring_dma = ring_dma;
+
+	ring_space = pci_alloc_consistent(pci_dev, RX_TOTAL_SIZE, &ring_dma);
+	if (!ring_space) {
+		ret = -ENOMEM;
+		goto err_unmap_tx;
+	}
+	sis_priv->rx_ring = (BufferDesc *)ring_space;
+	sis_priv->rx_ring_dma = ring_dma;
+		
 	/* The SiS900-specific entries in the device structure. */
 	net_dev->open = &sis900_open;
 	net_dev->hard_start_xmit = &sis900_start_xmit;
@@ -366,7 +387,7 @@
 	
 	ret = register_netdev(net_dev);
 	if (ret)
-		goto err_out_cleardev;
+		goto err_unmap_rx;
 		
 	/* Get Mac address according to the chip revision */
 	pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision);
@@ -401,6 +422,12 @@
 
  err_out_unregister:
  	unregister_netdev(net_dev);
+ err_unmap_rx:
+	pci_free_consistent(pci_dev, RX_TOTAL_SIZE, sis_priv->rx_ring,
+		sis_priv->rx_ring_dma);
+ err_unmap_tx:
+	pci_free_consistent(pci_dev, TX_TOTAL_SIZE, sis_priv->tx_ring,
+		sis_priv->tx_ring_dma);
  err_out_cleardev:
  	pci_set_drvdata(pci_dev, NULL);
 	pci_release_regions(pci_dev);
@@ -808,7 +835,7 @@
 {
 	struct sis900_private *sis_priv = net_dev->priv;
 	long ioaddr = net_dev->base_addr;
-	u8  revision;
+	u8 revision;
 	int ret;
 
 	/* Soft reset the chip. */
@@ -907,14 +934,14 @@
 	for (i = 0; i < NUM_TX_DESC; i++) {
 		sis_priv->tx_skbuff[i] = NULL;
 
-		sis_priv->tx_ring[i].link = (u32) virt_to_bus(&sis_priv->tx_ring[i+1]);
+		sis_priv->tx_ring[i].link = sis_priv->tx_ring_dma +
+			((i+1)%NUM_TX_DESC)*sizeof(BufferDesc);
 		sis_priv->tx_ring[i].cmdsts = 0;
 		sis_priv->tx_ring[i].bufptr = 0;
 	}
-	sis_priv->tx_ring[i-1].link = (u32) virt_to_bus(&sis_priv->tx_ring[0]);
 
 	/* load Transmit Descriptor Register */
-	outl(virt_to_bus(&sis_priv->tx_ring[0]), ioaddr + txdp);
+	outl(sis_priv->tx_ring_dma, ioaddr + txdp);
 	if (sis900_debug > 2)
 		printk(KERN_INFO "%s: TX descriptor register loaded with: %8.8x\n",
 		       net_dev->name, inl(ioaddr + txdp));
@@ -942,11 +969,11 @@
 	for (i = 0; i < NUM_RX_DESC; i++) {
 		sis_priv->rx_skbuff[i] = NULL;
 
-		sis_priv->rx_ring[i].link = (u32) virt_to_bus(&sis_priv->rx_ring[i+1]);
+		sis_priv->rx_ring[i].link = sis_priv->rx_ring_dma +
+			((i+1)%NUM_RX_DESC)*sizeof(BufferDesc);
 		sis_priv->rx_ring[i].cmdsts = 0;
 		sis_priv->rx_ring[i].bufptr = 0;
 	}
-	sis_priv->rx_ring[i-1].link = (u32) virt_to_bus(&sis_priv->rx_ring[0]);
 
 	/* allocate sock buffers */
 	for (i = 0; i < NUM_RX_DESC; i++) {
@@ -962,12 +989,13 @@
 		skb->dev = net_dev;
 		sis_priv->rx_skbuff[i] = skb;
 		sis_priv->rx_ring[i].cmdsts = RX_BUF_SIZE;
-		sis_priv->rx_ring[i].bufptr = virt_to_bus(skb->tail);
+                sis_priv->rx_ring[i].bufptr = pci_map_single(sis_priv->pci_dev,
+                        skb->tail, RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
 	}
 	sis_priv->dirty_rx = (unsigned int) (i - NUM_RX_DESC);
 
 	/* load Receive Descriptor Register */
-	outl(virt_to_bus(&sis_priv->rx_ring[0]), ioaddr + rxdp);
+	outl(sis_priv->rx_ring_dma, ioaddr + rxdp);
 	if (sis900_debug > 2)
 		printk(KERN_INFO "%s: RX descriptor register loaded with: %8.8x\n",
 		       net_dev->name, inl(ioaddr + rxdp));
@@ -1012,7 +1040,8 @@
 	       revision == SIS630A_900_REV) )
 		return;
 
-	if ((dev = pci_find_device(SIS630_VENDOR_ID, SIS630_DEVICE_ID, dev)))
+	dev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630, dev);
+	if (dev)
 		pci_read_config_byte(dev, PCI_CLASS_REVISION, &host_bridge_rev);
 
 	if (netif_carrier_ok(net_dev)) {
@@ -1320,8 +1349,13 @@
 	/* discard unsent packets */
 	sis_priv->dirty_tx = sis_priv->cur_tx = 0;
 	for (i = 0; i < NUM_TX_DESC; i++) {
-		if (sis_priv->tx_skbuff[i] != NULL) {
-			dev_kfree_skb(sis_priv->tx_skbuff[i]);
+		struct sk_buff *skb = sis_priv->tx_skbuff[i];
+
+		if (skb) {
+			pci_unmap_single(sis_priv->pci_dev, 
+				sis_priv->tx_ring[i].bufptr, skb->len,
+				PCI_DMA_TODEVICE);
+			dev_kfree_skb(skb);
 			sis_priv->tx_skbuff[i] = 0;
 			sis_priv->tx_ring[i].cmdsts = 0;
 			sis_priv->tx_ring[i].bufptr = 0;
@@ -1368,7 +1402,8 @@
 	sis_priv->tx_skbuff[entry] = skb;
 
 	/* set the transmit buffer descriptor and enable Transmit State Machine */
-	sis_priv->tx_ring[entry].bufptr = virt_to_bus(skb->data);
+	sis_priv->tx_ring[entry].bufptr = pci_map_single(sis_priv->pci_dev,
+		skb->data, skb->len, PCI_DMA_TODEVICE);
 	sis_priv->tx_ring[entry].cmdsts = (OWN | skb->len);
 	outl(TxENA, ioaddr + cr);
 
@@ -1509,7 +1544,13 @@
 				break;
 			}
 
-			/* gvie the socket buffer to upper layers */
+			pci_dma_sync_single(sis_priv->pci_dev, 
+				sis_priv->rx_ring[entry].bufptr, RX_BUF_SIZE, 
+				PCI_DMA_FROMDEVICE);
+			pci_unmap_single(sis_priv->pci_dev, 
+				sis_priv->rx_ring[entry].bufptr, RX_BUF_SIZE, 
+				PCI_DMA_FROMDEVICE);
+			/* give the socket buffer to upper layers */
 			skb = sis_priv->rx_skbuff[entry];
 			skb_put(skb, rx_size);
 			skb->protocol = eth_type_trans(skb, net_dev);
@@ -1542,7 +1583,9 @@
 			skb->dev = net_dev;
 			sis_priv->rx_skbuff[entry] = skb;
 			sis_priv->rx_ring[entry].cmdsts = RX_BUF_SIZE;
-			sis_priv->rx_ring[entry].bufptr = virt_to_bus(skb->tail);
+                	sis_priv->rx_ring[entry].bufptr = 
+				pci_map_single(sis_priv->pci_dev, skb->tail, 
+					RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
 			sis_priv->dirty_rx++;
 		}
 		sis_priv->cur_rx++;
@@ -1572,7 +1615,9 @@
 			skb->dev = net_dev;
 			sis_priv->rx_skbuff[entry] = skb;
 			sis_priv->rx_ring[entry].cmdsts = RX_BUF_SIZE;
-			sis_priv->rx_ring[entry].bufptr = virt_to_bus(skb->tail);
+                	sis_priv->rx_ring[entry].bufptr =
+				pci_map_single(sis_priv->pci_dev, skb->tail,
+					RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
 		}
 	}
 	/* re-enable the potentially idle receive state matchine */
@@ -1596,6 +1641,7 @@
 	struct sis900_private *sis_priv = net_dev->priv;
 
 	for (; sis_priv->dirty_tx < sis_priv->cur_tx; sis_priv->dirty_tx++) {
+		struct sk_buff *skb;
 		unsigned int entry;
 		u32 tx_status;
 
@@ -1631,7 +1677,11 @@
 			sis_priv->stats.tx_packets++;
 		}
 		/* Free the original skb. */
-		dev_kfree_skb_irq(sis_priv->tx_skbuff[entry]);
+		skb = sis_priv->tx_skbuff[entry];
+		pci_unmap_single(sis_priv->pci_dev, 
+			sis_priv->tx_ring[entry].bufptr, skb->len,
+			PCI_DMA_TODEVICE);
+		dev_kfree_skb_irq(skb);
 		sis_priv->tx_skbuff[entry] = NULL;
 		sis_priv->tx_ring[entry].bufptr = 0;
 		sis_priv->tx_ring[entry].cmdsts = 0;
@@ -1659,6 +1709,7 @@
 {
 	long ioaddr = net_dev->base_addr;
 	struct sis900_private *sis_priv = net_dev->priv;
+	struct sk_buff *skb;
 	int i;
 
 	netif_stop_queue(net_dev);
@@ -1676,14 +1727,24 @@
 
 	/* Free Tx and RX skbuff */
 	for (i = 0; i < NUM_RX_DESC; i++) {
-		if (sis_priv->rx_skbuff[i] != NULL)
-			dev_kfree_skb(sis_priv->rx_skbuff[i]);
-		sis_priv->rx_skbuff[i] = 0;
+		skb = sis_priv->rx_skbuff[i];
+		if (skb) {
+			pci_unmap_single(sis_priv->pci_dev, 
+				sis_priv->rx_ring[i].bufptr,
+				RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+			dev_kfree_skb(skb);
+			sis_priv->rx_skbuff[i] = 0;
+		}
 	}
 	for (i = 0; i < NUM_TX_DESC; i++) {
-		if (sis_priv->tx_skbuff[i] != NULL)
-			dev_kfree_skb(sis_priv->tx_skbuff[i]);
-		sis_priv->tx_skbuff[i] = 0;
+		skb = sis_priv->tx_skbuff[i];
+		if (skb) {
+			pci_unmap_single(sis_priv->pci_dev, 
+				sis_priv->tx_ring[i].bufptr, skb->len,
+				PCI_DMA_TODEVICE);
+			dev_kfree_skb(skb);
+			sis_priv->tx_skbuff[i] = 0;
+		}
 	}
 
 	/* Green! Put the chip in low-power mode. */
@@ -2007,6 +2068,10 @@
 		kfree(phy);
 	}
 
+	pci_free_consistent(pci_dev, RX_TOTAL_SIZE, sis_priv->rx_ring,
+		sis_priv->rx_ring_dma);
+	pci_free_consistent(pci_dev, TX_TOTAL_SIZE, sis_priv->tx_ring,
+		sis_priv->tx_ring_dma);
 	unregister_netdev(net_dev);
 	kfree(net_dev);
 	pci_release_regions(pci_dev);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)