Commit ac5ccb22 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/jgarzik/irda-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 7b455189 887ac0a0
...@@ -402,7 +402,7 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev) ...@@ -402,7 +402,7 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
usb_fill_bulk_urb(urb, self->usbdev, usb_fill_bulk_urb(urb, self->usbdev,
usb_sndbulkpipe(self->usbdev, self->bulk_out_ep), usb_sndbulkpipe(self->usbdev, self->bulk_out_ep),
skb->data, IRDA_USB_MAX_MTU, skb->data, IRDA_SKB_MAX_MTU,
write_bulk_callback, skb); write_bulk_callback, skb);
urb->transfer_buffer_length = skb->len; urb->transfer_buffer_length = skb->len;
/* Note : unlink *must* be Asynchronous because of the code in /* Note : unlink *must* be Asynchronous because of the code in
...@@ -442,6 +442,9 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev) ...@@ -442,6 +442,9 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
* would be lost in the noise - Jean II */ * would be lost in the noise - Jean II */
diff += IU_USB_MIN_RTT; diff += IU_USB_MIN_RTT;
#endif /* IU_USB_MIN_RTT */ #endif /* IU_USB_MIN_RTT */
/* If the usec counter did wraparound, the diff will
* go negative (tv_usec is a long), so we need to
* correct it by one second. Jean II */
if (diff < 0) if (diff < 0)
diff += 1000000; diff += 1000000;
...@@ -701,30 +704,11 @@ static void irda_usb_submit(struct irda_usb_cb *self, struct sk_buff *skb, struc ...@@ -701,30 +704,11 @@ static void irda_usb_submit(struct irda_usb_cb *self, struct sk_buff *skb, struc
IRDA_DEBUG(2, "%s()\n", __FUNCTION__); IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
/* Check that we have an urb */ /* This should never happen */
if (!urb) { ASSERT(skb != NULL, return;);
WARNING("%s(), Bug : urb == NULL\n", __FUNCTION__); ASSERT(urb != NULL, return;);
return;
}
/* Allocate new skb if it has not been recycled */
if (!skb) {
skb = dev_alloc_skb(IRDA_USB_MAX_MTU + 1);
if (!skb) {
/* If this ever happen, we are in deep s***.
* Basically, the Rx path will stop... */
WARNING("%s(), Failed to allocate Rx skb\n", __FUNCTION__);
return;
}
} else {
/* Reset recycled skb */
skb->data = skb->tail = skb->head;
skb->len = 0;
}
/* Make sure IP header get aligned (IrDA header is 5 bytes ) */
skb_reserve(skb, 1);
/* Save ourselves */ /* Save ourselves in the skb */
cb = (struct irda_skb_cb *) skb->cb; cb = (struct irda_skb_cb *) skb->cb;
cb->context = self; cb->context = self;
...@@ -758,7 +742,9 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs) ...@@ -758,7 +742,9 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
struct sk_buff *skb = (struct sk_buff *) urb->context; struct sk_buff *skb = (struct sk_buff *) urb->context;
struct irda_usb_cb *self; struct irda_usb_cb *self;
struct irda_skb_cb *cb; struct irda_skb_cb *cb;
struct sk_buff *new; struct sk_buff *newskb;
struct sk_buff *dataskb;
int docopy;
IRDA_DEBUG(2, "%s(), len=%d\n", __FUNCTION__, urb->actual_length); IRDA_DEBUG(2, "%s(), len=%d\n", __FUNCTION__, urb->actual_length);
...@@ -808,38 +794,55 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs) ...@@ -808,38 +794,55 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
*/ */
do_gettimeofday(&self->stamp); do_gettimeofday(&self->stamp);
/* Fix skb, and remove USB-IrDA header */ /* Check if we need to copy the data to a new skb or not.
skb_put(skb, urb->actual_length); * For most frames, we use ZeroCopy and pass the already
skb_pull(skb, USB_IRDA_HEADER); * allocated skb up the stack.
* If the frame is small, it is more efficient to copy it
/* Don't waste a lot of memory on small IrDA frames */ * to save memory (copy will be fast anyway - that's
if (skb->len < RX_COPY_THRESHOLD) { * called Rx-copy-break). Jean II */
new = dev_alloc_skb(skb->len+1); docopy = (urb->actual_length < IRDA_RX_COPY_THRESHOLD);
if (!new) {
/* Allocate a new skb */
newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU);
if (!newskb) {
self->stats.rx_dropped++; self->stats.rx_dropped++;
/* We could deliver the current skb, but this would stall
* the Rx path. Better drop the packet... Jean II */
goto done; goto done;
} }
/* Make sure IP header get aligned (IrDA header is 5 bytes) */ /* Make sure IP header get aligned (IrDA header is 5 bytes) */
skb_reserve(new, 1); /* But IrDA-USB header is 1 byte. Jean II */
//skb_reserve(newskb, USB_IRDA_HEADER - 1);
if(docopy) {
/* Copy packet, so we can recycle the original */ /* Copy packet, so we can recycle the original */
memcpy(skb_put(new, skb->len), skb->data, skb->len); memcpy(newskb->data, skb->data, urb->actual_length);
/* We will cleanup the skb in irda_usb_submit() */ /* Deliver this new skb */
dataskb = newskb;
/* And hook the old skb to the URB
* Note : we don't need to "clean up" the old skb,
* as we never touched it. Jean II */
} else { } else {
/* Deliver the original skb */ /* We are using ZeroCopy. Deliver old skb */
new = skb; dataskb = skb;
skb = NULL; /* And hook the new skb to the URB */
skb = newskb;
} }
self->stats.rx_bytes += new->len; /* Set proper length on skb & remove USB-IrDA header */
self->stats.rx_packets++; skb_put(dataskb, urb->actual_length);
skb_pull(dataskb, USB_IRDA_HEADER);
/* Ask the networking layer to queue the packet for the IrDA stack */ /* Ask the networking layer to queue the packet for the IrDA stack */
new->dev = self->netdev; dataskb->dev = self->netdev;
new->mac.raw = new->data; dataskb->mac.raw = dataskb->data;
new->protocol = htons(ETH_P_IRDA); dataskb->protocol = htons(ETH_P_IRDA);
netif_rx(new); netif_rx(dataskb);
/* Keep stats up to date */
self->stats.rx_bytes += dataskb->len;
self->stats.rx_packets++;
self->netdev->last_rx = jiffies; self->netdev->last_rx = jiffies;
done: done:
...@@ -973,8 +976,17 @@ static int irda_usb_net_open(struct net_device *netdev) ...@@ -973,8 +976,17 @@ static int irda_usb_net_open(struct net_device *netdev)
/* Now that we can pass data to IrLAP, allow the USB layer /* Now that we can pass data to IrLAP, allow the USB layer
* to send us some data... */ * to send us some data... */
for (i = 0; i < IU_MAX_ACTIVE_RX_URBS; i++) for (i = 0; i < IU_MAX_ACTIVE_RX_URBS; i++) {
irda_usb_submit(self, NULL, self->rx_urb[i]); struct sk_buff *skb = dev_alloc_skb(IRDA_SKB_MAX_MTU);
if (!skb) {
/* If this ever happen, we are in deep s***.
* Basically, we can't start the Rx path... */
WARNING("%s(), Failed to allocate Rx skb\n", __FUNCTION__);
return -1;
}
//skb_reserve(newskb, USB_IRDA_HEADER - 1);
irda_usb_submit(self, skb, self->rx_urb[i]);
}
/* Ready to play !!! */ /* Ready to play !!! */
return 0; return 0;
...@@ -1168,9 +1180,6 @@ static inline int irda_usb_open(struct irda_usb_cb *self) ...@@ -1168,9 +1180,6 @@ static inline int irda_usb_open(struct irda_usb_cb *self)
irda_usb_init_qos(self); irda_usb_init_qos(self);
/* Initialise list of skb beeing curently transmitted */
self->tx_list = hashbin_new(HB_NOLOCK); /* unused */
/* Allocate the buffer for speed changes */ /* Allocate the buffer for speed changes */
/* Don't change this buffer size and allocation without doing /* Don't change this buffer size and allocation without doing
* some heavy and complete testing. Don't ask why :-( * some heavy and complete testing. Don't ask why :-(
...@@ -1228,8 +1237,6 @@ static inline int irda_usb_close(struct irda_usb_cb *self) ...@@ -1228,8 +1237,6 @@ static inline int irda_usb_close(struct irda_usb_cb *self)
self->netdev = NULL; self->netdev = NULL;
rtnl_unlock(); rtnl_unlock();
} }
/* Delete all pending skbs */
hashbin_delete(self->tx_list, (FREE_FUNC) &dev_kfree_skb_any);
/* Remove the speed buffer */ /* Remove the speed buffer */
if (self->speed_buff != NULL) { if (self->speed_buff != NULL) {
kfree(self->speed_buff); kfree(self->speed_buff);
...@@ -1492,8 +1499,10 @@ static int irda_usb_probe(struct usb_interface *intf, ...@@ -1492,8 +1499,10 @@ static int irda_usb_probe(struct usb_interface *intf,
case 0: case 0:
break; break;
case -EPIPE: /* -EPIPE = -32 */ case -EPIPE: /* -EPIPE = -32 */
usb_clear_halt(dev, usb_sndctrlpipe(dev, 0)); /* Martin Diehl says if we get a -EPIPE we should
IRDA_DEBUG(0, "%s(), Clearing stall on control interface\n", __FUNCTION__); * be fine and we don't need to do a usb_clear_halt().
* - Jean II */
IRDA_DEBUG(0, "%s(), Received -EPIPE, ignoring...\n", __FUNCTION__);
break; break;
default: default:
IRDA_DEBUG(0, "%s(), Unknown error %d\n", __FUNCTION__, ret); IRDA_DEBUG(0, "%s(), Unknown error %d\n", __FUNCTION__, ret);
......
...@@ -223,25 +223,24 @@ int sirdev_receive(struct sir_dev *dev, const unsigned char *cp, size_t count) ...@@ -223,25 +223,24 @@ int sirdev_receive(struct sir_dev *dev, const unsigned char *cp, size_t count)
} }
/* Read the characters into the buffer */ /* Read the characters into the buffer */
while (count--) {
if (likely(atomic_read(&dev->enable_rx))) { if (likely(atomic_read(&dev->enable_rx))) {
while (count--)
/* Unwrap and destuff one byte */ /* Unwrap and destuff one byte */
async_unwrap_char(dev->netdev, &dev->stats, async_unwrap_char(dev->netdev, &dev->stats,
&dev->rx_buff, *cp++); &dev->rx_buff, *cp++);
} } else {
else { while (count--) {
/* rx not enabled: save the raw bytes and never /* rx not enabled: save the raw bytes and never
* trigger any netif_rx. The received bytes are flushed * trigger any netif_rx. The received bytes are flushed
* later when we re-enable rx but might be read meanwhile * later when we re-enable rx but might be read meanwhile
* by the dongle driver. * by the dongle driver.
*/ */
dev->rx_buff.data[dev->rx_buff.len++] = *cp++; dev->rx_buff.data[dev->rx_buff.len++] = *cp++;
}
/* What should we do when the buffer is full? */ /* What should we do when the buffer is full? */
if (unlikely(dev->rx_buff.len == dev->rx_buff.truesize)) if (unlikely(dev->rx_buff.len == dev->rx_buff.truesize))
dev->rx_buff.len = 0; dev->rx_buff.len = 0;
}
} }
return 0; return 0;
...@@ -423,19 +422,24 @@ static int sirdev_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) ...@@ -423,19 +422,24 @@ static int sirdev_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
static int sirdev_alloc_buffers(struct sir_dev *dev) static int sirdev_alloc_buffers(struct sir_dev *dev)
{ {
dev->rx_buff.truesize = SIRBUF_ALLOCSIZE;
dev->tx_buff.truesize = SIRBUF_ALLOCSIZE; dev->tx_buff.truesize = SIRBUF_ALLOCSIZE;
dev->rx_buff.truesize = IRDA_SKB_MAX_MTU;
dev->rx_buff.head = kmalloc(dev->rx_buff.truesize, GFP_KERNEL); /* Bootstrap ZeroCopy Rx */
if (dev->rx_buff.head == NULL) dev->rx_buff.skb = __dev_alloc_skb(dev->rx_buff.truesize, GFP_KERNEL);
if (dev->rx_buff.skb == NULL)
return -ENOMEM; return -ENOMEM;
memset(dev->rx_buff.head, 0, dev->rx_buff.truesize); skb_reserve(dev->rx_buff.skb, 1);
dev->rx_buff.head = dev->rx_buff.skb->data;
/* No need to memset the buffer, unless you are really pedantic */
dev->tx_buff.head = kmalloc(dev->tx_buff.truesize, GFP_KERNEL); dev->tx_buff.head = kmalloc(dev->tx_buff.truesize, GFP_KERNEL);
if (dev->tx_buff.head == NULL) { if (dev->tx_buff.head == NULL) {
kfree(dev->rx_buff.head); kfree_skb(dev->rx_buff.skb);
dev->rx_buff.skb = NULL;
dev->rx_buff.head = NULL; dev->rx_buff.head = NULL;
return -ENOMEM; return -ENOMEM;
/* Hu ??? This should not be here, Martin ? */
memset(dev->tx_buff.head, 0, dev->tx_buff.truesize); memset(dev->tx_buff.head, 0, dev->tx_buff.truesize);
} }
...@@ -451,11 +455,12 @@ static int sirdev_alloc_buffers(struct sir_dev *dev) ...@@ -451,11 +455,12 @@ static int sirdev_alloc_buffers(struct sir_dev *dev)
static void sirdev_free_buffers(struct sir_dev *dev) static void sirdev_free_buffers(struct sir_dev *dev)
{ {
if (dev->rx_buff.head) if (dev->rx_buff.skb)
kfree(dev->rx_buff.head); kfree_skb(dev->rx_buff.skb);
if (dev->tx_buff.head) if (dev->tx_buff.head)
kfree(dev->tx_buff.head); kfree(dev->tx_buff.head);
dev->rx_buff.head = dev->tx_buff.head = NULL; dev->rx_buff.head = dev->tx_buff.head = NULL;
dev->rx_buff.skb = NULL;
} }
static int sirdev_open(struct net_device *ndev) static int sirdev_open(struct net_device *ndev)
......
...@@ -52,8 +52,8 @@ struct irda_sock { ...@@ -52,8 +52,8 @@ struct irda_sock {
__u8 max_header_size; __u8 max_header_size;
struct qos_info qos_tx; struct qos_info qos_tx;
__u16 mask; /* Hint bits mask */ __u16_host_order mask; /* Hint bits mask */
__u16 hints; /* Hint bits */ __u16_host_order hints; /* Hint bits */
void *ckey; /* IrLMP client handle */ void *ckey; /* IrLMP client handle */
void *skey; /* IrLMP service handle */ void *skey; /* IrLMP service handle */
...@@ -63,7 +63,7 @@ struct irda_sock { ...@@ -63,7 +63,7 @@ struct irda_sock {
struct ias_value *ias_result; /* Result of remote IAS query */ struct ias_value *ias_result; /* Result of remote IAS query */
hashbin_t *cachelog; /* Result of discovery query */ hashbin_t *cachelog; /* Result of discovery query */
struct discovery_t *cachediscovery; /* Result of selective discovery query */ __u32 cachedaddr; /* Result of selective discovery query */
int nslots; /* Number of slots to use for discovery */ int nslots; /* Number of slots to use for discovery */
......
...@@ -46,12 +46,20 @@ ...@@ -46,12 +46,20 @@
* little endian format. A little endian machine stores MSB of word in * little endian format. A little endian machine stores MSB of word in
* byte[1] and LSB in byte[0]. A big endian machine stores MSB in byte[0] * byte[1] and LSB in byte[0]. A big endian machine stores MSB in byte[0]
* and LSB in byte[1]. * and LSB in byte[1].
*
* This structure is used in the code for things that are endian neutral
* but that fit in a word so that we can manipulate them efficiently.
* By endian neutral, I mean things that are really an array of bytes,
* and always used as such, for example the hint bits. Jean II
*/ */
typedef union { typedef union {
__u16 word; __u16 word;
__u8 byte[2]; __u8 byte[2];
} __u16_host_order; } __u16_host_order;
/* Same purpose, different application */
#define u16ho(array) (* ((__u16 *) array))
/* Types of discovery */ /* Types of discovery */
typedef enum { typedef enum {
DISCOVERY_LOG, /* What's in our discovery log */ DISCOVERY_LOG, /* What's in our discovery log */
...@@ -62,30 +70,31 @@ typedef enum { ...@@ -62,30 +70,31 @@ typedef enum {
#define NICKNAME_MAX_LEN 21 #define NICKNAME_MAX_LEN 21
/* Basic discovery information about a peer */
typedef struct irda_device_info discinfo_t; /* linux/irda.h */
/* /*
* The DISCOVERY structure is used for both discovery requests and responses * The DISCOVERY structure is used for both discovery requests and responses
*/ */
typedef struct discovery_t { typedef struct discovery_t {
irda_queue_t q; /* Must be first! */ irda_queue_t q; /* Must be first! */
__u32 saddr; /* Which link the device was discovered */ discinfo_t data; /* Basic discovery information */
__u32 daddr; /* Remote device address */
LAP_REASON condition; /* More info about the discovery */
__u16_host_order hints; /* Discovery hint bits */
__u8 charset; /* Encoding of nickname */
char nickname[22]; /* The name of the device (21 bytes + \0) */
int name_len; /* Lenght of nickname */ int name_len; /* Lenght of nickname */
int gen_addr_bit; /* Need to generate a new device address? */ LAP_REASON condition; /* More info about the discovery */
int nslots; /* Number of slots to use when discovering */ int gen_addr_bit; /* Need to generate a new device
unsigned long timestamp; /* Time discovered */ * address? */
unsigned long first_timestamp; /* First time discovered */ int nslots; /* Number of slots to use when
* discovering */
unsigned long timestamp; /* Last time discovered */
unsigned long firststamp; /* First time discovered */
} discovery_t; } discovery_t;
void irlmp_add_discovery(hashbin_t *cachelog, discovery_t *discovery); void irlmp_add_discovery(hashbin_t *cachelog, discovery_t *discovery);
void irlmp_add_discovery_log(hashbin_t *cachelog, hashbin_t *log); void irlmp_add_discovery_log(hashbin_t *cachelog, hashbin_t *log);
void irlmp_expire_discoveries(hashbin_t *log, __u32 saddr, int force); void irlmp_expire_discoveries(hashbin_t *log, __u32 saddr, int force);
struct irda_device_info *irlmp_copy_discoveries(hashbin_t *log, int *pn, __u16 mask); struct irda_device_info *irlmp_copy_discoveries(hashbin_t *log, int *pn,
__u16 mask, int old_entries);
#endif #endif
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
#include <net/irda/irlan_event.h> #include <net/irda/irlan_event.h>
void irlan_client_start_kick_timer(struct irlan_cb *self, int timeout); void irlan_client_start_kick_timer(struct irlan_cb *self, int timeout);
void irlan_client_discovery_indication(discovery_t *, DISCOVERY_MODE, void *); void irlan_client_discovery_indication(discinfo_t *, DISCOVERY_MODE, void *);
void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr); void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr);
void irlan_client_open_ctrl_tsap( struct irlan_cb *self); void irlan_client_open_ctrl_tsap( struct irlan_cb *self);
......
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
#define LM_IDLE_TIMEOUT 2*HZ /* 2 seconds for now */ #define LM_IDLE_TIMEOUT 2*HZ /* 2 seconds for now */
typedef enum { typedef enum {
S_PNP, S_PNP = 0,
S_PDA, S_PDA,
S_COMPUTER, S_COMPUTER,
S_PRINTER, S_PRINTER,
...@@ -72,22 +72,24 @@ typedef enum { ...@@ -72,22 +72,24 @@ typedef enum {
S_END, S_END,
} SERVICE; } SERVICE;
typedef void (*DISCOVERY_CALLBACK1) (discovery_t *, DISCOVERY_MODE, void *); /* For selective discovery */
typedef void (*DISCOVERY_CALLBACK2) (hashbin_t *, void *); typedef void (*DISCOVERY_CALLBACK1) (discinfo_t *, DISCOVERY_MODE, void *);
/* For expiry (the same) */
typedef void (*DISCOVERY_CALLBACK2) (discinfo_t *, DISCOVERY_MODE, void *);
typedef struct { typedef struct {
irda_queue_t queue; /* Must be first */ irda_queue_t queue; /* Must be first */
__u16 hints; /* Hint bits */ __u16_host_order hints; /* Hint bits */
} irlmp_service_t; } irlmp_service_t;
typedef struct { typedef struct {
irda_queue_t queue; /* Must be first */ irda_queue_t queue; /* Must be first */
__u16 hint_mask; __u16_host_order hint_mask;
DISCOVERY_CALLBACK1 disco_callback; /* Selective discovery */ DISCOVERY_CALLBACK1 disco_callback; /* Selective discovery */
DISCOVERY_CALLBACK1 expir_callback; /* Selective expiration */ DISCOVERY_CALLBACK2 expir_callback; /* Selective expiration */
void *priv; /* Used to identify client */ void *priv; /* Used to identify client */
} irlmp_client_t; } irlmp_client_t;
...@@ -199,11 +201,11 @@ __u16 irlmp_service_to_hint(int service); ...@@ -199,11 +201,11 @@ __u16 irlmp_service_to_hint(int service);
void *irlmp_register_service(__u16 hints); void *irlmp_register_service(__u16 hints);
int irlmp_unregister_service(void *handle); int irlmp_unregister_service(void *handle);
void *irlmp_register_client(__u16 hint_mask, DISCOVERY_CALLBACK1 disco_clb, void *irlmp_register_client(__u16 hint_mask, DISCOVERY_CALLBACK1 disco_clb,
DISCOVERY_CALLBACK1 expir_clb, void *priv); DISCOVERY_CALLBACK2 expir_clb, void *priv);
int irlmp_unregister_client(void *handle); int irlmp_unregister_client(void *handle);
int irlmp_update_client(void *handle, __u16 hint_mask, int irlmp_update_client(void *handle, __u16 hint_mask,
DISCOVERY_CALLBACK1 disco_clb, DISCOVERY_CALLBACK1 disco_clb,
DISCOVERY_CALLBACK1 expir_clb, void *priv); DISCOVERY_CALLBACK2 expir_clb, void *priv);
void irlmp_register_link(struct irlap_cb *, __u32 saddr, notify_t *); void irlmp_register_link(struct irlap_cb *, __u32 saddr, notify_t *);
void irlmp_unregister_link(__u32 saddr); void irlmp_unregister_link(__u32 saddr);
...@@ -222,11 +224,11 @@ int irlmp_disconnect_request(struct lsap_cb *, struct sk_buff *userdata); ...@@ -222,11 +224,11 @@ int irlmp_disconnect_request(struct lsap_cb *, struct sk_buff *userdata);
void irlmp_discovery_confirm(hashbin_t *discovery_log, DISCOVERY_MODE mode); void irlmp_discovery_confirm(hashbin_t *discovery_log, DISCOVERY_MODE mode);
void irlmp_discovery_request(int nslots); void irlmp_discovery_request(int nslots);
struct irda_device_info *irlmp_get_discoveries(int *pn, __u16 mask, int nslots); discinfo_t *irlmp_get_discoveries(int *pn, __u16 mask, int nslots);
void irlmp_do_expiry(void); void irlmp_do_expiry(void);
void irlmp_do_discovery(int nslots); void irlmp_do_discovery(int nslots);
discovery_t *irlmp_get_discovery_response(void); discovery_t *irlmp_get_discovery_response(void);
void irlmp_discovery_expiry(discovery_t *expiry); void irlmp_discovery_expiry(discinfo_t *expiry, int number);
int irlmp_data_request(struct lsap_cb *, struct sk_buff *); int irlmp_data_request(struct lsap_cb *, struct sk_buff *);
void irlmp_data_indication(struct lsap_cb *, struct sk_buff *); void irlmp_data_indication(struct lsap_cb *, struct sk_buff *);
......
...@@ -401,11 +401,10 @@ static void irda_getvalue_confirm(int result, __u16 obj_id, ...@@ -401,11 +401,10 @@ static void irda_getvalue_confirm(int result, __u16 obj_id,
* *
* Got a selective discovery indication from IrLMP. * Got a selective discovery indication from IrLMP.
* *
* IrLMP is telling us that this node is matching our hint bit * IrLMP is telling us that this node is new and matching our hint bit
* filter. Check if it's a newly discovered node (or if node changed its * filter. Wake up any process waiting for answer...
* hint bits), and then wake up any process waiting for answer...
*/ */
static void irda_selective_discovery_indication(discovery_t *discovery, static void irda_selective_discovery_indication(discinfo_t *discovery,
DISCOVERY_MODE mode, DISCOVERY_MODE mode,
void *priv) void *priv)
{ {
...@@ -419,18 +418,8 @@ static void irda_selective_discovery_indication(discovery_t *discovery, ...@@ -419,18 +418,8 @@ static void irda_selective_discovery_indication(discovery_t *discovery,
return; return;
} }
/* Check if node is discovered is a new one or an old one.
* We check when how long ago this node was discovered, with a
* coarse timeout (we may miss some discovery events or be delayed).
* Note : by doing this test here, we avoid waking up a process ;-)
*/
if((jiffies - discovery->first_timestamp) >
(sysctl_discovery_timeout * HZ)) {
return; /* Too old, not interesting -> goodbye */
}
/* Pass parameter to the caller */ /* Pass parameter to the caller */
self->cachediscovery = discovery; self->cachedaddr = discovery->daddr;
/* Wake up process if its waiting for device to be discovered */ /* Wake up process if its waiting for device to be discovered */
wake_up_interruptible(&self->query_wait); wake_up_interruptible(&self->query_wait);
...@@ -455,7 +444,7 @@ static void irda_discovery_timeout(u_long priv) ...@@ -455,7 +444,7 @@ static void irda_discovery_timeout(u_long priv)
/* Nothing for the caller */ /* Nothing for the caller */
self->cachelog = NULL; self->cachelog = NULL;
self->cachediscovery = NULL; self->cachedaddr = 0;
self->errno = -ETIME; self->errno = -ETIME;
/* Wake up process if its still waiting... */ /* Wake up process if its still waiting... */
...@@ -627,7 +616,7 @@ static int irda_find_lsap_sel(struct irda_sock *self, char *name) ...@@ -627,7 +616,7 @@ static int irda_find_lsap_sel(struct irda_sock *self, char *name)
*/ */
static int irda_discover_daddr_and_lsap_sel(struct irda_sock *self, char *name) static int irda_discover_daddr_and_lsap_sel(struct irda_sock *self, char *name)
{ {
struct irda_device_info *discoveries; /* Copy of the discovery log */ discinfo_t *discoveries; /* Copy of the discovery log */
int number; /* Number of nodes in the log */ int number; /* Number of nodes in the log */
int i; int i;
int err = -ENETUNREACH; int err = -ENETUNREACH;
...@@ -642,7 +631,8 @@ static int irda_discover_daddr_and_lsap_sel(struct irda_sock *self, char *name) ...@@ -642,7 +631,8 @@ static int irda_discover_daddr_and_lsap_sel(struct irda_sock *self, char *name)
* Note : we have to use irlmp_get_discoveries(), as opposed * Note : we have to use irlmp_get_discoveries(), as opposed
* to play with the cachelog directly, because while we are * to play with the cachelog directly, because while we are
* making our ias query, le log might change... */ * making our ias query, le log might change... */
discoveries = irlmp_get_discoveries(&number, self->mask, self->nslots); discoveries = irlmp_get_discoveries(&number, self->mask.word,
self->nslots);
/* Check if the we got some results */ /* Check if the we got some results */
if (discoveries == NULL) if (discoveries == NULL)
return -ENETUNREACH; /* No nodes discovered */ return -ENETUNREACH; /* No nodes discovered */
...@@ -1137,7 +1127,7 @@ static int irda_create(struct socket *sock, int protocol) ...@@ -1137,7 +1127,7 @@ static int irda_create(struct socket *sock, int protocol)
/* Register as a client with IrLMP */ /* Register as a client with IrLMP */
self->ckey = irlmp_register_client(0, NULL, NULL, NULL); self->ckey = irlmp_register_client(0, NULL, NULL, NULL);
self->mask = 0xffff; self->mask.word = 0xffff;
self->rx_flow = self->tx_flow = FLOW_START; self->rx_flow = self->tx_flow = FLOW_START;
self->nslots = DISCOVERY_DEFAULT_SLOTS; self->nslots = DISCOVERY_DEFAULT_SLOTS;
self->daddr = DEV_ADDR_ANY; /* Until we get connected */ self->daddr = DEV_ADDR_ANY; /* Until we get connected */
...@@ -1997,6 +1987,7 @@ static int irda_setsockopt(struct socket *sock, int level, int optname, ...@@ -1997,6 +1987,7 @@ static int irda_setsockopt(struct socket *sock, int level, int optname,
if (optlen < sizeof(int)) if (optlen < sizeof(int))
return -EINVAL; return -EINVAL;
/* The input is really a (__u8 hints[2]), easier as an int */
if (get_user(opt, (int *)optval)) if (get_user(opt, (int *)optval))
return -EFAULT; return -EFAULT;
...@@ -2015,16 +2006,17 @@ static int irda_setsockopt(struct socket *sock, int level, int optname, ...@@ -2015,16 +2006,17 @@ static int irda_setsockopt(struct socket *sock, int level, int optname,
if (optlen < sizeof(int)) if (optlen < sizeof(int))
return -EINVAL; return -EINVAL;
/* The input is really a (__u8 hints[2]), easier as an int */
if (get_user(opt, (int *)optval)) if (get_user(opt, (int *)optval))
return -EFAULT; return -EFAULT;
/* Set the new hint mask */ /* Set the new hint mask */
self->mask = (__u16) opt; self->mask.word = (__u16) opt;
/* Mask out extension bits */ /* Mask out extension bits */
self->mask &= 0x7f7f; self->mask.word &= 0x7f7f;
/* Check if no bits */ /* Check if no bits */
if(!self->mask) if(!self->mask.word)
self->mask = 0xFFFF; self->mask.word = 0xFFFF;
break; break;
default: default:
...@@ -2115,7 +2107,7 @@ static int irda_getsockopt(struct socket *sock, int level, int optname, ...@@ -2115,7 +2107,7 @@ static int irda_getsockopt(struct socket *sock, int level, int optname,
switch (optname) { switch (optname) {
case IRLMP_ENUMDEVICES: case IRLMP_ENUMDEVICES:
/* Ask lmp for the current discovery log */ /* Ask lmp for the current discovery log */
discoveries = irlmp_get_discoveries(&list.len, self->mask, discoveries = irlmp_get_discoveries(&list.len, self->mask.word,
self->nslots); self->nslots);
/* Check if the we got some results */ /* Check if the we got some results */
if (discoveries == NULL) if (discoveries == NULL)
...@@ -2347,7 +2339,7 @@ static int irda_getsockopt(struct socket *sock, int level, int optname, ...@@ -2347,7 +2339,7 @@ static int irda_getsockopt(struct socket *sock, int level, int optname,
return -EFAULT; return -EFAULT;
/* Tell IrLMP we want to be notified */ /* Tell IrLMP we want to be notified */
irlmp_update_client(self->ckey, self->mask, irlmp_update_client(self->ckey, self->mask.word,
irda_selective_discovery_indication, irda_selective_discovery_indication,
NULL, (void *) self); NULL, (void *) self);
...@@ -2355,7 +2347,7 @@ static int irda_getsockopt(struct socket *sock, int level, int optname, ...@@ -2355,7 +2347,7 @@ static int irda_getsockopt(struct socket *sock, int level, int optname,
irlmp_discovery_request(self->nslots); irlmp_discovery_request(self->nslots);
/* Wait until a node is discovered */ /* Wait until a node is discovered */
if (!self->cachediscovery) { if (!self->cachedaddr) {
int ret = 0; int ret = 0;
IRDA_DEBUG(1, "%s(), nothing discovered yet, going to sleep...\n", __FUNCTION__); IRDA_DEBUG(1, "%s(), nothing discovered yet, going to sleep...\n", __FUNCTION__);
...@@ -2370,7 +2362,7 @@ static int irda_getsockopt(struct socket *sock, int level, int optname, ...@@ -2370,7 +2362,7 @@ static int irda_getsockopt(struct socket *sock, int level, int optname,
/* Wait for IR-LMP to call us back */ /* Wait for IR-LMP to call us back */
__wait_event_interruptible(self->query_wait, __wait_event_interruptible(self->query_wait,
(self->cachediscovery!=NULL || self->errno==-ETIME), (self->cachedaddr != 0 || self->errno == -ETIME),
ret); ret);
/* If watchdog is still activated, kill it! */ /* If watchdog is still activated, kill it! */
...@@ -2387,19 +2379,25 @@ static int irda_getsockopt(struct socket *sock, int level, int optname, ...@@ -2387,19 +2379,25 @@ static int irda_getsockopt(struct socket *sock, int level, int optname,
__FUNCTION__); __FUNCTION__);
/* Tell IrLMP that we have been notified */ /* Tell IrLMP that we have been notified */
irlmp_update_client(self->ckey, self->mask, NULL, NULL, NULL); irlmp_update_client(self->ckey, self->mask.word,
NULL, NULL, NULL);
/* Check if the we got some results */ /* Check if the we got some results */
if (!self->cachediscovery) if (!self->cachedaddr)
return -EAGAIN; /* Didn't find any devices */ return -EAGAIN; /* Didn't find any devices */
daddr = self->cachedaddr;
/* Cleanup */ /* Cleanup */
self->cachediscovery = NULL; self->cachedaddr = 0;
/* Note : We don't return anything to the user. /* We return the daddr of the device that trigger the
* We could return the device that triggered the wake up, * wakeup. As irlmp pass us only the new devices, we
* but it's probably better to force the user to query * are sure that it's not an old device.
* the whole discovery log and let him pick one device... * If the user want more details, he should query
* the whole discovery log and pick one device...
*/ */
if (put_user(daddr, (int *)optval))
return -EFAULT;
break; break;
default: default:
return -ENOPROTOOPT; return -ENOPROTOOPT;
......
...@@ -59,7 +59,7 @@ void irlmp_add_discovery(hashbin_t *cachelog, discovery_t *new) ...@@ -59,7 +59,7 @@ void irlmp_add_discovery(hashbin_t *cachelog, discovery_t *new)
unsigned long flags; unsigned long flags;
/* Set time of first discovery if node is new (see below) */ /* Set time of first discovery if node is new (see below) */
new->first_timestamp = new->timestamp; new->firststamp = new->timestamp;
spin_lock_irqsave(&cachelog->hb_spinlock, flags); spin_lock_irqsave(&cachelog->hb_spinlock, flags);
...@@ -76,24 +76,24 @@ void irlmp_add_discovery(hashbin_t *cachelog, discovery_t *new) ...@@ -76,24 +76,24 @@ void irlmp_add_discovery(hashbin_t *cachelog, discovery_t *new)
/* Be sure to stay one item ahead */ /* Be sure to stay one item ahead */
discovery = (discovery_t *) hashbin_get_next(cachelog); discovery = (discovery_t *) hashbin_get_next(cachelog);
if ((node->saddr == new->saddr) && if ((node->data.saddr == new->data.saddr) &&
((node->daddr == new->daddr) || ((node->data.daddr == new->data.daddr) ||
(strcmp(node->nickname, new->nickname) == 0))) (strcmp(node->data.info, new->data.info) == 0)))
{ {
/* This discovery is a previous discovery /* This discovery is a previous discovery
* from the same device, so just remove it * from the same device, so just remove it
*/ */
hashbin_remove_this(cachelog, (irda_queue_t *) node); hashbin_remove_this(cachelog, (irda_queue_t *) node);
/* Check if hints bits have changed */ /* Check if hints bits are unchanged */
if(node->hints.word == new->hints.word) if(u16ho(node->data.hints) == u16ho(new->data.hints))
/* Set time of first discovery for this node */ /* Set time of first discovery for this node */
new->first_timestamp = node->first_timestamp; new->firststamp = node->firststamp;
kfree(node); kfree(node);
} }
} }
/* Insert the new and updated version */ /* Insert the new and updated version */
hashbin_insert(cachelog, (irda_queue_t *) new, new->daddr, NULL); hashbin_insert(cachelog, (irda_queue_t *) new, new->data.daddr, NULL);
spin_unlock_irqrestore(&cachelog->hb_spinlock, flags); spin_unlock_irqrestore(&cachelog->hb_spinlock, flags);
} }
...@@ -147,27 +147,50 @@ void irlmp_add_discovery_log(hashbin_t *cachelog, hashbin_t *log) ...@@ -147,27 +147,50 @@ void irlmp_add_discovery_log(hashbin_t *cachelog, hashbin_t *log)
*/ */
void irlmp_expire_discoveries(hashbin_t *log, __u32 saddr, int force) void irlmp_expire_discoveries(hashbin_t *log, __u32 saddr, int force)
{ {
discovery_t *discovery, *curr; discovery_t * discovery;
discovery_t * curr;
unsigned long flags; unsigned long flags;
discinfo_t * buffer = NULL;
int n; /* Size of the full log */
int i = 0; /* How many we expired */
ASSERT(log != NULL, return;);
IRDA_DEBUG(4, "%s()\n", __FUNCTION__); IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
spin_lock_irqsave(&log->hb_spinlock, flags); spin_lock_irqsave(&log->hb_spinlock, flags);
discovery = (discovery_t *) hashbin_get_first(log); discovery = (discovery_t *) hashbin_get_first(log);
while (discovery != NULL) { while (discovery != NULL) {
curr = discovery;
/* Be sure to be one item ahead */ /* Be sure to be one item ahead */
curr = discovery;
discovery = (discovery_t *) hashbin_get_next(log); discovery = (discovery_t *) hashbin_get_next(log);
/* Test if it's time to expire this discovery */ /* Test if it's time to expire this discovery */
if ((curr->saddr == saddr) && if ((curr->data.saddr == saddr) &&
(force || (force ||
((jiffies - curr->timestamp) > DISCOVERY_EXPIRE_TIMEOUT))) ((jiffies - curr->timestamp) > DISCOVERY_EXPIRE_TIMEOUT)))
{ {
/* Tell IrLMP and registered clients about it */ /* Create buffer as needed.
irlmp_discovery_expiry(curr); * As this function get called a lot and most time
* we don't have anything to put in the log (we are
* quite picky), we can save a lot of overhead
* by not calling kmalloc. Jean II */
if(buffer == NULL) {
/* Create the client specific buffer */
n = HASHBIN_GET_SIZE(log);
buffer = kmalloc(n * sizeof(struct irda_device_info), GFP_ATOMIC);
if (buffer == NULL) {
spin_unlock_irqrestore(&log->hb_spinlock, flags);
return;
}
}
/* Copy discovery information */
memcpy(&(buffer[i]), &(curr->data),
sizeof(discinfo_t));
i++;
/* Remove it from the log */ /* Remove it from the log */
curr = hashbin_remove_this(log, (irda_queue_t *) curr); curr = hashbin_remove_this(log, (irda_queue_t *) curr);
if (curr) if (curr)
...@@ -175,9 +198,23 @@ void irlmp_expire_discoveries(hashbin_t *log, __u32 saddr, int force) ...@@ -175,9 +198,23 @@ void irlmp_expire_discoveries(hashbin_t *log, __u32 saddr, int force)
} }
} }
/* Drop the spinlock before calling the higher layers, as
* we can't guarantee they won't call us back and create a
* deadlock. We will work on our own private data, so we
* don't care to be interupted. - Jean II */
spin_unlock_irqrestore(&log->hb_spinlock, flags); spin_unlock_irqrestore(&log->hb_spinlock, flags);
if(buffer == NULL)
return;
/* Tell IrLMP and registered clients about it */
irlmp_discovery_expiry(buffer, i);
/* Free up our buffer */
kfree(buffer);
} }
#if 0
/* /*
* Function irlmp_dump_discoveries (log) * Function irlmp_dump_discoveries (log)
* *
...@@ -193,13 +230,14 @@ void irlmp_dump_discoveries(hashbin_t *log) ...@@ -193,13 +230,14 @@ void irlmp_dump_discoveries(hashbin_t *log)
discovery = (discovery_t *) hashbin_get_first(log); discovery = (discovery_t *) hashbin_get_first(log);
while (discovery != NULL) { while (discovery != NULL) {
IRDA_DEBUG(0, "Discovery:\n"); IRDA_DEBUG(0, "Discovery:\n");
IRDA_DEBUG(0, " daddr=%08x\n", discovery->daddr); IRDA_DEBUG(0, " daddr=%08x\n", discovery->data.daddr);
IRDA_DEBUG(0, " saddr=%08x\n", discovery->saddr); IRDA_DEBUG(0, " saddr=%08x\n", discovery->data.saddr);
IRDA_DEBUG(0, " nickname=%s\n", discovery->nickname); IRDA_DEBUG(0, " nickname=%s\n", discovery->data.info);
discovery = (discovery_t *) hashbin_get_next(log); discovery = (discovery_t *) hashbin_get_next(log);
} }
} }
#endif
/* /*
* Function irlmp_copy_discoveries (log, pn, mask) * Function irlmp_copy_discoveries (log, pn, mask)
...@@ -221,23 +259,36 @@ void irlmp_dump_discoveries(hashbin_t *log) ...@@ -221,23 +259,36 @@ void irlmp_dump_discoveries(hashbin_t *log)
* Note : the client must kfree himself() the log... * Note : the client must kfree himself() the log...
* Jean II * Jean II
*/ */
struct irda_device_info *irlmp_copy_discoveries(hashbin_t *log, int *pn, __u16 mask) struct irda_device_info *irlmp_copy_discoveries(hashbin_t *log, int *pn,
__u16 mask, int old_entries)
{ {
discovery_t * discovery; discovery_t * discovery;
unsigned long flags; unsigned long flags;
struct irda_device_info * buffer; discinfo_t * buffer = NULL;
int i = 0; int j_timeout = (sysctl_discovery_timeout * HZ);
int n; int n; /* Size of the full log */
int i = 0; /* How many we picked */
ASSERT(pn != NULL, return NULL;); ASSERT(pn != NULL, return NULL;);
ASSERT(log != NULL, return NULL;);
/* Check if log is empty */ /* Save spin lock */
if(log == NULL)
return NULL;
/* Save spin lock - spinlock should be discovery specific */
spin_lock_irqsave(&log->hb_spinlock, flags); spin_lock_irqsave(&log->hb_spinlock, flags);
discovery = (discovery_t *) hashbin_get_first(log);
while (discovery != NULL) {
/* Mask out the ones we don't want :
* We want to match the discovery mask, and to get only
* the most recent one (unless we want old ones) */
if ((u16ho(discovery->data.hints) & mask) &&
((old_entries) ||
((jiffies - discovery->firststamp) < j_timeout)) ) {
/* Create buffer as needed.
* As this function get called a lot and most time
* we don't have anything to put in the log (we are
* quite picky), we can save a lot of overhead
* by not calling kmalloc. Jean II */
if(buffer == NULL) {
/* Create the client specific buffer */ /* Create the client specific buffer */
n = HASHBIN_GET_SIZE(log); n = HASHBIN_GET_SIZE(log);
buffer = kmalloc(n * sizeof(struct irda_device_info), GFP_ATOMIC); buffer = kmalloc(n * sizeof(struct irda_device_info), GFP_ATOMIC);
...@@ -246,18 +297,11 @@ struct irda_device_info *irlmp_copy_discoveries(hashbin_t *log, int *pn, __u16 m ...@@ -246,18 +297,11 @@ struct irda_device_info *irlmp_copy_discoveries(hashbin_t *log, int *pn, __u16 m
return NULL; return NULL;
} }
discovery = (discovery_t *) hashbin_get_first(log); }
while ((discovery != NULL) && (i < n)) {
/* Mask out the ones we don't want */
if (discovery->hints.word & mask) {
/* Copy discovery information */ /* Copy discovery information */
buffer[i].saddr = discovery->saddr; memcpy(&(buffer[i]), &(discovery->data),
buffer[i].daddr = discovery->daddr; sizeof(discinfo_t));
buffer[i].charset = discovery->charset;
buffer[i].hints[0] = discovery->hints.byte[0];
buffer[i].hints[1] = discovery->hints.byte[1];
strncpy(buffer[i].info, discovery->nickname,
NICKNAME_MAX_LEN);
i++; i++;
} }
discovery = (discovery_t *) hashbin_get_next(log); discovery = (discovery_t *) hashbin_get_next(log);
...@@ -288,14 +332,14 @@ __u32 irlmp_find_device(hashbin_t *cachelog, char *name, __u32 *saddr) ...@@ -288,14 +332,14 @@ __u32 irlmp_find_device(hashbin_t *cachelog, char *name, __u32 *saddr)
d = (discovery_t *) hashbin_get_first(cachelog); d = (discovery_t *) hashbin_get_first(cachelog);
while (d != NULL) { while (d != NULL) {
IRDA_DEBUG(1, "Discovery:\n"); IRDA_DEBUG(1, "Discovery:\n");
IRDA_DEBUG(1, " daddr=%08x\n", d->daddr); IRDA_DEBUG(1, " daddr=%08x\n", d->data.daddr);
IRDA_DEBUG(1, " nickname=%s\n", d->nickname); IRDA_DEBUG(1, " nickname=%s\n", d->data.info);
if (strcmp(name, d->nickname) == 0) { if (strcmp(name, d->data.info) == 0) {
*saddr = d->saddr; *saddr = d->data.saddr;
spin_unlock_irqrestore(&cachelog->hb_spinlock, flags); spin_unlock_irqrestore(&cachelog->hb_spinlock, flags);
return d->daddr; return d->data.daddr;
} }
d = (discovery_t *) hashbin_get_next(cachelog); d = (discovery_t *) hashbin_get_next(cachelog);
} }
...@@ -328,41 +372,41 @@ int discovery_proc_read(char *buf, char **start, off_t offset, int length, ...@@ -328,41 +372,41 @@ int discovery_proc_read(char *buf, char **start, off_t offset, int length,
discovery = (discovery_t *) hashbin_get_first(cachelog); discovery = (discovery_t *) hashbin_get_first(cachelog);
while (( discovery != NULL) && (len < length)) { while (( discovery != NULL) && (len < length)) {
len += sprintf(buf+len, "nickname: %s,", discovery->nickname); len += sprintf(buf+len, "nickname: %s,", discovery->data.info);
len += sprintf(buf+len, " hint: 0x%02x%02x", len += sprintf(buf+len, " hint: 0x%02x%02x",
discovery->hints.byte[0], discovery->data.hints[0],
discovery->hints.byte[1]); discovery->data.hints[1]);
#if 0 #if 0
if ( discovery->hints.byte[0] & HINT_PNP) if ( discovery->data.hints[0] & HINT_PNP)
len += sprintf( buf+len, "PnP Compatible "); len += sprintf( buf+len, "PnP Compatible ");
if ( discovery->hints.byte[0] & HINT_PDA) if ( discovery->data.hints[0] & HINT_PDA)
len += sprintf( buf+len, "PDA/Palmtop "); len += sprintf( buf+len, "PDA/Palmtop ");
if ( discovery->hints.byte[0] & HINT_COMPUTER) if ( discovery->data.hints[0] & HINT_COMPUTER)
len += sprintf( buf+len, "Computer "); len += sprintf( buf+len, "Computer ");
if ( discovery->hints.byte[0] & HINT_PRINTER) if ( discovery->data.hints[0] & HINT_PRINTER)
len += sprintf( buf+len, "Printer "); len += sprintf( buf+len, "Printer ");
if ( discovery->hints.byte[0] & HINT_MODEM) if ( discovery->data.hints[0] & HINT_MODEM)
len += sprintf( buf+len, "Modem "); len += sprintf( buf+len, "Modem ");
if ( discovery->hints.byte[0] & HINT_FAX) if ( discovery->data.hints[0] & HINT_FAX)
len += sprintf( buf+len, "Fax "); len += sprintf( buf+len, "Fax ");
if ( discovery->hints.byte[0] & HINT_LAN) if ( discovery->data.hints[0] & HINT_LAN)
len += sprintf( buf+len, "LAN Access "); len += sprintf( buf+len, "LAN Access ");
if ( discovery->hints.byte[1] & HINT_TELEPHONY) if ( discovery->data.hints[1] & HINT_TELEPHONY)
len += sprintf( buf+len, "Telephony "); len += sprintf( buf+len, "Telephony ");
if ( discovery->hints.byte[1] & HINT_FILE_SERVER) if ( discovery->data.hints[1] & HINT_FILE_SERVER)
len += sprintf( buf+len, "File Server "); len += sprintf( buf+len, "File Server ");
if ( discovery->hints.byte[1] & HINT_COMM) if ( discovery->data.hints[1] & HINT_COMM)
len += sprintf( buf+len, "IrCOMM "); len += sprintf( buf+len, "IrCOMM ");
if ( discovery->hints.byte[1] & HINT_OBEX) if ( discovery->data.hints[1] & HINT_OBEX)
len += sprintf( buf+len, "IrOBEX "); len += sprintf( buf+len, "IrOBEX ");
#endif #endif
len += sprintf(buf+len, ", saddr: 0x%08x", len += sprintf(buf+len, ", saddr: 0x%08x",
discovery->saddr); discovery->data.saddr);
len += sprintf(buf+len, ", daddr: 0x%08x\n", len += sprintf(buf+len, ", daddr: 0x%08x\n",
discovery->daddr); discovery->data.daddr);
len += sprintf(buf+len, "\n"); len += sprintf(buf+len, "\n");
......
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
#include <net/irda/ircomm_tty_attach.h> #include <net/irda/ircomm_tty_attach.h>
static void ircomm_tty_ias_register(struct ircomm_tty_cb *self); static void ircomm_tty_ias_register(struct ircomm_tty_cb *self);
static void ircomm_tty_discovery_indication(discovery_t *discovery, static void ircomm_tty_discovery_indication(discinfo_t *discovery,
DISCOVERY_MODE mode, DISCOVERY_MODE mode,
void *priv); void *priv);
static void ircomm_tty_getvalue_confirm(int result, __u16 obj_id, static void ircomm_tty_getvalue_confirm(int result, __u16 obj_id,
...@@ -305,7 +305,7 @@ int ircomm_tty_send_initial_parameters(struct ircomm_tty_cb *self) ...@@ -305,7 +305,7 @@ int ircomm_tty_send_initial_parameters(struct ircomm_tty_cb *self)
* device it is, and which services it has. * device it is, and which services it has.
* *
*/ */
static void ircomm_tty_discovery_indication(discovery_t *discovery, static void ircomm_tty_discovery_indication(discinfo_t *discovery,
DISCOVERY_MODE mode, DISCOVERY_MODE mode,
void *priv) void *priv)
{ {
......
...@@ -145,7 +145,7 @@ void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr) ...@@ -145,7 +145,7 @@ void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr)
* Remote device with IrLAN server support discovered * Remote device with IrLAN server support discovered
* *
*/ */
void irlan_client_discovery_indication(discovery_t *discovery, void irlan_client_discovery_indication(discinfo_t *discovery,
DISCOVERY_MODE mode, DISCOVERY_MODE mode,
void *priv) void *priv)
{ {
......
...@@ -419,7 +419,7 @@ static int irlap_state_ndm(struct irlap_cb *self, IRLAP_EVENT event, ...@@ -419,7 +419,7 @@ static int irlap_state_ndm(struct irlap_cb *self, IRLAP_EVENT event,
info->s); info->s);
if (self->slot == info->s) { if (self->slot == info->s) {
discovery_rsp = irlmp_get_discovery_response(); discovery_rsp = irlmp_get_discovery_response();
discovery_rsp->daddr = info->daddr; discovery_rsp->data.daddr = info->daddr;
irlap_send_discovery_xid_frame(self, info->S, irlap_send_discovery_xid_frame(self, info->S,
self->slot, self->slot,
...@@ -576,7 +576,7 @@ static int irlap_state_query(struct irlap_cb *self, IRLAP_EVENT event, ...@@ -576,7 +576,7 @@ static int irlap_state_query(struct irlap_cb *self, IRLAP_EVENT event,
ASSERT(info->discovery != NULL, return -1;); ASSERT(info->discovery != NULL, return -1;);
IRDA_DEBUG(4, "%s(), daddr=%08x\n", __FUNCTION__, IRDA_DEBUG(4, "%s(), daddr=%08x\n", __FUNCTION__,
info->discovery->daddr); info->discovery->data.daddr);
if (!self->discovery_log) { if (!self->discovery_log) {
WARNING("%s: discovery log is gone! " WARNING("%s: discovery log is gone! "
...@@ -586,7 +586,7 @@ static int irlap_state_query(struct irlap_cb *self, IRLAP_EVENT event, ...@@ -586,7 +586,7 @@ static int irlap_state_query(struct irlap_cb *self, IRLAP_EVENT event,
} }
hashbin_insert(self->discovery_log, hashbin_insert(self->discovery_log,
(irda_queue_t *) info->discovery, (irda_queue_t *) info->discovery,
info->discovery->daddr, NULL); info->discovery->data.daddr, NULL);
/* Keep state */ /* Keep state */
/* irlap_next_state(self, LAP_QUERY); */ /* irlap_next_state(self, LAP_QUERY); */
...@@ -704,7 +704,7 @@ static int irlap_state_reply(struct irlap_cb *self, IRLAP_EVENT event, ...@@ -704,7 +704,7 @@ static int irlap_state_reply(struct irlap_cb *self, IRLAP_EVENT event,
irlap_discovery_indication(self, info->discovery); irlap_discovery_indication(self, info->discovery);
} else if ((info->s >= self->slot) && (!self->frame_sent)) { } else if ((info->s >= self->slot) && (!self->frame_sent)) {
discovery_rsp = irlmp_get_discovery_response(); discovery_rsp = irlmp_get_discovery_response();
discovery_rsp->daddr = info->daddr; discovery_rsp->data.daddr = info->daddr;
irlap_send_discovery_xid_frame(self, info->S, irlap_send_discovery_xid_frame(self, info->S,
self->slot, FALSE, self->slot, FALSE,
...@@ -982,15 +982,48 @@ static int irlap_state_xmit_p(struct irlap_cb *self, IRLAP_EVENT event, ...@@ -982,15 +982,48 @@ static int irlap_state_xmit_p(struct irlap_cb *self, IRLAP_EVENT event,
* Only send frame if send-window > 0. * Only send frame if send-window > 0.
*/ */
if ((self->window > 0) && (!self->remote_busy)) { if ((self->window > 0) && (!self->remote_busy)) {
int nextfit;
#ifdef CONFIG_IRDA_DYNAMIC_WINDOW #ifdef CONFIG_IRDA_DYNAMIC_WINDOW
struct sk_buff *skb_next;
/* With DYNAMIC_WINDOW, we keep the window size
* maximum, and adapt on the packets we are sending.
* At 115k, we can send only 2 packets of 2048 bytes
* in a 500 ms turnaround. Without this option, we
* would always limit the window to 2. With this
* option, if we send smaller packets, we can send
* up to 7 of them (always depending on QoS).
* Jean II */
/* Look at the next skb. This is safe, as we are
* the only consumer of the Tx queue (if we are not,
* we have other problems) - Jean II */
skb_next = skb_peek(&self->txq);
/* Check if a subsequent skb exist and would fit in
* the current window (with respect to turnaround
* time).
* This allow us to properly mark the current packet
* with the pf bit, to avoid falling back on the
* second test below, and avoid waiting the
* end of the window and sending a extra RR.
* Note : (skb_next != NULL) <=> (skb_queue_len() > 0)
* Jean II */
nextfit = ((skb_next != NULL) &&
((skb_next->len + skb->len) <=
self->bytes_left));
/* /*
* The current packet may not fit ! Because of test
* above, this should not happen any more !!!
* Test if we have transmitted more bytes over the * Test if we have transmitted more bytes over the
* link than its possible to do with the current * link than its possible to do with the current
* speed and turn-around-time. * speed and turn-around-time.
*/ */
if (skb->len > self->bytes_left) { if((!nextfit) && (skb->len > self->bytes_left)) {
IRDA_DEBUG(4, "%s(), Not allowed to transmit" IRDA_DEBUG(0, "%s(), Not allowed to transmit"
" more bytes!\n", __FUNCTION__); " more bytes!\n", __FUNCTION__);
/* Requeue the skb */
skb_queue_head(&self->txq, skb_get(skb)); skb_queue_head(&self->txq, skb_get(skb));
/* /*
* We should switch state to LAP_NRM_P, but * We should switch state to LAP_NRM_P, but
...@@ -1000,20 +1033,33 @@ static int irlap_state_xmit_p(struct irlap_cb *self, IRLAP_EVENT event, ...@@ -1000,20 +1033,33 @@ static int irlap_state_xmit_p(struct irlap_cb *self, IRLAP_EVENT event,
* trigger anyway now, so we just wait for it * trigger anyway now, so we just wait for it
* DB * DB
*/ */
/*
* Sorry, but that's not totally true. If
* we send 2000B packets, we may wait another
* 1000B until our turnaround expire. That's
* why we need to be proactive in avoiding
* comming here. - Jean II
*/
return -EPROTO; return -EPROTO;
} }
/* Substract space used by this skb */
self->bytes_left -= skb->len; self->bytes_left -= skb->len;
#else /* CONFIG_IRDA_DYNAMIC_WINDOW */
/* Window has been adjusted for the max packet
* size, so much simpler... - Jean II */
nextfit = (skb_queue_len(&self->txq) > 0);
#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */ #endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
/* /*
* Send data with poll bit cleared only if window > 1 * Send data with poll bit cleared only if window > 1
* and there is more frames after this one to be sent * and there is more frames after this one to be sent
*/ */
if ((self->window > 1) && if ((self->window > 1) && (nextfit)) {
skb_queue_len( &self->txq) > 0) /* More packet to send in current window */
{
irlap_send_data_primary(self, skb); irlap_send_data_primary(self, skb);
irlap_next_state(self, LAP_XMIT_P); irlap_next_state(self, LAP_XMIT_P);
} else { } else {
/* Final packet of window */
irlap_send_data_primary_poll(self, skb); irlap_send_data_primary_poll(self, skb);
irlap_next_state(self, LAP_NRM_P); irlap_next_state(self, LAP_NRM_P);
...@@ -1683,16 +1729,37 @@ static int irlap_state_xmit_s(struct irlap_cb *self, IRLAP_EVENT event, ...@@ -1683,16 +1729,37 @@ static int irlap_state_xmit_s(struct irlap_cb *self, IRLAP_EVENT event,
switch (event) { switch (event) {
case SEND_I_CMD: case SEND_I_CMD:
/* /*
* Send frame only if send window > 1 * Send frame only if send window > 0
*/ */
if ((self->window > 0) && (!self->remote_busy)) { if ((self->window > 0) && (!self->remote_busy)) {
int nextfit;
#ifdef CONFIG_IRDA_DYNAMIC_WINDOW #ifdef CONFIG_IRDA_DYNAMIC_WINDOW
struct sk_buff *skb_next;
/*
* Same deal as in irlap_state_xmit_p(), so see
* the comments at that point.
* We are the secondary, so there are only subtle
* differences. - Jean II
*/
/* Check if a subsequent skb exist and would fit in
* the current window (with respect to turnaround
* time). - Jean II */
skb_next = skb_peek(&self->txq);
nextfit = ((skb_next != NULL) &&
((skb_next->len + skb->len) <=
self->bytes_left));
/* /*
* Test if we have transmitted more bytes over the * Test if we have transmitted more bytes over the
* link than its possible to do with the current * link than its possible to do with the current
* speed and turn-around-time. * speed and turn-around-time.
*/ */
if (skb->len > self->bytes_left) { if((!nextfit) && (skb->len > self->bytes_left)) {
IRDA_DEBUG(0, "%s(), Not allowed to transmit"
" more bytes!\n", __FUNCTION__);
/* Requeue the skb */
skb_queue_head(&self->txq, skb_get(skb)); skb_queue_head(&self->txq, skb_get(skb));
/* /*
...@@ -1706,18 +1773,24 @@ static int irlap_state_xmit_s(struct irlap_cb *self, IRLAP_EVENT event, ...@@ -1706,18 +1773,24 @@ static int irlap_state_xmit_s(struct irlap_cb *self, IRLAP_EVENT event,
irlap_start_wd_timer(self, self->wd_timeout); irlap_start_wd_timer(self, self->wd_timeout);
irlap_next_state(self, LAP_NRM_S); irlap_next_state(self, LAP_NRM_S);
/* Slight difference with primary :
* here we would wait for the other side to
* expire the turnaround. - Jean II */
return -EPROTO; /* Try again later */ return -EPROTO; /* Try again later */
} }
/* Substract space used by this skb */
self->bytes_left -= skb->len; self->bytes_left -= skb->len;
#else /* CONFIG_IRDA_DYNAMIC_WINDOW */
/* Window has been adjusted for the max packet
* size, so much simpler... - Jean II */
nextfit = (skb_queue_len(&self->txq) > 0);
#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */ #endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
/* /*
* Send data with final bit cleared only if window > 1 * Send data with final bit cleared only if window > 1
* and there is more frames to be sent * and there is more frames to be sent
*/ */
if ((self->window > 1) && if ((self->window > 1) && (nextfit)) {
skb_queue_len(&self->txq) > 0)
{
irlap_send_data_secondary(self, skb); irlap_send_data_secondary(self, skb);
irlap_next_state(self, LAP_XMIT_S); irlap_next_state(self, LAP_XMIT_S);
} else { } else {
......
...@@ -335,7 +335,7 @@ void irlap_send_discovery_xid_frame(struct irlap_cb *self, int S, __u8 s, ...@@ -335,7 +335,7 @@ void irlap_send_discovery_xid_frame(struct irlap_cb *self, int S, __u8 s,
if (command) if (command)
frame->daddr = cpu_to_le32(bcast); frame->daddr = cpu_to_le32(bcast);
else else
frame->daddr = cpu_to_le32(discovery->daddr); frame->daddr = cpu_to_le32(discovery->data.daddr);
switch (S) { switch (S) {
case 1: case 1:
...@@ -366,20 +366,20 @@ void irlap_send_discovery_xid_frame(struct irlap_cb *self, int S, __u8 s, ...@@ -366,20 +366,20 @@ void irlap_send_discovery_xid_frame(struct irlap_cb *self, int S, __u8 s,
if (!command || (frame->slotnr == 0xff)) { if (!command || (frame->slotnr == 0xff)) {
int len; int len;
if (discovery->hints.byte[0] & HINT_EXTENSION) { if (discovery->data.hints[0] & HINT_EXTENSION) {
info = skb_put(skb, 2); info = skb_put(skb, 2);
info[0] = discovery->hints.byte[0]; info[0] = discovery->data.hints[0];
info[1] = discovery->hints.byte[1]; info[1] = discovery->data.hints[1];
} else { } else {
info = skb_put(skb, 1); info = skb_put(skb, 1);
info[0] = discovery->hints.byte[0]; info[0] = discovery->data.hints[0];
} }
info = skb_put(skb, 1); info = skb_put(skb, 1);
info[0] = discovery->charset; info[0] = discovery->data.charset;
len = IRDA_MIN(discovery->name_len, skb_tailroom(skb)); len = IRDA_MIN(discovery->name_len, skb_tailroom(skb));
info = skb_put(skb, len); info = skb_put(skb, len);
memcpy(info, discovery->nickname, len); memcpy(info, discovery->data.info, len);
} }
irlap_queue_xmit(self, skb); irlap_queue_xmit(self, skb);
} }
...@@ -422,24 +422,25 @@ static void irlap_recv_discovery_xid_rsp(struct irlap_cb *self, ...@@ -422,24 +422,25 @@ static void irlap_recv_discovery_xid_rsp(struct irlap_cb *self,
} }
memset(discovery, 0, sizeof(discovery_t)); memset(discovery, 0, sizeof(discovery_t));
discovery->daddr = info->daddr; discovery->data.daddr = info->daddr;
discovery->saddr = self->saddr; discovery->data.saddr = self->saddr;
discovery->timestamp = jiffies; discovery->timestamp = jiffies;
IRDA_DEBUG(4, "%s(), daddr=%08x\n", __FUNCTION__, discovery->daddr); IRDA_DEBUG(4, "%s(), daddr=%08x\n", __FUNCTION__,
discovery->data.daddr);
discovery_info = skb_pull(skb, sizeof(struct xid_frame)); discovery_info = skb_pull(skb, sizeof(struct xid_frame));
/* Get info returned from peer */ /* Get info returned from peer */
discovery->hints.byte[0] = discovery_info[0]; discovery->data.hints[0] = discovery_info[0];
if (discovery_info[0] & HINT_EXTENSION) { if (discovery_info[0] & HINT_EXTENSION) {
IRDA_DEBUG(4, "EXTENSION\n"); IRDA_DEBUG(4, "EXTENSION\n");
discovery->hints.byte[1] = discovery_info[1]; discovery->data.hints[1] = discovery_info[1];
discovery->charset = discovery_info[2]; discovery->data.charset = discovery_info[2];
text = (char *) &discovery_info[3]; text = (char *) &discovery_info[3];
} else { } else {
discovery->hints.byte[1] = 0; discovery->data.hints[1] = 0;
discovery->charset = discovery_info[1]; discovery->data.charset = discovery_info[1];
text = (char *) &discovery_info[2]; text = (char *) &discovery_info[2];
} }
/* /*
...@@ -447,8 +448,8 @@ static void irlap_recv_discovery_xid_rsp(struct irlap_cb *self, ...@@ -447,8 +448,8 @@ static void irlap_recv_discovery_xid_rsp(struct irlap_cb *self,
* FCS bytes resides. * FCS bytes resides.
*/ */
skb->data[skb->len] = '\0'; skb->data[skb->len] = '\0';
strncpy(discovery->nickname, text, NICKNAME_MAX_LEN); strncpy(discovery->data.info, text, NICKNAME_MAX_LEN);
discovery->name_len = strlen(discovery->nickname); discovery->name_len = strlen(discovery->data.info);
info->discovery = discovery; info->discovery = discovery;
...@@ -523,18 +524,18 @@ static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self, ...@@ -523,18 +524,18 @@ static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,
return; return;
} }
discovery->daddr = info->daddr; discovery->data.daddr = info->daddr;
discovery->saddr = self->saddr; discovery->data.saddr = self->saddr;
discovery->timestamp = jiffies; discovery->timestamp = jiffies;
discovery->hints.byte[0] = discovery_info[0]; discovery->data.hints[0] = discovery_info[0];
if (discovery_info[0] & HINT_EXTENSION) { if (discovery_info[0] & HINT_EXTENSION) {
discovery->hints.byte[1] = discovery_info[1]; discovery->data.hints[1] = discovery_info[1];
discovery->charset = discovery_info[2]; discovery->data.charset = discovery_info[2];
text = (char *) &discovery_info[3]; text = (char *) &discovery_info[3];
} else { } else {
discovery->hints.byte[1] = 0; discovery->data.hints[1] = 0;
discovery->charset = discovery_info[1]; discovery->data.charset = discovery_info[1];
text = (char *) &discovery_info[2]; text = (char *) &discovery_info[2];
} }
/* /*
...@@ -542,8 +543,8 @@ static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self, ...@@ -542,8 +543,8 @@ static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,
* FCS bytes resides. * FCS bytes resides.
*/ */
skb->data[skb->len] = '\0'; skb->data[skb->len] = '\0';
strncpy(discovery->nickname, text, NICKNAME_MAX_LEN); strncpy(discovery->data.info, text, NICKNAME_MAX_LEN);
discovery->name_len = strlen(discovery->nickname); discovery->name_len = strlen(discovery->data.info);
info->discovery = discovery; info->discovery = discovery;
} else } else
......
This diff is collapsed.
...@@ -225,6 +225,10 @@ ...@@ -225,6 +225,10 @@
* *
* v13 - 30.5.02 - Jean II * v13 - 30.5.02 - Jean II
* o Update module init code * o Update module init code
*
* v14 - 20.2.03 - Jean II
* o Add discovery hint bits in the control channel.
* o Remove obsolete MOD_INC/DEC_USE_COUNT in favor of .owner
*/ */
/***************************** INCLUDES *****************************/ /***************************** INCLUDES *****************************/
...@@ -476,6 +480,7 @@ typedef struct irnet_log ...@@ -476,6 +480,7 @@ typedef struct irnet_log
__u32 saddr; __u32 saddr;
__u32 daddr; __u32 daddr;
char name[NICKNAME_MAX_LEN + 1]; /* 21 + 1 */ char name[NICKNAME_MAX_LEN + 1]; /* 21 + 1 */
__u16_host_order hints; /* Discovery hint bits */
} irnet_log; } irnet_log;
/* /*
......
...@@ -28,7 +28,8 @@ irnet_post_event(irnet_socket * ap, ...@@ -28,7 +28,8 @@ irnet_post_event(irnet_socket * ap,
irnet_event event, irnet_event event,
__u32 saddr, __u32 saddr,
__u32 daddr, __u32 daddr,
char * name) char * name,
__u16 hints)
{ {
unsigned long flags; /* For spinlock */ unsigned long flags; /* For spinlock */
int index; /* In the log */ int index; /* In the log */
...@@ -52,6 +53,8 @@ irnet_post_event(irnet_socket * ap, ...@@ -52,6 +53,8 @@ irnet_post_event(irnet_socket * ap,
strcpy(irnet_events.log[index].name, name); strcpy(irnet_events.log[index].name, name);
else else
irnet_events.log[index].name[0] = '\0'; irnet_events.log[index].name[0] = '\0';
/* Copy hints */
irnet_events.log[index].hints.word = hints;
/* Try to get ppp unit number */ /* Try to get ppp unit number */
if((ap != (irnet_socket *) NULL) && (ap->ppp_open)) if((ap != (irnet_socket *) NULL) && (ap->ppp_open))
irnet_events.log[index].unit = ppp_unit_number(&ap->chan); irnet_events.log[index].unit = ppp_unit_number(&ap->chan);
...@@ -609,7 +612,7 @@ irda_irnet_destroy(irnet_socket * self) ...@@ -609,7 +612,7 @@ irda_irnet_destroy(irnet_socket * self)
* doesn't exist anymore when we post the event, so we need to pass * doesn't exist anymore when we post the event, so we need to pass
* NULL as the first arg... */ * NULL as the first arg... */
irnet_post_event(NULL, IRNET_DISCONNECT_TO, irnet_post_event(NULL, IRNET_DISCONNECT_TO,
self->saddr, self->daddr, self->rname); self->saddr, self->daddr, self->rname, 0);
} }
/* Prevent various IrDA callbacks from messing up things /* Prevent various IrDA callbacks from messing up things
...@@ -862,7 +865,7 @@ irnet_connect_socket(irnet_socket * server, ...@@ -862,7 +865,7 @@ irnet_connect_socket(irnet_socket * server,
/* Notify the control channel */ /* Notify the control channel */
irnet_post_event(new, IRNET_CONNECT_FROM, irnet_post_event(new, IRNET_CONNECT_FROM,
new->saddr, new->daddr, server->rname); new->saddr, new->daddr, server->rname, 0);
DEXIT(IRDA_SERV_TRACE, "\n"); DEXIT(IRDA_SERV_TRACE, "\n");
return 0; return 0;
...@@ -893,7 +896,7 @@ irnet_disconnect_server(irnet_socket * self, ...@@ -893,7 +896,7 @@ irnet_disconnect_server(irnet_socket * self,
/* Notify the control channel (see irnet_find_socket()) */ /* Notify the control channel (see irnet_find_socket()) */
irnet_post_event(NULL, IRNET_REQUEST_FROM, irnet_post_event(NULL, IRNET_REQUEST_FROM,
self->saddr, self->daddr, self->rname); self->saddr, self->daddr, self->rname, 0);
/* Clean up the server to keep it in listen state */ /* Clean up the server to keep it in listen state */
irttp_listen(self->tsap); irttp_listen(self->tsap);
...@@ -1108,12 +1111,12 @@ irnet_disconnect_indication(void * instance, ...@@ -1108,12 +1111,12 @@ irnet_disconnect_indication(void * instance,
/* If we were active, notify the control channel */ /* If we were active, notify the control channel */
if(test_open) if(test_open)
irnet_post_event(self, IRNET_DISCONNECT_FROM, irnet_post_event(self, IRNET_DISCONNECT_FROM,
self->saddr, self->daddr, self->rname); self->saddr, self->daddr, self->rname, 0);
else else
/* If we were trying to connect, notify the control channel */ /* If we were trying to connect, notify the control channel */
if((self->tsap) && (self != &irnet_server.s)) if((self->tsap) && (self != &irnet_server.s))
irnet_post_event(self, IRNET_NOANSWER_FROM, irnet_post_event(self, IRNET_NOANSWER_FROM,
self->saddr, self->daddr, self->rname); self->saddr, self->daddr, self->rname, 0);
/* Close our IrTTP connection, cleanup tsap */ /* Close our IrTTP connection, cleanup tsap */
if((self->tsap) && (self != &irnet_server.s)) if((self->tsap) && (self != &irnet_server.s))
...@@ -1213,7 +1216,7 @@ irnet_connect_confirm(void * instance, ...@@ -1213,7 +1216,7 @@ irnet_connect_confirm(void * instance,
/* Notify the control channel */ /* Notify the control channel */
irnet_post_event(self, IRNET_CONNECT_TO, irnet_post_event(self, IRNET_CONNECT_TO,
self->saddr, self->daddr, self->rname); self->saddr, self->daddr, self->rname, 0);
DEXIT(IRDA_TCB_TRACE, "\n"); DEXIT(IRDA_TCB_TRACE, "\n");
} }
...@@ -1282,7 +1285,7 @@ irnet_status_indication(void * instance, ...@@ -1282,7 +1285,7 @@ irnet_status_indication(void * instance,
{ {
case STATUS_NO_ACTIVITY: case STATUS_NO_ACTIVITY:
irnet_post_event(self, IRNET_BLOCKED_LINK, irnet_post_event(self, IRNET_BLOCKED_LINK,
self->saddr, self->daddr, self->rname); self->saddr, self->daddr, self->rname, 0);
break; break;
default: default:
DEBUG(IRDA_CB_INFO, "Unknown status...\n"); DEBUG(IRDA_CB_INFO, "Unknown status...\n");
...@@ -1616,8 +1619,8 @@ irnet_discovervalue_confirm(int result, ...@@ -1616,8 +1619,8 @@ irnet_discovervalue_confirm(int result,
* *
* Got a discovery indication from IrLMP, post an event * Got a discovery indication from IrLMP, post an event
* *
* Note : IrLMP take care of matching the hint mask for us, we only * Note : IrLMP take care of matching the hint mask for us, and also
* check if it is a "new" node... * check if it is a "new" node for us...
* *
* As IrLMP filter on the IrLAN hint bit, we get both IrLAN and IrNET * As IrLMP filter on the IrLAN hint bit, we get both IrLAN and IrNET
* nodes, so it's only at connection time that we will know if the * nodes, so it's only at connection time that we will know if the
...@@ -1633,7 +1636,7 @@ irnet_discovervalue_confirm(int result, ...@@ -1633,7 +1636,7 @@ irnet_discovervalue_confirm(int result,
* is to messy, so we leave that to user space... * is to messy, so we leave that to user space...
*/ */
static void static void
irnet_discovery_indication(discovery_t * discovery, irnet_discovery_indication(discinfo_t * discovery,
DISCOVERY_MODE mode, DISCOVERY_MODE mode,
void * priv) void * priv)
{ {
...@@ -1643,21 +1646,13 @@ irnet_discovery_indication(discovery_t * discovery, ...@@ -1643,21 +1646,13 @@ irnet_discovery_indication(discovery_t * discovery,
DASSERT(priv == &irnet_server, , IRDA_OCB_ERROR, DASSERT(priv == &irnet_server, , IRDA_OCB_ERROR,
"Invalid instance (0x%X) !!!\n", (unsigned int) priv); "Invalid instance (0x%X) !!!\n", (unsigned int) priv);
/* Check if node is discovered is a new one or an old one.
* We check when how long ago this node was discovered, with a
* coarse timeout (we may miss some discovery events or be delayed).
*/
if((jiffies - discovery->first_timestamp) >= (sysctl_discovery_timeout * HZ))
{
return; /* Too old, not interesting -> goodbye */
}
DEBUG(IRDA_OCB_INFO, "Discovered new IrNET/IrLAN node %s...\n", DEBUG(IRDA_OCB_INFO, "Discovered new IrNET/IrLAN node %s...\n",
discovery->nickname); discovery->info);
/* Notify the control channel */ /* Notify the control channel */
irnet_post_event(NULL, IRNET_DISCOVER, irnet_post_event(NULL, IRNET_DISCOVER,
discovery->saddr, discovery->daddr, discovery->nickname); discovery->saddr, discovery->daddr, discovery->info,
u16ho(discovery->hints));
DEXIT(IRDA_OCB_TRACE, "\n"); DEXIT(IRDA_OCB_TRACE, "\n");
} }
...@@ -1672,7 +1667,7 @@ irnet_discovery_indication(discovery_t * discovery, ...@@ -1672,7 +1667,7 @@ irnet_discovery_indication(discovery_t * discovery,
* check if it is a "new" node... * check if it is a "new" node...
*/ */
static void static void
irnet_expiry_indication(discovery_t * expiry, irnet_expiry_indication(discinfo_t * expiry,
DISCOVERY_MODE mode, DISCOVERY_MODE mode,
void * priv) void * priv)
{ {
...@@ -1683,11 +1678,12 @@ irnet_expiry_indication(discovery_t * expiry, ...@@ -1683,11 +1678,12 @@ irnet_expiry_indication(discovery_t * expiry,
"Invalid instance (0x%X) !!!\n", (unsigned int) priv); "Invalid instance (0x%X) !!!\n", (unsigned int) priv);
DEBUG(IRDA_OCB_INFO, "IrNET/IrLAN node %s expired...\n", DEBUG(IRDA_OCB_INFO, "IrNET/IrLAN node %s expired...\n",
expiry->nickname); expiry->info);
/* Notify the control channel */ /* Notify the control channel */
irnet_post_event(NULL, IRNET_EXPIRE, irnet_post_event(NULL, IRNET_EXPIRE,
expiry->saddr, expiry->daddr, expiry->nickname); expiry->saddr, expiry->daddr, expiry->info,
u16ho(expiry->hints));
DEXIT(IRDA_OCB_TRACE, "\n"); DEXIT(IRDA_OCB_TRACE, "\n");
} }
......
...@@ -69,7 +69,8 @@ static void ...@@ -69,7 +69,8 @@ static void
irnet_event, irnet_event,
__u32, __u32,
__u32, __u32,
char *); char *,
__u16);
/* ----------------------- IRDA SUBROUTINES ----------------------- */ /* ----------------------- IRDA SUBROUTINES ----------------------- */
static inline int static inline int
irnet_open_tsap(irnet_socket *); irnet_open_tsap(irnet_socket *);
...@@ -150,11 +151,11 @@ static void ...@@ -150,11 +151,11 @@ static void
void *); void *);
#ifdef DISCOVERY_EVENTS #ifdef DISCOVERY_EVENTS
static void static void
irnet_discovery_indication(discovery_t *, irnet_discovery_indication(discinfo_t *,
DISCOVERY_MODE, DISCOVERY_MODE,
void *); void *);
static void static void
irnet_expiry_indication(discovery_t *, irnet_expiry_indication(discinfo_t *,
DISCOVERY_MODE, DISCOVERY_MODE,
void *); void *);
#endif #endif
......
...@@ -213,10 +213,12 @@ irnet_read_discovery_log(irnet_socket * ap, ...@@ -213,10 +213,12 @@ irnet_read_discovery_log(irnet_socket * ap,
if(ap->disco_index < ap->disco_number) if(ap->disco_index < ap->disco_number)
{ {
/* Write an event */ /* Write an event */
sprintf(event, "Found %08x (%s) behind %08x\n", sprintf(event, "Found %08x (%s) behind %08x {hints %02X-%02X}\n",
ap->discoveries[ap->disco_index].daddr, ap->discoveries[ap->disco_index].daddr,
ap->discoveries[ap->disco_index].info, ap->discoveries[ap->disco_index].info,
ap->discoveries[ap->disco_index].saddr); ap->discoveries[ap->disco_index].saddr,
ap->discoveries[ap->disco_index].hints[0],
ap->discoveries[ap->disco_index].hints[1]);
DEBUG(CTRL_INFO, "Writing discovery %d : %s\n", DEBUG(CTRL_INFO, "Writing discovery %d : %s\n",
ap->disco_index, ap->discoveries[ap->disco_index].info); ap->disco_index, ap->discoveries[ap->disco_index].info);
...@@ -313,16 +315,20 @@ irnet_ctrl_read(irnet_socket * ap, ...@@ -313,16 +315,20 @@ irnet_ctrl_read(irnet_socket * ap,
switch(irnet_events.log[ap->event_index].event) switch(irnet_events.log[ap->event_index].event)
{ {
case IRNET_DISCOVER: case IRNET_DISCOVER:
sprintf(event, "Discovered %08x (%s) behind %08x\n", sprintf(event, "Discovered %08x (%s) behind %08x {hints %02X-%02X}\n",
irnet_events.log[ap->event_index].daddr, irnet_events.log[ap->event_index].daddr,
irnet_events.log[ap->event_index].name, irnet_events.log[ap->event_index].name,
irnet_events.log[ap->event_index].saddr); irnet_events.log[ap->event_index].saddr,
irnet_events.log[ap->event_index].hints.byte[0],
irnet_events.log[ap->event_index].hints.byte[1]);
break; break;
case IRNET_EXPIRE: case IRNET_EXPIRE:
sprintf(event, "Expired %08x (%s) behind %08x\n", sprintf(event, "Expired %08x (%s) behind %08x {hints %02X-%02X}\n",
irnet_events.log[ap->event_index].daddr, irnet_events.log[ap->event_index].daddr,
irnet_events.log[ap->event_index].name, irnet_events.log[ap->event_index].name,
irnet_events.log[ap->event_index].saddr); irnet_events.log[ap->event_index].saddr,
irnet_events.log[ap->event_index].hints.byte[0],
irnet_events.log[ap->event_index].hints.byte[1]);
break; break;
case IRNET_CONNECT_TO: case IRNET_CONNECT_TO:
sprintf(event, "Connected to %08x (%s) on ppp%d\n", sprintf(event, "Connected to %08x (%s) on ppp%d\n",
...@@ -445,8 +451,6 @@ dev_irnet_open(struct inode * inode, ...@@ -445,8 +451,6 @@ dev_irnet_open(struct inode * inode,
ap = kmalloc(sizeof(*ap), GFP_KERNEL); ap = kmalloc(sizeof(*ap), GFP_KERNEL);
DABORT(ap == NULL, -ENOMEM, FS_ERROR, "Can't allocate struct irnet...\n"); DABORT(ap == NULL, -ENOMEM, FS_ERROR, "Can't allocate struct irnet...\n");
MOD_INC_USE_COUNT;
/* initialize the irnet structure */ /* initialize the irnet structure */
memset(ap, 0, sizeof(*ap)); memset(ap, 0, sizeof(*ap));
ap->file = file; ap->file = file;
...@@ -469,7 +473,6 @@ dev_irnet_open(struct inode * inode, ...@@ -469,7 +473,6 @@ dev_irnet_open(struct inode * inode,
{ {
DERROR(FS_ERROR, "Can't setup IrDA link...\n"); DERROR(FS_ERROR, "Can't setup IrDA link...\n");
kfree(ap); kfree(ap);
MOD_DEC_USE_COUNT;
return err; return err;
} }
...@@ -514,7 +517,6 @@ dev_irnet_close(struct inode * inode, ...@@ -514,7 +517,6 @@ dev_irnet_close(struct inode * inode,
} }
kfree(ap); kfree(ap);
MOD_DEC_USE_COUNT;
DEXIT(FS_TRACE, "\n"); DEXIT(FS_TRACE, "\n");
return 0; return 0;
......
...@@ -98,6 +98,7 @@ static int ...@@ -98,6 +98,7 @@ static int
/* Filesystem callbacks (to call us) */ /* Filesystem callbacks (to call us) */
static struct file_operations irnet_device_fops = static struct file_operations irnet_device_fops =
{ {
.owner = THIS_MODULE,
.read = dev_irnet_read, .read = dev_irnet_read,
.write = dev_irnet_write, .write = dev_irnet_write,
.poll = dev_irnet_poll, .poll = dev_irnet_poll,
......
...@@ -39,8 +39,8 @@ static void irlap_query_timer_expired(void* data); ...@@ -39,8 +39,8 @@ static void irlap_query_timer_expired(void* data);
static void irlap_final_timer_expired(void* data); static void irlap_final_timer_expired(void* data);
static void irlap_wd_timer_expired(void* data); static void irlap_wd_timer_expired(void* data);
static void irlap_backoff_timer_expired(void* data); static void irlap_backoff_timer_expired(void* data);
static void irlap_media_busy_expired(void* data); static void irlap_media_busy_expired(void* data);
/* /*
* Function irda_start_timer (timer, timeout) * Function irda_start_timer (timer, timeout)
* *
...@@ -50,19 +50,18 @@ static void irlap_media_busy_expired(void* data); ...@@ -50,19 +50,18 @@ static void irlap_media_busy_expired(void* data);
void irda_start_timer(struct timer_list *ptimer, int timeout, void *data, void irda_start_timer(struct timer_list *ptimer, int timeout, void *data,
TIMER_CALLBACK callback) TIMER_CALLBACK callback)
{ {
del_timer(ptimer);
ptimer->data = (unsigned long) data;
/* /*
* For most architectures void * is the same as unsigned long, but * For most architectures void * is the same as unsigned long, but
* at least we try to use void * as long as possible. Since the * at least we try to use void * as long as possible. Since the
* timer functions use unsigned long, we cast the function here * timer functions use unsigned long, we cast the function here
*/ */
ptimer->function = (void (*)(unsigned long)) callback; ptimer->function = (void (*)(unsigned long)) callback;
ptimer->expires = jiffies + timeout; ptimer->data = (unsigned long) data;
add_timer(ptimer); /* Set new value for timer (update or add timer).
* We use mod_timer() because it's more efficient and also
* safer with respect to race conditions - Jean II */
mod_timer(ptimer, jiffies + timeout);
} }
void irlap_start_slot_timer(struct irlap_cb *self, int timeout) void irlap_start_slot_timer(struct irlap_cb *self, int timeout)
...@@ -136,7 +135,6 @@ void irlmp_start_idle_timer(struct lap_cb *self, int timeout) ...@@ -136,7 +135,6 @@ void irlmp_start_idle_timer(struct lap_cb *self, int timeout)
void irlmp_stop_idle_timer(struct lap_cb *self) void irlmp_stop_idle_timer(struct lap_cb *self)
{ {
/* If timer is activated, kill it! */ /* If timer is activated, kill it! */
if(timer_pending(&self->idle_timer))
del_timer(&self->idle_timer); del_timer(&self->idle_timer);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment