summaryrefslogtreecommitdiffstats
path: root/net/irda/irttp.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-06-13 16:29:25 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-06-13 16:29:25 +0000
commitdb7d4daea91e105e3859cf461d7e53b9b77454b2 (patch)
tree9bb65b95440af09e8aca63abe56970dd3360cc57 /net/irda/irttp.c
parent9c1c01ead627bdda9211c9abd5b758d6c687d8ac (diff)
Merge with Linux 2.2.8.
Diffstat (limited to 'net/irda/irttp.c')
-rw-r--r--net/irda/irttp.c1142
1 files changed, 620 insertions, 522 deletions
diff --git a/net/irda/irttp.c b/net/irda/irttp.c
index 3da804e7d..bf0624eee 100644
--- a/net/irda/irttp.c
+++ b/net/irda/irttp.c
@@ -1,12 +1,12 @@
/*********************************************************************
*
* Filename: irttp.c
- * Version: 0.4
+ * Version: 1.2
* Description: Tiny Transport Protocol (TTP) implementation
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun Aug 31 20:14:31 1997
- * Modified at: Tue Jan 19 23:56:58 1999
+ * Modified at: Sat Apr 10 10:32:21 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>,
@@ -28,33 +28,35 @@
#include <linux/init.h>
#include <asm/byteorder.h>
+#include <asm/unaligned.h>
#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
#include <net/irda/irlmp.h>
#include <net/irda/irttp.h>
struct irttp_cb *irttp = NULL;
-static void __irttp_close_tsap( struct tsap_cb *self);
+static void __irttp_close_tsap(struct tsap_cb *self);
-static void irttp_data_indication( void *instance, void *sap,
- struct sk_buff *skb);
-static void irttp_udata_indication( void *instance, void *sap,
- struct sk_buff *skb);
-static void irttp_disconnect_indication( void *instance, void *sap,
- LM_REASON reason,
- struct sk_buff *);
-static void irttp_connect_indication( void *instance, void *sap,
- struct qos_info *qos, int max_sdu_size,
- struct sk_buff *skb);
+static int irttp_data_indication(void *instance, void *sap,
+ struct sk_buff *skb);
+static int irttp_udata_indication(void *instance, void *sap,
+ struct sk_buff *skb);
+static void irttp_disconnect_indication(void *instance, void *sap,
+ LM_REASON reason,
+ struct sk_buff *);
+static void irttp_connect_indication(void *instance, void *sap,
+ struct qos_info *qos, __u32 max_sdu_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_run_tx_queue(struct tsap_cb *self);
+static void irttp_run_rx_queue(struct tsap_cb *self);
-static void irttp_flush_queues( 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_start_todo_timer( struct tsap_cb *self, int timeout);
+static void irttp_flush_queues(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_start_todo_timer(struct tsap_cb *self, int timeout);
/*
* Function irttp_init (void)
@@ -64,21 +66,19 @@ static void irttp_start_todo_timer( struct tsap_cb *self, int timeout);
*/
__initfunc(int irttp_init(void))
{
- DEBUG( 4, "--> irttp_init\n");
-
/* Initialize the irttp structure. */
- if ( irttp == NULL) {
- irttp = kmalloc( sizeof(struct irttp_cb), GFP_KERNEL);
- if ( irttp == NULL)
+ if (irttp == NULL) {
+ irttp = kmalloc(sizeof(struct irttp_cb), GFP_KERNEL);
+ if (irttp == NULL)
return -ENOMEM;
}
- memset( irttp, 0, sizeof(struct irttp_cb));
-
+ memset(irttp, 0, sizeof(struct irttp_cb));
+
irttp->magic = TTP_MAGIC;
- irttp->tsaps = hashbin_new( HB_LOCAL);
- if ( !irttp->tsaps) {
- printk( KERN_WARNING "IrDA: Can't allocate IrTTP hashbin!\n");
+ irttp->tsaps = hashbin_new(HB_LOCAL);
+ if (!irttp->tsaps) {
+ printk(KERN_WARNING "IrDA: Can't allocate IrTTP hashbin!\n");
return -ENOMEM;
}
@@ -91,69 +91,73 @@ __initfunc(int irttp_init(void))
* Called by module destruction/cleanup code
*
*/
+#ifdef MODULE
void irttp_cleanup(void)
{
- DEBUG( 4, "irttp_cleanup\n");
-
/* Check for main structure */
- ASSERT( irttp != NULL, return;);
- ASSERT( irttp->magic == TTP_MAGIC, return;);
+ ASSERT(irttp != NULL, return;);
+ ASSERT(irttp->magic == TTP_MAGIC, return;);
/*
* Delete hashbin and close all TSAP instances in it
*/
- hashbin_delete( irttp->tsaps, (FREE_FUNC) __irttp_close_tsap);
+ hashbin_delete(irttp->tsaps, (FREE_FUNC) __irttp_close_tsap);
- irttp->magic = ~TTP_MAGIC;
+ irttp->magic = 0;
/* De-allocate main structure */
- kfree( irttp);
+ kfree(irttp);
irttp = NULL;
}
+#endif
/*
* Function irttp_open_tsap (stsap, notify)
*
* Create TSAP connection endpoint,
*/
-struct tsap_cb *irttp_open_tsap( __u8 stsap_sel, int credit,
- struct notify_t *notify)
+struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit,
+ struct notify_t *notify)
{
struct notify_t ttp_notify;
struct tsap_cb *self;
struct lsap_cb *lsap;
- ASSERT( irttp != NULL, return NULL;);
- ASSERT( irttp->magic == TTP_MAGIC, return NULL;);
+ ASSERT(irttp != NULL, return NULL;);
+ ASSERT(irttp->magic == TTP_MAGIC, return NULL;);
- self = kmalloc( sizeof(struct tsap_cb), GFP_ATOMIC);
- if ( self == NULL) {
- printk( KERN_ERR "IrTTP: Can't allocate memory for "
- "TSAP control block!\n");
+ self = kmalloc(sizeof(struct tsap_cb), GFP_ATOMIC);
+ if (self == NULL) {
+ DEBUG(0, __FUNCTION__ "(), unable to kmalloc!\n");
return NULL;
}
- memset( self, 0, sizeof(struct tsap_cb));
+ memset(self, 0, sizeof(struct tsap_cb));
- init_timer( &self->todo_timer);
+ init_timer(&self->todo_timer);
/* Initialize callbacks for IrLMP to use */
-
- irda_notify_init( &ttp_notify);
+ irda_notify_init(&ttp_notify);
ttp_notify.connect_confirm = irttp_connect_confirm;
ttp_notify.connect_indication = irttp_connect_indication;
ttp_notify.disconnect_indication = irttp_disconnect_indication;
ttp_notify.data_indication = irttp_data_indication;
ttp_notify.udata_indication = irttp_udata_indication;
ttp_notify.instance = self;
- strncpy( ttp_notify.name, notify->name, NOTIFY_MAX_NAME);
+ strncpy(ttp_notify.name, notify->name, NOTIFY_MAX_NAME);
+ 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
*/
- lsap = irlmp_open_lsap( stsap_sel, &ttp_notify);
- if ( lsap == NULL) {
- printk( KERN_ERR "IrTTP, Unable to get LSAP!!\n");
+ lsap = irlmp_open_lsap(stsap_sel, &ttp_notify);
+ if (lsap == NULL) {
+ printk(KERN_ERR "IrTTP, Unable to get LSAP!!\n");
return NULL;
}
@@ -163,27 +167,19 @@ struct tsap_cb *irttp_open_tsap( __u8 stsap_sel, int credit,
* the stsap_sel we have might not be valid anymore
*/
self->stsap_sel = lsap->slsap_sel;
- DEBUG( 4, __FUNCTION__ "(), stsap_sel=%02x\n", self->stsap_sel);
+ DEBUG(4, __FUNCTION__ "(), stsap_sel=%02x\n", self->stsap_sel);
self->notify = *notify;
self->lsap = lsap;
- self->magic = TTP_TSAP_MAGIC;
- skb_queue_head_init( &self->rx_queue);
- skb_queue_head_init( &self->tx_queue);
- skb_queue_head_init( &self->rx_fragments);
+ hashbin_insert(irttp->tsaps, (QUEUE *) self, (int) self, NULL);
- /*
- * Insert ourself into the hashbin
- */
- hashbin_insert( irttp->tsaps, (QUEUE *) self, self->stsap_sel, NULL);
-
- if ( credit > TTP_MAX_QUEUE)
+ if (credit > TTP_MAX_QUEUE)
self->initial_credit = TTP_MAX_QUEUE;
else
self->initial_credit = credit;
-
- return self;
+
+ return self;
}
/*
@@ -193,27 +189,20 @@ struct tsap_cb *irttp_open_tsap( __u8 stsap_sel, int credit,
* deallocation of the TSAP, and resetting of the TSAPs values;
*
*/
-static void __irttp_close_tsap( struct tsap_cb *self)
+static void __irttp_close_tsap(struct tsap_cb *self)
{
- DEBUG( 4, __FUNCTION__ "()\n");
-
/* First make sure we're connected. */
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
- irttp_flush_queues( self);
+ irttp_flush_queues(self);
- del_timer( &self->todo_timer);
+ del_timer(&self->todo_timer);
self->connected = FALSE;
self->magic = ~TTP_TSAP_MAGIC;
- /*
- * Deallocate structure
- */
- kfree( self);
-
- DEBUG( 4, "irttp_close_tsap() -->\n");
+ kfree(self);
}
/*
@@ -223,24 +212,41 @@ static void __irttp_close_tsap( struct tsap_cb *self)
* associated with this TSAP
*
*/
-void irttp_close_tsap( struct tsap_cb *self)
+int irttp_close_tsap(struct tsap_cb *self)
{
struct tsap_cb *tsap;
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+ DEBUG(4, __FUNCTION__ "()\n");
- tsap = hashbin_remove( irttp->tsaps, self->stsap_sel, NULL);
+ ASSERT(self != NULL, return -1;);
+ ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
- ASSERT( tsap == self, return;);
+ /* Make sure tsap has been disconnected */
+ if (self->connected) {
+ /* Check if disconnect is not pending */
+ if (!self->disconnect_pend) {
+ DEBUG(0, __FUNCTION__ "(), TSAP still connected!\n");
+ irttp_disconnect_request(self, NULL, P_NORMAL);
+ }
+ self->close_pend = TRUE;
+ irttp_start_todo_timer(self, 100);
+
+ return 0; /* Will be back! */
+ }
+
+ tsap = hashbin_remove(irttp->tsaps, (int) self, NULL);
+
+ ASSERT(tsap == self, return -1;);
/* Close corresponding LSAP */
- if ( self->lsap) {
- irlmp_close_lsap( self->lsap);
+ if (self->lsap) {
+ irlmp_close_lsap(self->lsap);
self->lsap = NULL;
}
- __irttp_close_tsap( self);
+ __irttp_close_tsap(self);
+
+ return 0;
}
/*
@@ -249,26 +255,26 @@ void irttp_close_tsap( struct tsap_cb *self)
* Send unreliable data on this TSAP
*
*/
-int irttp_udata_request( struct tsap_cb *self, struct sk_buff *skb)
+int irttp_udata_request(struct tsap_cb *self, struct sk_buff *skb)
{
- ASSERT( self != NULL, return -1;);
- ASSERT( self->magic == TTP_TSAP_MAGIC, return -1;);
- ASSERT( skb != NULL, return -1;);
+ ASSERT(self != NULL, return -1;);
+ ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+ ASSERT(skb != NULL, return -1;);
- DEBUG( 4, __FUNCTION__ "()\n");
+ DEBUG(4, __FUNCTION__ "()\n");
/* Check that nothing bad happens */
- if (( skb->len == 0) || ( !self->connected)) {
- DEBUG( 0, __FUNCTION__ "(), No data, or not connected\n");
+ if ((skb->len == 0) || (!self->connected)) {
+ DEBUG(1, __FUNCTION__ "(), No data, or not connected\n");
return -1;
}
- if ( skb->len > self->max_seg_size) {
- DEBUG( 0, __FUNCTION__ "(), UData is to large for IrLAP!\n");
+ if (skb->len > self->max_seg_size) {
+ DEBUG(1, __FUNCTION__ "(), UData is to large for IrLAP!\n");
return -1;
}
- irlmp_udata_request( self->lsap, skb);
+ irlmp_udata_request(self->lsap, skb);
self->stats.tx_packets++;
return 0;
@@ -280,66 +286,62 @@ int irttp_udata_request( struct tsap_cb *self, struct sk_buff *skb)
* Queue frame for transmission. If SAR is enabled, fragement the frame
* and queue the fragments for transmission
*/
-int irttp_data_request( struct tsap_cb *self, struct sk_buff *skb)
+int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb)
{
__u8 *frame;
- DEBUG( 4, __FUNCTION__ "()\n");
-
- ASSERT( self != NULL, return -1;);
- ASSERT( self->magic == TTP_TSAP_MAGIC, return -1;);
- ASSERT( skb != NULL, return -1;);
+ ASSERT(self != NULL, return -1;);
+ ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+ ASSERT(skb != NULL, return -1;);
/* Check that nothing bad happens */
- if (( skb->len == 0) || ( !self->connected)) {
- DEBUG( 4, __FUNCTION__ "(), No data, or not connected\n");
- return -1;
+ if ((skb->len == 0) || (!self->connected)) {
+ DEBUG(4, __FUNCTION__ "(), No data, or not connected\n");
+ return -ENOTCONN;
}
/*
* Check if SAR is disabled, and the frame is larger than what fits
* inside an IrLAP frame
*/
- if (( self->tx_max_sdu_size == 0) &&
- ( skb->len > self->max_seg_size))
- {
- DEBUG( 0, __FUNCTION__
+ if ((self->tx_max_sdu_size == 0) && (skb->len > self->max_seg_size)) {
+ DEBUG(1, __FUNCTION__
"(), SAR disabled, and data is to large for IrLAP!\n");
- return -1;
+ return -EMSGSIZE;
}
/*
* Check if SAR is enabled, and the frame is larger than the
* TxMaxSduSize
*/
- if (( self->tx_max_sdu_size != 0) &&
+ if ((self->tx_max_sdu_size != 0) &&
+ (self->tx_max_sdu_size != SAR_UNBOUND) &&
(skb->len > self->tx_max_sdu_size))
{
- DEBUG( 0, __FUNCTION__ "(), SAR enabled, "
+ DEBUG(1, __FUNCTION__ "(), SAR enabled, "
"but data is larger than TxMaxSduSize!\n");
- return -1;
+ return -EMSGSIZE;
}
/*
* Check if transmit queue is full
*/
- if ( skb_queue_len( &self->tx_queue) >= TTP_MAX_QUEUE) {
+ if (skb_queue_len(&self->tx_queue) >= TTP_MAX_QUEUE) {
/*
* Give it a chance to empty itself
*/
- irttp_run_tx_queue( self);
+ irttp_run_tx_queue(self);
- return -1;
+ return -ENOBUFS;
}
/* Queue frame, or queue frame segments */
- if (( self->tx_max_sdu_size == 0) ||
- ( skb->len < self->max_seg_size)) {
+ if ((self->tx_max_sdu_size == 0) || (skb->len < self->max_seg_size)) {
/* Queue frame */
- frame = skb_push( skb, TTP_HEADER);
+ frame = skb_push(skb, TTP_HEADER);
frame[0] = 0x00; /* Clear more bit */
- DEBUG( 4, __FUNCTION__ "(), queueing original skb\n");
- skb_queue_tail( &self->tx_queue, skb);
+ DEBUG(4, __FUNCTION__ "(), queueing original skb\n");
+ skb_queue_tail(&self->tx_queue, skb);
} else {
/*
* Fragment the frame, this function will also queue the
@@ -347,117 +349,103 @@ int irttp_data_request( struct tsap_cb *self, struct sk_buff *skb)
* queue may be overfilled by all the segments for a little
* while
*/
- irttp_fragment_skb( self, skb);
+ irttp_fragment_skb(self, skb);
}
/* Check if we can accept more data from client */
- if (( !self->tx_sdu_busy) &&
- ( skb_queue_len( &self->tx_queue) > HIGH_THRESHOLD)) {
+ if ((!self->tx_sdu_busy) &&
+ (skb_queue_len(&self->tx_queue) > HIGH_THRESHOLD)) {
/* Tx queue filling up, so stop client */
self->tx_sdu_busy = TRUE;
- if ( self->notify.flow_indication) {
- self->notify.flow_indication( self->notify.instance,
- self,
- FLOW_STOP);
+ if (self->notify.flow_indication) {
+ self->notify.flow_indication(
+ self->notify.instance, self, FLOW_STOP);
}
}
/* Try to make some progress */
- irttp_run_tx_queue( self);
+ irttp_run_tx_queue(self);
return 0;
}
/*
- * Function irttp_xmit (self)
+ * Function irttp_run_tx_queue (self)
*
* If possible, transmit a frame queued for transmission.
*
*/
-static void irttp_run_tx_queue( struct tsap_cb *self)
+static void irttp_run_tx_queue(struct tsap_cb *self)
{
struct sk_buff *skb = NULL;
unsigned long flags;
__u8 *frame;
int n;
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
-
- if ( irda_lock( &self->tx_queue_lock) == FALSE)
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+
+ if (irda_lock(&self->tx_queue_lock) == FALSE)
return;
- while (( self->send_credit > 0) && !skb_queue_empty( &self->tx_queue)){
-
- skb = skb_dequeue( &self->tx_queue);
- ASSERT( skb != NULL, return;);
+ while ((self->send_credit > 0) && !skb_queue_empty(&self->tx_queue)) {
+ skb = skb_dequeue(&self->tx_queue);
+ ASSERT(skb != NULL, return;);
/* Make room for TTP header */
- ASSERT( skb_headroom( skb) >= TTP_HEADER, return;);
+ ASSERT(skb_headroom(skb) >= TTP_HEADER, return;);
/*
* Since we can transmit and receive frames concurrently,
* the code below is a critical region and we must assure that
* nobody messes with the credits while we update them.
*/
- save_flags( flags);
- cli();
+ spin_lock_irqsave(&self->lock, flags);
n = self->avail_credit;
self->avail_credit = 0;
- /* Only space for 127 credits in frame */
- if ( n > 127) {
+ /* Only room for 127 credits in frame */
+ if (n > 127) {
self->avail_credit = n-127;
n = 127;
}
self->remote_credit += n;
self->send_credit--;
- restore_flags(flags);
+ spin_unlock_irqrestore(&self->lock, flags);
- DEBUG( 4, "irttp_xmit: Giving away %d credits\n", n);
-
/*
* More bit must be set by the data_request() or fragment()
* functions
*/
frame = skb->data;
- DEBUG( 4, __FUNCTION__ "(), More=%s\n", frame[0] & 0x80 ?
+ DEBUG(4, __FUNCTION__ "(), More=%s\n", frame[0] & 0x80 ?
"TRUE" : "FALSE" );
frame[0] |= (__u8) (n & 0x7f);
- irlmp_data_request( self->lsap, skb);
+ irlmp_data_request(self->lsap, skb);
self->stats.tx_packets++;
/* Check if we can accept more frames from client */
- if (( self->tx_sdu_busy) &&
- ( skb_queue_len( &self->tx_queue) < LOW_THRESHOLD)) {
+ if ((self->tx_sdu_busy) &&
+ (skb_queue_len(&self->tx_queue) < LOW_THRESHOLD))
+ {
self->tx_sdu_busy = FALSE;
- if ( self->notify.flow_indication)
- self->notify.flow_indication( self->notify.instance,
- self,
- FLOW_START);
+ if (self->notify.flow_indication)
+ self->notify.flow_indication(
+ self->notify.instance, self,
+ FLOW_START);
}
}
/* Reset lock */
self->tx_queue_lock = 0;
-
- /* Check if there is any disconnect request pending */
- if ( self->disconnect_pend) {
- if ( self->disconnect_skb) {
- irttp_disconnect_request( self, self->disconnect_skb,
- P_NORMAL);
- self->disconnect_skb = NULL;
- } else
- irttp_disconnect_request( self, NULL, P_NORMAL);
- }
}
/*
@@ -466,80 +454,78 @@ static void irttp_run_tx_queue( struct tsap_cb *self)
* Send a dataless flowdata TTP-PDU and give available credit to peer
* TSAP
*/
-void irttp_give_credit( struct tsap_cb *self)
+void irttp_give_credit(struct tsap_cb *self)
{
struct sk_buff *tx_skb = NULL;
unsigned long flags;
int n;
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
- DEBUG( 4, "irttp_give_credit() send=%d,avail=%d,remote=%d\n",
+ DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n",
self->send_credit, self->avail_credit, self->remote_credit);
/* Give credit to peer */
- tx_skb = dev_alloc_skb( 64);
- if ( tx_skb == NULL) {
- DEBUG( 0, "irttp_give_credit: "
- "Could not allocate an sk_buff of length %d\n", 64);
+ tx_skb = dev_alloc_skb(64);
+ if (!tx_skb)
return;
- }
/* Reserve space for LMP, and LAP header */
- skb_reserve( tx_skb, LMP_HEADER+LAP_HEADER);
+ skb_reserve(tx_skb, LMP_HEADER+LAP_HEADER);
/*
* Since we can transmit and receive frames concurrently,
* the code below is a critical region and we must assure that
* nobody messes with the credits while we update them.
*/
- save_flags( flags);
- cli();
+ spin_lock_irqsave(&self->lock, flags);
n = self->avail_credit;
self->avail_credit = 0;
/* Only space for 127 credits in frame */
- if ( n > 127) {
+ if (n > 127) {
self->avail_credit = n - 127;
n = 127;
}
self->remote_credit += n;
- restore_flags(flags);
+ spin_unlock_irqrestore(&self->lock, flags);
- skb_put( tx_skb, 1);
- tx_skb->data[0] = (__u8) ( n & 0x7f);
+ skb_put(tx_skb, 1);
+ tx_skb->data[0] = (__u8) (n & 0x7f);
- irlmp_data_request( self->lsap, tx_skb);
+ irlmp_data_request(self->lsap, tx_skb);
self->stats.tx_packets++;
}
/*
* Function irttp_udata_indication (instance, sap, skb)
*
- *
+ * Received some unit-data (unreliable)
*
*/
-void irttp_udata_indication( void *instance, void *sap, struct sk_buff *skb)
+static int irttp_udata_indication(void *instance, void *sap,
+ struct sk_buff *skb)
{
struct tsap_cb *self;
- DEBUG( 4, __FUNCTION__ "()\n");
+ DEBUG(4, __FUNCTION__ "()\n");
self = (struct tsap_cb *) instance;
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
- ASSERT( skb != NULL, return;);
+ ASSERT(self != NULL, return -1;);
+ ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+ ASSERT(skb != NULL, return -1;);
/* Just pass data to layer above */
- if ( self->notify.udata_indication) {
- self->notify.udata_indication( self->notify.instance, self,
- skb);
+ if (self->notify.udata_indication) {
+ self->notify.udata_indication(self->notify.instance, self, skb);
}
self->stats.rx_packets++;
+
+ return 0;
}
/*
@@ -548,7 +534,8 @@ void irttp_udata_indication( void *instance, void *sap, struct sk_buff *skb)
* Receive segment from IrLMP.
*
*/
-void irttp_data_indication( void *instance, void *sap, struct sk_buff *skb)
+static int irttp_data_indication(void *instance, void *sap,
+ struct sk_buff *skb)
{
struct tsap_cb *self;
int more;
@@ -557,17 +544,17 @@ void irttp_data_indication( void *instance, void *sap, struct sk_buff *skb)
self = (struct tsap_cb *) instance;
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
- ASSERT( skb != NULL, return;);
+ ASSERT(self != NULL, return -1;);
+ ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+ ASSERT(skb != NULL, return -1;);
frame = skb->data;
n = frame[0] & 0x7f; /* Extract the credits */
more = frame[0] & 0x80;
- DEBUG( 4, __FUNCTION__"(), got %d credits, TSAP sel=%02x\n",
- n, self->stsap_sel);
+ DEBUG(3, __FUNCTION__"(), got %d credits, TSAP sel=%02x\n",
+ n, self->stsap_sel);
self->stats.rx_packets++;
@@ -575,7 +562,7 @@ void irttp_data_indication( void *instance, void *sap, struct sk_buff *skb)
* Data or dataless frame? Dataless frames only contain the
* TTP_HEADER
*/
- if ( skb->len == 1) {
+ if (skb->len == 1) {
/* Dataless flowdata TTP-PDU */
self->send_credit += n;
} else {
@@ -587,27 +574,28 @@ void irttp_data_indication( void *instance, void *sap, struct sk_buff *skb)
* We don't remove the TTP header, since we must preserve the
* more bit, so the defragment routing knows what to do
*/
- skb_queue_tail( &self->rx_queue, skb);
+ skb_queue_tail(&self->rx_queue, skb);
}
- irttp_run_rx_queue( self);
+ irttp_run_rx_queue(self);
/*
* Give avay some credits to peer?
*/
- if (( skb_queue_empty( &self->tx_queue)) &&
- ( self->remote_credit < LOW_THRESHOLD) &&
- ( self->avail_credit > 0))
+ if ((skb_queue_empty(&self->tx_queue)) &&
+ (self->remote_credit < LOW_THRESHOLD) &&
+ (self->avail_credit > 0))
{
/* Schedule to start immediately after this thread */
- irttp_start_todo_timer( self, 0);
+ irttp_start_todo_timer(self, 0);
}
/* If peer has given us some credites and we didn't have anyone
* from before, the we need to shedule the tx queue?
*/
- if ( self->send_credit == n)
- irttp_start_todo_timer( self, 0);
+ if (self->send_credit == n)
+ irttp_start_todo_timer(self, 0);
+ return 0;
}
/*
@@ -617,26 +605,26 @@ void irttp_data_indication( void *instance, void *sap, struct sk_buff *skb)
* delivering frames if the receive queues are starting to get full, or
* to tell IrTTP to start delivering frames again.
*/
-void irttp_flow_request( struct tsap_cb *self, LOCAL_FLOW flow)
+void irttp_flow_request(struct tsap_cb *self, LOCAL_FLOW flow)
{
- DEBUG( 0, __FUNCTION__ "()\n");
+ DEBUG(1, __FUNCTION__ "()\n");
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
- switch ( flow) {
+ switch (flow) {
case FLOW_STOP:
- DEBUG( 0, __FUNCTION__ "(), flow stop\n");
+ DEBUG(1, __FUNCTION__ "(), flow stop\n");
self->rx_sdu_busy = TRUE;
break;
case FLOW_START:
- DEBUG( 0, __FUNCTION__ "(), flow start\n");
+ DEBUG(1, __FUNCTION__ "(), flow start\n");
self->rx_sdu_busy = FALSE;
- irttp_run_rx_queue( self);
+ irttp_run_rx_queue(self);
break;
default:
- DEBUG( 0, __FUNCTION__ "(), Unknown flow command!\n");
+ DEBUG(1, __FUNCTION__ "(), Unknown flow command!\n");
}
}
@@ -646,38 +634,36 @@ void irttp_flow_request( struct tsap_cb *self, LOCAL_FLOW flow)
* Try to connect to remote destination TSAP selector
*
*/
-void irttp_connect_request( struct tsap_cb *self, __u8 dtsap_sel, __u32 daddr,
- struct qos_info *qos, int max_sdu_size,
- struct sk_buff *userdata)
+int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel,
+ __u32 saddr, __u32 daddr,
+ struct qos_info *qos, __u32 max_sdu_size,
+ struct sk_buff *userdata)
{
struct sk_buff *skb;
__u8 *frame;
__u8 n;
- DEBUG( 4, __FUNCTION__ "(), max_sdu_size=%d\n", max_sdu_size);
+ DEBUG(4, __FUNCTION__ "(), max_sdu_size=%d\n", max_sdu_size);
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+ ASSERT(self != NULL, return -1;);
+ ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
/* Any userdata supplied? */
- if ( userdata == NULL) {
- skb = dev_alloc_skb( 64);
- if (skb == NULL) {
- DEBUG( 0, __FUNCTION__ "Could not allocate an "
- "sk_buff of length %d\n", 64);
- return;
- }
+ if (userdata == NULL) {
+ skb = dev_alloc_skb(64);
+ if (!skb)
+ return -ENOMEM;
/* Reserve space for MUX_CONTROL and LAP header */
- skb_reserve( skb, (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER));
+ skb_reserve(skb, (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER));
} else {
skb = userdata;
/*
* Check that the client has reserved enough space for
* headers
*/
- ASSERT( skb_headroom( userdata) >=
- (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER), return;);
+ ASSERT(skb_headroom(userdata) >=
+ (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER), return -1;);
}
/* Initialize connection parameters */
@@ -696,7 +682,7 @@ void irttp_connect_request( struct tsap_cb *self, __u8 dtsap_sel, __u32 daddr,
/*
* Give away max 127 credits for now
*/
- if ( n > 127) {
+ if (n > 127) {
self->avail_credit=n-127;
n = 127;
}
@@ -704,29 +690,32 @@ void irttp_connect_request( struct tsap_cb *self, __u8 dtsap_sel, __u32 daddr,
self->remote_credit = n;
/* SAR enabled? */
- if ( max_sdu_size > 0) {
- ASSERT( skb_headroom( skb) >=
+ if (max_sdu_size > 0) {
+ ASSERT(skb_headroom(skb) >=
(TTP_HEADER_WITH_SAR+LMP_CONTROL_HEADER+LAP_HEADER),
- return;);
+ return -1;);
/* Insert SAR parameters */
- frame = skb_push( skb, TTP_HEADER_WITH_SAR);
+ frame = skb_push(skb, TTP_HEADER_WITH_SAR);
frame[0] = TTP_PARAMETERS | n;
frame[1] = 0x04; /* Length */
frame[2] = 0x01; /* MaxSduSize */
frame[3] = 0x02; /* Value length */
- *((__u16 *) (frame+4))= htons( max_sdu_size); /* Big endian! */
+
+ put_unaligned(cpu_to_be16((__u16) max_sdu_size),
+ (__u16 *)(frame+4));
} else {
/* Insert plain TTP header */
- frame = skb_push( skb, TTP_HEADER);
+ frame = skb_push(skb, TTP_HEADER);
/* Insert initial credit in frame */
frame[0] = n & 0x7f;
}
/* Connect with IrLMP. No QoS parameters for now */
- irlmp_connect_request( self->lsap, dtsap_sel, daddr, qos, skb);
+ return irlmp_connect_request(self->lsap, dtsap_sel, saddr, daddr, qos,
+ skb);
}
/*
@@ -735,24 +724,22 @@ void irttp_connect_request( struct tsap_cb *self, __u8 dtsap_sel, __u32 daddr,
* Sevice user confirms TSAP connection with peer.
*
*/
-void irttp_connect_confirm( void *instance, void *sap, struct qos_info *qos,
- int max_seg_size, struct sk_buff *skb)
+void irttp_connect_confirm(void *instance, void *sap, struct qos_info *qos,
+ __u32 max_seg_size, struct sk_buff *skb)
{
struct tsap_cb *self;
+ int parameters;
__u8 *frame;
+ __u8 plen, pi, pl;
__u8 n;
- int parameters;
- DEBUG( 4, __FUNCTION__ "()\n");
+ DEBUG(4, __FUNCTION__ "()\n");
self = (struct tsap_cb *) instance;
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
- ASSERT( skb != NULL, return;);
-
- /* FIXME: just remove this when we know its working */
- ASSERT( max_seg_size == qos->data_size.value, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+ ASSERT(skb != NULL, return;);
self->max_seg_size = max_seg_size-LMP_HEADER-LAP_HEADER;
@@ -760,40 +747,59 @@ void irttp_connect_confirm( void *instance, void *sap, struct qos_info *qos,
* Check if we have got some QoS parameters back! This should be the
* negotiated QoS for the link.
*/
- if ( qos) {
- DEBUG( 4, "IrTTP, Negotiated BAUD_RATE: %02x\n",
+ if (qos) {
+ DEBUG(4, "IrTTP, Negotiated BAUD_RATE: %02x\n",
qos->baud_rate.bits);
- DEBUG( 4, "IrTTP, Negotiated BAUD_RATE: %d bps.\n",
+ DEBUG(4, "IrTTP, Negotiated BAUD_RATE: %d bps.\n",
qos->baud_rate.value);
}
frame = skb->data;
n = frame[0] & 0x7f;
- DEBUG( 4, __FUNCTION__ "(), Initial send_credit=%d\n", n);
+ DEBUG(4, __FUNCTION__ "(), Initial send_credit=%d\n", n);
self->send_credit = n;
self->tx_max_sdu_size = 0;
self->connected = TRUE;
parameters = frame[0] & 0x80;
- if ( parameters) {
- DEBUG( 4, __FUNCTION__ "(), Contains parameters!\n");
-
- self->tx_max_sdu_size = ntohs(*(__u16 *)(frame+4));
- DEBUG( 4, __FUNCTION__ "(), RxMaxSduSize=%d\n",
- self->tx_max_sdu_size);
+ if (parameters) {
+ plen = frame[1];
+ pi = frame[2];
+ pl = frame[3];
+
+ switch (pl) {
+ case 1:
+ self->tx_max_sdu_size = *(frame+4);
+ break;
+ case 2:
+ self->tx_max_sdu_size =
+ be16_to_cpu(get_unaligned((__u16 *)(frame+4)));
+ break;
+ case 4:
+ self->tx_max_sdu_size =
+ be32_to_cpu(get_unaligned((__u32 *)(frame+4)));
+ break;
+ default:
+ printk(KERN_ERR __FUNCTION__
+ "() illegal value length for max_sdu_size!\n");
+ self->tx_max_sdu_size = 0;
+ };
+
+ DEBUG(4, __FUNCTION__ "(), RxMaxSduSize=%d\n",
+ self->tx_max_sdu_size);
}
- DEBUG( 4, "irttp_connect_confirm() send=%d,avail=%d,remote=%d\n",
- self->send_credit, self->avail_credit, self->remote_credit);
+ DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n",
+ self->send_credit, self->avail_credit, self->remote_credit);
- skb_pull( skb, TTP_HEADER);
+ skb_pull(skb, TTP_HEADER);
- if ( self->notify.connect_confirm) {
- self->notify.connect_confirm( self->notify.instance, self,
- qos, self->tx_max_sdu_size,
- skb);
+ if (self->notify.connect_confirm) {
+ self->notify.connect_confirm(self->notify.instance, self,
+ qos, self->tx_max_sdu_size,
+ skb);
}
}
@@ -803,32 +809,31 @@ void irttp_connect_confirm( void *instance, void *sap, struct qos_info *qos,
* Some other device is connecting to this TSAP
*
*/
-void irttp_connect_indication( void *instance, void *sap,
- struct qos_info *qos, int max_seg_size,
- struct sk_buff *skb)
+void irttp_connect_indication(void *instance, void *sap,
+ struct qos_info *qos, __u32 max_seg_size,
+ struct sk_buff *skb)
{
struct tsap_cb *self;
- __u8 *frame;
+ struct lsap_cb *lsap;
int parameters;
- int n;
+ __u8 *frame;
+ __u8 plen, pi, pl;
+ __u8 n;
self = (struct tsap_cb *) instance;
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
- ASSERT( skb != NULL, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+ ASSERT(skb != NULL, return;);
- /* FIXME: just remove this when we know its working */
- ASSERT( max_seg_size == qos->data_size.value, return;);
+ lsap = (struct lsap_cb *) sap;
self->max_seg_size = max_seg_size-LMP_HEADER-LAP_HEADER;
- DEBUG( 4, "irttp_connect_indication(), TSAP sel=%02x\n",
- self->stsap_sel);
+ DEBUG(4, __FUNCTION__ "(), TSAP sel=%02x\n", self->stsap_sel);
- /* FIXME: Need to update dtsap_sel if its equal to LSAP_ANY */
-/* if ( self->dtsap_sel == LSAP_ANY) */
-/* self->dtsap_sel = lsap->dlsap_sel; */
+ /* Need to update dtsap_sel if its equal to LSAP_ANY */
+ self->dtsap_sel = lsap->dlsap_sel;
frame = skb->data;
n = frame[0] & 0x7f;
@@ -837,22 +842,43 @@ void irttp_connect_indication( void *instance, void *sap,
self->tx_max_sdu_size = 0;
parameters = frame[0] & 0x80;
- if ( parameters) {
- DEBUG( 4, __FUNCTION__ "(), Contains parameters!\n");
-
- self->tx_max_sdu_size = ntohs(*(__u16 *)(frame+4));
- DEBUG( 4, __FUNCTION__ "(), MaxSduSize=%d\n",
- self->tx_max_sdu_size);
+ if (parameters) {
+ DEBUG(3, __FUNCTION__ "(), Contains parameters!\n");
+ plen = frame[1];
+ pi = frame[2];
+ pl = frame[3];
+
+ switch (pl) {
+ case 1:
+ self->tx_max_sdu_size = *(frame+4);
+ break;
+ case 2:
+ self->tx_max_sdu_size =
+ be16_to_cpu(get_unaligned((__u16 *)(frame+4)));
+ break;
+ case 4:
+ self->tx_max_sdu_size =
+ be32_to_cpu(get_unaligned((__u32 *)(frame+4)));
+ break;
+ default:
+ printk(KERN_ERR __FUNCTION__
+ "() illegal value length for max_sdu_size!\n");
+ self->tx_max_sdu_size = 0;
+ };
+
+
+ DEBUG(3, __FUNCTION__ "(), MaxSduSize=%d\n",
+ self->tx_max_sdu_size);
}
- DEBUG( 4, "irttp_connect_indication: initial send_credit=%d\n", n);
+ DEBUG(4, __FUNCTION__ "(), initial send_credit=%d\n", n);
- skb_pull( skb, 1);
+ skb_pull(skb, 1); /* Remove TTP header */
- if ( self->notify.connect_indication) {
- self->notify.connect_indication( self->notify.instance, self,
- qos, self->rx_max_sdu_size,
- skb);
+ if (self->notify.connect_indication) {
+ self->notify.connect_indication(self->notify.instance, self,
+ qos, self->rx_max_sdu_size,
+ skb);
}
}
@@ -863,37 +889,34 @@ void irttp_connect_indication( void *instance, void *sap,
* IrLMP!
*
*/
-void irttp_connect_response( struct tsap_cb *self, int max_sdu_size,
- struct sk_buff *userdata)
+void irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size,
+ struct sk_buff *userdata)
{
struct sk_buff *skb;
__u8 *frame;
__u8 n;
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
- DEBUG( 4, __FUNCTION__ "(), Source TSAP selector=%02x\n",
- self->stsap_sel);
+ DEBUG(4, __FUNCTION__ "(), Source TSAP selector=%02x\n",
+ self->stsap_sel);
/* Any userdata supplied? */
- if ( userdata == NULL) {
- skb = dev_alloc_skb( 64);
- if (skb == NULL) {
- DEBUG( 0, __FUNCTION__ "Could not allocate an "
- "sk_buff of length %d\n", 64);
+ if (userdata == NULL) {
+ skb = dev_alloc_skb(64);
+ if (!skb)
return;
- }
/* Reserve space for MUX_CONTROL and LAP header */
- skb_reserve( skb, (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER));
+ skb_reserve(skb, (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER));
} else {
skb = userdata;
/*
* Check that the client has reserved enough space for
* headers
*/
- ASSERT( skb_headroom( skb) >=
+ ASSERT(skb_headroom(skb) >=
(TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER), return;);
}
@@ -906,7 +929,7 @@ void irttp_connect_response( struct tsap_cb *self, int max_sdu_size,
n = self->initial_credit;
/* Frame has only space for max 127 credits (7 bits) */
- if ( n > 127) {
+ if (n > 127) {
self->avail_credit = n - 127;
n = 127;
}
@@ -915,117 +938,152 @@ void irttp_connect_response( struct tsap_cb *self, int max_sdu_size,
self->connected = TRUE;
/* SAR enabled? */
- if ( max_sdu_size > 0) {
- ASSERT( skb_headroom( skb) >=
- (TTP_HEADER_WITH_SAR+LMP_CONTROL_HEADER+LAP_HEADER),
- return;);
+ if (max_sdu_size > 0) {
+ ASSERT(skb_headroom(skb) >=
+ (TTP_HEADER_WITH_SAR+LMP_CONTROL_HEADER+LAP_HEADER),
+ return;);
/* Insert TTP header with SAR parameters */
- frame = skb_push( skb, TTP_HEADER_WITH_SAR);
+ frame = skb_push(skb, TTP_HEADER_WITH_SAR);
frame[0] = TTP_PARAMETERS | n;
frame[1] = 0x04; /* Length */
frame[2] = 0x01; /* MaxSduSize */
frame[3] = 0x02; /* Value length */
- *((__u16 *) (frame+4))= htons( max_sdu_size);
+
+ put_unaligned(cpu_to_be16((__u16) max_sdu_size),
+ (__u16 *)(frame+4));
} else {
/* Insert TTP header */
- frame = skb_push( skb, TTP_HEADER);
+ frame = skb_push(skb, TTP_HEADER);
frame[0] = n & 0x7f;
}
- irlmp_connect_response( self->lsap, skb);
+ irlmp_connect_response(self->lsap, skb);
+}
+
+/*
+ * Function irttp_dup (self, instance)
+ *
+ * Duplicate TSAP, can be used by servers to confirm a connection on a
+ * new TSAP so it can keep listening on the old one.
+ */
+struct tsap_cb *irttp_dup(struct tsap_cb *orig, void *instance)
+{
+ struct tsap_cb *new;
+
+ DEBUG(1, __FUNCTION__ "()\n");
+
+ if (!hashbin_find(irttp->tsaps, (int) orig, NULL)) {
+ DEBUG(0, __FUNCTION__ "(), unable to find TSAP\n");
+ return NULL;
+ }
+ new = kmalloc(sizeof(struct tsap_cb), GFP_ATOMIC);
+ if (!new) {
+ DEBUG(0, __FUNCTION__ "(), unable to kmalloc\n");
+ return NULL;
+ }
+ /* Dup */
+ memcpy(new, orig, sizeof(struct tsap_cb));
+ new->notify.instance = instance;
+ new->lsap = irlmp_dup(orig->lsap, new);
+
+ /* Not everything should be copied */
+ 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);
+
+ hashbin_insert(irttp->tsaps, (QUEUE *) new, (int) new, NULL);
+
+ return new;
}
/*
- * Function irttp_disconnect_request ( self)
+ * Function irttp_disconnect_request (self)
*
* Close this connection please! If priority is high, the queued data
* segments, if any, will be deallocated first
*
*/
-void irttp_disconnect_request( struct tsap_cb *self, struct sk_buff *userdata,
- int priority)
+void irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *userdata,
+ int priority)
{
struct sk_buff *skb;
- DEBUG( 4, __FUNCTION__ "()\n");
+ DEBUG(2, __FUNCTION__ "()\n");
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
/* Already disconnected? */
- if ( !self->connected) {
- DEBUG( 4, __FUNCTION__ "(), already disconnected!\n");
+ if (!self->connected) {
+ DEBUG(4, __FUNCTION__ "(), already disconnected!\n");
return;
}
/* Disconnect already pending? */
- if ( self->disconnect_pend) {
- DEBUG( 0, __FUNCTION__ "(), disconnect already pending\n");
- if ( userdata) {
- dev_kfree_skb( userdata);
+ if (self->disconnect_pend) {
+ DEBUG(1, __FUNCTION__ "(), disconnect already pending\n");
+ if (userdata) {
+ dev_kfree_skb(userdata);
}
/* Try to make some progress */
- irttp_run_rx_queue( self);
+ irttp_run_rx_queue(self);
return;
}
/*
* Check if there is still data segments in the transmit queue
*/
- if ( skb_queue_len( &self->tx_queue) > 0) {
- if ( priority == P_HIGH) {
- DEBUG( 0, __FUNCTION__ "High priority!!()\n" );
+ if (skb_queue_len(&self->tx_queue) > 0) {
+ if (priority == P_HIGH) {
+ DEBUG(1, __FUNCTION__ "High priority!!()\n" );
/*
* No need to send the queued data, if we are
* disconnecting right now since the data will
* not have any usable connection to be sent on
*/
- irttp_flush_queues( self);
- } else if ( priority == P_NORMAL) {
+ irttp_flush_queues(self);
+ } else if (priority == P_NORMAL) {
/*
* Must delay disconnect til after all data segments
* have been sent an the tx_queue is empty
*/
- if ( userdata)
+ if (userdata)
self->disconnect_skb = userdata;
else
self->disconnect_skb = NULL;
self->disconnect_pend = TRUE;
- irttp_run_tx_queue( self);
- /*
- * irttp_xmit will call us again when the tx_queue
- * is empty
- */
+ irttp_run_tx_queue(self);
+
+ irttp_start_todo_timer(self, 100);
return;
}
}
- DEBUG( 0, __FUNCTION__ "(), Disconnecting ...\n");
+ DEBUG(1, __FUNCTION__ "(), Disconnecting ...\n");
self->connected = FALSE;
- if ( !userdata) {
- skb = dev_alloc_skb( 64);
- if (skb == NULL) {
- DEBUG( 0, __FUNCTION__ "(), Could not allocate an "
- "sk_buff of length %d\n", 64);
+ if (!userdata) {
+ skb = dev_alloc_skb(64);
+ if (!skb)
return;
- }
-
+
/*
* Reserve space for MUX and LAP header
*/
- skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER);
-
+ skb_reserve(skb, LMP_CONTROL_HEADER+LAP_HEADER);
+
userdata = skb;
}
- irlmp_disconnect_request( self->lsap, userdata);
+ irlmp_disconnect_request(self->lsap, userdata);
}
/*
@@ -1034,26 +1092,58 @@ void irttp_disconnect_request( struct tsap_cb *self, struct sk_buff *userdata,
* Disconnect indication, TSAP disconnected by peer?
*
*/
-void irttp_disconnect_indication( void *instance, void *sap, LM_REASON reason,
- struct sk_buff *userdata)
+void irttp_disconnect_indication(void *instance, void *sap, LM_REASON reason,
+ struct sk_buff *userdata)
{
struct tsap_cb *self;
- DEBUG( 4, "irttp_disconnect_indication()\n");
+ DEBUG(4, __FUNCTION__ "()\n");
- self = ( struct tsap_cb *) instance;
+ self = (struct tsap_cb *) instance;
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
self->connected = FALSE;
- /*
- * Use callback to notify layer above
+ if (!self->notify.disconnect_indication)
+ return;
+
+ self->notify.disconnect_indication(self->notify.instance, self, reason,
+ userdata);
+}
+
+/*
+ * Function irttp_do_data_indication (self, skb)
+ *
+ * Try to deliver reassebled skb to layer above, and requeue it if that
+ * for some reason should fail. We mark rx sdu as busy to apply back
+ * pressure is necessary.
+ */
+void irttp_do_data_indication(struct tsap_cb *self, struct sk_buff *skb)
+{
+ int err;
+
+ err = self->notify.data_indication(self->notify.instance, self, skb);
+
+ /* Usually the layer above will notify that it's input queue is
+ * starting to get filled by using the flow request, but this may
+ * be difficult, so it can instead just refuse to eat it and just
+ * give an error back
*/
- if ( self->notify.disconnect_indication)
- self->notify.disconnect_indication( self->notify.instance,
- self, reason, userdata);
+ if (err == -ENOMEM) {
+ DEBUG(0, __FUNCTION__ "() requeueing skb!\n");
+
+ /* Make sure we take a break */
+ self->rx_sdu_busy = TRUE;
+
+ /* Need to push the header in again */
+ skb_push(skb, TTP_HEADER);
+ skb->data[0] = 0x00; /* Make sure MORE bit is cleared */
+
+ /* Put skb back on queue */
+ skb_queue_head(&self->rx_queue, skb);
+ }
}
/*
@@ -1062,43 +1152,27 @@ void irttp_disconnect_indication( void *instance, void *sap, LM_REASON reason,
* Check if we have any frames to be transmitted, or if we have any
* available credit to give away.
*/
-void irttp_run_rx_queue( struct tsap_cb *self)
+void irttp_run_rx_queue(struct tsap_cb *self)
{
struct sk_buff *skb;
- __u8 *frame;
int more = 0;
- void *instance;
-
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
-
- instance = self->notify.instance;
- ASSERT( instance != NULL, return;);
- DEBUG( 4, "irttp_do_events() send=%d,avail=%d,remote=%d\n",
+ DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n",
self->send_credit, self->avail_credit, self->remote_credit);
- if ( irda_lock( &self->rx_queue_lock) == FALSE)
+ if (irda_lock(&self->rx_queue_lock) == FALSE)
return;
/*
- * Process receive queue
+ * Reassemble all frames in receive queue and deliver them
*/
- while (( !skb_queue_empty( &self->rx_queue)) && !self->rx_sdu_busy) {
-
- skb = skb_dequeue( &self->rx_queue);
- if ( !skb)
- break; /* Should not happend, but ... */
-
+ while (!self->rx_sdu_busy && (skb = skb_dequeue(&self->rx_queue))) {
self->avail_credit++;
- frame = skb->data;
- more = frame[0] & 0x80;
- DEBUG( 4, __FUNCTION__ "(), More=%s\n", more ? "TRUE" :
- "FALSE");
+ more = skb->data[0] & 0x80;
/* Remove TTP header */
- skb_pull( skb, TTP_HEADER);
+ skb_pull(skb, TTP_HEADER);
/* Add the length of the remaining data */
self->rx_sdu_size += skb->len;
@@ -1109,57 +1183,61 @@ void irttp_run_rx_queue( struct tsap_cb *self)
* immediately. This can be requested by clients that
* implements byte streams without any message boundaries
*/
- if ((self->no_defrag) || (self->rx_max_sdu_size == 0)) {
- self->notify.data_indication( instance, self, skb);
+ if (self->rx_max_sdu_size == SAR_DISABLE) {
+ irttp_do_data_indication(self, skb);
self->rx_sdu_size = 0;
continue;
}
/* Check if this is a fragment, and not the last fragment */
- if ( more) {
+ if (more) {
/*
* Queue the fragment if we still are within the
* limits of the maximum size of the rx_sdu
*/
- if ( self->rx_sdu_size <= self->rx_max_sdu_size) {
- DEBUG( 4, __FUNCTION__
- "(), queueing fragment\n");
-
- skb_queue_tail( &self->rx_fragments, skb);
+ if (self->rx_sdu_size <= self->rx_max_sdu_size) {
+ DEBUG(4, __FUNCTION__ "(), queueing frag\n");
+ skb_queue_tail(&self->rx_fragments, skb);
} else {
- DEBUG( 0, __FUNCTION__ "(), Error!\n");
+ /* Free the part of the SDU that is too big */
+ dev_kfree_skb(skb);
}
- } else {
- /*
- * This is the last fragment, so time to reassemble!
+ continue;
+ }
+ /*
+ * This is the last fragment, so time to reassemble!
+ */
+ if ((self->rx_sdu_size <= self->rx_max_sdu_size) ||
+ (self->rx_max_sdu_size == SAR_UNBOUND))
+ {
+ /*
+ * A little optimizing. Only queue the fragment if
+ * there are other fragments. Since if this is the
+ * last and only fragment, there is no need to
+ * reassemble :-)
*/
- if ( self->rx_sdu_size <= self->rx_max_sdu_size) {
-
- /* A little optimizing. Only queue the
- * fragment if there is other fragments. Since
- * if this is the last and only fragment,
- * there is no need to reassemble
- */
- if ( !skb_queue_empty( &self->rx_fragments)) {
-
- DEBUG( 4, __FUNCTION__
- "(), queueing fragment\n");
- skb_queue_tail( &self->rx_fragments,
- skb);
-
- skb = irttp_reassemble_skb( self);
- }
- self->notify.data_indication( instance, self,
- skb);
- } else {
- DEBUG( 0, __FUNCTION__
- "(), Truncated frame\n");
- self->notify.data_indication(
- self->notify.instance, self, skb);
+ if (!skb_queue_empty(&self->rx_fragments)) {
+ skb_queue_tail(&self->rx_fragments,
+ skb);
+
+ skb = irttp_reassemble_skb(self);
}
- self->rx_sdu_size = 0;
+
+ /* Now we can deliver the reassembled skb */
+ irttp_do_data_indication(self, skb);
+ } else {
+ DEBUG(1, __FUNCTION__ "(), Truncated frame\n");
+
+ /* Free the part of the SDU that is too big */
+ dev_kfree_skb(skb);
+
+ /* Deliver only the valid but truncated part of SDU */
+ skb = irttp_reassemble_skb(self);
+
+ irttp_do_data_indication(self, skb);
}
+ self->rx_sdu_size = 0;
}
/* Reset lock */
self->rx_queue_lock = 0;
@@ -1170,28 +1248,26 @@ void irttp_run_rx_queue( struct tsap_cb *self)
*
* Flushes (removes all frames) in transitt-buffer (tx_list)
*/
-void irttp_flush_queues( struct tsap_cb *self)
+void irttp_flush_queues(struct tsap_cb *self)
{
struct sk_buff* skb;
- DEBUG( 4, __FUNCTION__ "()\n");
+ DEBUG(4, __FUNCTION__ "()\n");
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
/* Deallocate frames waiting to be sent */
- while (( skb = skb_dequeue( &self->tx_queue)) != NULL) {
- dev_kfree_skb( skb);
- }
+ while ((skb = skb_dequeue(&self->tx_queue)) != NULL)
+ dev_kfree_skb(skb);
+
/* Deallocate received frames */
- while (( skb = skb_dequeue( &self->rx_queue)) != NULL) {
- dev_kfree_skb( skb);
- }
- /* Deallocate received fragments */
- while (( skb = skb_dequeue( &self->rx_fragments)) != NULL) {
- dev_kfree_skb( skb);
- }
+ while ((skb = skb_dequeue(&self->rx_queue)) != NULL)
+ dev_kfree_skb(skb);
+ /* Deallocate received fragments */
+ while ((skb = skb_dequeue(&self->rx_fragments)) != NULL)
+ dev_kfree_skb(skb);
}
/*
@@ -1201,40 +1277,43 @@ void irttp_flush_queues( struct tsap_cb *self)
* queue
*
*/
-static struct sk_buff *irttp_reassemble_skb( struct tsap_cb *self)
+static struct sk_buff *irttp_reassemble_skb(struct tsap_cb *self)
{
struct sk_buff *skb, *frag;
int n = 0; /* Fragment index */
+
+ ASSERT(self != NULL, return NULL;);
+ ASSERT(self->magic == TTP_TSAP_MAGIC, return NULL;);
- ASSERT( self != NULL, return NULL;);
- ASSERT( self->magic == TTP_TSAP_MAGIC, return NULL;);
-
- DEBUG( 4, __FUNCTION__ "(), self->rx_sdu_size=%d\n",
- self->rx_sdu_size);
+ DEBUG(4, __FUNCTION__ "(), self->rx_sdu_size=%d\n",
+ self->rx_sdu_size);
- skb = dev_alloc_skb( self->rx_sdu_size);
- if ( !skb) {
- DEBUG( 0, __FUNCTION__ "(), unable to allocate skb\n");
+ skb = dev_alloc_skb(self->rx_sdu_size);
+ if (!skb)
return NULL;
- }
- skb_put( skb, self->rx_sdu_size);
+ /*
+ * Need to reserve space for TTP header in case this skb needs to
+ * be requeued in case delivery failes
+ */
+ skb_reserve(skb, TTP_HEADER);
+ skb_put(skb, self->rx_sdu_size);
/*
* Copy all fragments to a new buffer
*/
- while (( frag = skb_dequeue( &self->rx_fragments)) != NULL) {
- memcpy( skb->data+n, frag->data, frag->len);
+ while ((frag = skb_dequeue(&self->rx_fragments)) != NULL) {
+ memcpy(skb->data+n, frag->data, frag->len);
n += frag->len;
- dev_kfree_skb( frag);
+ dev_kfree_skb(frag);
}
- DEBUG( 4, __FUNCTION__ "(), frame len=%d\n", n);
+ DEBUG(4, __FUNCTION__ "(), frame len=%d\n", n);
/* Set the new length */
- DEBUG( 4, __FUNCTION__ "(), rx_sdu_size=%d\n", self->rx_sdu_size);
- ASSERT( n <= self->rx_sdu_size, return NULL;);
- skb_trim( skb, n);
+ DEBUG(4, __FUNCTION__ "(), rx_sdu_size=%d\n", self->rx_sdu_size);
+ ASSERT(n <= self->rx_sdu_size, return NULL;);
+ skb_trim(skb, n);
self->rx_sdu_size = 0;
@@ -1247,60 +1326,57 @@ static struct sk_buff *irttp_reassemble_skb( struct tsap_cb *self)
* Fragments a frame and queues all the fragments for transmission
*
*/
-static void irttp_fragment_skb( struct tsap_cb *self, struct sk_buff *skb)
+static void irttp_fragment_skb(struct tsap_cb *self, struct sk_buff *skb)
{
struct sk_buff *frag;
__u8 *frame;
- DEBUG( 4, __FUNCTION__ "()\n");
+ DEBUG(4, __FUNCTION__ "()\n");
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
- ASSERT( skb != NULL, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+ ASSERT(skb != NULL, return;);
/*
* Split frame into a number of segments
*/
- while ( skb->len > 0) {
+ while (skb->len > 0) {
/*
* Instead of making the last segment, we just
* queue what is left of the original skb
*/
- if ( skb->len < self->max_seg_size) {
- DEBUG( 4, __FUNCTION__
+ if (skb->len < self->max_seg_size) {
+ DEBUG(4, __FUNCTION__
"(), queuing last segment\n");
- frame = skb_push( skb, TTP_HEADER);
+ frame = skb_push(skb, TTP_HEADER);
frame[0] = 0x00; /* Clear more bit */
- skb_queue_tail( &self->tx_queue, skb);
+ skb_queue_tail(&self->tx_queue, skb);
return;
}
/* Make new segment */
- frag = dev_alloc_skb( self->max_seg_size+
- TTP_HEADER+LMP_HEADER+
- LAP_HEADER);
- if ( frag == NULL) {
- DEBUG( 0, __FUNCTION__
- "(), Couldn't allocate skbuff!\n");
+ frag = dev_alloc_skb(self->max_seg_size+
+ TTP_HEADER+LMP_HEADER+
+ LAP_HEADER);
+ if (!frag)
return;
- }
- skb_reserve( frag, LMP_HEADER+LAP_HEADER);
+ skb_reserve(frag, LMP_HEADER+LAP_HEADER);
/*
* Copy data from the original skb into this fragment. We
* first insert the TTP header with the more bit set
*/
- frame = skb_put( frag, self->max_seg_size+TTP_HEADER);
+ frame = skb_put(frag, self->max_seg_size+TTP_HEADER);
frame[0] = TTP_MORE;
- memcpy( frag->data+1, skb->data, self->max_seg_size);
+ memcpy(frag->data+1, skb->data, self->max_seg_size);
/* Hide the copied data from the original skb */
- skb_pull( skb, self->max_seg_size);
+ skb_pull(skb, self->max_seg_size);
- skb_queue_tail( &self->tx_queue, frag);
+ skb_queue_tail(&self->tx_queue, frag);
}
}
@@ -1310,31 +1386,54 @@ static void irttp_fragment_skb( struct tsap_cb *self, struct sk_buff *skb)
* Todo timer has expired!
*
*/
-static void irttp_todo_expired( unsigned long data)
+static void irttp_todo_expired(unsigned long data)
{
- struct tsap_cb *self = ( struct tsap_cb *) data;
+ struct tsap_cb *self = (struct tsap_cb *) data;
- DEBUG( 4, __FUNCTION__ "()\n");
+ DEBUG(4, __FUNCTION__ "()\n");
/* Check that we still exist */
- if ( !self || self->magic != TTP_TSAP_MAGIC) {
+ if (!self || self->magic != TTP_TSAP_MAGIC) {
return;
}
- irttp_run_rx_queue( self);
- irttp_run_tx_queue( self);
+ irttp_run_rx_queue(self);
+ irttp_run_tx_queue(self);
/* Give avay some credits to peer? */
- if (( skb_queue_empty( &self->tx_queue)) &&
- ( self->remote_credit < LOW_THRESHOLD) &&
- ( self->avail_credit > 0))
+ if ((skb_queue_empty(&self->tx_queue)) &&
+ (self->remote_credit < LOW_THRESHOLD) &&
+ (self->avail_credit > 0))
{
- DEBUG( 4, "irttp_do_events: sending credit!\n");
- irttp_give_credit( self);
+ DEBUG(4, __FUNCTION__ "(), sending credit!\n");
+ irttp_give_credit(self);
}
-
- /* Rearm! */
- /* irttp_start_todo_timer( self, 50); */
+
+ /* Check if time for disconnect */
+ if (self->disconnect_pend) {
+ /* Check if it's possible to disconnect yet */
+ if (skb_queue_empty(&self->tx_queue)) {
+
+ /* Make sure disconnect is not pending anymore */
+ self->disconnect_pend = FALSE;
+ if (self->disconnect_skb) {
+ irttp_disconnect_request(
+ self, self->disconnect_skb, P_NORMAL);
+ self->disconnect_skb = NULL;
+ } else
+ irttp_disconnect_request(self, NULL, P_NORMAL);
+ } else {
+ /* Try again later */
+ irttp_start_todo_timer(self, 100);
+
+ /* No reason to try and close now */
+ return;
+ }
+ }
+
+ /* Check if it's closing time */
+ if (self->close_pend)
+ irttp_close_tsap(self);
}
/*
@@ -1343,18 +1442,18 @@ static void irttp_todo_expired( unsigned long data)
* Start todo timer.
*
*/
-static void irttp_start_todo_timer( struct tsap_cb *self, int timeout)
+static void irttp_start_todo_timer(struct tsap_cb *self, int timeout)
{
- ASSERT( self != NULL, return;);
- ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
- del_timer( &self->todo_timer);
+ del_timer(&self->todo_timer);
self->todo_timer.data = (unsigned long) self;
self->todo_timer.function = &irttp_todo_expired;
self->todo_timer.expires = jiffies + timeout;
- add_timer( &self->todo_timer);
+ add_timer(&self->todo_timer);
}
#ifdef CONFIG_PROC_FS
@@ -1363,65 +1462,64 @@ static void irttp_start_todo_timer( struct tsap_cb *self, int timeout)
*
* Give some info to the /proc file system
*/
-int irttp_proc_read( char *buf, char **start, off_t offset, int len,
- int unused)
+int irttp_proc_read(char *buf, char **start, off_t offset, int len, int unused)
{
struct tsap_cb *self;
unsigned long flags;
int i = 0;
- ASSERT( irttp != NULL, return 0;);
+ ASSERT(irttp != NULL, return 0;);
len = 0;
save_flags(flags);
cli();
- self = ( struct tsap_cb *) hashbin_get_first( irttp->tsaps);
- while ( self != NULL) {
- if ( !self || self->magic != TTP_TSAP_MAGIC) {
- DEBUG( 0, "irttp_proc_read: bad ptr self\n");
+ self = (struct tsap_cb *) hashbin_get_first(irttp->tsaps);
+ while (self != NULL) {
+ if (!self || self->magic != TTP_TSAP_MAGIC) {
+ DEBUG(1, "irttp_proc_read: bad ptr self\n");
return len;
}
- len += sprintf( buf+len, "TSAP %d, ", i++);
- len += sprintf( buf+len, "stsap_sel: %02x, ",
+ len += sprintf(buf+len, "TSAP %d, ", i++);
+ len += sprintf(buf+len, "stsap_sel: %02x, ",
self->stsap_sel);
- len += sprintf( buf+len, "dtsap_sel: %02x\n",
+ len += sprintf(buf+len, "dtsap_sel: %02x\n",
self->dtsap_sel);
- len += sprintf( buf+len, " connected: %s, ",
+ len += sprintf(buf+len, " connected: %s, ",
self->connected? "TRUE":"FALSE");
- len += sprintf( buf+len, "avail credit: %d, ",
+ len += sprintf(buf+len, "avail credit: %d, ",
self->avail_credit);
- len += sprintf( buf+len, "remote credit: %d, ",
+ len += sprintf(buf+len, "remote credit: %d, ",
self->remote_credit);
- len += sprintf( buf+len, "send credit: %d\n",
+ len += sprintf(buf+len, "send credit: %d\n",
self->send_credit);
- len += sprintf( buf+len, " tx packets: %d, ",
+ len += sprintf(buf+len, " tx packets: %d, ",
self->stats.tx_packets);
- len += sprintf( buf+len, "rx packets: %d, ",
+ len += sprintf(buf+len, "rx packets: %d, ",
self->stats.rx_packets);
- len += sprintf( buf+len, "tx_queue len: %d ",
- skb_queue_len( &self->tx_queue));
- len += sprintf( buf+len, "rx_queue len: %d\n",
- skb_queue_len( &self->rx_queue));
- len += sprintf( buf+len, " tx_sdu_busy: %s, ",
+ len += sprintf(buf+len, "tx_queue len: %d ",
+ skb_queue_len(&self->tx_queue));
+ len += sprintf(buf+len, "rx_queue len: %d\n",
+ skb_queue_len(&self->rx_queue));
+ len += sprintf(buf+len, " tx_sdu_busy: %s, ",
self->tx_sdu_busy? "TRUE":"FALSE");
- len += sprintf( buf+len, "rx_sdu_busy: %s\n",
+ len += sprintf(buf+len, "rx_sdu_busy: %s\n",
self->rx_sdu_busy? "TRUE":"FALSE");
- len += sprintf( buf+len, " max_seg_size: %d, ",
+ len += sprintf(buf+len, " max_seg_size: %d, ",
self->max_seg_size);
- len += sprintf( buf+len, "tx_max_sdu_size: %d, ",
+ len += sprintf(buf+len, "tx_max_sdu_size: %d, ",
self->tx_max_sdu_size);
- len += sprintf( buf+len, "rx_max_sdu_size: %d\n",
+ len += sprintf(buf+len, "rx_max_sdu_size: %d\n",
self->rx_max_sdu_size);
- len += sprintf( buf+len, " Used by (%s)\n",
+ len += sprintf(buf+len, " Used by (%s)\n",
self->notify.name);
- len += sprintf( buf+len, "\n");
+ len += sprintf(buf+len, "\n");
- self = ( struct tsap_cb *) hashbin_get_next( irttp->tsaps);
+ self = (struct tsap_cb *) hashbin_get_next(irttp->tsaps);
}
restore_flags(flags);