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 {
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
*/
......@@ -140,18 +155,14 @@ struct lap_cb {
struct qos_info *qos; /* LAP QoS for this session */
struct timer_list idle_timer;
};
/*
* 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;
#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
};
/*
* Main structure for IrLMP
......@@ -166,9 +177,6 @@ struct irlmp_cb {
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;
hashbin_t *links; /* IrLAP connection table */
......
......@@ -93,9 +93,6 @@ int __init irlmp_init(void)
irlmp->cachelog = hashbin_new(HB_GLOBAL);
irlmp->free_lsap_sel = 0x10; /* Reserved 0x00-0x0f */
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
irlmp->cache.valid = FALSE;
#endif
strcpy(sysctl_devname, "Linux");
/* Do discovery every 3 seconds */
......@@ -208,10 +205,6 @@ static void __irlmp_close_lsap(struct lsap_cb *self)
if (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);
}
......@@ -247,6 +240,9 @@ void irlmp_close_lsap(struct lsap_cb *self)
}
/* Now, remove from the link */
lsap = hashbin_remove(lap->lsaps, (int) self, NULL);
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
lap->cache.valid = FALSE;
#endif
}
self->lap = NULL;
/* 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)
lap->saddr = saddr;
lap->daddr = DEV_ADDR_ANY;
lap->lsaps = hashbin_new(HB_GLOBAL);
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
lap->cache.valid = FALSE;
#endif
lap->lap_state = LAP_STANDBY;
......@@ -602,7 +601,7 @@ struct lsap_cb *irlmp_dup(struct lsap_cb *orig, void *instance)
/* Make sure that we invalidate the cache */
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
irlmp->cache.valid = FALSE;
new->lap->cache.valid = FALSE;
#endif /* CONFIG_IRDA_CACHE_LAST_LSAP */
return new;
......@@ -692,10 +691,6 @@ void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason,
return;
}
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
irlmp->cache.valid = FALSE;
#endif
/*
* Remove association between this LSAP and the link it used
*/
......@@ -703,6 +698,9 @@ void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason,
ASSERT(self->lap->lsaps != NULL, return;);
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 == self, return;);
......
......@@ -408,13 +408,14 @@ void irlmp_link_discovery_confirm(struct lap_cb *self, hashbin_t *log)
}
#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 */
irlmp->cache.dlsap_sel = self->dlsap_sel;
irlmp->cache.slsap_sel = self->slsap_sel;
irlmp->cache.lsap = self;
irlmp->cache.valid = TRUE;
lap->cache.dlsap_sel = lsap->dlsap_sel;
lap->cache.slsap_sel = lsap->slsap_sel;
lap->cache.lsap = lsap;
lap->cache.valid = TRUE;
}
#endif
......@@ -423,6 +424,17 @@ inline void irlmp_update_cache(struct lsap_cb *self)
*
* 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,
__u8 slsap_sel, int status,
......@@ -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
*/
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
if ((irlmp->cache.valid) &&
(irlmp->cache.slsap_sel == slsap_sel) &&
(irlmp->cache.dlsap_sel == dlsap_sel))
if ((self->cache.valid) &&
(self->cache.slsap_sel == slsap_sel) &&
(self->cache.dlsap_sel == dlsap_sel))
{
return (irlmp->cache.lsap);
return (self->cache.lsap);
}
#endif
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,
lsap->dlsap_sel = dlsap_sel;
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
irlmp_update_cache(lsap);
irlmp_update_cache(self, lsap);
#endif
return lsap;
}
......@@ -469,7 +481,7 @@ static struct lsap_cb *irlmp_find_lsap(struct lap_cb *self, __u8 dlsap_sel,
(lsap->dlsap_sel == dlsap_sel))
{
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
irlmp_update_cache(lsap);
irlmp_update_cache(self, lsap);
#endif
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