Commit 2863ffcb authored by Jean Tourrilhes's avatar Jean Tourrilhes Committed by David S. Miller

[IRDA]: Adaptive discovery query timer

o [FEATURE] Adapt to the rate of the peer discovery (passive discovery)
o [FEATURE] Add extra safety margin in passive discovery
Allow to interoperate properly with device performing slow discovery
Signed-off-by: default avatarJean Tourrilhes <jt@hpl.hp.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent dbc5a5f9
......@@ -58,14 +58,16 @@ struct lap_cb;
* Slot timer must never exceed 85 ms, and must always be at least 25 ms,
* suggested to 75-85 msec by IrDA lite. This doesn't work with a lot of
* devices, and other stackes uses a lot more, so it's best we do it as well
* (Note : this is the default value and sysctl overides it - Jean II)
*/
#define SLOT_TIMEOUT (90*HZ/1000)
/*
* We set the query timeout to 100 ms and then expect the value to be
* multiplied with the number of slots to product the actual timeout value
* The latest discovery frame (XID) is longer due to the extra discovery
* information (hints, device name...). This is its extra length.
* We use that when setting the query timeout. Jean II
*/
#define QUERY_TIMEOUT (HZ/10)
#define XIDEXTRA_TIMEOUT (34*HZ/1000) /* 34 msec */
#define WATCHDOG_TIMEOUT (20*HZ) /* 20 sec */
......@@ -85,7 +87,7 @@ static inline void irda_start_timer(struct timer_list *ptimer, int timeout,
void irlap_start_slot_timer(struct irlap_cb *self, int timeout);
void irlap_start_query_timer(struct irlap_cb *self, int timeout);
void irlap_start_query_timer(struct irlap_cb *self, int S, int s);
void irlap_start_final_timer(struct irlap_cb *self, int timeout);
void irlap_start_wd_timer(struct irlap_cb *self, int timeout);
void irlap_start_backoff_timer(struct irlap_cb *self, int timeout);
......
......@@ -433,10 +433,11 @@ static int irlap_state_ndm(struct irlap_cb *self, IRLAP_EVENT event,
self->frame_sent = FALSE;
/*
* Remember to multiply the query timeout value with
* the number of slots used
* Go to reply state until end of discovery to
* inhibit our own transmissions. Set the timer
* to not stay forever there... Jean II
*/
irlap_start_query_timer(self, QUERY_TIMEOUT*info->S);
irlap_start_query_timer(self, info->S, info->s);
irlap_next_state(self, LAP_REPLY);
} else {
/* This is the final slot. How is it possible ?
......@@ -452,6 +453,9 @@ static int irlap_state_ndm(struct irlap_cb *self, IRLAP_EVENT event,
* Not much. It's too late to answer those discovery frames,
* so we just pass the info to IrLMP who will put it in the
* log (and post an event).
* Another cause would be devices that do discovery much
* slower than us, however the latest fixes should minimise
* those cases...
* Jean II
*/
IRDA_DEBUG(1, "%s(), Receiving final discovery request, missed the discovery slots :-(\n", __FUNCTION__);
......@@ -691,7 +695,7 @@ static int irlap_state_reply(struct irlap_cb *self, IRLAP_EVENT event,
switch (event) {
case QUERY_TIMER_EXPIRED:
IRDA_DEBUG(2, "%s(), QUERY_TIMER_EXPIRED <%ld>\n",
IRDA_DEBUG(0, "%s(), QUERY_TIMER_EXPIRED <%ld>\n",
__FUNCTION__, jiffies);
irlap_next_state(self, LAP_NDM);
break;
......@@ -707,16 +711,26 @@ static int irlap_state_reply(struct irlap_cb *self, IRLAP_EVENT event,
irlap_next_state(self, LAP_NDM);
irlap_discovery_indication(self, info->discovery);
} else if ((info->s >= self->slot) && (!self->frame_sent)) {
discovery_rsp = irlmp_get_discovery_response();
discovery_rsp->data.daddr = info->daddr;
} else {
/* If it's our slot, send our reply */
if ((info->s >= self->slot) && (!self->frame_sent)) {
discovery_rsp = irlmp_get_discovery_response();
discovery_rsp->data.daddr = info->daddr;
irlap_send_discovery_xid_frame(self, info->S,
self->slot, FALSE,
discovery_rsp);
irlap_send_discovery_xid_frame(self, info->S,
self->slot,
FALSE,
discovery_rsp);
self->frame_sent = TRUE;
irlap_next_state(self, LAP_REPLY);
self->frame_sent = TRUE;
}
/* Readjust our timer to accomodate devices
* doing faster or slower discovery than us...
* Jean II */
irlap_start_query_timer(self, info->S, info->s);
/* Keep state */
//irlap_next_state(self, LAP_REPLY);
}
break;
default:
......
......@@ -34,6 +34,8 @@
#include <net/irda/irlap.h>
#include <net/irda/irlmp.h>
extern int sysctl_slot_timeout;
static void irlap_slot_timer_expired(void* data);
static void irlap_query_timer_expired(void* data);
static void irlap_final_timer_expired(void* data);
......@@ -47,8 +49,25 @@ void irlap_start_slot_timer(struct irlap_cb *self, int timeout)
irlap_slot_timer_expired);
}
void irlap_start_query_timer(struct irlap_cb *self, int timeout)
void irlap_start_query_timer(struct irlap_cb *self, int S, int s)
{
int timeout;
/* Calculate when the peer discovery should end. Normally, we
* get the end-of-discovery frame, so this is just in case
* we miss it.
* Basically, we multiply the number of remaining slots by our
* slot time, plus add some extra time to properly receive the last
* discovery packet (which is longer due to extra discovery info),
* to avoid messing with for incomming connections requests and
* to accomodate devices that perform discovery slower than us.
* Jean II */
timeout = ((sysctl_slot_timeout * HZ / 1000) * (S - s)
+ XIDEXTRA_TIMEOUT + SMALLBUSY_TIMEOUT);
/* Set or re-set the timer. We reset the timer for each received
* discovery query, which allow us to automatically adjust to
* the speed of the peer discovery (faster or slower). Jean II */
irda_start_timer( &self->query_timer, timeout, (void *) self,
irlap_query_timer_expired);
}
......
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