@@ -318,13 +318,19 @@ struct gsm_mux {
318
318
struct gsm_control * pending_cmd ;/* Our current pending command */
319
319
spinlock_t control_lock ; /* Protects the pending command */
320
320
321
+ /* Keep-alive */
322
+ struct timer_list ka_timer ; /* Keep-alive response timer */
323
+ u8 ka_num ; /* Keep-alive match pattern */
324
+ signed int ka_retries ; /* Keep-alive retry counter, -1 if not yet initialized */
325
+
321
326
/* Configuration */
322
327
int adaption ; /* 1 or 2 supported */
323
328
u8 ftype ; /* UI or UIH */
324
329
int t1 , t2 ; /* Timers in 1/100th of a sec */
325
330
unsigned int t3 ; /* Power wake-up timer in seconds. */
326
331
int n2 ; /* Retry count */
327
332
u8 k ; /* Window size */
333
+ u32 keep_alive ; /* Control channel keep-alive in 10ms */
328
334
329
335
/* Statistics (not currently exposed) */
330
336
unsigned long bad_fcs ;
@@ -1903,11 +1909,13 @@ static void gsm_control_response(struct gsm_mux *gsm, unsigned int command,
1903
1909
const u8 * data , int clen )
1904
1910
{
1905
1911
struct gsm_control * ctrl ;
1912
+ struct gsm_dlci * dlci ;
1906
1913
unsigned long flags ;
1907
1914
1908
1915
spin_lock_irqsave (& gsm -> control_lock , flags );
1909
1916
1910
1917
ctrl = gsm -> pending_cmd ;
1918
+ dlci = gsm -> dlci [0 ];
1911
1919
command |= 1 ;
1912
1920
/* Does the reply match our command */
1913
1921
if (ctrl != NULL && (command == ctrl -> cmd || command == CMD_NSC )) {
@@ -1922,6 +1930,53 @@ static void gsm_control_response(struct gsm_mux *gsm, unsigned int command,
1922
1930
/* Or did we receive the PN response to our PN command */
1923
1931
} else if (command == CMD_PN ) {
1924
1932
gsm_control_negotiation (gsm , 0 , data , clen );
1933
+ /* Or did we receive the TEST response to our TEST command */
1934
+ } else if (command == CMD_TEST && clen == 1 && * data == gsm -> ka_num ) {
1935
+ gsm -> ka_retries = -1 ; /* trigger new keep-alive message */
1936
+ if (dlci && !dlci -> dead )
1937
+ mod_timer (& gsm -> ka_timer , jiffies + gsm -> keep_alive * HZ / 100 );
1938
+ }
1939
+ spin_unlock_irqrestore (& gsm -> control_lock , flags );
1940
+ }
1941
+
1942
+ /**
1943
+ * gsm_control_keep_alive - check timeout or start keep-alive
1944
+ * @t: timer contained in our gsm object
1945
+ *
1946
+ * Called off the keep-alive timer expiry signaling that our link
1947
+ * partner is not responding anymore. Link will be closed.
1948
+ * This is also called to startup our timer.
1949
+ */
1950
+
1951
+ static void gsm_control_keep_alive (struct timer_list * t )
1952
+ {
1953
+ struct gsm_mux * gsm = from_timer (gsm , t , ka_timer );
1954
+ unsigned long flags ;
1955
+
1956
+ spin_lock_irqsave (& gsm -> control_lock , flags );
1957
+ if (gsm -> ka_num && gsm -> ka_retries == 0 ) {
1958
+ /* Keep-alive expired -> close the link */
1959
+ if (debug & DBG_ERRORS )
1960
+ pr_debug ("%s keep-alive timed out\n" , __func__ );
1961
+ spin_unlock_irqrestore (& gsm -> control_lock , flags );
1962
+ if (gsm -> dlci [0 ])
1963
+ gsm_dlci_begin_close (gsm -> dlci [0 ]);
1964
+ return ;
1965
+ } else if (gsm -> keep_alive && gsm -> dlci [0 ] && !gsm -> dlci [0 ]-> dead ) {
1966
+ if (gsm -> ka_retries > 0 ) {
1967
+ /* T2 expired for keep-alive -> resend */
1968
+ gsm -> ka_retries -- ;
1969
+ } else {
1970
+ /* Start keep-alive timer */
1971
+ gsm -> ka_num ++ ;
1972
+ if (!gsm -> ka_num )
1973
+ gsm -> ka_num ++ ;
1974
+ gsm -> ka_retries = (signed int )gsm -> n2 ;
1975
+ }
1976
+ gsm_control_command (gsm , CMD_TEST , & gsm -> ka_num ,
1977
+ sizeof (gsm -> ka_num ));
1978
+ mod_timer (& gsm -> ka_timer ,
1979
+ jiffies + gsm -> t2 * HZ / 100 );
1925
1980
}
1926
1981
spin_unlock_irqrestore (& gsm -> control_lock , flags );
1927
1982
}
@@ -2067,8 +2122,10 @@ static void gsm_dlci_close(struct gsm_dlci *dlci)
2067
2122
/* Ensure that gsmtty_open() can return. */
2068
2123
tty_port_set_initialized (& dlci -> port , false);
2069
2124
wake_up_interruptible (& dlci -> port .open_wait );
2070
- } else
2125
+ } else {
2126
+ del_timer (& dlci -> gsm -> ka_timer );
2071
2127
dlci -> gsm -> dead = true;
2128
+ }
2072
2129
/* A DLCI 0 close is a MUX termination so we need to kick that
2073
2130
back to userspace somehow */
2074
2131
gsm_dlci_data_kick (dlci );
@@ -2084,6 +2141,8 @@ static void gsm_dlci_close(struct gsm_dlci *dlci)
2084
2141
2085
2142
static void gsm_dlci_open (struct gsm_dlci * dlci )
2086
2143
{
2144
+ struct gsm_mux * gsm = dlci -> gsm ;
2145
+
2087
2146
/* Note that SABM UA .. SABM UA first UA lost can mean that we go
2088
2147
open -> open */
2089
2148
del_timer (& dlci -> t1 );
@@ -2093,8 +2152,15 @@ static void gsm_dlci_open(struct gsm_dlci *dlci)
2093
2152
if (debug & DBG_ERRORS )
2094
2153
pr_debug ("DLCI %d goes open.\n" , dlci -> addr );
2095
2154
/* Send current modem state */
2096
- if (dlci -> addr )
2155
+ if (dlci -> addr ) {
2097
2156
gsm_modem_update (dlci , 0 );
2157
+ } else {
2158
+ /* Start keep-alive control */
2159
+ gsm -> ka_num = 0 ;
2160
+ gsm -> ka_retries = -1 ;
2161
+ mod_timer (& gsm -> ka_timer ,
2162
+ jiffies + gsm -> keep_alive * HZ / 100 );
2163
+ }
2098
2164
gsm_dlci_data_kick (dlci );
2099
2165
wake_up (& dlci -> gsm -> event );
2100
2166
}
@@ -2847,6 +2913,7 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc)
2847
2913
/* Finish outstanding timers, making sure they are done */
2848
2914
del_timer_sync (& gsm -> kick_timer );
2849
2915
del_timer_sync (& gsm -> t2_timer );
2916
+ del_timer_sync (& gsm -> ka_timer );
2850
2917
2851
2918
/* Finish writing to ldisc */
2852
2919
flush_work (& gsm -> tx_work );
@@ -2994,6 +3061,7 @@ static struct gsm_mux *gsm_alloc_mux(void)
2994
3061
INIT_LIST_HEAD (& gsm -> tx_data_list );
2995
3062
timer_setup (& gsm -> kick_timer , gsm_kick_timer , 0 );
2996
3063
timer_setup (& gsm -> t2_timer , gsm_control_retransmit , 0 );
3064
+ timer_setup (& gsm -> ka_timer , gsm_control_keep_alive , 0 );
2997
3065
INIT_WORK (& gsm -> tx_work , gsmld_write_task );
2998
3066
init_waitqueue_head (& gsm -> event );
2999
3067
spin_lock_init (& gsm -> control_lock );
@@ -3010,6 +3078,7 @@ static struct gsm_mux *gsm_alloc_mux(void)
3010
3078
gsm -> mru = 64 ; /* Default to encoding 1 so these should be 64 */
3011
3079
gsm -> mtu = 64 ;
3012
3080
gsm -> dead = true; /* Avoid early tty opens */
3081
+ gsm -> keep_alive = 0 ; /* Disabled */
3013
3082
3014
3083
/* Store the instance to the mux array or abort if no space is
3015
3084
* available.
@@ -3145,6 +3214,29 @@ static int gsm_config(struct gsm_mux *gsm, struct gsm_config *c)
3145
3214
return 0 ;
3146
3215
}
3147
3216
3217
+ static void gsm_copy_config_ext_values (struct gsm_mux * gsm ,
3218
+ struct gsm_config_ext * ce )
3219
+ {
3220
+ memset (ce , 0 , sizeof (* ce ));
3221
+ ce -> keep_alive = gsm -> keep_alive ;
3222
+ }
3223
+
3224
+ static int gsm_config_ext (struct gsm_mux * gsm , struct gsm_config_ext * ce )
3225
+ {
3226
+ unsigned int i ;
3227
+
3228
+ /*
3229
+ * Check that userspace doesn't put stuff in here to prevent breakages
3230
+ * in the future.
3231
+ */
3232
+ for (i = 0 ; i < ARRAY_SIZE (ce -> reserved ); i ++ )
3233
+ if (ce -> reserved [i ])
3234
+ return - EINVAL ;
3235
+
3236
+ gsm -> keep_alive = ce -> keep_alive ;
3237
+ return 0 ;
3238
+ }
3239
+
3148
3240
/**
3149
3241
* gsmld_output - write to link
3150
3242
* @gsm: our mux
@@ -3463,6 +3555,7 @@ static int gsmld_ioctl(struct tty_struct *tty, unsigned int cmd,
3463
3555
unsigned long arg )
3464
3556
{
3465
3557
struct gsm_config c ;
3558
+ struct gsm_config_ext ce ;
3466
3559
struct gsm_mux * gsm = tty -> disc_data ;
3467
3560
unsigned int base ;
3468
3561
@@ -3479,6 +3572,15 @@ static int gsmld_ioctl(struct tty_struct *tty, unsigned int cmd,
3479
3572
case GSMIOC_GETFIRST :
3480
3573
base = mux_num_to_base (gsm );
3481
3574
return put_user (base + 1 , (__u32 __user * )arg );
3575
+ case GSMIOC_GETCONF_EXT :
3576
+ gsm_copy_config_ext_values (gsm , & ce );
3577
+ if (copy_to_user ((void __user * )arg , & ce , sizeof (ce )))
3578
+ return - EFAULT ;
3579
+ return 0 ;
3580
+ case GSMIOC_SETCONF_EXT :
3581
+ if (copy_from_user (& ce , (void __user * )arg , sizeof (ce )))
3582
+ return - EFAULT ;
3583
+ return gsm_config_ext (gsm , & ce );
3482
3584
default :
3483
3585
return n_tty_ioctl_helper (tty , cmd , arg );
3484
3586
}
0 commit comments