summaryrefslogtreecommitdiffstats
path: root/net/irda
diff options
context:
space:
mode:
Diffstat (limited to 'net/irda')
-rw-r--r--net/irda/af_irda.c5
-rw-r--r--net/irda/ircomm/ircomm_core.c12
-rw-r--r--net/irda/irda_device.c169
-rw-r--r--net/irda/iriap.c2
-rw-r--r--net/irda/irlap_event.c25
-rw-r--r--net/irda/irlmp.c7
-rw-r--r--net/irda/irlmp_event.c4
-rw-r--r--net/irda/irsysctl.c56
8 files changed, 76 insertions, 204 deletions
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index 07dfa7fdd2a0..240b0cbfb532 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -2410,9 +2410,8 @@ bed:
/* Set watchdog timer to expire in <val> ms. */
self->errno = 0;
- init_timer(&self->watchdog);
- self->watchdog.function = irda_discovery_timeout;
- self->watchdog.data = (unsigned long) self;
+ setup_timer(&self->watchdog, irda_discovery_timeout,
+ (unsigned long)self);
self->watchdog.expires = jiffies + (val * HZ/1000);
add_timer(&(self->watchdog));
diff --git a/net/irda/ircomm/ircomm_core.c b/net/irda/ircomm/ircomm_core.c
index 2d63fa8e1556..b825399fc160 100644
--- a/net/irda/ircomm/ircomm_core.c
+++ b/net/irda/ircomm/ircomm_core.c
@@ -363,6 +363,18 @@ void ircomm_process_data(struct ircomm_cb *self, struct sk_buff *skb)
clen = skb->data[0];
/*
+ * Input validation check: a stir4200/mcp2150 combinations sometimes
+ * results in frames with clen > remaining packet size. These are
+ * illegal; if we throw away just this frame then it seems to carry on
+ * fine
+ */
+ if (unlikely(skb->len < (clen + 1))) {
+ IRDA_DEBUG(2, "%s() throwing away illegal frame\n",
+ __FUNCTION__ );
+ return;
+ }
+
+ /*
* If there are any data hiding in the control channel, we must
* deliver it first. The side effect is that the control channel
* will be removed from the skb
diff --git a/net/irda/irda_device.c b/net/irda/irda_device.c
index 435b563d29a6..87185910d0ee 100644
--- a/net/irda/irda_device.c
+++ b/net/irda/irda_device.c
@@ -57,20 +57,6 @@ static void __irda_task_delete(struct irda_task *task);
static hashbin_t *dongles = NULL;
static hashbin_t *tasks = NULL;
-#ifdef CONFIG_IRDA_DEBUG
-static const char *task_state[] = {
- "IRDA_TASK_INIT",
- "IRDA_TASK_DONE",
- "IRDA_TASK_WAIT",
- "IRDA_TASK_WAIT1",
- "IRDA_TASK_WAIT2",
- "IRDA_TASK_WAIT3",
- "IRDA_TASK_CHILD_INIT",
- "IRDA_TASK_CHILD_WAIT",
- "IRDA_TASK_CHILD_DONE",
-};
-#endif /* CONFIG_IRDA_DEBUG */
-
static void irda_task_timer_expired(void *data);
int __init irda_device_init( void)
@@ -176,14 +162,6 @@ int irda_device_is_receiving(struct net_device *dev)
return req.ifr_receiving;
}
-void irda_task_next_state(struct irda_task *task, IRDA_TASK_STATE state)
-{
- IRDA_DEBUG(2, "%s(), state = %s\n", __FUNCTION__, task_state[state]);
-
- task->state = state;
-}
-EXPORT_SYMBOL(irda_task_next_state);
-
static void __irda_task_delete(struct irda_task *task)
{
del_timer(&task->timer);
@@ -191,14 +169,13 @@ static void __irda_task_delete(struct irda_task *task)
kfree(task);
}
-void irda_task_delete(struct irda_task *task)
+static void irda_task_delete(struct irda_task *task)
{
/* Unregister task */
hashbin_remove(tasks, (long) task, NULL);
__irda_task_delete(task);
}
-EXPORT_SYMBOL(irda_task_delete);
/*
* Function irda_task_kick (task)
@@ -272,51 +249,6 @@ static int irda_task_kick(struct irda_task *task)
}
/*
- * Function irda_task_execute (instance, function, finished)
- *
- * This function registers and tries to execute tasks that may take some
- * time to complete. We do it this hairy way since we may have been
- * called from interrupt context, so it's not possible to use
- * schedule_timeout()
- * Two important notes :
- * o Make sure you irda_task_delete(task); in case you delete the
- * calling instance.
- * o No real need to lock when calling this function, but you may
- * want to lock within the task handler.
- * Jean II
- */
-struct irda_task *irda_task_execute(void *instance,
- IRDA_TASK_CALLBACK function,
- IRDA_TASK_CALLBACK finished,
- struct irda_task *parent, void *param)
-{
- struct irda_task *task;
-
- IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
-
- task = kmalloc(sizeof(struct irda_task), GFP_ATOMIC);
- if (!task)
- return NULL;
-
- task->state = IRDA_TASK_INIT;
- task->instance = instance;
- task->function = function;
- task->finished = finished;
- task->parent = parent;
- task->param = param;
- task->magic = IRDA_TASK_MAGIC;
-
- init_timer(&task->timer);
-
- /* Register task */
- hashbin_insert(tasks, (irda_queue_t *) task, (long) task, NULL);
-
- /* No time to waste, so lets get going! */
- return irda_task_kick(task) ? NULL : task;
-}
-EXPORT_SYMBOL(irda_task_execute);
-
-/*
* Function irda_task_timer_expired (data)
*
* Task time has expired. We now try to execute task (again), and restart
@@ -364,105 +296,6 @@ struct net_device *alloc_irdadev(int sizeof_priv)
}
EXPORT_SYMBOL(alloc_irdadev);
-/*
- * Function irda_device_init_dongle (self, type, qos)
- *
- * Initialize attached dongle.
- *
- * Important : request_module require us to call this function with
- * a process context and irq enabled. - Jean II
- */
-dongle_t *irda_device_dongle_init(struct net_device *dev, int type)
-{
- struct dongle_reg *reg;
- dongle_t *dongle = kzalloc(sizeof(dongle_t), GFP_KERNEL);
-
- might_sleep();
-
- spin_lock(&dongles->hb_spinlock);
- reg = hashbin_find(dongles, type, NULL);
-
-#ifdef CONFIG_KMOD
- /* Try to load the module needed */
- if (!reg && capable(CAP_SYS_MODULE)) {
- spin_unlock(&dongles->hb_spinlock);
-
- request_module("irda-dongle-%d", type);
-
- spin_lock(&dongles->hb_spinlock);
- reg = hashbin_find(dongles, type, NULL);
- }
-#endif
-
- if (!reg || !try_module_get(reg->owner) ) {
- IRDA_ERROR("IrDA: Unable to find requested dongle type %x\n",
- type);
- kfree(dongle);
- dongle = NULL;
- }
- if (dongle) {
- /* Bind the registration info to this particular instance */
- dongle->issue = reg;
- dongle->dev = dev;
- }
- spin_unlock(&dongles->hb_spinlock);
- return dongle;
-}
-EXPORT_SYMBOL(irda_device_dongle_init);
-
-/*
- * Function irda_device_dongle_cleanup (dongle)
- */
-int irda_device_dongle_cleanup(dongle_t *dongle)
-{
- IRDA_ASSERT(dongle != NULL, return -1;);
-
- dongle->issue->close(dongle);
- module_put(dongle->issue->owner);
- kfree(dongle);
-
- return 0;
-}
-EXPORT_SYMBOL(irda_device_dongle_cleanup);
-
-/*
- * Function irda_device_register_dongle (dongle)
- */
-int irda_device_register_dongle(struct dongle_reg *new)
-{
- spin_lock(&dongles->hb_spinlock);
- /* Check if this dongle has been registered before */
- if (hashbin_find(dongles, new->type, NULL)) {
- IRDA_MESSAGE("%s: Dongle type %x already registered\n",
- __FUNCTION__, new->type);
- } else {
- /* Insert IrDA dongle into hashbin */
- hashbin_insert(dongles, (irda_queue_t *) new, new->type, NULL);
- }
- spin_unlock(&dongles->hb_spinlock);
-
- return 0;
-}
-EXPORT_SYMBOL(irda_device_register_dongle);
-
-/*
- * Function irda_device_unregister_dongle (dongle)
- *
- * Unregister dongle, and remove dongle from list of registered dongles
- *
- */
-void irda_device_unregister_dongle(struct dongle_reg *dongle)
-{
- struct dongle *node;
-
- spin_lock(&dongles->hb_spinlock);
- node = hashbin_remove(dongles, dongle->type, NULL);
- if (!node)
- IRDA_ERROR("%s: dongle not found!\n", __FUNCTION__);
- spin_unlock(&dongles->hb_spinlock);
-}
-EXPORT_SYMBOL(irda_device_unregister_dongle);
-
#ifdef CONFIG_ISA_DMA_API
/*
* Function setup_dma (idev, buffer, count, mode)
diff --git a/net/irda/iriap.c b/net/irda/iriap.c
index a86a5d83786b..390a790886eb 100644
--- a/net/irda/iriap.c
+++ b/net/irda/iriap.c
@@ -579,7 +579,7 @@ static void iriap_getvaluebyclass_response(struct iriap_cb *self,
fp[n++] = ret_code;
/* Insert list length (MSB first) */
- tmp_be16 = __constant_htons(0x0001);
+ tmp_be16 = htons(0x0001);
memcpy(fp+n, &tmp_be16, 2); n += 2;
/* Insert object identifier ( MSB first) */
diff --git a/net/irda/irlap_event.c b/net/irda/irlap_event.c
index 4c33bf5c8354..6af86eba7463 100644
--- a/net/irda/irlap_event.c
+++ b/net/irda/irlap_event.c
@@ -1199,6 +1199,19 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
switch (event) {
case RECV_I_RSP: /* Optimize for the common case */
+ if (unlikely(skb->len <= LAP_ADDR_HEADER + LAP_CTRL_HEADER)) {
+ /*
+ * Input validation check: a stir4200/mcp2150
+ * combination sometimes results in an empty i:rsp.
+ * This makes no sense; we can just ignore the frame
+ * and send an rr:cmd immediately. This happens before
+ * changing nr or ns so triggers a retransmit
+ */
+ irlap_wait_min_turn_around(self, &self->qos_tx);
+ irlap_send_rr_frame(self, CMD_FRAME);
+ /* Keep state */
+ break;
+ }
/* FIXME: must check for remote_busy below */
#ifdef CONFIG_IRDA_FAST_RR
/*
@@ -1514,9 +1527,15 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
/* N2 is the disconnect timer. Until we reach it, we retry */
if (self->retry_count < self->N2) {
- /* Retry sending the pf bit to the secondary */
- irlap_wait_min_turn_around(self, &self->qos_tx);
- irlap_send_rr_frame(self, CMD_FRAME);
+ if (skb_peek(&self->wx_list) == NULL) {
+ /* Retry sending the pf bit to the secondary */
+ IRDA_DEBUG(4, "nrm_p: resending rr");
+ irlap_wait_min_turn_around(self, &self->qos_tx);
+ irlap_send_rr_frame(self, CMD_FRAME);
+ } else {
+ IRDA_DEBUG(4, "nrm_p: resend frames");
+ irlap_resend_rejected_frames(self, CMD_FRAME);
+ }
irlap_start_final_timer(self, self->final_timeout);
self->retry_count++;
diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c
index f24cb755908e..135ac6907bbf 100644
--- a/net/irda/irlmp.c
+++ b/net/irda/irlmp.c
@@ -103,9 +103,12 @@ int __init irlmp_init(void)
irlmp->last_lsap_sel = 0x0f; /* Reserved 0x00-0x0f */
strcpy(sysctl_devname, "Linux");
- /* Do discovery every 3 seconds */
init_timer(&irlmp->discovery_timer);
- irlmp_start_discovery_timer(irlmp, sysctl_discovery_timeout*HZ);
+
+ /* Do discovery every 3 seconds, conditionaly */
+ if (sysctl_discovery)
+ irlmp_start_discovery_timer(irlmp,
+ sysctl_discovery_timeout*HZ);
return 0;
}
diff --git a/net/irda/irlmp_event.c b/net/irda/irlmp_event.c
index 1bba87e78609..150cd3f1129a 100644
--- a/net/irda/irlmp_event.c
+++ b/net/irda/irlmp_event.c
@@ -174,9 +174,7 @@ void irlmp_discovery_timer_expired(void *data)
/* We always cleanup the log (active & passive discovery) */
irlmp_do_expiry();
- /* Active discovery is conditional */
- if (sysctl_discovery)
- irlmp_do_discovery(sysctl_discovery_slots);
+ irlmp_do_discovery(sysctl_discovery_slots);
/* Restart timer */
irlmp_start_discovery_timer(irlmp, sysctl_discovery_timeout * HZ);
diff --git a/net/irda/irsysctl.c b/net/irda/irsysctl.c
index 565cbf0421cd..9ab3df15425d 100644
--- a/net/irda/irsysctl.c
+++ b/net/irda/irsysctl.c
@@ -29,6 +29,8 @@
#include <linux/init.h>
#include <net/irda/irda.h> /* irda_debug */
+#include <net/irda/irlmp.h>
+#include <net/irda/timer.h>
#include <net/irda/irias_object.h>
extern int sysctl_discovery;
@@ -45,6 +47,8 @@ extern int sysctl_max_noreply_time;
extern int sysctl_warn_noreply_time;
extern int sysctl_lap_keepalive_time;
+extern struct irlmp_cb *irlmp;
+
/* this is needed for the proc_dointvec_minmax - Jean II */
static int max_discovery_slots = 16; /* ??? */
static int min_discovery_slots = 1;
@@ -85,6 +89,27 @@ static int do_devname(ctl_table *table, int write, struct file *filp,
return ret;
}
+
+static int do_discovery(ctl_table *table, int write, struct file *filp,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ int ret;
+
+ ret = proc_dointvec(table, write, filp, buffer, lenp, ppos);
+ if (ret)
+ return ret;
+
+ if (irlmp == NULL)
+ return -ENODEV;
+
+ if (sysctl_discovery)
+ irlmp_start_discovery_timer(irlmp, sysctl_discovery_timeout*HZ);
+ else
+ del_timer_sync(&irlmp->discovery_timer);
+
+ return ret;
+}
+
/* One file */
static ctl_table irda_table[] = {
{
@@ -93,7 +118,8 @@ static ctl_table irda_table[] = {
.data = &sysctl_discovery,
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &proc_dointvec
+ .proc_handler = &do_discovery,
+ .strategy = &sysctl_intvec
},
{
.ctl_name = NET_IRDA_DEVNAME,
@@ -234,28 +260,10 @@ static ctl_table irda_table[] = {
{ .ctl_name = 0 }
};
-/* One directory */
-static ctl_table irda_net_table[] = {
- {
- .ctl_name = NET_IRDA,
- .procname = "irda",
- .maxlen = 0,
- .mode = 0555,
- .child = irda_table
- },
- { .ctl_name = 0 }
-};
-
-/* The parent directory */
-static ctl_table irda_root_table[] = {
- {
- .ctl_name = CTL_NET,
- .procname = "net",
- .maxlen = 0,
- .mode = 0555,
- .child = irda_net_table
- },
- { .ctl_name = 0 }
+static struct ctl_path irda_path[] = {
+ { .procname = "net", .ctl_name = CTL_NET, },
+ { .procname = "irda", .ctl_name = NET_IRDA, },
+ { }
};
static struct ctl_table_header *irda_table_header;
@@ -268,7 +276,7 @@ static struct ctl_table_header *irda_table_header;
*/
int __init irda_sysctl_register(void)
{
- irda_table_header = register_sysctl_table(irda_root_table);
+ irda_table_header = register_sysctl_paths(irda_path, irda_table);
if (!irda_table_header)
return -ENOMEM;