netdev
[Top] [All Lists]

[PATCH] hamradio/scc -

To: Jeff Garzik <jgarzik@xxxxxxxxx>
Subject: [PATCH] hamradio/scc -
From: Stephen Hemminger <shemminger@xxxxxxxx>
Date: Mon, 15 Sep 2003 16:23:35 -0700
Cc: linux-hams@xxxxxxxxxxxxxxx, netdev@xxxxxxxxxxx
Organization: Open Source Development Lab
Sender: netdev-bounce@xxxxxxxxxxx
Update hamradio/scc for 2.6.0-test5
        - use seq_file for /proc
        - get rid of dev_get()
        - use alloc_netdev

Don't have hardware, but can load/unload the module fine.

diff -Nru a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
--- a/drivers/net/hamradio/scc.c        Mon Sep 15 16:20:49 2003
+++ b/drivers/net/hamradio/scc.c        Mon Sep 15 16:20:49 2003
@@ -171,6 +171,7 @@
 #include <linux/ctype.h>
 #include <linux/kernel.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 #include <net/ax25.h>
 
@@ -202,8 +203,8 @@
 static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs *regs);
 static void scc_init_timer(struct scc_channel *scc);
 
-static int scc_net_setup(struct scc_channel *scc, unsigned char *name, int 
addev);
-static int scc_net_init(struct net_device *dev);
+static int scc_net_alloc(const char *name, struct scc_channel *scc);
+static void scc_net_setup(struct net_device *dev);
 static int scc_net_open(struct net_device *dev);
 static int scc_net_close(struct net_device *dev);
 static void scc_net_rx(struct scc_channel *scc, struct sk_buff *skb);
@@ -235,7 +236,7 @@
 
 /* These provide interrupt save 2-step access to the Z8530 registers */
 
-static spinlock_t iolock;      /* Guards paired accesses */
+static spinlock_t iolock = SPIN_LOCK_UNLOCKED; /* Guards paired accesses */
 
 static inline unsigned char InReg(io_port port, unsigned char reg)
 {
@@ -1512,34 +1513,28 @@
  * Allocate device structure, err, instance, and register driver
  */
 
-static int scc_net_setup(struct scc_channel *scc, unsigned char *name, int 
addev)
+static int scc_net_alloc(const char *name, struct scc_channel *scc)
 {
+       int err;
        struct net_device *dev;
 
-       if (dev_get(name))
-       {
-               printk(KERN_INFO "Z8530drv: device %s already exists.\n", name);
-               return -EEXIST;
-       }
-
-       if ((scc->dev = (struct net_device *) kmalloc(sizeof(struct 
net_device), GFP_KERNEL)) == NULL)
+       dev = alloc_netdev(0, name, scc_net_setup);
+       if (!dev) 
                return -ENOMEM;
 
-       dev = scc->dev;
-       memset(dev, 0, sizeof(struct net_device));
-
-       strcpy(dev->name, name);
-       dev->priv = (void *) scc;
-       dev->init = scc_net_init;
-
+       dev->priv = scc;
+       scc->dev = dev;
        spin_lock_init(&scc->lock);
-       
-       if ((addev? register_netdevice(dev) : register_netdev(dev)) != 0) {
-               kfree(dev);
-                return -EIO;
-        }
 
-       SET_MODULE_OWNER(dev);
+       err = register_netdev(dev);
+       if (err) {
+               printk(KERN_ERR "%s: can't register network device (%d)\n", 
+                      name, err);
+               free_netdev(dev);
+               scc->dev = NULL;
+               return err;
+       }
+
        return 0;
 }
 
@@ -1556,8 +1551,9 @@
 
 /* ----> Initialize device <----- */
 
-static int scc_net_init(struct net_device *dev)
+static void scc_net_setup(struct net_device *dev)
 {
+       SET_MODULE_OWNER(dev);
        dev->tx_queue_len    = 16;      /* should be enough... */
 
        dev->open            = scc_net_open;
@@ -1581,7 +1577,6 @@
        dev->mtu = AX25_DEF_PACLEN;
        dev->addr_len = AX25_ADDR_LEN;
 
-       return 0;
 }
 
 /* ----> open network device <---- */
@@ -1719,10 +1714,10 @@
        struct scc_mem_config memcfg;
        struct scc_hw_config hwcfg;
        struct scc_calibrate cal;
+       struct scc_channel *scc;
        int chan;
-       unsigned char device_name[10];
+       unsigned char device_name[IFNAMSIZ];
        void *arg;
-       struct scc_channel *scc;
        
        scc = (struct scc_channel *) dev->priv;
        arg = (void *) ifr->ifr_data;
@@ -1828,8 +1823,10 @@
                                {
                                        
request_region(SCC_Info[2*Nchips+chan].ctrl, 1, "scc ctrl");
                                        
request_region(SCC_Info[2*Nchips+chan].data, 1, "scc data");
-                                       if (Nchips+chan != 0)
-                                               
scc_net_setup(&SCC_Info[2*Nchips+chan], device_name, 1);
+                                       if (Nchips+chan != 0 &&
+                                           scc_net_alloc(device_name, 
+                                                         
&SCC_Info[2*Nchips+chan]))
+                                           return -EINVAL;
                                }
                        }
                        
