aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/irda/stir4200.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/irda/stir4200.c')
-rw-r--r--drivers/net/irda/stir4200.c199
1 files changed, 76 insertions, 123 deletions
diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
index 31867e4b891..dd1bd1060ec 100644
--- a/drivers/net/irda/stir4200.c
+++ b/drivers/net/irda/stir4200.c
@@ -15,8 +15,7 @@
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
+* the Free Software Foundation; either version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -42,7 +41,6 @@
#include <linux/kernel.h>
#include <linux/types.h>
-#include <linux/init.h>
#include <linux/time.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
@@ -50,15 +48,16 @@
#include <linux/delay.h>
#include <linux/usb.h>
#include <linux/crc32.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
#include <net/irda/irda.h>
-#include <net/irda/irlap.h>
#include <net/irda/irda_device.h>
#include <net/irda/wrapper.h>
#include <net/irda/crc.h>
#include <asm/byteorder.h>
#include <asm/unaligned.h>
-MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>");
+MODULE_AUTHOR("Stephen Hemminger <shemminger@linux-foundation.org>");
MODULE_DESCRIPTION("IrDA-USB Dongle Driver for SigmaTel STIr4200");
MODULE_LICENSE("GPL");
@@ -142,14 +141,9 @@ enum StirCtrl2Mask {
};
enum StirFifoCtlMask {
- FIFOCTL_EOF = 0x80,
- FIFOCTL_UNDER = 0x40,
- FIFOCTL_OVER = 0x20,
FIFOCTL_DIR = 0x10,
FIFOCTL_CLR = 0x08,
FIFOCTL_EMPTY = 0x04,
- FIFOCTL_RXERR = 0x02,
- FIFOCTL_TXERR = 0x01,
};
enum StirDiagMask {
@@ -169,13 +163,11 @@ struct stir_cb {
struct usb_device *usbdev; /* init: probe_irda */
struct net_device *netdev; /* network layer */
struct irlap_cb *irlap; /* The link layer we are binded to */
- struct net_device_stats stats; /* network statistics */
+
struct qos_info qos;
unsigned speed; /* Current speed */
- wait_queue_head_t thr_wait; /* transmit thread wakeup */
- struct completion thr_exited;
- pid_t thr_pid;
+ struct task_struct *thread; /* transmit thread */
struct sk_buff *tx_pending;
void *io_buf; /* transmit/receive buffer */
@@ -226,7 +218,7 @@ static inline int read_reg(struct stir_cb *stir, __u16 reg,
static inline int isfir(u32 speed)
{
- return (speed == 4000000);
+ return speed == 4000000;
}
/*
@@ -330,16 +322,16 @@ static void fir_eof(struct stir_cb *stir)
pr_debug("%s: short frame len %d\n",
stir->netdev->name, len);
- ++stir->stats.rx_errors;
- ++stir->stats.rx_length_errors;
+ ++stir->netdev->stats.rx_errors;
+ ++stir->netdev->stats.rx_length_errors;
return;
}
fcs = ~(crc32_le(~0, rx_buff->data, len));
- if (fcs != le32_to_cpu(get_unaligned((u32 *)(rx_buff->data+len)))) {
+ if (fcs != get_unaligned_le32(rx_buff->data + len)) {
pr_debug("crc error calc 0x%x len %d\n", fcs, len);
- stir->stats.rx_errors++;
- stir->stats.rx_crc_errors++;
+ stir->netdev->stats.rx_errors++;
+ stir->netdev->stats.rx_crc_errors++;
return;
}
@@ -347,16 +339,16 @@ static void fir_eof(struct stir_cb *stir)
if (len < IRDA_RX_COPY_THRESHOLD) {
nskb = dev_alloc_skb(len + 1);
if (unlikely(!nskb)) {
- ++stir->stats.rx_dropped;
+ ++stir->netdev->stats.rx_dropped;
return;
}
skb_reserve(nskb, 1);
skb = nskb;
- memcpy(nskb->data, rx_buff->data, len);
+ skb_copy_to_linear_data(nskb, rx_buff->data, len);
} else {
nskb = dev_alloc_skb(rx_buff->truesize);
if (unlikely(!nskb)) {
- ++stir->stats.rx_dropped;
+ ++stir->netdev->stats.rx_dropped;
return;
}
skb_reserve(nskb, 1);
@@ -367,14 +359,14 @@ static void fir_eof(struct stir_cb *stir)
skb_put(skb, len);
- skb->mac.raw = skb->data;
+ skb_reset_mac_header(skb);
skb->protocol = htons(ETH_P_IRDA);
skb->dev = stir->netdev;
netif_rx(skb);
- stir->stats.rx_packets++;
- stir->stats.rx_bytes += len;
+ stir->netdev->stats.rx_packets++;
+ stir->netdev->stats.rx_bytes += len;
rx_buff->data = rx_buff->head;
rx_buff->len = 0;
@@ -444,7 +436,7 @@ static void stir_fir_chars(struct stir_cb *stir,
if (unlikely(rx_buff->len >= rx_buff->truesize)) {
pr_debug("%s: fir frame exceeds %d\n",
stir->netdev->name, rx_buff->truesize);
- ++stir->stats.rx_over_errors;
+ ++stir->netdev->stats.rx_over_errors;
goto error_recovery;
}
@@ -452,10 +444,10 @@ static void stir_fir_chars(struct stir_cb *stir,
continue;
frame_error:
- ++stir->stats.rx_frame_errors;
+ ++stir->netdev->stats.rx_frame_errors;
error_recovery:
- ++stir->stats.rx_errors;
+ ++stir->netdev->stats.rx_errors;
rx_buff->state = OUTSIDE_FRAME;
rx_buff->in_frame = FALSE;
}
@@ -468,7 +460,7 @@ static void stir_sir_chars(struct stir_cb *stir,
int i;
for (i = 0; i < len; i++)
- async_unwrap_char(stir->netdev, &stir->stats,
+ async_unwrap_char(stir->netdev, &stir->netdev->stats,
&stir->rx_buff, bytes[i]);
}
@@ -513,7 +505,7 @@ static int change_speed(struct stir_cb *stir, unsigned speed)
goto found;
}
- warn("%s: invalid speed %d", stir->netdev->name, speed);
+ dev_warn(&stir->netdev->dev, "invalid speed %d\n", speed);
return -EINVAL;
found:
@@ -567,7 +559,8 @@ static int change_speed(struct stir_cb *stir, unsigned speed)
/*
* Called from net/core when new frame is available.
*/
-static int stir_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
+static netdev_tx_t stir_hard_xmit(struct sk_buff *skb,
+ struct net_device *netdev)
{
struct stir_cb *stir = netdev_priv(netdev);
@@ -577,7 +570,7 @@ static int stir_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
SKB_LINEAR_ASSERT(skb);
skb = xchg(&stir->tx_pending, skb);
- wake_up(&stir->thr_wait);
+ wake_up_process(stir->thread);
/* this should never happen unless stop/wakeup problem */
if (unlikely(skb)) {
@@ -585,7 +578,7 @@ static int stir_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
dev_kfree_skb(skb);
}
- return 0;
+ return NETDEV_TX_OK;
}
/*
@@ -598,14 +591,15 @@ static int fifo_txwait(struct stir_cb *stir, int space)
{
int err;
unsigned long count, status;
+ unsigned long prev_count = 0x1fff;
/* Read FIFO status and count */
- for(;;) {
+ for (;; prev_count = count) {
err = read_reg(stir, REG_FIFOCTL, stir->fifo_status,
FIFO_REGS_SIZE);
if (unlikely(err != FIFO_REGS_SIZE)) {
- warn("%s: FIFO register read error: %d",
- stir->netdev->name, err);
+ dev_warn(&stir->netdev->dev,
+ "FIFO register read error: %d\n", err);
return err;
}
@@ -616,36 +610,27 @@ static int fifo_txwait(struct stir_cb *stir, int space)
pr_debug("fifo status 0x%lx count %lu\n", status, count);
- /* error when receive/transmit fifo gets confused */
- if (status & FIFOCTL_RXERR) {
- stir->stats.rx_fifo_errors++;
- stir->stats.rx_errors++;
- break;
- }
-
- if (status & FIFOCTL_TXERR) {
- stir->stats.tx_fifo_errors++;
- stir->stats.tx_errors++;
- break;
- }
-
/* is fifo receiving already, or empty */
- if (!(status & FIFOCTL_DIR)
- || (status & FIFOCTL_EMPTY))
+ if (!(status & FIFOCTL_DIR) ||
+ (status & FIFOCTL_EMPTY))
return 0;
if (signal_pending(current))
return -EINTR;
/* shutting down? */
- if (!netif_running(stir->netdev)
- || !netif_device_present(stir->netdev))
+ if (!netif_running(stir->netdev) ||
+ !netif_device_present(stir->netdev))
return -ESHUTDOWN;
/* only waiting for some space */
if (space >= 0 && STIR_FIFO_SIZE - 4 > space + count)
return 0;
+ /* queue confused */
+ if (prev_count < count)
+ break;
+
/* estimate transfer time for remaining chars */
msleep((count * 8000) / stir->speed);
}
@@ -707,7 +692,7 @@ static void receive_stop(struct stir_cb *stir)
usb_kill_urb(stir->rx_urb);
if (stir->rx_buff.in_frame)
- stir->stats.collisions++;
+ stir->netdev->stats.collisions++;
}
/*
* Wrap data in socket buffer and send it.
@@ -733,15 +718,15 @@ static void stir_send(struct stir_cb *stir, struct sk_buff *skb)
if (!first_frame)
fifo_txwait(stir, wraplen);
- stir->stats.tx_packets++;
- stir->stats.tx_bytes += skb->len;
+ stir->netdev->stats.tx_packets++;
+ stir->netdev->stats.tx_bytes += skb->len;
stir->netdev->trans_start = jiffies;
pr_debug("send %d (%d)\n", skb->len, wraplen);
if (usb_bulk_msg(stir->usbdev, usb_sndbulkpipe(stir->usbdev, 1),
stir->io_buf, wraplen,
NULL, TRANSMIT_TIMEOUT))
- stir->stats.tx_errors++;
+ stir->netdev->stats.tx_errors++;
}
/*
@@ -753,13 +738,7 @@ static int stir_transmit_thread(void *arg)
struct net_device *dev = stir->netdev;
struct sk_buff *skb;
- daemonize("%s", dev->name);
- allow_signal(SIGTERM);
-
- while (netif_running(dev)
- && netif_device_present(dev)
- && !signal_pending(current))
- {
+ while (!kthread_should_stop()) {
#ifdef CONFIG_PM
/* if suspending, then power off and wait */
if (unlikely(freezing(current))) {
@@ -770,7 +749,7 @@ static int stir_transmit_thread(void *arg)
write_reg(stir, REG_CTRL1, CTRL1_TXPWD|CTRL1_RXPWD);
- refrigerator();
+ try_to_freeze();
if (change_speed(stir, stir->speed))
break;
@@ -796,16 +775,17 @@ static int stir_transmit_thread(void *arg)
}
/* nothing to send? start receiving */
- if (!stir->receiving
- && irda_device_txqueue_empty(dev)) {
+ if (!stir->receiving &&
+ irda_device_txqueue_empty(dev)) {
/* Wait otherwise chip gets confused. */
if (fifo_txwait(stir, -1))
break;
if (unlikely(receive_start(stir))) {
if (net_ratelimit())
- info("%s: receive usb submit failed",
- stir->netdev->name);
+ dev_info(&dev->dev,
+ "%s: receive usb submit failed\n",
+ stir->netdev->name);
stir->receiving = 0;
msleep(10);
continue;
@@ -813,10 +793,11 @@ static int stir_transmit_thread(void *arg)
}
/* sleep if nothing to send */
- wait_event_interruptible(stir->thr_wait, stir->tx_pending);
- }
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
- complete_and_exit (&stir->thr_exited, 0);
+ }
+ return 0;
}
@@ -825,7 +806,7 @@ static int stir_transmit_thread(void *arg)
* Wakes up every ms (usb round trip) with wrapped
* data.
*/
-static void stir_rcv_irq(struct urb *urb, struct pt_regs *regs)
+static void stir_rcv_irq(struct urb *urb)
{
struct stir_cb *stir = urb->context;
int err;
@@ -843,7 +824,6 @@ static void stir_rcv_irq(struct urb *urb, struct pt_regs *regs)
unwrap_chars(stir, urb->transfer_buffer,
urb->actual_length);
- stir->netdev->last_rx = jiffies;
do_gettimeofday(&stir->rx_time);
}
@@ -856,10 +836,10 @@ static void stir_rcv_irq(struct urb *urb, struct pt_regs *regs)
/* in case of error, the kernel thread will restart us */
if (err) {
- warn("%s: usb receive submit error: %d",
- stir->netdev->name, err);
+ dev_warn(&stir->netdev->dev, "usb receive submit error: %d\n",
+ err);
stir->receiving = 0;
- wake_up(&stir->thr_wait);
+ wake_up_process(stir->thread);
}
}
@@ -923,16 +903,16 @@ static int stir_net_open(struct net_device *netdev)
sprintf(hwname, "usb#%d", stir->usbdev->devnum);
stir->irlap = irlap_open(netdev, &stir->qos, hwname);
if (!stir->irlap) {
- err("stir4200: irlap_open failed");
+ dev_err(&stir->usbdev->dev, "irlap_open failed\n");
goto err_out5;
}
/** Start kernel thread for transmit. */
- stir->thr_pid = kernel_thread(stir_transmit_thread, stir,
- CLONE_FS|CLONE_FILES);
- if (stir->thr_pid < 0) {
- err = stir->thr_pid;
- err("stir4200: unable to start kernel thread");
+ stir->thread = kthread_run(stir_transmit_thread, stir,
+ "%s", stir->netdev->name);
+ if (IS_ERR(stir->thread)) {
+ err = PTR_ERR(stir->thread);
+ dev_err(&stir->usbdev->dev, "unable to start kernel thread\n");
goto err_out6;
}
@@ -968,8 +948,7 @@ static int stir_net_close(struct net_device *netdev)
netif_stop_queue(netdev);
/* Kill transmit thread */
- kill_proc(stir->thr_pid, SIGTERM, 1);
- wait_for_completion(&stir->thr_exited);
+ kthread_stop(stir->thread);
kfree(stir->fifo_status);
/* Mop up receive urb's */
@@ -1028,14 +1007,12 @@ static int stir_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
return ret;
}
-/*
- * Get device stats (for /proc/net/dev and ifconfig)
- */
-static struct net_device_stats *stir_net_get_stats(struct net_device *netdev)
-{
- struct stir_cb *stir = netdev_priv(netdev);
- return &stir->stats;
-}
+static const struct net_device_ops stir_netdev_ops = {
+ .ndo_open = stir_net_open,
+ .ndo_stop = stir_net_close,
+ .ndo_start_xmit = stir_hard_xmit,
+ .ndo_do_ioctl = stir_net_ioctl,
+};
/*
* This routine is called by the USB subsystem for each new device
@@ -1057,7 +1034,6 @@ static int stir_probe(struct usb_interface *intf,
if(!net)
goto err_out1;
- SET_MODULE_OWNER(net);
SET_NETDEV_DEV(net, &intf->dev);
stir = netdev_priv(net);
stir->netdev = net;
@@ -1065,7 +1041,7 @@ static int stir_probe(struct usb_interface *intf,
ret = usb_reset_configuration(dev);
if (ret != 0) {
- err("stir4200: usb reset configuration failed");
+ dev_err(&intf->dev, "usb reset configuration failed\n");
goto err_out2;
}
@@ -1084,21 +1060,15 @@ static int stir_probe(struct usb_interface *intf,
stir->qos.min_turn_time.bits &= qos_mtt_bits;
irda_qos_bits_to_value(&stir->qos);
- init_completion (&stir->thr_exited);
- init_waitqueue_head (&stir->thr_wait);
-
/* Override the network functions we need to use */
- net->hard_start_xmit = stir_hard_xmit;
- net->open = stir_net_open;
- net->stop = stir_net_close;
- net->get_stats = stir_net_get_stats;
- net->do_ioctl = stir_net_ioctl;
+ net->netdev_ops = &stir_netdev_ops;
ret = register_netdev(net);
if (ret != 0)
goto err_out2;
- info("IrDA: Registered SigmaTel device %s", net->name);
+ dev_info(&intf->dev, "IrDA: Registered SigmaTel device %s\n",
+ net->name);
usb_set_intfdata(intf, stir);
@@ -1162,21 +1132,4 @@ static struct usb_driver irda_driver = {
#endif
};
-/*
- * Module insertion
- */
-static int __init stir_init(void)
-{
- return usb_register(&irda_driver);
-}
-module_init(stir_init);
-
-/*
- * Module removal
- */
-static void __exit stir_cleanup(void)
-{
- /* Deregister the driver and remove all pending instances */
- usb_deregister(&irda_driver);
-}
-module_exit(stir_cleanup);
+module_usb_driver(irda_driver);