ir245_sysctl-2.diff :
-------------------
        o [CORRECT] Check min/max boundary on various sysctl
        o [FEATURE] Add min_tx_turn_time sysctl and make it default to 10
          This fixes problem with some broken cellular phones
        o [FEATURE] Simplify retry_count tests
        o [FEATURE] Allow to set the "no activity" event timeout via sysctl
        o [FEATURE] "no activity" event generated each multiple of timeout
          and not only the first time. This allow apps to know is connectivity
          is restored (they don't receive anymore the event).

diff -u -p linux/net/irda/irsysctl.d3.c linux/net/irda/irsysctl.c
--- linux/net/irda/irsysctl.d3.c        Mon Nov 19 17:25:26 2001
+++ linux/net/irda/irsysctl.c   Tue Nov 20 11:25:46 2001
@@ -10,6 +10,7 @@
  * Modified by:   Dag Brattli <[EMAIL PROTECTED]>
  * 
  *     Copyright (c) 1997, 1999 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 2000-2001 Jean Tourrilhes <[EMAIL PROTECTED]>
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -32,24 +33,47 @@
 #include <net/irda/irias_object.h>
 
 #define NET_IRDA 412 /* Random number */
-enum { DISCOVERY=1, DEVNAME, DEBUG, SLOTS, DISCOVERY_TIMEOUT, 
-       SLOT_TIMEOUT, MAX_BAUD_RATE, MAX_INACTIVE_TIME, LAP_KEEPALIVE_TIME, };
+enum { DISCOVERY=1, DEVNAME, DEBUG, FAST_POLL, DISCOVERY_SLOTS,
+       DISCOVERY_TIMEOUT, SLOT_TIMEOUT, MAX_BAUD_RATE, MIN_TX_TURN_TIME,
+       MAX_NOREPLY_TIME, WARN_NOREPLY_TIME, LAP_KEEPALIVE_TIME };
 
 extern int  sysctl_discovery;
 extern int  sysctl_discovery_slots;
 extern int  sysctl_discovery_timeout;
-extern int  sysctl_slot_timeout;
+extern int  sysctl_slot_timeout;       /* Candidate */
 extern int  sysctl_fast_poll_increase;
 int         sysctl_compression = 0;
 extern char sysctl_devname[];
 extern int  sysctl_max_baud_rate;
-extern int  sysctl_max_inactive_time;
+extern int  sysctl_min_tx_turn_time;
+extern int  sysctl_max_noreply_time;
+extern int  sysctl_warn_noreply_time;
 extern int  sysctl_lap_keepalive_time;
 
 #ifdef CONFIG_IRDA_DEBUG
 extern unsigned int irda_debug;
 #endif
 
+/* this is needed for the proc_dointvec_minmax - Jean II */
+static int max_discovery_slots = 16;           /* ??? */
+static int min_discovery_slots = 1;
+/* IrLAP 6.13.2 says 25ms to 10+70ms - allow higher since some devices
+ * seems to require it. (from Dag's comment) */
+static int max_slot_timeout = 160;
+static int min_slot_timeout = 20;
+static int max_max_baud_rate = 16000000;       /* See qos.c - IrLAP spec */
+static int min_max_baud_rate = 2400;
+static int max_min_tx_turn_time = 10000;       /* See qos.c - IrLAP spec */
+static int min_min_tx_turn_time = 0;
+static int max_max_noreply_time = 40;          /* See qos.c - IrLAP spec */
+static int min_max_noreply_time = 3;
+static int max_warn_noreply_time = 3;          /* 3s == standard */
+static int min_warn_noreply_time = 1;          /* 1s == min WD_TIMER */
+static int max_lap_keepalive_time = 10000;     /* 10s */
+static int min_lap_keepalive_time = 100;       /* 100us */
+/* For other sysctl, I've no idea of the range. Maybe Dag could help
+ * us on that - Jean II */
+
 static int do_devname(ctl_table *table, int write, struct file *filp,
                      void *buffer, size_t *lenp)
 {
@@ -77,21 +101,32 @@ static ctl_table irda_table[] = {
          sizeof(int), 0644, NULL, &proc_dointvec },
 #endif
 #ifdef CONFIG_IRDA_FAST_RR
-        { SLOTS, "fast_poll_increase", &sysctl_fast_poll_increase,
+        { FAST_POLL, "fast_poll_increase", &sysctl_fast_poll_increase,
          sizeof(int), 0644, NULL, &proc_dointvec },
 #endif
-       { SLOTS, "discovery_slots", &sysctl_discovery_slots,
-         sizeof(int), 0644, NULL, &proc_dointvec },
+       { DISCOVERY_SLOTS, "discovery_slots", &sysctl_discovery_slots,
+         sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
+         NULL, &min_discovery_slots, &max_discovery_slots },
        { DISCOVERY_TIMEOUT, "discovery_timeout", &sysctl_discovery_timeout,
          sizeof(int), 0644, NULL, &proc_dointvec },
        { SLOT_TIMEOUT, "slot_timeout", &sysctl_slot_timeout,
-         sizeof(int), 0644, NULL, &proc_dointvec },
+         sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
+         NULL, &min_slot_timeout, &max_slot_timeout },
        { MAX_BAUD_RATE, "max_baud_rate", &sysctl_max_baud_rate,
-         sizeof(int), 0644, NULL, &proc_dointvec },
-       { MAX_INACTIVE_TIME, "max_inactive_time", &sysctl_max_inactive_time,
-         sizeof(int), 0644, NULL, &proc_dointvec },
+         sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
+         NULL, &min_max_baud_rate, &max_max_baud_rate },
+       { MIN_TX_TURN_TIME, "min_tx_turn_time", &sysctl_min_tx_turn_time,
+         sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
+         NULL, &min_min_tx_turn_time, &max_min_tx_turn_time },
+       { MAX_NOREPLY_TIME, "max_noreply_time", &sysctl_max_noreply_time,
+         sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
+         NULL, &min_max_noreply_time, &max_max_noreply_time },
+       { WARN_NOREPLY_TIME, "warn_noreply_time", &sysctl_warn_noreply_time,
+         sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
+         NULL, &min_warn_noreply_time, &max_warn_noreply_time },
        { LAP_KEEPALIVE_TIME, "lap_keepalive_time", &sysctl_lap_keepalive_time,
-         sizeof(int), 0644, NULL, &proc_dointvec },
+         sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
+         NULL, &min_lap_keepalive_time, &max_lap_keepalive_time },
        { 0 }
 };
 
