[PATCH] hamradio/scc -

From: Stephen Hemminger (kpjsnmr@relay.tunkki.fi)
Date: Tue Sep 16 2003 - 02:23:35 EEST

  • Next message: Tim Neu: "Packet Problem"

    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 */
    -
    To unsubscribe from this list: send the line "unsubscribe linux-hams" in
    the body of a message to aycjqk.sjuywvhfa@mail.dy.fi
    More majordomo info at http://vger.kernel.org/majordomo-info.html



    This archive was generated by hypermail 2b30 : Tue Sep 16 2003 - 02:24:54 EEST