Commit cc21ca79 authored by Jean Tourrilhes's avatar Jean Tourrilhes Committed by Jeff Garzik

IrDA update 3/3:

 <Following patch from Christoph Bartelmus, mangled by me>
o [CORRECT] replace the global LSAP cache with LSAP caches private
to each LAP.
Fix a bug where two simultaneous connections from two devices
using the same LSAPs would get mixed up.
Should also improve performance in similar cases. 
parent 4bab61d6
...@@ -119,6 +119,21 @@ struct lsap_cb { ...@@ -119,6 +119,21 @@ struct lsap_cb {
struct lap_cb *lap; /* Pointer to LAP connection structure */ struct lap_cb *lap; /* Pointer to LAP connection structure */
}; };
/*
* Used for caching the last slsap->dlsap->handle mapping
*
* We don't need to keep/match the remote address in the cache because
* we are associated with a specific LAP (which implies it).
* Jean II
*/
typedef struct {
int valid;
__u8 slsap_sel;
__u8 dlsap_sel;
struct lsap_cb *lsap;
} CACHE_ENTRY;
/* /*
* Information about each registred IrLAP layer * Information about each registred IrLAP layer
*/ */
...@@ -140,19 +155,15 @@ struct lap_cb { ...@@ -140,19 +155,15 @@ struct lap_cb {
struct qos_info *qos; /* LAP QoS for this session */ struct qos_info *qos; /* LAP QoS for this session */
struct timer_list idle_timer; struct timer_list idle_timer;
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
/* The lsap cache was moved from struct irlmp_cb to here because
* it must be associated with the specific LAP. Also, this
* improves performance. - Jean II */
CACHE_ENTRY cache; /* Caching last slsap->dlsap->handle mapping */
#endif
}; };
/*
* Used for caching the last slsap->dlsap->handle mapping
*/
typedef struct {
int valid;
__u8 slsap_sel;
__u8 dlsap_sel;
struct lsap_cb *lsap;
} CACHE_ENTRY;
/* /*
* Main structure for IrLMP * Main structure for IrLMP
*/ */
...@@ -166,9 +177,6 @@ struct irlmp_cb { ...@@ -166,9 +177,6 @@ struct irlmp_cb {
int free_lsap_sel; int free_lsap_sel;
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
CACHE_ENTRY cache; /* Caching last slsap->dlsap->handle mapping */
#endif
struct timer_list discovery_timer; struct timer_list discovery_timer;
hashbin_t *links; /* IrLAP connection table */ hashbin_t *links; /* IrLAP connection table */
......
...@@ -93,9 +93,6 @@ int __init irlmp_init(void) ...@@ -93,9 +93,6 @@ int __init irlmp_init(void)
irlmp->cachelog = hashbin_new(HB_GLOBAL); irlmp->cachelog = hashbin_new(HB_GLOBAL);
irlmp->free_lsap_sel = 0x10; /* Reserved 0x00-0x0f */ irlmp->free_lsap_sel = 0x10; /* Reserved 0x00-0x0f */
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
irlmp->cache.valid = FALSE;
#endif
strcpy(sysctl_devname, "Linux"); strcpy(sysctl_devname, "Linux");
/* Do discovery every 3 seconds */ /* Do discovery every 3 seconds */
...@@ -208,10 +205,6 @@ static void __irlmp_close_lsap(struct lsap_cb *self) ...@@ -208,10 +205,6 @@ static void __irlmp_close_lsap(struct lsap_cb *self)
if (self->conn_skb) if (self->conn_skb)
dev_kfree_skb(self->conn_skb); dev_kfree_skb(self->conn_skb);
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
ASSERT(irlmp != NULL, return;);
irlmp->cache.valid = FALSE;
#endif
kfree(self); kfree(self);
} }
...@@ -247,6 +240,9 @@ void irlmp_close_lsap(struct lsap_cb *self) ...@@ -247,6 +240,9 @@ void irlmp_close_lsap(struct lsap_cb *self)
} }
/* Now, remove from the link */ /* Now, remove from the link */
lsap = hashbin_remove(lap->lsaps, (int) self, NULL); lsap = hashbin_remove(lap->lsaps, (int) self, NULL);
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
lap->cache.valid = FALSE;
#endif
} }
self->lap = NULL; self->lap = NULL;
/* Check if we found the LSAP! If not then try the unconnected lsaps */ /* Check if we found the LSAP! If not then try the unconnected lsaps */
...@@ -292,6 +288,9 @@ void irlmp_register_link(struct irlap_cb *irlap, __u32 saddr, notify_t *notify) ...@@ -292,6 +288,9 @@ void irlmp_register_link(struct irlap_cb *irlap, __u32 saddr, notify_t *notify)
lap->saddr = saddr; lap->saddr = saddr;
lap->daddr = DEV_ADDR_ANY; lap->daddr = DEV_ADDR_ANY;
lap->lsaps = hashbin_new(HB_GLOBAL); lap->lsaps = hashbin_new(HB_GLOBAL);
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
lap->cache.valid = FALSE;
#endif
lap->lap_state = LAP_STANDBY; lap->lap_state = LAP_STANDBY;
...@@ -602,7 +601,7 @@ struct lsap_cb *irlmp_dup(struct lsap_cb *orig, void *instance) ...@@ -602,7 +601,7 @@ struct lsap_cb *irlmp_dup(struct lsap_cb *orig, void *instance)
/* Make sure that we invalidate the cache */ /* Make sure that we invalidate the cache */
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP #ifdef CONFIG_IRDA_CACHE_LAST_LSAP
irlmp->cache.valid = FALSE; new->lap->cache.valid = FALSE;
#endif /* CONFIG_IRDA_CACHE_LAST_LSAP */ #endif /* CONFIG_IRDA_CACHE_LAST_LSAP */
return new; return new;
...@@ -692,17 +691,16 @@ void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason, ...@@ -692,17 +691,16 @@ void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason,
return; return;
} }
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
irlmp->cache.valid = FALSE;
#endif
/* /*
* Remove association between this LSAP and the link it used * Remove association between this LSAP and the link it used
*/ */
ASSERT(self->lap != NULL, return;); ASSERT(self->lap != NULL, return;);
ASSERT(self->lap->lsaps != NULL, return;); ASSERT(self->lap->lsaps != NULL, return;);
lsap = hashbin_remove(self->lap->lsaps, (int) self, NULL); lsap = hashbin_remove(self->lap->lsaps, (int) self, NULL);
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
self->lap->cache.valid = FALSE;
#endif
ASSERT(lsap != NULL, return;); ASSERT(lsap != NULL, return;);
ASSERT(lsap == self, return;); ASSERT(lsap == self, return;);
......
...@@ -408,13 +408,14 @@ void irlmp_link_discovery_confirm(struct lap_cb *self, hashbin_t *log) ...@@ -408,13 +408,14 @@ void irlmp_link_discovery_confirm(struct lap_cb *self, hashbin_t *log)
} }
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP #ifdef CONFIG_IRDA_CACHE_LAST_LSAP
inline void irlmp_update_cache(struct lsap_cb *self) static inline void irlmp_update_cache(struct lap_cb *lap,
struct lsap_cb *lsap)
{ {
/* Update cache entry */ /* Update cache entry */
irlmp->cache.dlsap_sel = self->dlsap_sel; lap->cache.dlsap_sel = lsap->dlsap_sel;
irlmp->cache.slsap_sel = self->slsap_sel; lap->cache.slsap_sel = lsap->slsap_sel;
irlmp->cache.lsap = self; lap->cache.lsap = lsap;
irlmp->cache.valid = TRUE; lap->cache.valid = TRUE;
} }
#endif #endif
...@@ -423,6 +424,17 @@ inline void irlmp_update_cache(struct lsap_cb *self) ...@@ -423,6 +424,17 @@ inline void irlmp_update_cache(struct lsap_cb *self)
* *
* Find handle assosiated with destination and source LSAP * Find handle assosiated with destination and source LSAP
* *
* Any IrDA connection (LSAP/TSAP) is uniquely identified by
* 3 parameters, the local lsap, the remote lsap and the remote address.
* We may initiate multiple connections to the same remote service
* (they will have different local lsap), a remote device may initiate
* multiple connections to the same local service (they will have
* different remote lsap), or multiple devices may connect to the same
* service and may use the same remote lsap (and they will have
* different remote address).
* So, where is the remote address ? Each LAP connection is made with
* a single remote device, so imply a specific remote address.
* Jean II
*/ */
static struct lsap_cb *irlmp_find_lsap(struct lap_cb *self, __u8 dlsap_sel, static struct lsap_cb *irlmp_find_lsap(struct lap_cb *self, __u8 dlsap_sel,
__u8 slsap_sel, int status, __u8 slsap_sel, int status,
...@@ -436,11 +448,11 @@ static struct lsap_cb *irlmp_find_lsap(struct lap_cb *self, __u8 dlsap_sel, ...@@ -436,11 +448,11 @@ static struct lsap_cb *irlmp_find_lsap(struct lap_cb *self, __u8 dlsap_sel,
* cache first to avoid the linear search * cache first to avoid the linear search
*/ */
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP #ifdef CONFIG_IRDA_CACHE_LAST_LSAP
if ((irlmp->cache.valid) && if ((self->cache.valid) &&
(irlmp->cache.slsap_sel == slsap_sel) && (self->cache.slsap_sel == slsap_sel) &&
(irlmp->cache.dlsap_sel == dlsap_sel)) (self->cache.dlsap_sel == dlsap_sel))
{ {
return (irlmp->cache.lsap); return (self->cache.lsap);
} }
#endif #endif
lsap = (struct lsap_cb *) hashbin_get_first(queue); lsap = (struct lsap_cb *) hashbin_get_first(queue);
...@@ -458,7 +470,7 @@ static struct lsap_cb *irlmp_find_lsap(struct lap_cb *self, __u8 dlsap_sel, ...@@ -458,7 +470,7 @@ static struct lsap_cb *irlmp_find_lsap(struct lap_cb *self, __u8 dlsap_sel,
lsap->dlsap_sel = dlsap_sel; lsap->dlsap_sel = dlsap_sel;
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP #ifdef CONFIG_IRDA_CACHE_LAST_LSAP
irlmp_update_cache(lsap); irlmp_update_cache(self, lsap);
#endif #endif
return lsap; return lsap;
} }
...@@ -469,7 +481,7 @@ static struct lsap_cb *irlmp_find_lsap(struct lap_cb *self, __u8 dlsap_sel, ...@@ -469,7 +481,7 @@ static struct lsap_cb *irlmp_find_lsap(struct lap_cb *self, __u8 dlsap_sel,
(lsap->dlsap_sel == dlsap_sel)) (lsap->dlsap_sel == dlsap_sel))
{ {
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP #ifdef CONFIG_IRDA_CACHE_LAST_LSAP
irlmp_update_cache(lsap); irlmp_update_cache(self, lsap);
#endif #endif
return lsap; return lsap;
} }
......
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