aboutsummaryrefslogtreecommitdiff
path: root/drivers/char/pcmcia
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/pcmcia')
-rw-r--r--drivers/char/pcmcia/cm4000_cs.c118
-rw-r--r--drivers/char/pcmcia/cm4040_cs.c23
-rw-r--r--drivers/char/pcmcia/ipwireless/hardware.c24
-rw-r--r--drivers/char/pcmcia/ipwireless/main.c1
-rw-r--r--drivers/char/pcmcia/synclink_cs.c32
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;
}
/**