netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] skfddi - convert to new pci model.
@ 2003-12-05  0:39 Stephen Hemminger
  2003-12-05  0:59 ` Alexander Viro
  0 siblings, 1 reply; 5+ messages in thread
From: Stephen Hemminger @ 2003-12-05  0:39 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: netdev, Alexander Viro

# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.1502  -> 1.1503 
#	drivers/net/skfp/skfddi.c	1.20    -> 1.21   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/12/04	shemminger@osdl.org	1.1503
# Convert skfddi device to 2.6.
#  * use new pci device bus initialization
#  * allocate network device with alloc_fddidev
#    and use dev->priv
#  * get rid of special module/non module distinctions.
#  * fix error unwinds and return values on initialization
# --------------------------------------------
#
diff -Nru a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c
--- a/drivers/net/skfp/skfddi.c	Thu Dec  4 16:36:03 2003
+++ b/drivers/net/skfp/skfddi.c	Thu Dec  4 16:36:03 2003
@@ -58,6 +58,7 @@
  *		07-May-00	DM	64 bit fixes, new dma interface
  *		31-Jul-03	DB	Audit copy_*_user in skfp_ioctl
  *					  Daniele Bellucci <bellucda@tiscali.it>
+ *		03-Dec-03	SH	Convert to PCI device model
  *
  * Compilation options (-Dxxx):
  *              DRIVERDEBUG     print lots of messages to log file
@@ -70,7 +71,7 @@
 
 /* Version information string - should be updated prior to */
 /* each new release!!! */
-#define VERSION		"2.06"
+#define VERSION		"2.07"
 
 static const char *boot_msg = 
 	"SysKonnect FDDI PCI Adapter driver v" VERSION " for\n"
@@ -80,15 +81,11 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/ctype.h>	// isdigit
 #include <linux/netdevice.h>
 #include <linux/fddidevice.h>
 #include <linux/skbuff.h>
@@ -107,11 +104,6 @@
 
 
 // Define module-wide (static) routines
-static struct net_device *alloc_device(struct net_device *dev, u_long iobase);
-static struct net_device *insert_device(struct net_device *dev);
-static int fddi_dev_index(unsigned char *s);
-static void init_dev(struct net_device *dev, u_long iobase);
-static void link_modules(struct net_device *dev, struct net_device *tmp);
 static int skfp_driver_init(struct net_device *dev);
 static int skfp_open(struct net_device *dev);
 static int skfp_close(struct net_device *dev);
@@ -188,15 +180,6 @@
 // Define module-wide (static) variables
 
 static int num_boards;	/* total number of adapters configured */
-static int num_fddi;
-static int autoprobed;
-
-#ifdef MODULE
-static struct net_device *unlink_modules(struct net_device *p);
-static int loading_module = 1;
-#else
-static int loading_module;
-#endif				// MODULE
 
 #ifdef DRIVERDEBUG
 #define PRINTK(s, args...) printk(s, ## args)
@@ -207,9 +190,9 @@
 #define PRIV(dev) (&(((struct s_smc *)dev->priv)->os))
 
 /*
- * ==============
- * = skfp_probe =
- * ==============
+ * =================
+ * = skfp_init_one =
+ * =================
  *   
  * Overview:
  *   Probes for supported FDDI PCI controllers
@@ -218,30 +201,11 @@
  *   Condition code
  *       
  * Arguments:
- *   dev - pointer to device information
+ *   pdev - pointer to PCI device information
  *
  * Functional Description:
- *   This routine is called by the OS for each FDDI device name (fddi0,
- *   fddi1,...,fddi6, fddi7) specified in drivers/net/Space.c.
- *   If loaded as a module, it will detect and initialize all 
- *   adapters the first time it is called.
- *
- *   Let's say that skfp_probe() is getting called to initialize fddi0.
- *   Furthermore, let's say there are three supported controllers in the
- *   system.  Before skfp_probe() leaves, devices fddi0, fddi1, and fddi2
- *   will be initialized and a global flag will be set to indicate that
- *   skfp_probe() has already been called.
- *
- *   However...the OS doesn't know that we've already initialized
- *   devices fddi1 and fddi2 so skfp_probe() gets called again and again
- *   until it reaches the end of the device list for FDDI (presently,
- *   fddi7).  It's important that the driver "pretend" to probe for
- *   devices fddi1 and fddi2 and return success.  Devices fddi3
- *   through fddi7 will return failure since they weren't initialized.
- *
- *   This algorithm seems to work for the time being.  As other FDDI
- *   drivers are written for Linux, a more generic approach (perhaps
- *   similar to the Ethernet card approach) may need to be implemented.
+ *   This is now called by PCI driver registration process
+ *   for each board found.
  *   
  * Return Codes:
  *   0           - This device (fddi0, fddi1, etc) configured successfully
@@ -254,370 +218,166 @@
  *   initialized and the board resources are read and stored in
  *   the device structure.
  */
-static int skfp_probe(struct net_device *dev)
+static __init int skfp_init_one(struct pci_dev *pdev,
+				const struct pci_device_id *ent)
 {
-	int i;			/* used in for loops */
-	struct pci_dev *pdev = NULL;	/* PCI device structure */
-#ifndef MEM_MAPPED_IO
-	u16 port;		/* temporary I/O (port) address */
-	int port_len;		/* length of port address range (in bytes) */
-#else
-	unsigned long port;
-#endif
-	u16 command;	/* PCI Configuration space Command register val */
+	struct net_device *dev;
 	struct s_smc *smc;	/* board pointer */
-	struct net_device *tmp = dev;
-	u8 first_dev_used = 0;
-	u16 SubSysId;
+	u32 port, len;
+	int err;
 
 	PRINTK(KERN_INFO "entering skfp_probe\n");
 
-	/*
-	 * Verify whether we're going through skfp_probe() again
-	 *
-	 * If so, see if we're going through for a subsequent fddi device that
-	 * we've already initialized.  If we are, return success (0).  If not,
-	 * return failure (-ENODEV).
-	 */
+	if (num_boards == 0) 
+		printk("%s\n", boot_msg);
 
-	if (autoprobed) {
-		PRINTK(KERN_INFO "Already entered skfp_probe\n");
-		if (dev != NULL) {
-			if ((strncmp(dev->name, "fddi", 4) == 0) &&
-			    (dev->base_addr != 0)) {
-				return (0);
-			}
-			return (-ENODEV);
-		}
+	err = pci_enable_device(pdev);
+	if (err)
+		goto err_out1;
+
+
+#ifdef MEM_MAPPED_IO
+	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+		printk(KERN_ERR "skfp: region is not an MMIO resource\n");
+		err = -EIO;
+		goto err_out1;
+	}
+	port = pci_resource_start(pdev, 0);
+	len = pci_resource_len(pdev, 0);
+
+	if (len < 0x4000) {
+		printk(KERN_ERR "skfp: Invalid PCI region size: %d\n", len);
+		err = -EIO;
+		goto err_out1;
 	}
-	autoprobed = 1;		/* set global flag */
-
-	printk("%s\n", boot_msg);
-
-	/* Scan for Syskonnect FDDI PCI controllers */
-	for (i = 0; i < SKFP_MAX_NUM_BOARDS; i++) {	// scan for PCI cards
-		PRINTK(KERN_INFO "Check device %d\n", i);
-		if ((pdev=pci_find_device(PCI_VENDOR_ID_SK, PCI_DEVICE_ID_SK_FP,
-			pdev)) == 0) {
-			break;
-		}
-		if (pci_enable_device(pdev))
-			continue;
-
-#ifndef MEM_MAPPED_IO
-		/* Verify that I/O enable bit is set (PCI slot is enabled) */
-		pci_read_config_word(pdev, PCI_COMMAND, &command);
-		if ((command & PCI_COMMAND_IO) == 0) {
-			PRINTK("I/O enable bit not set!");
-			PRINTK(" Verify that slot is enabled\n");
-			continue;
-		}
-
-		/* Turn off memory mapped space and enable mastering */
-
-		PRINTK(KERN_INFO "Command Reg: %04x\n", command);
-		command |= PCI_COMMAND_MASTER;
-		command &= ~PCI_COMMAND_MEMORY;
-		pci_write_config_word(pdev, PCI_COMMAND, command);
-
-		/* Read I/O base address from PCI Configuration Space */
-
-		pci_read_config_word(pdev, PCI_BASE_ADDRESS_1, &port);
-		port &= PCI_BASE_ADDRESS_IO_MASK; // clear I/O bit (bit 0)
-
-		/* Verify port address range is not already being used */
-
-		port_len = FP_IO_LEN;
-		if (check_region(port, port_len) != 0) {
-			printk("I/O range allocated to adapter");
-			printk(" (0x%X-0x%X) is already being used!\n", port,
-			       (port + port_len - 1));
-			continue;
-		}
 #else
-		/* Verify that MEM enable bit is set (PCI slot is enabled) */
-		pci_read_config_word(pdev, PCI_COMMAND, &command);
-		if ((command & PCI_COMMAND_MEMORY) == 0) {
-			PRINTK("MEMORY-I/O enable bit not set!");
-			PRINTK(" Verify that slot is enabled\n");
-			continue;
-		}
-
-		/* Turn off IO mapped space and enable mastering */
-
-		PRINTK(KERN_INFO "Command Reg: %04x\n", command);
-		command |= PCI_COMMAND_MASTER;
-		command &= ~PCI_COMMAND_IO;
-		pci_write_config_word(pdev, PCI_COMMAND, command);
-
-		port = pci_resource_start(pdev, 0);
-
-		port = (unsigned long)ioremap(port, 0x4000);
-		if (!port){
-			printk("skfp:  Unable to map MEMORY register, "
-			"FDDI adapter will be disabled.\n");
-			break;
-		}
-#endif
-
-		if ((!loading_module) || first_dev_used) {
-			/* Allocate a device structure for this adapter */
-			tmp = alloc_device(dev, port);
-		}
-		first_dev_used = 1;	// only significant first time
-
-		pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &SubSysId);
-
-		if (tmp != NULL) {
-			if (loading_module)
-				link_modules(dev, tmp);
-			dev = tmp;
-			init_dev(dev, port);
-			dev->irq = pdev->irq;
-
-			/* Initialize board structure with bus-specific info */
-
-			smc = (struct s_smc *) dev->priv;
-			smc->os.dev = dev;
-			smc->os.bus_type = SK_BUS_TYPE_PCI;
-			smc->os.pdev = *pdev;
-			smc->os.QueueSkb = MAX_TX_QUEUE_LEN;
-			smc->os.MaxFrameSize = MAX_FRAME_SIZE;
-			smc->os.dev = dev;
-			smc->hw.slot = -1;
-			smc->os.ResetRequested = FALSE;
-			skb_queue_head_init(&smc->os.SendSkbQueue);
-
-			if (skfp_driver_init(dev) == 0) {
-				int SubSysId = pdev->subsystem_device;
-				// only increment global board 
-				// count on success
-				num_boards++;
-				if ((SubSysId & 0xff00) == 0x5500 ||
-					(SubSysId & 0xff00) == 0x5800) {
-				printk("%s: SysKonnect FDDI PCI adapter"
-				       " found (SK-%04X)\n", dev->name,
-					SubSysId);
-				} else {
-					printk("%s: FDDI PCI adapter found\n",
-					       dev->name);
-				}
-			} else {
-				kfree(dev);
-				i = SKFP_MAX_NUM_BOARDS;	// stop search
-			}
-		}		// if (dev != NULL)
-	}			// for SKFP_MAX_NUM_BOARDS
-
-	/*
-	 * If we're at this point we're going through skfp_probe() for the
-	 * first time. Return success (0) if we've initialized 1 or more
-	 * boards. Otherwise, return failure (-ENODEV).
-	 */
-
-	if (num_boards > 0)
-		return (0);
-	else {
-		release_region (dev->base_addr, FP_IO_LEN);
-		printk("no SysKonnect FDDI adapter found\n");
-		return (-ENODEV);
+	if (!(pci_resource_flags(pdev, 1) & IO_RESOURCE_IO)) {
+		printk(KERN_ERR "skfp: region is not PIO resource\n");
+		err = -EIO;
+		goto err_out1;
 	}
-}				// skfp_probe
-
-
-/************************
- *
- * Search the entire 'fddi' device list for a fixed probe. If a match isn't
- * found then check for an autoprobe or unused device location. If they
- * are not available then insert a new device structure at the end of
- * the current list.
- *
- ************************/
-static struct net_device *alloc_device(struct net_device *dev, u_long iobase)
-{
-	struct net_device *adev = NULL;
-	int fixed = 0, new_dev = 0;
 
-	PRINTK(KERN_INFO "entering alloc_device\n");
-	if (!dev)
-		return dev;
-
-	num_fddi = fddi_dev_index(dev->name);
-	if (loading_module) {
-		num_fddi++;
-		dev = insert_device(dev);
-		return dev;
+	port = pci_resource_start(pdev, 1);
+	len = pci_resource_len(pdev, 1);
+	if (len < FP_IO_LEN) {
+		printk(KERN_ERR "skfp: Invalid PCI region size: %d\n",
+		       io_len);
+		err = -EIO;
+		goto err_out1;
 	}
-	while (1) {
-		if (((dev->base_addr == NO_ADDRESS) ||
-		     (dev->base_addr == 0)) && !adev) {
-			adev = dev;
-		} else if ((dev->priv == NULL) && (dev->base_addr == iobase)) {
-			fixed = 1;
-		} else {
-			if (dev->next == NULL) {
-				new_dev = 1;
-			} else if (strncmp(dev->next->name, "fddi", 4) != 0) {
-				new_dev = 1;
-			}
-		}
-		if ((dev->next == NULL) || new_dev || fixed)
-			break;
-		dev = dev->next;
-		num_fddi++;
-	}			// while (1)
-
-	if (adev && !fixed) {
-		dev = adev;
-		num_fddi = fddi_dev_index(dev->name);
-		new_dev = 0;
-	}
-	if (((dev->next == NULL) && ((dev->base_addr != NO_ADDRESS) &&
-				     (dev->base_addr != 0)) && !fixed) ||
-	    new_dev) {
-		num_fddi++;	/* New device */
-		dev = insert_device(dev);
-	}
-	if (dev) {
-		if (!dev->priv) {
-			/* Allocate space for private board structure */
-			dev->priv = (void *) kmalloc(sizeof(struct s_smc),
-						     GFP_KERNEL);
-			if (dev->priv == NULL) {
-				printk("%s: Could not allocate memory for",
-					dev->name);
-				printk(" private board structure!\n");
-				return (NULL);
-			}
-			/* clear structure */
-			memset(dev->priv, 0, sizeof(struct s_smc));
-		}
+#endif
+	err = pci_request_regions(pdev, "skfddi");
+	if (err)
+		goto err_out1;
+
+	pci_set_master(pdev);
+
+	dev = alloc_fddidev(sizeof(struct s_smc));
+	if (!dev) {
+		printk(KERN_ERR "skfp: Unable to allocate fddi device, "
+				"FDDI adapter will be disabled.\n");
+		err = -ENOMEM;
+		goto err_out2;
+	}
+
+#ifdef MEM_MAPPED_IO
+	dev->base_addr = (unsigned long) ioremap(port, len);
+	if (!dev->base_addr) {
+		printk(KERN_ERR "skfp:  Unable to map MEMORY register, "
+				"FDDI adapter will be disabled.\n");
+		err = -EIO;
+		goto err_out3;
 	}
-	return dev;
-}				// alloc_device
-
-
-
-/************************
- *
- * Initialize device structure
- *
- ************************/
-static void init_dev(struct net_device *dev, u_long iobase)
-{
-	/* Initialize new device structure */
-
-	dev->mem_end = 0;	/* shared memory isn't used */
-	dev->mem_start = 0;	/* shared memory isn't used */
-	dev->base_addr = iobase;	/* save port (I/O) base address */
-	dev->if_port = 0;	/* not applicable to FDDI adapters */
-	dev->dma = 0;		/* Bus Master DMA doesn't require channel */
-	dev->irq = 0;
-
-	netif_start_queue(dev);
+#else
+	dev->base_addr = port;
+#endif
 
+	dev->irq = pdev->irq;
 	dev->get_stats = &skfp_ctl_get_stats;
 	dev->open = &skfp_open;
 	dev->stop = &skfp_close;
+	dev->init = &skfp_driver_init;
 	dev->hard_start_xmit = &skfp_send_pkt;
-	dev->hard_header = NULL;	/* set in fddi_setup() */
-	dev->rebuild_header = NULL;	/* set in fddi_setup() */
 	dev->set_multicast_list = &skfp_ctl_set_multicast_list;
 	dev->set_mac_address = &skfp_ctl_set_mac_address;
 	dev->do_ioctl = &skfp_ioctl;
-	dev->set_config = NULL;	/* not supported for now &&& */
 	dev->header_cache_update = NULL;	/* not supported */
-	dev->change_mtu = NULL;	/* set in fddi_setup() */
 
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 
-	/* Initialize remaining device structure information */
-	fddi_setup(dev);
-}				// init_device
+	/* Initialize board structure with bus-specific info */
+	smc = (struct s_smc *) dev->priv;
+	smc->os.dev = dev;
+	smc->os.bus_type = SK_BUS_TYPE_PCI;
+	smc->os.pdev = *pdev;
+	smc->os.QueueSkb = MAX_TX_QUEUE_LEN;
+	smc->os.MaxFrameSize = MAX_FRAME_SIZE;
+	smc->os.dev = dev;
+	smc->hw.slot = -1;
+	smc->os.ResetRequested = FALSE;
+	skb_queue_head_init(&smc->os.SendSkbQueue);
+
+	err = register_netdev(dev);
+	if (err)
+		goto err_out4;
+
+	++num_boards;
+	pci_set_drvdata(pdev, dev);
+
+	if ((pdev->subsystem_device & 0xff00) == 0x5500 ||
+	    (pdev->subsystem_device & 0xff00) == 0x5800) 
+		printk("%s: SysKonnect FDDI PCI adapter"
+		       " found (SK-%04X)\n", dev->name,	
+		       pdev->subsystem_device);
+	else
+		printk("%s: FDDI PCI adapter found\n", dev->name);
 
+	return 0;
+err_out4:
+#ifdef MEM_MAPPED_IO
+	iounmap((void *) dev->base_addr);
+#endif
+err_out3:
+	free_netdev(dev);
+err_out2:
+	pci_release_regions(pdev);
+err_out1:
+	return err;
+}
 
-/************************
- *
- * If at end of fddi device list and can't use current entry, malloc
- * one up. If memory could not be allocated, print an error message.
- *
-************************/
-static struct net_device *insert_device(struct net_device *dev)
+/*
+ * Called for each adapter board from pci_unregister_driver
+ */
+static void __devexit skfp_remove_one(struct pci_dev *pdev)
 {
-	struct net_device *new;
-	int len;
+	struct net_device *p = pci_get_drvdata(pdev);
+	struct s_smc *lp = p->priv;
 
-	PRINTK(KERN_INFO "entering insert_device\n");
-	len = sizeof(struct net_device) + sizeof(struct s_smc);
-	new = (struct net_device *) kmalloc(len, GFP_KERNEL);
-	if (new == NULL) {
-		printk("fddi%d: Device not initialised, insufficient memory\n",
-		       num_fddi);
-		return NULL;
-	} else {
-		memset((char *) new, 0, len);
-		new->priv = (struct s_smc *) (new + 1);
-		new->init = skfp_probe;
-		if (!loading_module) {
-			new->next = dev->next;
-			dev->next = new;
-		}
-		/* create new device name */
-		if (num_fddi > 999) {
-			sprintf(new->name, "fddi????");
-		} else {
-			sprintf(new->name, "fddi%d", num_fddi);
-		}
-	}
-	return new;
-}				// insert_device
-
-
-/************************
- *
- * Get the number of a "fddiX" string
- *
- ************************/
-static int fddi_dev_index(unsigned char *s)
-{
-	int i = 0, j = 0;
+	unregister_netdev(p);
 
-	for (; *s; s++) {
-		if (isdigit(*s)) {
-			j = 1;
-			i = (i * 10) + (*s - '0');
-		} else if (j)
-			break;
+	if (lp->os.SharedMemAddr) {
+		pci_free_consistent(&lp->os.pdev,
+				    lp->os.SharedMemSize,
+				    lp->os.SharedMemAddr,
+				    lp->os.SharedMemDMA);
+		lp->os.SharedMemAddr = NULL;
+	}
+	if (lp->os.LocalRxBuffer) {
+		pci_free_consistent(&lp->os.pdev,
+				    MAX_FRAME_SIZE,
+				    lp->os.LocalRxBuffer,
+				    lp->os.LocalRxBufferDMA);
+		lp->os.LocalRxBuffer = NULL;
 	}
-	return i;
-}				// fddi_dev_index
-
-
-/************************
- *
- * Used if loaded as module only. Link the device structures
- * together. Needed to release them all at unload.
- *
-************************/
-static void link_modules(struct net_device *dev, struct net_device *tmp)
-{
-	struct net_device *p = dev;
-
-	if (p) {
-		while (((struct s_smc *) (p->priv))->os.next_module) {
-			p = ((struct s_smc *) (p->priv))->os.next_module;
-		}
-
-		if (dev != tmp) {
-			((struct s_smc *) (p->priv))->os.next_module = tmp;
-		} else {
-			((struct s_smc *) (p->priv))->os.next_module = NULL;
-		}
-	}
-	return;
-}				// link_modules
-
+#ifdef MEM_MAPPED_IO
+	iounmap((void *) p->base_addr);
+#endif
+	pci_release_regions(pdev);
+	free_netdev(p);
 
+	pci_set_drvdata(pdev, NULL);
+}
 
 /*
  * ====================
@@ -644,11 +404,12 @@
  *    0 - initialization succeeded
  *   -1 - initialization failed
  */
-static int skfp_driver_init(struct net_device *dev)
+static __init int skfp_driver_init(struct net_device *dev)
 {
 	struct s_smc *smc = (struct s_smc *) dev->priv;
 	skfddi_priv *bp = PRIV(dev);
 	u8 val;			/* used for I/O read/writes */
+	int err = -EIO;
 
 	PRINTK(KERN_INFO "entering skfp_driver_init\n");
 
@@ -729,7 +490,7 @@
 				    bp->LocalRxBuffer, bp->LocalRxBufferDMA);
 		bp->LocalRxBuffer = NULL;
 	}
-	return (-1);
+	return err;
 }				// skfp_driver_init
 
 
@@ -757,14 +518,15 @@
 static int skfp_open(struct net_device *dev)
 {
 	struct s_smc *smc = (struct s_smc *) dev->priv;
+	int err;
 
 	PRINTK(KERN_INFO "entering skfp_open\n");
 	/* Register IRQ - support shared interrupts by passing device ptr */
-	if (request_irq(dev->irq, (void *) skfp_interrupt, SA_SHIRQ,
-			dev->name, dev)) {
-		printk("%s: Requested IRQ %d is busy\n", dev->name, dev->irq);
-		return (-EAGAIN);
-	}
+	err = request_irq(dev->irq, (void *) skfp_interrupt, SA_SHIRQ,
+			  dev->name, dev);
+	if (err)
+		return err;
+
 	/*
 	 * Set current address to factory MAC address
 	 *
@@ -788,6 +550,7 @@
 	/* Disable promiscuous filter settings */
 	mac_drv_rx_mode(smc, RX_DISABLE_PROMISC);
 
+	netif_start_queue(dev);
 	return (0);
 }				// skfp_open
 
@@ -822,7 +585,6 @@
 static int skfp_close(struct net_device *dev)
 {
 	struct s_smc *smc = (struct s_smc *) dev->priv;
-	struct sk_buff *skb;
 	skfddi_priv *bp = PRIV(dev);
 
 	CLI_FBI();
@@ -835,13 +597,7 @@
 	/* Deregister (free) IRQ */
 	free_irq(dev->irq, dev);
 
-	for (;;) {
-		skb = skb_dequeue(&bp->SendSkbQueue);
-		if (skb == NULL)
-			break;
-		bp->QueueSkb++;
-		dev_kfree_skb(skb);
-	}
+	skb_queue_purge(&bp->SendSkbQueue);
 
 	return (0);
 }				// skfp_close
@@ -1276,6 +1032,8 @@
 		break;
 	default:
 		printk("ioctl for %s: unknow cmd: %04x\n", dev->name, ioc.cmd);
+		status = -EOPNOTSUPP;
+
 	}			// switch
 
 	return status;
@@ -2529,63 +2287,21 @@
 
 }				// drv_reset_indication
 
-
-static struct net_device *mdev;
+static struct pci_driver skfddi_pci_driver = {
+	.name		= "skfddi",
+	.id_table	= skfddi_pci_tbl,
+	.probe		= skfp_init_one,
+	.remove		= __devexit_p(skfp_remove_one),
+};
 
 static int __init skfd_init(void)
 {
-	struct net_device *p;
-
-	if ((mdev = insert_device(NULL)) == NULL)
-		return -ENOMEM;
-
-	for (p = mdev; p != NULL; p = ((struct s_smc *)p->priv)->os.next_module) {
-		if (register_netdev(p) != 0) {
-			printk("skfddi init_module failed\n");
-			return -EIO;
-		}
-	}
-
-	return 0;
+	return pci_module_init(&skfddi_pci_driver);
 }
 
-static struct net_device *unlink_modules(struct net_device *p)
-{
-	struct net_device *next = NULL;
-
-	if (p->priv) {		/* Private areas allocated? */
-		struct s_smc *lp = (struct s_smc *) p->priv;
-
-		next = lp->os.next_module;
-
-		if (lp->os.SharedMemAddr) {
-			pci_free_consistent(&lp->os.pdev,
-					    lp->os.SharedMemSize,
-					    lp->os.SharedMemAddr,
-					    lp->os.SharedMemDMA);
-			lp->os.SharedMemAddr = NULL;
-		}
-		if (lp->os.LocalRxBuffer) {
-			pci_free_consistent(&lp->os.pdev,
-					    MAX_FRAME_SIZE,
-					    lp->os.LocalRxBuffer,
-					    lp->os.LocalRxBufferDMA);
-			lp->os.LocalRxBuffer = NULL;
-		}
-		release_region(p->base_addr, 
-			(lp->os.bus_type == SK_BUS_TYPE_PCI ? FP_IO_LEN : 0));
-	}
-	unregister_netdev(p);
-	printk("%s: unloaded\n", p->name);
-	free_netdev(p);		/* Free the device structure */
-
-	return next;
-}				// unlink_modules
-
 static void __exit skfd_exit(void)
 {
-	while (mdev)
-		mdev = unlink_modules(mdev);
+	pci_unregister_driver(&skfddi_pci_driver);
 }
 
 module_init(skfd_init);

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] skfddi - convert to new pci model.
  2003-12-05  0:39 [PATCH] skfddi - convert to new pci model Stephen Hemminger
@ 2003-12-05  0:59 ` Alexander Viro
  2003-12-05 23:12   ` Stephen Hemminger
  0 siblings, 1 reply; 5+ messages in thread
From: Alexander Viro @ 2003-12-05  0:59 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: Jeff Garzik, netdev, Alexander Viro

On Thu, Dec 04, 2003 at 04:39:28PM -0800, Stephen Hemminger wrote:
> +	dev->irq = pdev->irq;
>  	dev->get_stats = &skfp_ctl_get_stats;
>  	dev->open = &skfp_open;
>  	dev->stop = &skfp_close;
> +	dev->init = &skfp_driver_init;

Ehh...  Don't do that, please.  net_device ->init() means trouble,
since getting failure from register_netdev() gives you no clue
whether it had failed before, during or after ->init().  Makes
for an interesting cleanup...

You can do that if required cleanup can be deduced from the state
of *dev after register_netdev() failure (e.g. if no cleanup is
ever needed), but generally it's less PITA to just call the
damn function directly before register_netdev() and leave ->init NULL.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] skfddi - convert to new pci model.
  2003-12-05  0:59 ` Alexander Viro
