diff options
Diffstat (limited to 'drivers/char/pcmcia')
-rw-r--r-- | drivers/char/pcmcia/cm4000_cs.c | 118 | ||||
-rw-r--r-- | drivers/char/pcmcia/cm4040_cs.c | 23 | ||||
-rw-r--r-- | drivers/char/pcmcia/ipwireless/hardware.c | 24 | ||||
-rw-r--r-- | drivers/char/pcmcia/ipwireless/main.c | 1 | ||||
-rw-r--r-- | drivers/char/pcmcia/synclink_cs.c | 32 |
5 files changed, 121 insertions, 77 deletions
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index 4a933d41342..e4a4fbd37d7 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -32,8 +32,9 @@ #include <linux/fs.h> #include <linux/delay.h> #include <linux/bitrev.h> -#include <asm/uaccess.h> -#include <asm/io.h> +#include <linux/smp_lock.h> +#include <linux/uaccess.h> +#include <linux/io.h> #include <pcmcia/cs_types.h> #include <pcmcia/cs.h> @@ -1405,11 +1406,11 @@ static void stop_monitor(struct cm4000_dev *dev) DEBUGP(3, dev, "<- stop_monitor\n"); } -static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) +static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct cm4000_dev *dev = filp->private_data; unsigned int iobase = dev->p_dev->io.BasePort1; + struct inode *inode = filp->f_path.dentry->d_inode; struct pcmcia_device *link; int size; int rc; @@ -1426,38 +1427,42 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, DEBUGP(3, dev, "cmm_ioctl(device=%d.%d) %s\n", imajor(inode), iminor(inode), ioctl_names[_IOC_NR(cmd)]); + lock_kernel(); + rc = -ENODEV; link = dev_table[iminor(inode)]; if (!pcmcia_dev_present(link)) { DEBUGP(4, dev, "DEV_OK false\n"); - return -ENODEV; + goto out; } if (test_bit(IS_CMM_ABSENT, &dev->flags)) { DEBUGP(4, dev, "CMM_ABSENT flag set\n"); - return -ENODEV; + goto out; } + rc = -EINVAL; if (_IOC_TYPE(cmd) != CM_IOC_MAGIC) { DEBUGP(4, dev, "ioctype mismatch\n"); - return -EINVAL; + goto out; } if (_IOC_NR(cmd) > CM_IOC_MAXNR) { DEBUGP(4, dev, "iocnr mismatch\n"); - return -EINVAL; + goto out; } size = _IOC_SIZE(cmd); - rc = 0; + rc = -EFAULT; DEBUGP(4, dev, "iocdir=%.4x iocr=%.4x iocw=%.4x iocsize=%d cmd=%.4x\n", _IOC_DIR(cmd), _IOC_READ, _IOC_WRITE, size, cmd); if (_IOC_DIR(cmd) & _IOC_READ) { if (!access_ok(VERIFY_WRITE, argp, size)) - return -EFAULT; + goto out; } if (_IOC_DIR(cmd) & _IOC_WRITE) { if (!access_ok(VERIFY_READ, argp, size)) - return -EFAULT; + goto out; } + rc = 0; switch (cmd) { case CM_IOCGSTATUS: @@ -1477,9 +1482,9 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, if (test_bit(IS_BAD_CARD, &dev->flags)) status |= CM_BAD_CARD; if (copy_to_user(argp, &status, sizeof(int))) - return -EFAULT; + rc = -EFAULT; } - return 0; + break; case CM_IOCGATR: DEBUGP(4, dev, "... in CM_IOCGATR\n"); { @@ -1492,25 +1497,29 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, || (test_bit(IS_ATR_PRESENT, (void *)&dev->flags) != 0)))) { if (filp->f_flags & O_NONBLOCK) - return -EAGAIN; - return -ERESTARTSYS; + rc = -EAGAIN; + else + rc = -ERESTARTSYS; + break; } + rc = -EFAULT; if (test_bit(IS_ATR_VALID, &dev->flags) == 0) { tmp = -1; if (copy_to_user(&(atreq->atr_len), &tmp, sizeof(int))) - return -EFAULT; + break; } else { if (copy_to_user(atreq->atr, dev->atr, dev->atr_len)) - return -EFAULT; + break; tmp = dev->atr_len; if (copy_to_user(&(atreq->atr_len), &tmp, sizeof(int))) - return -EFAULT; + break; } - return 0; + rc = 0; + break; } case CM_IOCARDOFF: @@ -1538,8 +1547,10 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, || (test_and_set_bit(LOCK_IO, (void *)&dev->flags) == 0)))) { if (filp->f_flags & O_NONBLOCK) - return -EAGAIN; - return -ERESTARTSYS; + rc = -EAGAIN; + else + rc = -ERESTARTSYS; + break; } /* Set Flags0 = 0x42 */ DEBUGP(4, dev, "Set Flags0=0x42 \n"); @@ -1554,8 +1565,10 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, || (test_bit(IS_ATR_VALID, (void *)&dev->flags) != 0)))) { if (filp->f_flags & O_NONBLOCK) - return -EAGAIN; - return -ERESTARTSYS; + rc = -EAGAIN; + else + rc = -ERESTARTSYS; + break; } } /* release lock */ @@ -1568,8 +1581,10 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, struct ptsreq krnptsreq; if (copy_from_user(&krnptsreq, argp, - sizeof(struct ptsreq))) - return -EFAULT; + sizeof(struct ptsreq))) { + rc = -EFAULT; + break; + } rc = 0; DEBUGP(4, dev, "... in CM_IOCSPTS\n"); @@ -1580,8 +1595,10 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, || (test_bit(IS_ATR_PRESENT, (void *)&dev->flags) != 0)))) { if (filp->f_flags & O_NONBLOCK) - return -EAGAIN; - return -ERESTARTSYS; + rc = -EAGAIN; + else + rc = -ERESTARTSYS; + break; } /* get IO lock */ if (wait_event_interruptible @@ -1590,8 +1607,10 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, || (test_and_set_bit(LOCK_IO, (void *)&dev->flags) == 0)))) { if (filp->f_flags & O_NONBLOCK) - return -EAGAIN; - return -ERESTARTSYS; + rc = -EAGAIN; + else + rc = -ERESTARTSYS; + break; } if ((rc = set_protocol(dev, &krnptsreq)) != 0) { @@ -1604,7 +1623,7 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, wake_up_interruptible(&dev->ioq); } - return rc; + break; #ifdef PCMCIA_DEBUG case CM_IOSDBGLVL: /* set debug log level */ { @@ -1612,18 +1631,20 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, old_pc_debug = pc_debug; if (copy_from_user(&pc_debug, argp, sizeof(int))) - return -EFAULT; - - if (old_pc_debug != pc_debug) + rc = -EFAULT; + else if (old_pc_debug != pc_debug) DEBUGP(0, dev, "Changed debug log level " "to %i\n", pc_debug); } - return rc; + break; #endif default: DEBUGP(4, dev, "... in default (unknown IOCTL code)\n"); - return -EINVAL; + rc = -ENOTTY; } +out: + unlock_kernel(); + return rc; } static int cmm_open(struct inode *inode, struct file *filp) @@ -1631,16 +1652,22 @@ static int cmm_open(struct inode *inode, struct file *filp) struct cm4000_dev *dev; struct pcmcia_device *link; int minor = iminor(inode); + int ret; if (minor >= CM4000_MAX_DEV) return -ENODEV; + lock_kernel(); link = dev_table[minor]; - if (link == NULL || !pcmcia_dev_present(link)) - return -ENODEV; + if (link == NULL || !pcmcia_dev_present(link)) { + ret = -ENODEV; + goto out; + } - if (link->open) - return -EBUSY; + if (link->open) { + ret = -EBUSY; + goto out; + } dev = link->priv; filp->private_data = dev; @@ -1660,8 +1687,10 @@ static int cmm_open(struct inode *inode, struct file *filp) * vaild = block until valid (or card * inserted) */ - if (filp->f_flags & O_NONBLOCK) - return -EAGAIN; + if (filp->f_flags & O_NONBLOCK) { + ret = -EAGAIN; + goto out; + } dev->mdelay = T_50MSEC; @@ -1671,7 +1700,10 @@ static int cmm_open(struct inode *inode, struct file *filp) link->open = 1; /* only one open per device */ DEBUGP(2, dev, "<- cmm_open\n"); - return nonseekable_open(inode, filp); + ret = nonseekable_open(inode, filp); +out: + unlock_kernel(); + return ret; } static int cmm_close(struct inode *inode, struct file *filp) @@ -1897,7 +1929,7 @@ static const struct file_operations cm4000_fops = { .owner = THIS_MODULE, .read = cmm_read, .write = cmm_write, - .ioctl = cmm_ioctl, + .unlocked_ioctl = cmm_ioctl, .open = cmm_open, .release= cmm_close, }; diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index 035084c0732..6181f8a9b0b 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c @@ -26,6 +26,7 @@ #include <linux/fs.h> #include <linux/delay.h> #include <linux/poll.h> +#include <linux/smp_lock.h> #include <linux/wait.h> #include <asm/uaccess.h> #include <asm/io.h> @@ -448,23 +449,30 @@ static int cm4040_open(struct inode *inode, struct file *filp) struct reader_dev *dev; struct pcmcia_device *link; int minor = iminor(inode); + int ret; if (minor >= CM_MAX_DEV) return -ENODEV; + lock_kernel(); link = dev_table[minor]; - if (link == NULL || !pcmcia_dev_present(link)) - return -ENODEV; + if (link == NULL || !pcmcia_dev_present(link)) { + ret = -ENODEV; + goto out; + } - if (link->open) - return -EBUSY; + if (link->open) { + ret = -EBUSY; + goto out; + } dev = link->priv; filp->private_data = dev; if (filp->f_flags & O_NONBLOCK) { DEBUGP(4, dev, "filep->f_flags O_NONBLOCK set\n"); - return -EAGAIN; + ret = -EAGAIN; + goto out; } link->open = 1; @@ -473,7 +481,10 @@ static int cm4040_open(struct inode *inode, struct file *filp) mod_timer(&dev->poll_timer, jiffies + POLL_PERIOD); DEBUGP(2, dev, "<- cm4040_open (successfully)\n"); - return nonseekable_open(inode, filp); + ret = nonseekable_open(inode, filp); +out: + unlock_kernel(); + return ret; } static int cm4040_close(struct inode *inode, struct file *filp) diff --git a/drivers/char/pcmcia/ipwireless/hardware.c b/drivers/char/pcmcia/ipwireless/hardware.c index fa9d3c945f3..929101ecbae 100644 --- a/drivers/char/pcmcia/ipwireless/hardware.c +++ b/drivers/char/pcmcia/ipwireless/hardware.c @@ -251,10 +251,11 @@ struct ipw_hardware { int init_loops; struct timer_list setup_timer; + /* Flag if hw is ready to send next packet */ int tx_ready; - struct list_head tx_queue[NL_NUM_OF_PRIORITIES]; - /* True if any packets are queued for transmission */ + /* Count of pending packets to be sent */ int tx_queued; + struct list_head tx_queue[NL_NUM_OF_PRIORITIES]; int rx_bytes_queued; struct list_head rx_queue; @@ -404,6 +405,8 @@ static int do_send_fragment(struct ipw_hardware *hw, const unsigned char *data, spin_lock_irqsave(&hw->spinlock, flags); + hw->tx_ready = 0; + if (hw->hw_version == HW_VERSION_1) { outw((unsigned short) length, hw->base_port + IODWR); @@ -492,6 +495,7 @@ static int do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet) spin_lock_irqsave(&hw->spinlock, flags); list_add(&packet->queue, &hw->tx_queue[0]); + hw->tx_queued++; spin_unlock_irqrestore(&hw->spinlock, flags); } else { if (packet->packet_callback) @@ -586,8 +590,10 @@ static struct ipw_rx_packet *pool_allocate(struct ipw_hardware *hw, packet = kmalloc(sizeof(struct ipw_rx_packet) + old_packet->length + minimum_free_space, GFP_ATOMIC); - if (!packet) + if (!packet) { + kfree(old_packet); return NULL; + } memcpy(packet, old_packet, sizeof(struct ipw_rx_packet) + old_packet->length); @@ -949,12 +955,10 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) unsigned long flags; spin_lock_irqsave(&hw->spinlock, flags); - if (hw->tx_queued && hw->tx_ready != 0) { + if (hw->tx_queued && hw->tx_ready) { int priority; struct ipw_tx_packet *packet = NULL; - hw->tx_ready--; - /* Pick a packet */ for (priority = 0; priority < priority_limit; priority++) { if (!list_empty(&hw->tx_queue[priority])) { @@ -963,6 +967,7 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) struct ipw_tx_packet, queue); + hw->tx_queued--; list_del(&packet->queue); break; @@ -973,6 +978,7 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) spin_unlock_irqrestore(&hw->spinlock, flags); return 0; } + spin_unlock_irqrestore(&hw->spinlock, flags); /* Send */ @@ -1063,7 +1069,7 @@ static irqreturn_t ipwireless_handle_v1_interrupt(int irq, if (irqn & IR_TXINTR) { ack |= IR_TXINTR; spin_lock_irqsave(&hw->spinlock, flags); - hw->tx_ready++; + hw->tx_ready = 1; spin_unlock_irqrestore(&hw->spinlock, flags); } /* Received data */ @@ -1170,7 +1176,7 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq, if (memrxdone & MEMRX_RX_DONE) { writew(0, &hw->memory_info_regs->memreg_rx_done); spin_lock_irqsave(&hw->spinlock, flags); - hw->tx_ready++; + hw->tx_ready = 1; spin_unlock_irqrestore(&hw->spinlock, flags); tx = 1; } @@ -1234,7 +1240,7 @@ static void send_packet(struct ipw_hardware *hw, int priority, spin_lock_irqsave(&hw->spinlock, flags); list_add_tail(&packet->queue, &hw->tx_queue[priority]); - hw->tx_queued = 1; + hw->tx_queued++; spin_unlock_irqrestore(&hw->spinlock, flags); flush_packets_to_hw(hw); diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c index 00c7f8407e3..cc7dcea2d28 100644 --- a/drivers/char/pcmcia/ipwireless/main.c +++ b/drivers/char/pcmcia/ipwireless/main.c @@ -28,7 +28,6 @@ #include <linux/sched.h> #include <linux/slab.h> -#include <pcmcia/version.h> #include <pcmcia/cisreg.h> #include <pcmcia/device_id.h> #include <pcmcia/ss.h> diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 1dd0e992c83..b694d430f10 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -514,8 +514,8 @@ static void ldisc_receive_buf(struct tty_struct *tty, return; ld = tty_ldisc_ref(tty); if (ld) { - if (ld->receive_buf) - ld->receive_buf(tty, data, flags, count); + if (ld->ops->receive_buf) + ld->ops->receive_buf(tty, data, flags, count); tty_ldisc_deref(ld); } } @@ -3886,9 +3886,8 @@ static bool rx_get_frame(MGSLPC_INFO *info) framesize = 0; #if SYNCLINK_GENERIC_HDLC { - struct net_device_stats *stats = hdlc_stats(info->netdev); - stats->rx_errors++; - stats->rx_frame_errors++; + info->netdev->stats.rx_errors++; + info->netdev->stats.rx_frame_errors++; } #endif } else @@ -4144,7 +4143,6 @@ static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev) { MGSLPC_INFO *info = dev_to_port(dev); - struct net_device_stats *stats = hdlc_stats(dev); unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) @@ -4159,8 +4157,8 @@ static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev) info->tx_put = info->tx_count = skb->len; /* update network statistics */ - stats->tx_packets++; - stats->tx_bytes += skb->len; + dev->stats.tx_packets++; + dev->stats.tx_bytes += skb->len; /* done with socket buffer, so free it */ dev_kfree_skb(skb); @@ -4376,14 +4374,13 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) static void hdlcdev_tx_timeout(struct net_device *dev) { MGSLPC_INFO *info = dev_to_port(dev); - struct net_device_stats *stats = hdlc_stats(dev); unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) printk("hdlcdev_tx_timeout(%s)\n",dev->name); - stats->tx_errors++; - stats->tx_aborted_errors++; + dev->stats.tx_errors++; + dev->stats.tx_aborted_errors++; spin_lock_irqsave(&info->lock,flags); tx_stop(info); @@ -4416,27 +4413,26 @@ static void hdlcdev_rx(MGSLPC_INFO *info, char *buf, int size) { struct sk_buff *skb = dev_alloc_skb(size); struct net_device *dev = info->netdev; - struct net_device_stats *stats = hdlc_stats(dev); if (debug_level >= DEBUG_LEVEL_INFO) printk("hdlcdev_rx(%s)\n",dev->name); if (skb == NULL) { printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", dev->name); - stats->rx_dropped++; + dev->stats.rx_dropped++; return; } - memcpy(skb_put(skb, size),buf,size); + memcpy(skb_put(skb, size), buf, size); - skb->protocol = hdlc_type_trans(skb, info->netdev); + skb->protocol = hdlc_type_trans(skb, dev); - stats->rx_packets++; - stats->rx_bytes += size; + dev->stats.rx_packets++; + dev->stats.rx_bytes += size; netif_rx(skb); - info->netdev->last_rx = jiffies; + dev->last_rx = jiffies; } /** |