diff -u -p linux/net/irda/qos.d3.c linux/net/irda/qos.c
--- linux/net/irda/qos.d3.c     Mon Nov 19 17:28:39 2001
+++ linux/net/irda/qos.c        Mon Nov 19 19:14:50 2001
@@ -51,7 +51,16 @@ int sysctl_max_baud_rate = 16000000;
  * may want to keep the LAP alive longuer or shorter in case of link failure.
  * Remember that the threshold time (early warning) is fixed to 3s...
  */
-int sysctl_max_inactive_time = 12;
+int sysctl_max_noreply_time = 12;
+/*
+ * Minimum turn time to be applied before transmitting to the peer.
+ * Nonzero values (usec) are used as lower limit to the per-connection
+ * mtt value which was announced by the other end during negotiation.
+ * Might be helpful if the peer device provides too short mtt.
+ * Default is 10 which means using the unmodified value given by the peer
+ * except if it's 0 (0 is likely a bug in the other stack).
+ */
+unsigned sysctl_min_tx_turn_time = 10;
 
 static int irlap_param_baud_rate(void *instance, irda_param_t *param, int get);
 static int irlap_param_link_disconnect(void *instance, irda_param_t *parm, 
@@ -184,7 +193,6 @@ static inline __u32 byte_value(__u8 byte
  * Function value_lower_bits (value, array)
  *
  *    Returns a bit field marking all possibility lower than value.
- *    We may need a "value_higher_bits" in the future...
  */
 static inline int value_lower_bits(__u32 value, __u32 *array, int size, __u16 *field)
 {
@@ -207,6 +215,33 @@ static inline int value_lower_bits(__u32
        return i;
 }
 
+/*
+ * Function value_highest_bit (value, array)
+ *
+ *    Returns a bit field marking the highest possibility lower than value.
+ */
+static inline int value_highest_bit(__u32 value, __u32 *array, int size, __u16 *field)
+{
+       int     i;
+       __u16   mask = 0x1;
+       __u16   result = 0x0;
+
+       for (i=0; i < size; i++) {
+               /* Finished ? */
+               if (array[i] <= value)
+                       break;
+               /* Shift mask */
+               mask <<= 1;
+       }
+       /* Set the current value to the bit field */
+       result |= mask;
+       /* Send back a valid index */
+       if(i >= size)
+         i = size - 1; /* Last item */
+       *field = result;
+       return i;
+}
+
 /* -------------------------- MAIN CALLS -------------------------- */
 
 /*
@@ -254,9 +289,9 @@ void irda_init_max_qos_capabilies(struct
        sysctl_max_baud_rate = index_value(i, baud_rates);
 
        /* Set configured max disc time */
-       i = value_lower_bits(sysctl_max_inactive_time, link_disc_times, 8,
+       i = value_lower_bits(sysctl_max_noreply_time, link_disc_times, 8,
                             &qos->link_disc_time.bits);
-       sysctl_max_inactive_time = index_value(i, link_disc_times);
+       sysctl_max_noreply_time = index_value(i, link_disc_times);
 
        /* LSB is first byte, MSB is second byte */
        qos->baud_rate.bits    &= 0x03ff;
@@ -281,6 +316,19 @@ void irlap_adjust_qos_settings(struct qo
        int index;
 
        IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+       /*
+        * Make sure the mintt is sensible.
+        */
+       if (sysctl_min_tx_turn_time > qos->min_turn_time.value) {
+               int i;
+
+               /* We don't really need bits, but easier this way */
+               i = value_highest_bit(sysctl_min_tx_turn_time, min_turn_times,
+                                     8, &qos->min_turn_time.bits);
+               sysctl_min_tx_turn_time = index_value(i, min_turn_times);
+               qos->min_turn_time.value = sysctl_min_tx_turn_time;
+       }
 
        /* 
         * Not allowed to use a max turn time less than 500 ms if the baudrate
diff -u -p linux/net/irda/irlap.d3.c linux/net/irda/irlap.c
--- linux/net/irda/irlap.d3.c   Mon Nov 19 17:24:34 2001
+++ linux/net/irda/irlap.c      Tue Nov 20 11:26:54 2001
@@ -51,6 +51,11 @@
 hashbin_t *irlap = NULL;
 int sysctl_slot_timeout = SLOT_TIMEOUT * 1000 / HZ;
 
+/* This is the delay of missed pf period before generating an event
+ * to the application. The spec mandate 3 seconds, but in some cases
+ * it's way too long. - Jean II */
+int sysctl_warn_noreply_time = 3;
+
 extern void irlap_queue_xmit(struct irlap_cb *self, struct sk_buff *skb);
 static void __irlap_close(struct irlap_cb *self);
 
@@ -527,22 +532,7 @@ void irlap_discovery_request(struct irla
        self->discovery_cmd = discovery;
        info.discovery = discovery;
        
-       /* Check if the slot timeout is within limits */
-       if (sysctl_slot_timeout < 20) {
-               ERROR(__FUNCTION__ 
-                     "(), to low value for slot timeout!\n");
-               sysctl_slot_timeout = 20;
-       }
-       /* 
-        * Highest value is actually 8, but we allow higher since
-        * some devices seems to require it.
-        */
-       if (sysctl_slot_timeout > 160) {
-               ERROR(__FUNCTION__ 
-                     "(), to high value for slot timeout!\n");
-               sysctl_slot_timeout = 160;
-       }
-       
+       /* sysctl_slot_timeout bounds are checked in irsysctl.c - Jean II */
        self->slot_timeout = sysctl_slot_timeout * HZ / 1000;
        
        irlap_do_event(self, DISCOVERY_REQUEST, NULL, &info);
@@ -931,9 +921,6 @@ void irlap_init_qos_capabilities(struct 
        /* Set data size */
        /*self->qos_rx.data_size.bits &= 0x03;*/
 
-       /* Set disconnect time -> done properly in qos.c */
-       /*self->qos_rx.link_disc_time.bits &= 0x07;*/
-
        irda_qos_bits_to_value(&self->qos_rx);
 }
 
@@ -1070,8 +1057,11 @@ void irlap_apply_connection_parameters(s
        /*
         *  Set N1 to 0 if Link Disconnect/Threshold Time = 3 and set it to 
         *  3 seconds otherwise. See page 71 in IrLAP for more details.
+        *  Actually, it's not always 3 seconds, as we allow to set
+        *  it via sysctl... Max maxtt is 500ms, and N1 need to be multiple
+        *  of 2, so 1 second is minimum we can allow. - Jean II
         */
-       if (self->qos_tx.link_disc_time.value == 3)
+       if (self->qos_tx.link_disc_time.value == sysctl_warn_noreply_time)
                /* 
                 * If we set N1 to 0, it will trigger immediately, which is
                 * not what we want. What we really want is to disable it,
@@ -1079,7 +1069,8 @@ void irlap_apply_connection_parameters(s
                 */
                self->N1 = -2; /* Disable - Need to be multiple of 2*/
        else
-               self->N1 = 3000 / self->qos_rx.max_turn_time.value;
+               self->N1 = sysctl_warn_noreply_time * 1000 /
+                 self->qos_rx.max_turn_time.value;
        
        IRDA_DEBUG(4, "Setting N1 = %d\n", self->N1);
        
diff -u -p linux/net/irda/irlap_event.d3.c linux/net/irda/irlap_event.c
--- linux/net/irda/irlap_event.d3.c     Mon Nov 19 17:11:42 2001
+++ linux/net/irda/irlap_event.c        Tue Nov 27 16:35:15 2001
@@ -1405,30 +1405,29 @@ static int irlap_state_nrm_p(struct irla
                }
                self->add_wait = FALSE;
 
-               if ((self->retry_count < self->N2) && 
-                   (self->retry_count != self->N1)) {
-                       
+               /* N2 is the disconnect timer. Until we reach it, we retry */
+               if (self->retry_count < self->N2) {
+                       /* Retry sending the pf bit to the secondary */
                        irlap_wait_min_turn_around(self, &self->qos_tx);
                        irlap_send_rr_frame(self, CMD_FRAME);
                        
                        irlap_start_final_timer(self, self->final_timeout);
                        self->retry_count++;
-
                        IRDA_DEBUG(4, "irlap_state_nrm_p: FINAL_TIMER_EXPIRED:"
                                   " retry_count=%d\n", self->retry_count);
-                       /* Keep state */
-               } else if (self->retry_count == self->N1) {
-                       irlap_status_indication(self, STATUS_NO_ACTIVITY);
-                       irlap_wait_min_turn_around(self, &self->qos_tx);
-                       irlap_send_rr_frame(self, CMD_FRAME);
-                       
-                       irlap_start_final_timer(self, self->final_timeout);
-                       self->retry_count++;
 
-                       IRDA_DEBUG(4, "retry count = N1; retry_count=%d\n", 
-                                  self->retry_count);
+                       /* Early warning event. I'm using a pretty liberal
+                        * interpretation of the spec and generate an event
+                        * every time the timer is multiple of N1 (and not
+                        * only the first time). This allow application
+                        * to know precisely if connectivity restart...
+                        * Jean II */
+                       if((self->retry_count % self->N1) == 0)
+                               irlap_status_indication(self,
+                                                       STATUS_NO_ACTIVITY);
+
                        /* Keep state */
-               } else if (self->retry_count >= self->N2) {
+               } else {
                        irlap_apply_default_connection_parameters(self);
 
                        /* Always switch state before calling upper layers */
@@ -1991,6 +1990,7 @@ static int irlap_state_nrm_s(struct irla
                 *  Wait until retry_count * n matches negotiated threshold/
                 *  disconnect time (note 2 in IrLAP p. 82)
                 *
+                * Similar to irlap_state_nrm_p() -> FINAL_TIMER_EXPIRED
                 * Note : self->wd_timeout = (self->final_timeout * 2),
                 *   which explain why we use (self->N2 / 2) here !!!
                 * Jean II
@@ -1998,16 +1998,15 @@ static int irlap_state_nrm_s(struct irla
                IRDA_DEBUG(1, __FUNCTION__ "(), retry_count = %d\n", 
                           self->retry_count);
 
-               if ((self->retry_count <  (self->N2 / 2))  && 
-                   (self->retry_count != (self->N1 / 2))) {
-                       
+               if (self->retry_count < (self->N2 / 2)) {
+                       /* No retry, just wait for primary */
                        irlap_start_wd_timer(self, self->wd_timeout);
                        self->retry_count++;
-               } else if (self->retry_count == (self->N1 / 2)) {
-                       irlap_status_indication(self, STATUS_NO_ACTIVITY);
-                       irlap_start_wd_timer(self, self->wd_timeout);
-                       self->retry_count++;
-               } else if (self->retry_count >= (self->N2 / 2)) {
+
+                       if((self->retry_count % (self->N1 / 2)) == 0)
+                               irlap_status_indication(self,
+                                                       STATUS_NO_ACTIVITY);
+               } else {
                        irlap_apply_default_connection_parameters(self);
                        
                        /* Always switch state before calling upper layers */
diff -u -p linux/net/irda/irlmp_event.d3.c linux/net/irda/irlmp_event.c
--- linux/net/irda/irlmp_event.d3.c     Tue Nov 20 11:22:32 2001
+++ linux/net/irda/irlmp_event.c        Tue Nov 20 11:25:14 2001
@@ -407,12 +407,7 @@ static void irlmp_state_active(struct la
                 *  removed later and moved to the list of unconnected LSAPs
                 */
                if (HASHBIN_GET_SIZE(self->lsaps) > 0) {
-                       /* Make sure the timer has sensible value (the user
-                        * may have set it) - Jean II */
-                       if(sysctl_lap_keepalive_time < 100)     /* 100ms */
-                               sysctl_lap_keepalive_time = 100;
-                       if(sysctl_lap_keepalive_time > 10000)   /* 10s */
-                               sysctl_lap_keepalive_time = 10000;
+                       /* Timer value is checked in irsysctl - Jean II */
                        irlmp_start_idle_timer(self, sysctl_lap_keepalive_time * HZ / 
1000);
                } else {
                        /* No more connections, so close IrLAP */
_______________________________________________
Linux-IrDA mailing list  -  [EMAIL PROTECTED]
http://www.pasta.cs.UiT.No/mailman/listinfo/linux-irda

Reply via email to