/*********************************************************************
- *
+ *
* Filename: irttp.c
* Version: 1.2
* Description: Tiny Transport Protocol (TTP) implementation
* Created at: Sun Aug 31 20:14:31 1997
* Modified at: Wed Jan 5 11:31:27 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
- *
- * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>,
+ *
+ * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>,
* All Rights Reserved.
* Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com>
- *
- * 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
+ *
+ * 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.
*
- * Neither Dag Brattli nor University of Tromsø admit liability nor
- * provide warranty for any of this software. This material is
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
********************************************************************/
-#include <linux/config.h>
#include <linux/skbuff.h>
#include <linux/init.h>
+#include <linux/fs.h>
#include <linux/seq_file.h>
#include <asm/byteorder.h>
#include <net/irda/parameters.h>
#include <net/irda/irttp.h>
-static struct irttp_cb *irttp = NULL;
+static struct irttp_cb *irttp;
static void __irttp_close_tsap(struct tsap_cb *self);
-static int irttp_data_indication(void *instance, void *sap,
+static int irttp_data_indication(void *instance, void *sap,
struct sk_buff *skb);
-static int irttp_udata_indication(void *instance, void *sap,
+static int irttp_udata_indication(void *instance, void *sap,
struct sk_buff *skb);
-static void irttp_disconnect_indication(void *instance, void *sap,
+static void irttp_disconnect_indication(void *instance, void *sap,
LM_REASON reason, struct sk_buff *);
-static void irttp_connect_indication(void *instance, void *sap,
+static void irttp_connect_indication(void *instance, void *sap,
struct qos_info *qos, __u32 max_sdu_size,
__u8 header_size, struct sk_buff *skb);
-static void irttp_connect_confirm(void *instance, void *sap,
- struct qos_info *qos, __u32 max_sdu_size,
+static void irttp_connect_confirm(void *instance, void *sap,
+ struct qos_info *qos, __u32 max_sdu_size,
__u8 header_size, struct sk_buff *skb);
static void irttp_run_tx_queue(struct tsap_cb *self);
static void irttp_run_rx_queue(struct tsap_cb *self);
static void irttp_fragment_skb(struct tsap_cb *self, struct sk_buff *skb);
static struct sk_buff *irttp_reassemble_skb(struct tsap_cb *self);
static void irttp_todo_expired(unsigned long data);
-static int irttp_param_max_sdu_size(void *instance, irda_param_t *param,
+static int irttp_param_max_sdu_size(void *instance, irda_param_t *param,
int get);
static void irttp_flow_indication(void *instance, void *sap, LOCAL_FLOW flow);
*/
int __init irttp_init(void)
{
- /* Initialize the irttp structure. */
- if (irttp == NULL) {
- irttp = kmalloc(sizeof(struct irttp_cb), GFP_KERNEL);
- if (irttp == NULL)
- return -ENOMEM;
- }
- memset(irttp, 0, sizeof(struct irttp_cb));
+ irttp = kzalloc(sizeof(struct irttp_cb), GFP_KERNEL);
+ if (irttp == NULL)
+ return -ENOMEM;
irttp->magic = TTP_MAGIC;
if (!irttp->tsaps) {
IRDA_ERROR("%s: can't allocate IrTTP hashbin!\n",
__FUNCTION__);
+ kfree(irttp);
return -ENOMEM;
}
* Called by module destruction/cleanup code
*
*/
-void __exit irttp_cleanup(void)
+void irttp_cleanup(void)
{
/* Check for main structure */
- IRDA_ASSERT(irttp != NULL, return;);
IRDA_ASSERT(irttp->magic == TTP_MAGIC, return;);
/*
* Copy all fragments to a new buffer
*/
while ((frag = skb_dequeue(&self->rx_fragments)) != NULL) {
- memcpy(skb->data+n, frag->data, frag->len);
+ skb_copy_to_linear_data_offset(skb, n, frag->data, frag->len);
n += frag->len;
dev_kfree_skb(frag);
IRDA_DEBUG(2, "%s(), fragmenting ...\n", __FUNCTION__);
/* Make new segment */
- frag = dev_alloc_skb(self->max_seg_size+self->max_header_size);
+ frag = alloc_skb(self->max_seg_size+self->max_header_size,
+ GFP_ATOMIC);
if (!frag)
return;
skb_reserve(frag, self->max_header_size);
/* Copy data from the original skb into this fragment. */
- memcpy(skb_put(frag, self->max_seg_size), skb->data,
- self->max_seg_size);
+ skb_copy_from_linear_data(skb, skb_put(frag, self->max_seg_size),
+ self->max_seg_size);
/* Insert TTP header, with the more bit set */
frame = skb_push(frag, TTP_HEADER);
/* Everything is happily mixed up. Waiting for next clean up - Jean II */
/*
+ * Initialization, that has to be done on new tsap
+ * instance allocation and on duplication
+ */
+static void irttp_init_tsap(struct tsap_cb *tsap)
+{
+ spin_lock_init(&tsap->lock);
+ init_timer(&tsap->todo_timer);
+
+ skb_queue_head_init(&tsap->rx_queue);
+ skb_queue_head_init(&tsap->tx_queue);
+ skb_queue_head_init(&tsap->rx_fragments);
+}
+
+/*
* Function irttp_open_tsap (stsap, notify)
*
* Create TSAP connection endpoint,
struct lsap_cb *lsap;
notify_t ttp_notify;
- IRDA_ASSERT(irttp != NULL, return NULL;);
IRDA_ASSERT(irttp->magic == TTP_MAGIC, return NULL;);
/* The IrLMP spec (IrLMP 1.1 p10) says that we have the right to
return NULL;
}
- self = kmalloc(sizeof(struct tsap_cb), GFP_ATOMIC);
+ self = kzalloc(sizeof(struct tsap_cb), GFP_ATOMIC);
if (self == NULL) {
IRDA_DEBUG(0, "%s(), unable to kmalloc!\n", __FUNCTION__);
return NULL;
}
- memset(self, 0, sizeof(struct tsap_cb));
- spin_lock_init(&self->lock);
+
+ /* Initialize internal objects */
+ irttp_init_tsap(self);
/* Initialise todo timer */
- init_timer(&self->todo_timer);
self->todo_timer.data = (unsigned long) self;
self->todo_timer.function = &irttp_todo_expired;
self->magic = TTP_TSAP_MAGIC;
self->connected = FALSE;
- skb_queue_head_init(&self->rx_queue);
- skb_queue_head_init(&self->tx_queue);
- skb_queue_head_init(&self->rx_fragments);
/*
* Create LSAP at IrLMP layer
*/
}
if (skb->len > self->max_seg_size) {
- IRDA_DEBUG(1, "%s(), UData is to large for IrLAP!\n",
+ IRDA_DEBUG(1, "%s(), UData is too large for IrLAP!\n",
__FUNCTION__);
goto err;
}
* inside an IrLAP frame
*/
if ((self->tx_max_sdu_size == 0) && (skb->len > self->max_seg_size)) {
- IRDA_ERROR("%s: SAR disabled, and data is to large for IrLAP!\n",
+ IRDA_ERROR("%s: SAR disabled, and data is too large for IrLAP!\n",
__FUNCTION__);
ret = -EMSGSIZE;
goto err;
self->send_credit, self->avail_credit, self->remote_credit);
/* Give credit to peer */
- tx_skb = dev_alloc_skb(64);
+ tx_skb = alloc_skb(TTP_MAX_HEADER, GFP_ATOMIC);
if (!tx_skb)
return;
/* Reserve space for LMP, and LAP header */
- skb_reserve(tx_skb, self->max_header_size);
+ skb_reserve(tx_skb, LMP_MAX_HEADER);
/*
* Since we can transmit and receive frames concurrently,
err = self->notify.udata_indication(self->notify.instance,
self,skb);
/* Same comment as in irttp_do_data_indication() */
- if (!err)
+ if (!err)
return 0;
}
/* Either no handler, or handler returns an error */
/*
* If the peer device has given us some credits and we didn't have
- * anyone from before, then we need to shedule the tx queue.
+ * anyone from before, then we need to shedule the tx queue.
* We need to do that because our Tx have stopped (so we may not
* get any LAP flow indication) and the user may be stopped as
* well. - Jean II
/* Any userdata supplied? */
if (userdata == NULL) {
- tx_skb = dev_alloc_skb(64);
+ tx_skb = alloc_skb(TTP_MAX_HEADER + TTP_SAR_HEADER,
+ GFP_ATOMIC);
if (!tx_skb)
return -ENOMEM;
/* Reserve space for MUX_CONTROL and LAP header */
- skb_reserve(tx_skb, TTP_MAX_HEADER);
+ skb_reserve(tx_skb, TTP_MAX_HEADER + TTP_SAR_HEADER);
} else {
tx_skb = userdata;
/*
frame[3] = 0x02; /* Value length */
put_unaligned(cpu_to_be16((__u16) max_sdu_size),
- (__u16 *)(frame+4));
+ (__be16 *)(frame+4));
} else {
/* Insert plain TTP header */
frame = skb_push(tx_skb, TTP_HEADER);
/* Any userdata supplied? */
if (userdata == NULL) {
- tx_skb = dev_alloc_skb(64);
+ tx_skb = alloc_skb(TTP_MAX_HEADER + TTP_SAR_HEADER,
+ GFP_ATOMIC);
if (!tx_skb)
return -ENOMEM;
/* Reserve space for MUX_CONTROL and LAP header */
- skb_reserve(tx_skb, TTP_MAX_HEADER);
+ skb_reserve(tx_skb, TTP_MAX_HEADER + TTP_SAR_HEADER);
} else {
tx_skb = userdata;
/*
frame[3] = 0x02; /* Value length */
put_unaligned(cpu_to_be16((__u16) max_sdu_size),
- (__u16 *)(frame+4));
+ (__be16 *)(frame+4));
} else {
/* Insert TTP header */
frame = skb_push(tx_skb, TTP_HEADER);
/* Not everything should be copied */
new->notify.instance = instance;
- init_timer(&new->todo_timer);
- skb_queue_head_init(&new->rx_queue);
- skb_queue_head_init(&new->tx_queue);
- skb_queue_head_init(&new->rx_fragments);
+ /* Initialize internal objects */
+ irttp_init_tsap(new);
/* This is locked */
hashbin_insert(irttp->tsaps, (irda_queue_t *) new, (long) new, NULL);
/*
* Check if there is still data segments in the transmit queue
*/
- if (skb_queue_len(&self->tx_queue) > 0) {
+ if (!skb_queue_empty(&self->tx_queue)) {
if (priority == P_HIGH) {
/*
* No need to send the queued data, if we are
if (!userdata) {
struct sk_buff *tx_skb;
- tx_skb = dev_alloc_skb(64);
+ tx_skb = alloc_skb(LMP_MAX_HEADER, GFP_ATOMIC);
if (!tx_skb)
return -ENOMEM;
/*
* Reserve space for MUX and LAP header
*/
- skb_reserve(tx_skb, TTP_MAX_HEADER);
+ skb_reserve(tx_skb, LMP_MAX_HEADER);
userdata = tx_skb;
}
spin_lock_irq(&irttp->tsaps->hb_spinlock);
iter->id = 0;
- for (self = (struct tsap_cb *) hashbin_get_first(irttp->tsaps);
+ for (self = (struct tsap_cb *) hashbin_get_first(irttp->tsaps);
self != NULL;
self = (struct tsap_cb *) hashbin_get_next(irttp->tsaps)) {
if (iter->id == *pos)
break;
++iter->id;
}
-
+
return self;
}
return 0;
}
-static struct seq_operations irttp_seq_ops = {
+static const struct seq_operations irttp_seq_ops = {
.start = irttp_seq_start,
.next = irttp_seq_next,
.stop = irttp_seq_stop,
static int irttp_seq_open(struct inode *inode, struct file *file)
{
- struct seq_file *seq;
- int rc = -ENOMEM;
- struct irttp_iter_state *s;
-
- IRDA_ASSERT(irttp != NULL, return -EINVAL;);
-
- s = kmalloc(sizeof(*s), GFP_KERNEL);
- if (!s)
- goto out;
-
- rc = seq_open(file, &irttp_seq_ops);
- if (rc)
- goto out_kfree;
-
- seq = file->private_data;
- seq->private = s;
- memset(s, 0, sizeof(*s));
-out:
- return rc;
-out_kfree:
- kfree(s);
- goto out;
+ return seq_open_private(file, &irttp_seq_ops,
+ sizeof(struct irttp_iter_state));
}
-struct file_operations irttp_seq_fops = {
+const struct file_operations irttp_seq_fops = {
.owner = THIS_MODULE,
.open = irttp_seq_open,
.read = seq_read,