@ 2003-12-05 23:12   ` Stephen Hemminger
  2003-12-05 23:27     ` Alexander Viro
  2003-12-16  5:43     ` Jeff Garzik
  0 siblings, 2 replies; 5+ messages in thread
From: Stephen Hemminger @ 2003-12-05 23:12 UTC (permalink / raw)
  To: Alexander Viro; +Cc: Jeff Garzik, netdev, Alexander Viro

Second revision of the cleanup of skfddi driver.
 * use new pci device bus initialization
 * allocate network device with alloc_fddidev
    and use dev->priv
  * get rid of special module/non module distinctions.

  * fix error unwinds and return values on initialization
  * call driver_init directly not via register_netdev
  * reset internal queue count after purge
  * get rid of h[iy]sterical comment that is no longer true

diff -Nru a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c
--- a/drivers/net/skfp/skfddi.c	Fri Dec  5 14:49:12 2003
+++ b/drivers/net/skfp/skfddi.c	Fri Dec  5 14:49:12 2003
@@ -39,12 +39,6 @@
  *   are skfddi.c, h/types.h, h/osdef1st.h, h/targetos.h.
  *   The others belong to the SysKonnect FDDI Hardware Module and
  *   should better not be changed.
- * NOTE:
- *   Compiling this driver produces some warnings, but I did not fix
- *   this, because the Hardware Module source is used for different
- *   drivers, and fixing it for Linux might bring problems on other
- *   projects. To keep the source common for all those drivers (and
- *   thus simplify fixes to it), please do not clean it up!
  *
  * Modification History:
  *              Date            Name    Description
@@ -58,6 +52,7 @@
  *		07-May-00	DM	64 bit fixes, new dma interface
  *		31-Jul-03	DB	Audit copy_*_user in skfp_ioctl
  *					  Daniele Bellucci <bellucda@tiscali.it>
+ *		03-Dec-03	SH	Convert to PCI device model
  *
  * Compilation options (-Dxxx):
  *              DRIVERDEBUG     print lots of messages to log file
@@ -70,7 +65,7 @@
 
 /* Version information string - should be updated prior to */
 /* each new release!!! */
-#define VERSION		"2.06"
+#define VERSION		"2.07"
 
 static const char *boot_msg = 
 	"SysKonnect FDDI PCI Adapter driver v" VERSION " for\n"
@@ -80,15 +75,11 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/ctype.h>	// isdigit
 #include <linux/netdevice.h>
 #include <linux/fddidevice.h>
 #include <linux/skbuff.h>
@@ -107,11 +98,6 @@
 
 
 // Define module-wide (static) routines
-static struct net_device *alloc_device(struct net_device *dev, u_long iobase);
-static struct net_device *insert_device(struct net_device *dev);
-static int fddi_dev_index(unsigned char *s);
-static void init_dev(struct net_device *dev, u_long iobase);
-static void link_modules(struct net_device *dev, struct net_device *tmp);
 static int skfp_driver_init(struct net_device *dev);
 static int skfp_open(struct net_device *dev);
 static int skfp_close(struct net_device *dev);
@@ -188,15 +174,6 @@
 // Define module-wide (static) variables
 
 static int num_boards;	/* total number of adapters configured */
-static int num_fddi;
-static int autoprobed;
-
-#ifdef MODULE
-static struct net_device *unlink_modules(struct net_device *p);
-static int loading_module = 1;
-#else
-static int loading_module;
-#endif				// MODULE
 
 #ifdef DRIVERDEBUG
 #define PRINTK(s, args...) printk(s, ## args)
@@ -207,9 +184,9 @@
 #define PRIV(dev) (&(((struct s_smc *)dev->priv)->os))
 
 /*
- * ==============
- * = skfp_probe =
- * ==============
+ * =================
+ * = skfp_init_one =
+ * =================
  *   
  * Overview:
  *   Probes for supported FDDI PCI controllers
@@ -218,30 +195,11 @@
  *   Condition code
  *       
  * Arguments:
- *   dev - pointer to device information
+ *   pdev - pointer to PCI device information
  *
  * Functional Description:
- *   This routine is called by the OS for each FDDI device name (fddi0,
- *   fddi1,...,fddi6, fddi7) specified in drivers/net/Space.c.
- *   If loaded as a module, it will detect and initialize all 
- *   adapters the first time it is called.
- *
- *   Let's say that skfp_probe() is getting called to initialize fddi0.
- *   Furthermore, let's say there are three supported controllers in the
- *   system.  Before skfp_probe() leaves, devices fddi0, fddi1, and fddi2
- *   will be initialized and a global flag will be set to indicate that
- *   skfp_probe() has already been called.
- *
- *   However...the OS doesn't know that we've already initialized
- *   devices fddi1 and fddi2 so skfp_probe() gets called again and again
- *   until it reaches the end of the device list for FDDI (presently,
- *   fddi7).  It's important that the driver "pretend" to probe for
- *   devices fddi1 and fddi2 and return success.  Devices fddi3
- *   through fddi7 will return failure since they weren't initialized.
- *
- *   This algorithm seems to work for the time being.  As other FDDI
- *   drivers are written for Linux, a more generic approach (perhaps
- *   similar to the Ethernet card approach) may need to be implemented.
+ *   This is now called by PCI driver registration process
+ *   for each board found.
  *   
  * Return Codes:
  *   0           - This device (fddi0, fddi1, etc) configured successfully
@@ -254,370 +212,176 @@
  *   initialized and the board resources are read and stored in
  *   the device structure.
  */
-static int skfp_probe(struct net_device *dev)
+static __init int skfp_init_one(struct pci_dev *pdev,
+				const struct pci_device_id *ent)
 {
-	int i;			/* used in for loops */
-	struct pci_dev *pdev = NULL;	/* PCI device structure */
-#ifndef MEM_MAPPED_IO
-	u16 port;		/* temporary I/O (port) address */
-	int port_len;		/* length of port address range (in bytes) */
-#else
-	unsigned long port;
-#endif
-	u16 command;	/* PCI Configuration space Command register val */
+	struct net_device *dev;
 	struct s_smc *smc;	/* board pointer */
-	struct net_device *tmp = dev;
-	u8 first_dev_used = 0;
-	u16 SubSysId;
+	u32 port, len;
+	int err;
 
 	PRINTK(KERN_INFO "entering skfp_probe\n");
 
-	/*
-	 * Verify whether we're going through skfp_probe() again
-	 *
-	 * If so, see if we're going through for a subsequent fddi device that
-	 * we've already initialized.  If we are, return success (0).  If not,
-	 * return failure (-ENODEV).
-	 */
+	if (num_boards == 0) 
+		printk("%s\n", boot_msg);
 
-	if (autoprobed) {
-		PRINTK(KERN_INFO "Already entered skfp_probe\n");
-		if (dev != NULL) {
-			if ((strncmp(dev->name, "fddi", 4) == 0) &&
-			    (dev->base_addr != 0)) {
-				return (0);
-			}
-			return (-ENODEV);
-		}
+	err = pci_enable_device(pdev);
+	if (err)
+		goto err_out1;
+
+
+#ifdef MEM_MAPPED_IO
+	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+		printk(KERN_ERR "skfp: region is not an MMIO resource\n");
+		err = -EIO;
+		goto err_out1;
+	}
+	port = pci_resource_start(pdev, 0);
+	len = pci_resource_len(pdev, 0);
+
+	if (len < 0x4000) {
+		printk(KERN_ERR "skfp: Invalid PCI region size: %d\n", len);
+		err = -EIO;
+		goto err_out1;
 	}
-	autoprobed = 1;		/* set global flag */
-
-	printk("%s\n", boot_msg);
-
-	/* Scan for Syskonnect FDDI PCI controllers */
-	for (i = 0; i < SKFP_MAX_NUM_BOARDS; i++) {	// scan for PCI cards
-		PRINTK(KERN_INFO "Check device %d\n", i);
-		if ((pdev=pci_find_device(PCI_VENDOR_ID_SK, PCI_DEVICE_ID_SK_FP,
-			pdev)) == 0) {
-			break;
-		}
-		if (pci_enable_device(pdev))
-			continue;
-
-#ifndef MEM_MAPPED_IO
-		/* Verify that I/O enable bit is set (PCI slot is enabled) */
-		pci_read_config_word(pdev, PCI_COMMAND, &command);
-		if ((command & PCI_COMMAND_IO) == 0) {
-			PRINTK("I/O enable bit not set!");
-			PRINTK(" Verify that slot is enabled\n");
-			continue;
-		}
-
-		/* Turn off memory mapped space and enable mastering */
-
-		PRINTK(KERN_INFO "Command Reg: %04x\n", command);
-		command |= PCI_COMMAND_MASTER;
-		command &= ~PCI_COMMAND_MEMORY;
-		pci_write_config_word(pdev, PCI_COMMAND, command);
-
-		/* Read I/O base address from PCI Configuration Space */
-
-		pci_read_config_word(pdev, PCI_BASE_ADDRESS_1, &port);
-		port &= PCI_BASE_ADDRESS_IO_MASK; // clear I/O bit (bit 0)
-
-		/* Verify port address range is not already being used */
-
-		port_len = FP_IO_LEN;
-		if (check_region(port, port_len) != 0) {
-			printk("I/O range allocated to adapter");
-			printk(" (0x%X-0x%X) is already being used!\n", port,
-			       (port + port_len - 1));
-			continue;
-		}
 #else
-		/* Verify that MEM enable bit is set (PCI slot is enabled) */
-		pci_read_config_word(pdev, PCI_COMMAND, &command);
-		if ((command & PCI_COMMAND_MEMORY) == 0) {
-			PRINTK("MEMORY-I/O enable bit not set!");
-			PRINTK(" Verify that slot is enabled\n");
-			continue;
-		}
-
-		/* Turn off IO mapped space and enable mastering */
-
-		PRINTK(KERN_INFO "Command Reg: %04x\n", command);
-		command |= PCI_COMMAND_MASTER;
-		command &= ~PCI_COMMAND_IO;
-		pci_write_config_word(pdev, PCI_COMMAND, command);
-
-		port = pci_resource_start(pdev, 0);
-
-		port = (unsigned long)ioremap(port, 0x4000);
-		if (!port){
-			printk("skfp:  Unable to map MEMORY register, "
-			"FDDI adapter will be disabled.\n");
-			break;
-		}
-#endif
-
-		if ((!loading_module) || first_dev_used) {
-			/* Allocate a device structure for this adapter */
-			tmp = alloc_device(dev, port);
-		}
-		first_dev_used = 1;	// only significant first time
-
-		pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &SubSysId);
-
-		if (tmp != NULL) {
-			if (loading_module)
-				link_modules(dev, tmp);
-			dev = tmp;
-			init_dev(dev, port);
-			dev->irq = pdev->irq;
-
-			/* Initialize board structure with bus-specific info */
-
-			smc = (struct s_smc *) dev->priv;
-			smc->os.dev = dev;
-			smc->os.bus_type = SK_BUS_TYPE_PCI;
-			smc->os.pdev = *pdev;
-			smc->os.QueueSkb = MAX_TX_QUEUE_LEN;
-			smc->os.MaxFrameSize = MAX_FRAME_SIZE;
-			smc->os.dev = dev;
-			smc->hw.slot = -1;
-			smc->os.ResetRequested = FALSE;
-			skb_queue_head_init(&smc->os.SendSkbQueue);
-
-			if (skfp_driver_init(dev) == 0) {
-				int SubSysId = pdev->subsystem_device;
-				// only increment global board 
-				// count on success
-				num_boards++;
-				if ((SubSysId & 0xff00) == 0x5500 ||
-					(SubSysId & 0xff00) == 0x5800) {
-				printk("%s: SysKonnect FDDI PCI adapter"
-				       " found (SK-%04X)\n", dev->name,
-					SubSysId);
-				} else {
-					printk("%s: FDDI PCI adapter found\n",
-					       dev->name);
-				}
-			} else {
-				kfree(dev);
-				i = SKFP_MAX_NUM_BOARDS;	// stop search
-			}
-		}		// if (dev != NULL)
-	}			// for SKFP_MAX_NUM_BOARDS
-
-	/*
-	 * If we're at this point we're going through skfp_probe() for the
-	 * first time. Return success (0) if we've initialized 1 or more
-	 * boards. Otherwise, return failure (-ENODEV).
-	 */
-
-	if (num_boards > 0)
-		return (0);
-	else {
-		release_region (dev->base_addr, FP_IO_LEN);
-		printk("no SysKonnect FDDI adapter found\n");
-		return (-ENODEV);
+	if (!(pci_resource_flags(pdev, 1) & IO_RESOURCE_IO)) {
+		printk(KERN_ERR "skfp: region is not PIO resource\n");
+		err = -EIO;
+		goto err_out1;
 	}
-}				// skfp_probe
 
-
-/************************
- *
- * Search the entire 'fddi' device list for a fixed probe. If a match isn't
- * found then check for an autoprobe or unused device location. If they
- * are not available then insert a new device structure at the end of
- * the current list.
- *
- ************************/
-static struct net_device *alloc_device(struct net_device *dev, u_long iobase)
-{
-	struct net_device *adev = NULL;
-	int fixed = 0, new_dev = 0;
-
-	PRINTK(KERN_INFO "entering alloc_device\n");
-	if (!dev)
-		return dev;
-
-	num_fddi = fddi_dev_index(dev->name);
-	if (loading_module) {
-		num_fddi++;
-		dev = insert_device(dev);
-		return dev;
+	port = pci_resource_start(pdev, 1);
+	len = pci_resource_len(pdev, 1);
+	if (len < FP_IO_LEN) {
+		printk(KERN_ERR "skfp: Invalid PCI region size: %d\n",
+		       io_len);
+		err = -EIO;
+		goto err_out1;
 	}
-	while (1) {
-		if (((dev->base_addr == NO_ADDRESS) ||
-		     (dev->base_addr == 0)) && !adev) {
-			adev = dev;
-		} else if ((dev->priv == NULL) && (dev->base_addr == iobase)) {
-			fixed = 1;
-		} else {
-			if (dev->next == NULL) {
-				new_dev = 1;
-			} else if (strncmp(dev->next->name, "fddi", 4) != 0) {
-				new_dev = 1;
-			}
-		}
-		if ((dev->next == NULL) || new_dev || fixed)
-			break;
-		dev = dev->next;
-		num_fddi++;
-	}			// while (1)
-
-	if (adev && !fixed) {
-		dev = adev;
-		num_fddi = fddi_dev_index(dev->name);
-		new_dev = 0;
-	}
-	if (((dev->next == NULL) && ((dev->base_addr != NO_ADDRESS) &&
-				     (dev->base_addr != 0)) && !fixed) ||
-	    new_dev) {
-		num_fddi++;	/* New device */
-		dev = insert_device(dev);
-	}
-	if (dev) {
-		if (!dev->priv) {
-			/* Allocate space for private board structure */
-			dev->priv = (void *) kmalloc(sizeof(struct s_smc),
-						     GFP_KERNEL);
-			if (dev->priv == NULL) {
-				printk("%s: Could not allocate memory for",
-					dev->name);
-				printk(" private board structure!\n");
-				return (NULL);
-			}
-			/* clear structure */
-			memset(dev->priv, 0, sizeof(struct s_smc));
-		}
+#endif
+	err = pci_request_regions(pdev, "skfddi");
+	if (err)
+		goto err_out1;
+
+	pci_set_master(pdev);
+
+	dev = alloc_fddidev(sizeof(struct s_smc));
+	if (!dev) {
+		printk(KERN_ERR "skfp: Unable to allocate fddi device, "
+				"FDDI adapter will be disabled.\n");
+		err = -ENOMEM;
+		goto err_out2;
+	}
+
+#ifdef MEM_MAPPED_IO
+	dev->base_addr = (unsigned long) ioremap(port, len);
+	if (!dev->base_addr) {
+		printk(KERN_ERR "skfp:  Unable to map MEMORY register, "
+				"FDDI adapter will be disabled.\n");
+		err = -EIO;
+		goto err_out3;
 	}
-	return dev;
-}				// alloc_device
-
-
-
-/************************
- *
- * Initialize device structure
- *
- ************************/
-static void init_dev(struct net_device *dev, u_long iobase)
-{
-	/* Initialize new device structure */
-
-	dev->mem_end = 0;	/* shared memory isn't used */
-	dev->mem_start = 0;	/* shared memory isn't used */
-	dev->base_addr = iobase;	/* save port (I/O) base address */
-	dev->if_port = 0;	/* not applicable to FDDI adapters */
-	dev->dma = 0;		/* Bus Master DMA doesn't require channel */
-	dev->irq = 0;
-
-	netif_start_queue(dev);
+#else
+	dev->base_addr = port;
+#endif
 
+	dev->irq = pdev->irq;
 	dev->get_stats = &skfp_ctl_get_stats;
 	dev->open = &skfp_open;
 	dev->stop = &skfp_close;
 	dev->hard_start_xmit = &skfp_send_pkt;
-	dev->hard_header = NULL;	/* set in fddi_setup() */
-	dev->rebuild_header = NULL;	/* set in fddi_setup() */
 	dev->set_multicast_list = &skfp_ctl_set_multicast_list;
 	dev->set_mac_address = &skfp_ctl_set_mac_address;
 	dev->do_ioctl = &skfp_ioctl;
-	dev->set_config = NULL;	/* not supported for now &&& */
 	dev->header_cache_update = NULL;	/* not supported */
-	dev->change_mtu = NULL;	/* set in fddi_setup() */
 
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 
-	/* Initialize remaining device structure information */
-	fddi_setup(dev);
-}				// init_device
-
-
-/************************
- *
- * If at end of fddi device list and can't use current entry, malloc
- * one up. If memory could not be allocated, print an error message.
- *
-************************/
-static struct net_device *insert_device(struct net_device *dev)
-{
-	struct net_device *new;
-	int len;
-
-	PRINTK(KERN_INFO "entering insert_device\n");
-	len = sizeof(struct net_device) + sizeof(struct s_smc);
-	new = (struct net_device *) kmalloc(len, GFP_KERNEL);
-	if (new == NULL) {
-		printk("fddi%d: Device not initialised, insufficient memory\n",
-		       num_fddi);
-		return NULL;
-	} else {
-		memset((char *) new, 0, len);
-		new->priv = (struct s_smc *) (new + 1);
-		new->init = skfp_probe;
-		if (!loading_module) {
-			new->next = dev->next;
-			dev->next = new;
-		}
-		/* create new device name */
-		if (num_fddi > 999) {
-			sprintf(new->name, "fddi????");
-		} else {
-			sprintf(new->name, "fddi%d", num_fddi);
-		}
-	}
-	return new;
-}				// insert_device
-
-
-/************************
- *
- * Get the number of a "fddiX" string
- *
- ************************/
-static int fddi_dev_index(unsigned char *s)
-{
-	int i = 0, j = 0;
-
-	for (; *s; s++) {
-		if (isdigit(*s)) {
-			j = 1;
-			i = (i * 10) + (*s - '0');
-		} else if (j)
-			break;
-	}
-	return i;
-}				// fddi_dev_index
+	/* Initialize board structure with bus-specific info */
+	smc = (struct s_smc *) dev->priv;
+	smc->os.dev = dev;
+	smc->os.bus_type = SK_BUS_TYPE_PCI;
+	smc->os.pdev = *pdev;
+	smc->os.QueueSkb = MAX_TX_QUEUE_LEN;
+	smc->os.MaxFrameSize = MAX_FRAME_SIZE;
+	smc->os.dev = dev;
+	smc->hw.slot = -1;
+	smc->os.ResetRequested = FALSE;
+	skb_queue_head_init(&smc->os.SendSkbQueue);
+
+	err = skfp_driver_init(dev);
+	if (err)
+		goto err_out4;
+
+	err = register_netdev(dev);
+	if (err)
+		goto err_out5;
+
+	++num_boards;
+	pci_set_drvdata(pdev, dev);
+
+	if ((pdev->subsystem_device & 0xff00) == 0x5500 ||
+	    (pdev->subsystem_device & 0xff00) == 0x5800) 
+		printk("%s: SysKonnect FDDI PCI adapter"
+		       " found (SK-%04X)\n", dev->name,	
+		       pdev->subsystem_device);
+	else
+		printk("%s: FDDI PCI adapter found\n", dev->name);
 
+	return 0;
+err_out5:
+	if (smc->os.SharedMemAddr) 
+		pci_free_consistent(pdev, smc->os.SharedMemSize,
+				    smc->os.SharedMemAddr, 
+				    smc->os.SharedMemDMA);
+	pci_free_consistent(pdev, MAX_FRAME_SIZE,
+			    smc->os.LocalRxBuffer, smc->os.LocalRxBufferDMA);
+err_out4:
+#ifdef MEM_MAPPED_IO
+	iounmap((void *) dev->base_addr);
+#endif
+err_out3:
+	free_netdev(dev);
+err_out2:
+	pci_release_regions(pdev);
+err_out1:
+	return err;
+}
 
-/************************
- *
- * Used if loaded as module only. Link the device structures
- * together. Needed to release them all at unload.
- *
-************************/
-static void link_modules(struct net_device *dev, struct net_device *tmp)
+/*
+ * Called for each adapter board from pci_unregister_driver
+ */
+static void __devexit skfp_remove_one(struct pci_dev *pdev)
 {
-	struct net_device *p = dev;
+	struct net_device *p = pci_get_drvdata(pdev);
+	struct s_smc *lp = p->priv;
 
-	if (p) {
-		while (((struct s_smc *) (p->priv))->os.next_module) {
-			p = ((struct s_smc *) (p->priv))->os.next_module;
-		}
+	unregister_netdev(p);
 
-		if (dev != tmp) {
-			((struct s_smc *) (p->priv))->os.next_module = tmp;
-		} else {
-			((struct s_smc *) (p->priv))->os.next_module = NULL;
-		}
+	if (lp->os.SharedMemAddr) {
+		pci_free_consistent(&lp->os.pdev,
+				    lp->os.SharedMemSize,
+				    lp->os.SharedMemAddr,
+				    lp->os.SharedMemDMA);
+		lp->os.SharedMemAddr = NULL;
+	}
+	if (lp->os.LocalRxBuffer) {
+		pci_free_consistent(&lp->os.pdev,
+				    MAX_FRAME_SIZE,
+				    lp->os.LocalRxBuffer,
+				    lp->os.LocalRxBufferDMA);
+		lp->os.LocalRxBuffer = NULL;
 	}
-	return;
-}				// link_modules
-
+#ifdef MEM_MAPPED_IO
+	iounmap((void *) p->base_addr);
+#endif
+	pci_release_regions(pdev);
+	free_netdev(p);
 
+	pci_set_drvdata(pdev, NULL);
+}
 
 /*
  * ====================
@@ -644,11 +408,11 @@
  *    0 - initialization succeeded
  *   -1 - initialization failed
  */
-static int skfp_driver_init(struct net_device *dev)
+static __init int skfp_driver_init(struct net_device *dev)
 {
 	struct s_smc *smc = (struct s_smc *) dev->priv;
 	skfddi_priv *bp = PRIV(dev);
-	u8 val;			/* used for I/O read/writes */
+	int err = -EIO;
 
 	PRINTK(KERN_INFO "entering skfp_driver_init\n");
 
@@ -657,9 +421,7 @@
 	smc->hw.iop = dev->base_addr;
 
 	// Get the interrupt level from the PCI Configuration Table
-	val = dev->irq;
-
-	smc->hw.irq = val;
+	smc->hw.irq = dev->irq;
 
 	spin_lock_init(&bp->DriverLock);
 	
@@ -729,7 +491,7 @@
 				    bp->LocalRxBuffer, bp->LocalRxBufferDMA);
 		bp->LocalRxBuffer = NULL;
 	}
-	return (-1);
+	return err;
 }				// skfp_driver_init
 
 
@@ -757,14 +519,15 @@
 static int skfp_open(struct net_device *dev)
 {
 	struct s_smc *smc = (struct s_smc *) dev->priv;
+	int err;
 
 	PRINTK(KERN_INFO "entering skfp_open\n");
 	/* Register IRQ - support shared interrupts by passing device ptr */
-	if (request_irq(dev->irq, (void *) skfp_interrupt, SA_SHIRQ,
-			dev->name, dev)) {
-		printk("%s: Requested IRQ %d is busy\n", dev->name, dev->irq);
-		return (-EAGAIN);
-	}
+	err = request_irq(dev->irq, (void *) skfp_interrupt, SA_SHIRQ,
+			  dev->name, dev);
+	if (err)
+		return err;
+
 	/*
 	 * Set current address to factory MAC address
 	 *
@@ -788,6 +551,7 @@
 	/* Disable promiscuous filter settings */
 	mac_drv_rx_mode(smc, RX_DISABLE_PROMISC);
 
+	netif_start_queue(dev);
 	return (0);
 }				// skfp_open
 
@@ -822,7 +586,6 @@
 static int skfp_close(struct net_device *dev)
 {
 	struct s_smc *smc = (struct s_smc *) dev->priv;
-	struct sk_buff *skb;
 	skfddi_priv *bp = PRIV(dev);
 
 	CLI_FBI();
@@ -835,13 +598,8 @@
 	/* Deregister (free) IRQ */
 	free_irq(dev->irq, dev);
 
-	for (;;) {
-		skb = skb_dequeue(&bp->SendSkbQueue);
-		if (skb == NULL)
-			break;
-		bp->QueueSkb++;
-		dev_kfree_skb(skb);
-	}
+	skb_queue_purge(&bp->SendSkbQueue);
+	bp->QueueSkb = MAX_TX_QUEUE_LEN;
 
 	return (0);
 }				// skfp_close
@@ -1276,6 +1034,8 @@
 		break;
 	default:
 		printk("ioctl for %s: unknow cmd: %04x\n", dev->name, ioc.cmd);
+		status = -EOPNOTSUPP;
+
 	}			// switch
 
 	return status;
@@ -2529,63 +2289,21 @@
 
 }				// drv_reset_indication
 
-
-static struct net_device *mdev;
+static struct pci_driver skfddi_pci_driver = {
+	.name		= "skfddi",
+	.id_table	= skfddi_pci_tbl,
+	.probe		= skfp_init_one,
+	.remove		= __devexit_p(skfp_remove_one),
+};
 
 static int __init skfd_init(void)
 {
-	struct net_device *p;
-
-	if ((mdev = insert_device(NULL)) == NULL)
-		return -ENOMEM;
-
-	for (p = mdev; p != NULL; p = ((struct s_smc *)p->priv)->os.next_module) {
-		if (register_netdev(p) != 0) {
-			printk("skfddi init_module failed\n");
-			return -EIO;
-		}
-	}
-
-	return 0;
+	return pci_module_init(&skfddi_pci_driver);
 }
 
-static struct net_device *unlink_modules(struct net_device *p)
-{
-	struct net_device *next = NULL;
-
-	if (p->priv) {		/* Private areas allocated? */
-		struct s_smc *lp = (struct s_smc *) p->priv;
-
-		next = lp->os.next_module;
-
-		if (lp->os.SharedMemAddr) {
-			pci_free_consistent(&lp->os.pdev,
-					    lp->os.SharedMemSize,
-					    lp->os.SharedMemAddr,
-					    lp->os.SharedMemDMA);
-			lp->os.SharedMemAddr = NULL;
-		}
-		if (lp->os.LocalRxBuffer) {
-			pci_free_consistent(&lp->os.pdev,
-					    MAX_FRAME_SIZE,
-					    lp->os.LocalRxBuffer,
-					    lp->os.LocalRxBufferDMA);
-			lp->os.LocalRxBuffer = NULL;
-		}
-		release_region(p->base_addr, 
-			(lp->os.bus_type == SK_BUS_TYPE_PCI ? FP_IO_LEN : 0));
-	}
-	unregister_netdev(p);
-	printk("%s: unloaded\n", p->name);
-	free_netdev(p);		/* Free the device structure */
-
-	return next;
-}				// unlink_modules
-
 static void __exit skfd_exit(void)
 {
-	while (mdev)
-		mdev = unlink_modules(mdev);
+	pci_unregister_driver(&skfddi_pci_driver);
 }
 
 module_init(skfd_init);

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] skfddi - convert to new pci model.
  2003-12-05 23:12   ` Stephen Hemminger
