From ec73a0c5afc56d551a67fb9932f813e5e9dd1d44 Mon Sep 17 00:00:00 2001
From: Jeff Garzik <jgarzik@redhat.com>
Date: Sun, 20 Apr 2003 04:10:07 -0400
Subject: [PATCH] Modernize rcpci45 I2O LAN driver (#204): * Convert to PCI DMA
 mapping API (Francios Romieu).  Gets driver   compiling again.  Fixes
 bugzilla bug #204. * use SET_MODULE_OWNER * remove MOD_*_USE_COUNT from all
 but one place   (and add FIXME to that one place) * fix printk in rclanmtl.c,
 though more work is needed

---
 drivers/net/rclanmtl.c |  8 ++--
 drivers/net/rclanmtl.h |  3 +-
 drivers/net/rcpci45.c  | 97 ++++++++++++++++++++++++------------------
 3 files changed, 62 insertions(+), 46 deletions(-)

diff --git a/drivers/net/rclanmtl.c b/drivers/net/rclanmtl.c
index 834d670df2c0..d763dd8a636a 100644
--- a/drivers/net/rclanmtl.c
+++ b/drivers/net/rclanmtl.c
@@ -301,13 +301,13 @@ RCInitI2OMsgLayer (struct net_device *dev,
 	PPAB pPab;
 	U32 pciBaseAddr = dev->base_addr;
 	PDPA pDpa = dev->priv;
-	PU8 p_msgbuf = pDpa->PLanApiPA;
-	PU8 p_phymsgbuf = (PU8) virt_to_bus ((void *) p_msgbuf);
+	PU8 p_msgbuf = pDpa->msgbuf;
+	PU8 p_phymsgbuf = (PU8) pDpa->msgbuf_dma;
 
 	dprintk
-	    ("InitI2O: Adapter:0x%04ux ATU:0x%08ulx msgbuf:0x%08ulx phymsgbuf:0x%08ulx\n"
+	    ("InitI2O: Adapter:0x%04ux ATU:0x%08ulx msgbuf:%p phymsgbuf:0x%08ulx\n"
 	     "TransmitCallbackFunction:0x%08ulx  ReceiveCallbackFunction:0x%08ulx\n",
-	     pDpa->id, pciBaseAddr, (u32) p_msgbuf, (u32) p_phymsgbuf,
+	     pDpa->id, pciBaseAddr, p_msgbuf, (u32) p_phymsgbuf,
 	     (u32) TransmitCallbackFunction, (u32) ReceiveCallbackFunction);
 
 	/* Check if this interface already initialized - if so, shut it down */
diff --git a/drivers/net/rclanmtl.h b/drivers/net/rclanmtl.h
index a65c1d94a83b..4f3568ed3b9f 100644
--- a/drivers/net/rclanmtl.h
+++ b/drivers/net/rclanmtl.h
@@ -182,6 +182,7 @@ typedef struct {
 	U32 pci_addr;		/* the pci address of the adapter */
 	U32 pci_addr_len;
 
+	struct pci_dev *pci_dev;
 	struct timer_list timer;	/*  timer */
 	struct net_device_stats stats;	/* the statistics structure */
 	unsigned long numOutRcvBuffers;	/* number of outstanding receive buffers */
@@ -189,7 +190,7 @@ typedef struct {
 	unsigned char reboot;
 	unsigned char nexus;
 	PU8 msgbuf;		/* Pointer to Lan Api Private Area */
-	PU8 PLanApiPA;		/* Pointer to Lan Api Private Area (aligned) */
+	dma_addr_t msgbuf_dma;
 	PPAB pPab;		/* Pointer to the PCI Adapter Block */
 } *PDPA;
 
diff --git a/drivers/net/rcpci45.c b/drivers/net/rcpci45.c
index a79d44acb804..8c5ce4161902 100644
--- a/drivers/net/rcpci45.c
+++ b/drivers/net/rcpci45.c
@@ -29,6 +29,8 @@
 **  along with this program; if not, write to the Free Software
 **  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 **
+**  Francois Romieu, Apr 2003: Converted to pci DMA mapping API.
+**
 **  Pete Popov, Oct 2001: Fixed a few bugs to make the driver functional
 **  again. Note that this card is not supported or manufactured by 
 **  RedCreek anymore.
@@ -47,8 +49,6 @@
 **
 ***************************************************************************/
 
-#error Please convert me to Documentation/DMA-mapping.txt
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
@@ -66,7 +66,7 @@
 #include <asm/uaccess.h>
 
 static char version[] __initdata =
-    "RedCreek Communications PCI linux driver version 2.20\n";
+    "RedCreek Communications PCI linux driver version 2.21\n";
 
 #define RC_LINUX_MODULE
 #include "rclanmtl.h"
@@ -95,6 +95,12 @@ static char version[] __initdata =
  */
 #define MSG_BUF_SIZE  16384
 
+/* 2003/04/20: I don't know about the hardware ability but the driver won't
+ * play safe with 64 bit addressing and DAC without NETIF_F_HIGHDMA doesn't
+ * really make sense anyway. Let's play safe - romieu.
+ */
+#define RCPCI45_DMA_MASK	((u64) 0xffffffff)
+
 static U32 DriverControlWord;
 
 static void rc_timer (unsigned long);
@@ -136,8 +142,8 @@ rcpci45_remove_one (struct pci_dev *pdev)
 	free_irq (dev->irq, dev);
 	iounmap ((void *) dev->base_addr);
 	pci_release_regions (pdev);
-	if (pDpa->msgbuf)
-		kfree (pDpa->msgbuf);
+	pci_free_consistent (pdev, MSG_BUF_SIZE, pDpa->msgbuf,
+			     pDpa->msgbuf_dma);
 	if (pDpa->pPab)
 		kfree (pDpa->pPab);
 	kfree (dev);
@@ -172,6 +178,7 @@ rcpci45_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 		error = -ENOMEM;
 		goto err_out;
 	}
+	SET_MODULE_OWNER(dev);
 
 	error = pci_enable_device (pdev);
 	if (error) {
@@ -180,7 +187,6 @@ rcpci45_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 			card_idx);
 		goto err_out;
 	}
-	error = -ENOMEM;
 	pci_start = pci_resource_start (pdev, 0);
 	pci_len = pci_resource_len (pdev, 0);
 	printk("pci_start %lx pci_len %lx\n", pci_start, pci_len);
@@ -189,6 +195,7 @@ rcpci45_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	pDpa = dev->priv;
 	pDpa->id = card_idx;
+	pDpa->pci_dev = pdev;
 	pDpa->pci_addr = pci_start;
 
 	if (!pci_start || !(pci_resource_flags (pdev, 0) & IORESOURCE_MEM)) {
@@ -200,24 +207,21 @@ rcpci45_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	/*
 	 * pDpa->msgbuf is where the card will dma the I2O 
-	 * messages. Thus, we need contiguous physical pages of
-	 * memory.
-	 */
-	pDpa->msgbuf = kmalloc (MSG_BUF_SIZE, GFP_DMA | GFP_KERNEL);
+	 * messages. Thus, we need contiguous physical pages of memory.
+	 * 2003/04/20:  pci_alloc_consistent() provides well over the needed
+	 * alignment on a 256 bytes boundary for the LAN API private area.
+	 * Thus it isn't needed anymore to align it by hand.
+         */
+	pDpa->msgbuf = pci_alloc_consistent (pdev, MSG_BUF_SIZE,
+					     &pDpa->msgbuf_dma);
 	if (!pDpa->msgbuf) {
 		printk (KERN_ERR "(rcpci45 driver:) \
 			Could not allocate %d byte memory for the \
 				private msgbuf!\n", MSG_BUF_SIZE);
+		error = -ENOMEM;
 		goto err_out_free_dev;
 	}
 
-	/*
-	 * Save the starting address of the LAN API private area.  We'll
-	 * pass that to RCInitI2OMsgLayer().
-	 *
-	 */
-	pDpa->PLanApiPA = (void *) (((long) pDpa->msgbuf + 0xff) & ~0xff);
-
 	/* The adapter is accessible through memory-access read/write, not
 	 * I/O read/write.  Thus, we need to map it to some virtual address
 	 * area in order to access the registers as normal memory.
@@ -226,12 +230,20 @@ rcpci45_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (error)
 		goto err_out_free_msgbuf;
 
+	error = pci_set_dma_mask (pdev, RCPCI45_DMA_MASK);
+	if (error) {
+		printk (KERN_ERR
+			"(rcpci45 driver:) pci_set_dma_mask failed!\n");
+		goto err_out_free_region;
+	}
+
 	vaddr = (ulong *) ioremap (pci_start, pci_len);
 	if (!vaddr) {
 		printk (KERN_ERR
 			"(rcpci45 driver:) \
 			Unable to remap address range from %lu to %lu\n",
 			pci_start, pci_start + pci_len);
+		error = -EIO;
 		goto err_out_free_region;
 	}
 
@@ -249,13 +261,14 @@ rcpci45_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 err_out_free_region:
 	pci_release_regions (pdev);
 err_out_free_msgbuf:
-	kfree (pDpa->msgbuf);
+	pci_free_consistent (pdev, MSG_BUF_SIZE, pDpa->msgbuf,
+			     pDpa->msgbuf_dma);
 err_out_free_dev:
 	unregister_netdev (dev);
 	kfree (dev);
 err_out:
 	card_idx--;
-	return -ENODEV;
+	return error;
 }
 
 static struct pci_driver rcpci45_driver = {
@@ -283,7 +296,6 @@ RCopen (struct net_device *dev)
 	int requested = 0;
 	int error;
 
-	MOD_INC_USE_COUNT;
 	if (pDpa->nexus) {
 		/* This is not the first time RCopen is called.  Thus,
 		 * the interface was previously opened and later closed
@@ -365,7 +377,6 @@ RCopen (struct net_device *dev)
 err_out_free_irq:
 	free_irq (dev->irq, dev);
 err_out:
-	MOD_DEC_USE_COUNT;
 	return error;
 }
 
@@ -402,7 +413,8 @@ RC_xmit_packet (struct sk_buff *skb, struct net_device *dev)
 	ptcb->b.context = (U32) skb;
 	ptcb->b.scount = 1;
 	ptcb->b.size = skb->len;
-	ptcb->b.addr = virt_to_bus ((void *) skb->data);
+	ptcb->b.addr = pci_map_single(pDpa->pci_dev, skb->data, skb->len,
+				      PCI_DMA_TODEVICE);
 
 	if ((status = RCI2OSendPacket (dev, (U32) NULL, (PRCTCB) ptcb))
 	    != RC_RTN_NO_ERROR) {
@@ -451,6 +463,8 @@ RCxmit_callback (U32 Status,
 	while (PcktCount--) {
 		skb = (struct sk_buff *) (BufferContext[0]);
 		BufferContext++;
+		pci_unmap_single(pDpa->pci_dev, BufferContext[1], skb->len,
+				 PCI_DMA_TODEVICE);
 		dev_kfree_skb_irq (skb);
 	}
 	netif_wake_queue (dev);
@@ -706,6 +720,7 @@ rc_timer (unsigned long data)
 			RCDisableI2OInterrupts (dev);
 			dev->flags &= ~IFF_UP;
 			MOD_DEC_USE_COUNT;
+			/* FIXME: kill MOD_DEC_USE_COUNT, use dev_put */
 		} else {
 			printk (KERN_INFO "%s: rescheduling timer...\n",
 					dev->name);
@@ -731,7 +746,6 @@ RCclose (struct net_device *dev)
 		printk (KERN_INFO "%s skipping reset -- adapter already in reboot mode\n", dev->name);
 		dev->flags &= ~IFF_UP;
 		pDpa->shutdown = 1;
-		MOD_DEC_USE_COUNT;
 		return 0;
 	}
 
@@ -749,7 +763,6 @@ RCclose (struct net_device *dev)
 			   (PFNCALLBACK) RCreset_callback);
 
 	dev->flags &= ~IFF_UP;
-	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
@@ -984,8 +997,9 @@ RC_allocate_and_post_buffers (struct net_device *dev, int numBuffers)
 	PU32 p;
 	psingleB pB;
 	struct sk_buff *skb;
+	PDPA pDpa = dev->priv;
 	RC_RETURN status;
-	U32 res;
+	U32 res = 0;
 
 	if (!numBuffers)
 		return 0;
@@ -1001,7 +1015,7 @@ RC_allocate_and_post_buffers (struct net_device *dev, int numBuffers)
 	if (!p) {
 		printk (KERN_WARNING "%s unable to allocate TCB\n",
 				dev->name);
-		return 0;
+		goto out;
 	}
 
 	p[0] = 0;		/* Buffer Count */
@@ -1013,18 +1027,14 @@ RC_allocate_and_post_buffers (struct net_device *dev, int numBuffers)
 			printk (KERN_WARNING 
 					"%s: unable to allocate enough skbs!\n",
 					dev->name);
-			if (*p != 0) {	/* did we allocate any buffers */
-				break;
-			} else {
-				kfree (p);	/* Free the TCB */
-				return 0;
-			}
+			goto err_out_unmap;
 		}
 		skb_reserve (skb, 2);	/* Align IP on 16 byte boundaries */
 		pB->context = (U32) skb;
 		pB->scount = 1;	/* segment count */
 		pB->size = MAX_ETHER_SIZE;
