diff options
Diffstat (limited to 'net/irda')
-rw-r--r-- | net/irda/af_irda.c | 5 | ||||
-rw-r--r-- | net/irda/ircomm/ircomm_core.c | 12 | ||||
-rw-r--r-- | net/irda/irda_device.c | 169 | ||||
-rw-r--r-- | net/irda/iriap.c | 2 | ||||
-rw-r--r-- | net/irda/irlap_event.c | 25 | ||||
-rw-r--r-- | net/irda/irlmp.c | 7 | ||||
-rw-r--r-- | net/irda/irlmp_event.c | 4 | ||||
-rw-r--r-- | net/irda/irsysctl.c | 56 |
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; |