@ 2003-12-05 23:27     ` Alexander Viro
  2003-12-16  5:43     ` Jeff Garzik
  1 sibling, 0 replies; 5+ messages in thread
From: Alexander Viro @ 2003-12-05 23:27 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: Alexander Viro, Jeff Garzik, netdev

On Fri, Dec 05, 2003 at 03:12:49PM -0800, Stephen Hemminger wrote:
> Second revision of the cleanup of skfddi driver.
>  * use new pci device bus initialization
>  * allocate network device with alloc_fddidev
>     and use dev->priv
>   * get rid of special module/non module distinctions.
> 
>   * fix error unwinds and return values on initialization
>   * call driver_init directly not via register_netdev
>   * reset internal queue count after purge
>   * get rid of h[iy]sterical comment that is no longer true

Looks sane.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] skfddi - convert to new pci model.
  2003-12-05 23:12   ` Stephen Hemminger
  2003-12-05 23:27     ` Alexander Viro
@ 2003-12-16  5:43     ` Jeff Garzik
  1 sibling, 0 replies; 5+ messages in thread
From: Jeff Garzik @ 2003-12-16  5:43 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: Alexander Viro, netdev

On Fri, Dec 05, 2003 at 03:12:49PM -0800, Stephen Hemminger wrote:
> Second revision of the cleanup of skfddi driver.
>  * use new pci device bus initialization
>  * allocate network device with alloc_fddidev
>     and use dev->priv
>   * get rid of special module/non module distinctions.
> 
>   * fix error unwinds and return values on initialization
>   * call driver_init directly not via register_netdev
>   * reset internal queue count after purge
>   * get rid of h[iy]sterical comment that is no longer true
> 
> diff -Nru a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c
> --- a/drivers/net/skfp/skfddi.c	Fri Dec  5 14:49:12 2003
> +++ b/drivers/net/skfp/skfddi.c	Fri Dec  5 14:49:12 2003
> @@ -39,12 +39,6 @@
>   *   are skfddi.c, h/types.h, h/osdef1st.h, h/targetos.h.
>   *   The others belong to the SysKonnect FDDI Hardware Module and
>   *   should better not be changed.
> - * NOTE:
> - *   Compiling this driver produces some warnings, but I did not fix
> - *   this, because the Hardware Module source is used for different
> - *   drivers, and fixing it for Linux might bring problems on other
> - *   projects. To keep the source common for all those drivers (and
> - *   thus simplify fixes to it), please do not clean it up!
>   *
>   * Modification History:
>   *              Date            Name    Description
> @@ -58,6 +52,7 @@
>   *		07-May-00	DM	64 bit fixes, new dma interface
>   *		31-Jul-03	DB	Audit copy_*_user in skfp_ioctl
>   *					  Daniele Bellucci <bellucda@tiscali.it>
> + *		03-Dec-03	SH	Convert to PCI device model
>   *
>   * Compilation options (-Dxxx):
>   *              DRIVERDEBUG     print lots of messages to log file
> @@ -70,7 +65,7 @@
>  
>  /* Version information string - should be updated prior to */
>  /* each new release!!! */
> -#define VERSION		"2.06"
> +#define VERSION		"2.07"
>  
>  static const char *boot_msg = 
>  	"SysKonnect FDDI PCI Adapter driver v" VERSION " for\n"
> @@ -80,15 +75,11 @@
>  
>  #include <linux/module.h>
>  #include <linux/kernel.h>
> -#include <linux/string.h>
> -#include <linux/ptrace.h>
>  #include <linux/errno.h>
>  #include <linux/ioport.h>
>  #include <linux/slab.h>
>  #include <linux/interrupt.h>
>  #include <linux/pci.h>
> -#include <linux/delay.h>
> -#include <linux/ctype.h>	// isdigit
>  #include <linux/netdevice.h>
>  #include <linux/fddidevice.h>
>  #include <linux/skbuff.h>
> @@ -107,11 +98,6 @@
>  
>  
>  // Define module-wide (static) routines
> -static struct net_device *alloc_device(struct net_device *dev, u_long iobase);
> -static struct net_device *insert_device(struct net_device *dev);
> -static int fddi_dev_index(unsigned char *s);
> -static void init_dev(struct net_device *dev, u_long iobase);
> -static void link_modules(struct net_device *dev, struct net_device *tmp);
>  static int skfp_driver_init(struct net_device *dev);
>  static int skfp_open(struct net_device *dev);
>  static int skfp_close(struct net_device *dev);
> @@ -188,15 +174,6 @@
>  // Define module-wide (static) variables
>  
>  static int num_boards;	/* total number of adapters configured */
> -static int num_fddi;
> -static int autoprobed;
> -
> -#ifdef MODULE
> -static struct net_device *unlink_modules(struct net_device *p);
> -static int loading_module = 1;
> -#else
> -static int loading_module;
> -#endif				// MODULE
>  
>  #ifdef DRIVERDEBUG
>  #define PRINTK(s, args...) printk(s, ## args)
> @@ -207,9 +184,9 @@
>  #define PRIV(dev) (&(((struct s_smc *)dev->priv)->os))
>  
>  /*
> - * ==============
> - * = skfp_probe =
> - * ==============
> + * =================
> + * = skfp_init_one =
> + * =================
>   *   
>   * Overview:
>   *   Probes for supported FDDI PCI controllers
> @@ -218,30 +195,11 @@
>   *   Condition code
>   *       
>   * Arguments:
> - *   dev - pointer to device information
> + *   pdev - pointer to PCI device information
>   *
>   * Functional Description:
> - *   This routine is called by the OS for each FDDI device name (fddi0,
> - *   fddi1,...,fddi6, fddi7) specified in drivers/net/Space.c.
> - *   If loaded as a module, it will detect and initialize all 
> - *   adapters the first time it is called.
> - *
> - *   Let's say that skfp_probe() is getting called to initialize fddi0.
> - *   Furthermore, let's say there are three supported controllers in the
> - *   system.  Before skfp_probe() leaves, devices fddi0, fddi1, and fddi2
> - *   will be initialized and a global flag will be set to indicate that
> - *   skfp_probe() has already been called.
> - *
> - *   However...the OS doesn't know that we've already initialized
> - *   devices fddi1 and fddi2 so skfp_probe() gets called again and again
> - *   until it reaches the end of the device list for FDDI (presently,
> - *   fddi7).  It's important that the driver "pretend" to probe for
> - *   devices fddi1 and fddi2 and return success.  Devices fddi3
> - *   through fddi7 will return failure since they weren't initialized.
> - *
> - *   This algorithm seems to work for the time being.  As other FDDI
> - *   drivers are written for Linux, a more generic approach (perhaps
> - *   similar to the Ethernet card approach) may need to be implemented.
> + *   This is now called by PCI driver registration process
> + *   for each board found.
>   *   
>   * Return Codes:
>   *   0           - This device (fddi0, fddi1, etc) configured successfully
> @@ -254,370 +212,176 @@
>   *   initialized and the board resources are read and stored in
>   *   the device structure.
>   */
> -static int skfp_probe(struct net_device *dev)
> +static __init int skfp_init_one(struct pci_dev *pdev,

I take back my private email... patch doesn't apply.

Can you please rediff, and also remove the above "__init" ?

	Jeff

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2003-12-16  5:43 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-12-05  0:39 [PATCH] skfddi - convert to new pci model Stephen Hemminger
2003-12-05  0:59 ` Alexander Viro
2003-12-05 23:12   ` Stephen Hemminger
2003-12-05 23:27     ` Alexander Viro
2003-12-16  5:43     ` Jeff Garzik

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).