-		pB->addr = virt_to_bus ((void *) skb->data);
+		pB->addr = pci_map_single(pDpa->pci_dev, skb->data, 
+					  MAX_ETHER_SIZE, PCI_DMA_FROMDEVICE);
 		p[0]++;
 		pB++;
 	}
@@ -1032,16 +1042,21 @@ RC_allocate_and_post_buffers (struct net_device *dev, int numBuffers)
 	if ((status = RCPostRecvBuffers (dev, (PRCTCB) p)) != RC_RTN_NO_ERROR) {
 		printk (KERN_WARNING "%s: Post buffer failed, error 0x%x\n",
 				dev->name, status);
-		/* point to the first buffer */
-		pB = (psingleB) ((U32) p + sizeof (U32));
-		while (p[0]) {
-			skb = (struct sk_buff *) pB->context;
-			dev_kfree_skb (skb);
-			p[0]--;
-			pB++;
-		}
+		goto err_out_unmap;
 	}
+out_free:
 	res = p[0];
 	kfree (p);
+out:
 	return (res);		/* return the number of posted buffers */
+
+err_out_unmap:
+	for (; p[0] > 0; p[0]--) {
+		--pB;
+		skb = (struct sk_buff *) pB->context;
+		pci_unmap_single(pDpa->pci_dev, pB->addr, MAX_ETHER_SIZE,
+				 PCI_DMA_FROMDEVICE);
+		dev_kfree_skb (skb);
+	}
+	goto out_free;
 }
-- 
2.30.9