@@ -1978,39 +1975,58 @@
 /* *           dump statistics to /proc/net/z8530drv                 * */
 /* ******************************************************************** */
 
+#ifdef CONFIG_PROC_FS
 
-static int scc_net_get_info(char *buffer, char **start, off_t offset, int 
length)
+static inline struct scc_channel *scc_net_seq_idx(loff_t pos)
 {
-       struct scc_channel *scc;
-       struct scc_kiss *kiss;
-       struct scc_stat *stat;
-       int len = 0;
-       off_t pos = 0;
-       off_t begin = 0;
        int k;
 
-       len += sprintf(buffer, "z8530drv-"VERSION"\n");
-
-       if (!Driver_Initialized)
-       {
-               len += sprintf(buffer+len, "not initialized\n");
-               goto done;
+       for (k = 0; k < Nchips*2; ++k) {
+               if (!SCC_Info[k].init) 
+                       continue;
+               if (pos-- == 0)
+                       return &SCC_Info[k];
        }
+       return NULL;
+}
 
-       if (!Nchips)
-       {
-               len += sprintf(buffer+len, "chips missing\n");
-               goto done;
+static void *scc_net_seq_start(struct seq_file *seq, loff_t *pos)
+{
+       return *pos ? scc_net_seq_idx(*pos - 1) : SEQ_START_TOKEN;
+       
+}
+
+static void *scc_net_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+       unsigned k;
+       struct scc_channel *scc = v;
+       ++*pos;
+       
+       for (k = (v == SEQ_START_TOKEN) ? 0 : (scc - SCC_Info)+1;
+            k < Nchips*2; ++k) {
+               if (SCC_Info[k].init) 
+                       return &SCC_Info[k];
        }
+       return NULL;
+}
 
-       for (k = 0; k < Nchips*2; k++)
-       {
-               scc = &SCC_Info[k];
-               stat = &scc->stat;
-               kiss = &scc->kiss;
+static void scc_net_seq_stop(struct seq_file *seq, void *v)
+{
+}
+
+static int scc_net_seq_show(struct seq_file *seq, void *v)
+{
+       if (v == SEQ_START_TOKEN) {
+               seq_puts(seq, "z8530drv-"VERSION"\n");
+       } else if (!Driver_Initialized) {
+               seq_puts(seq, "not initialized\n");
+       } else if (!Nchips) {
+               seq_puts(seq, "chips missing\n");
+       } else {
+               const struct scc_channel *scc = v;
+               const struct scc_stat *stat = &scc->stat;
+               const struct scc_kiss *kiss = &scc->kiss;
 
-               if (!scc->init)
-                       continue;
 
                /* dev  data ctrl irq clock brand enh vector special option 
                 *      baud nrz clocksrc softdcd bufsize
@@ -2021,24 +2037,24 @@
                 *      R ## ## XX ## ## ## ## ## XX ## ## ## ## ## ## ##
                 */
 
-               len += sprintf(buffer+len, "%s\t%3.3lx %3.3lx %d %lu %2.2x %d 
%3.3lx %3.3lx %d\n",
+               seq_printf(seq, "%s\t%3.3lx %3.3lx %d %lu %2.2x %d %3.3lx 
%3.3lx %d\n",
                                scc->dev->name,
                                scc->data, scc->ctrl, scc->irq, scc->clock, 
scc->brand,
                                scc->enhanced, Vector_Latch, scc->special,
                                scc->option);
-               len += sprintf(buffer+len, "\t%lu %d %d %d %d\n",
+               seq_printf(seq, "\t%lu %d %d %d %d\n",
                                scc->modem.speed, scc->modem.nrz,
                                scc->modem.clocksrc, kiss->softdcd,
                                stat->bufsize);
-               len += sprintf(buffer+len, "\t%lu %lu %lu %lu\n",
+               seq_printf(seq, "\t%lu %lu %lu %lu\n",
                                stat->rxints, stat->txints, stat->exints, 
stat->spints);
-               len += sprintf(buffer+len, "\t%lu %lu %d / %lu %lu %d / %d 
%d\n",
+               seq_printf(seq, "\t%lu %lu %d / %lu %lu %d / %d %d\n",
                                stat->rxframes, stat->rxerrs, stat->rx_over,
                                stat->txframes, stat->txerrs, stat->tx_under,
                                stat->nospace,  stat->tx_state);
 
 #define K(x) kiss->x
-               len += sprintf(buffer+len, "\t%d %d %d %d %d %d %d %d %d %d %d 
%d\n",
+               seq_printf(seq, "\t%d %d %d %d %d %d %d %d %d %d %d %d\n",
                                K(txdelay), K(persist), K(slottime), 
K(tailtime),
                                K(fulldup), K(waittime), K(mintime), 
K(maxkeyup),
                                K(idletime), K(maxdefer), K(tx_inhibit), 
K(group));
@@ -2047,43 +2063,49 @@
                {
                        int reg;
 
-               len += sprintf(buffer+len, "\tW ");
+               seq_printf(seq, "\tW ");
                        for (reg = 0; reg < 16; reg++)
-                               len += sprintf(buffer+len, "%2.2x ", 
scc->wreg[reg]);
-                       len += sprintf(buffer+len, "\n");
+                               seq_printf(seq, "%2.2x ", scc->wreg[reg]);
+                       seq_printf(seq, "\n");
                        
-               len += sprintf(buffer+len, "\tR %2.2x %2.2x XX ", 
InReg(scc->ctrl,R0), InReg(scc->ctrl,R1));
+               seq_printf(seq, "\tR %2.2x %2.2x XX ", InReg(scc->ctrl,R0), 
InReg(scc->ctrl,R1));
                        for (reg = 3; reg < 8; reg++)
-                               len += sprintf(buffer+len, "%2.2x ", 
InReg(scc->ctrl, reg));
-                       len += sprintf(buffer+len, "XX ");
+                               seq_printf(seq, "%2.2x ", InReg(scc->ctrl, 
reg));
+                       seq_printf(seq, "XX ");
                        for (reg = 9; reg < 16; reg++)
-                               len += sprintf(buffer+len, "%2.2x ", 
InReg(scc->ctrl, reg));
-                       len += sprintf(buffer+len, "\n");
+                               seq_printf(seq, "%2.2x ", InReg(scc->ctrl, 
reg));
+                       seq_printf(seq, "\n");
                }
 #endif
-               len += sprintf(buffer+len, "\n");
-
-                pos = begin + len;
-
-                if (pos < offset) {
-                        len   = 0;
-                        begin = pos;
-                }
-
-                if (pos > offset + length)
-                        break;
+               seq_putc(seq, '\n');
        }
 
-done:
+        return 0;
+}
 
-        *start = buffer + (offset - begin);
-        len   -= (offset - begin);
+static struct seq_operations scc_net_seq_ops = {
+       .start  = scc_net_seq_start,
+       .next   = scc_net_seq_next,
+       .stop   = scc_net_seq_stop,
+       .show   = scc_net_seq_show,
+};
 
-        if (len > length) len = length;
 
-        return len;
+static int scc_net_seq_open(struct inode *inode, struct file *file)
+{
+       return seq_open(file, &scc_net_seq_ops);
 }
 
+static struct file_operations scc_net_seq_fops = {
+       .owner   = THIS_MODULE,
+       .open    = scc_net_seq_open,
+       .read    = seq_read,
+       .llseek  = seq_lseek,
+       .release = seq_release_private,
+};
+
+#endif /* CONFIG_PROC_FS */
+
  
 /* ******************************************************************** */
 /* *                   Init SCC driver                               * */
@@ -2091,23 +2113,18 @@
 
 static int __init scc_init_driver (void)
 {
-       int result;
-       char devname[10];
+       char devname[IFNAMSIZ];
        
        printk(banner);
        
-       spin_lock_init(&iolock);
-       
        sprintf(devname,"%s0", SCC_DriverName);
        
-       result = scc_net_setup(SCC_Info, devname, 0);
-       if (result)
-       {
+       if (scc_net_alloc(devname, SCC_Info)) {
                printk(KERN_ERR "z8530drv: cannot initialize module\n");
-               return result;
+               return -EIO;
        }
 
-       proc_net_create("z8530drv", 0, scc_net_get_info);
+       proc_net_fops_create("z8530drv", 0, &scc_net_seq_fops);
 
        return 0;
 }
@@ -2117,11 +2134,12 @@
        io_port ctrl;
        int k;
        struct scc_channel *scc;
+       struct net_device *dev;
        
-       if (Nchips == 0)
+       if (Nchips == 0 && (dev = SCC_Info[0].dev)) 
        {
-               unregister_netdev(SCC_Info[0].dev);
-               free_netdev(SCC_Info[0].dev);
+               unregister_netdev(dev);
+               free_netdev(dev);
        }
 
        /* Guard against chip prattle */

<Prev in Thread] Current Thread [Next in Thread>