2019-05-20 19:08:06 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
2005-04-16 15:20:36 -07:00
/*
* LAPB release 002
*
* This code REQUIRES 2.1 .15 or higher / NET3 .038
*
* History
* LAPB 001 Jonathan Naylor Started Coding
* LAPB 002 Jonathan Naylor New timer architecture .
*/
2012-05-17 10:25:49 +00:00
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2005-04-16 15:20:36 -07:00
# include <linux/errno.h>
# include <linux/types.h>
# include <linux/socket.h>
# include <linux/in.h>
# include <linux/kernel.h>
# include <linux/jiffies.h>
# include <linux/timer.h>
# include <linux/string.h>
# include <linux/sockios.h>
# include <linux/net.h>
# include <linux/inet.h>
# include <linux/skbuff.h>
# include <net/sock.h>
2016-12-24 11:46:01 -08:00
# include <linux/uaccess.h>
2005-04-16 15:20:36 -07:00
# include <linux/fcntl.h>
# include <linux/mm.h>
# include <linux/interrupt.h>
# include <net/lapb.h>
2017-10-16 17:28:46 -07:00
static void lapb_t1timer_expiry ( struct timer_list * ) ;
static void lapb_t2timer_expiry ( struct timer_list * ) ;
2005-04-16 15:20:36 -07:00
void lapb_start_t1timer ( struct lapb_cb * lapb )
{
del_timer ( & lapb - > t1timer ) ;
2017-10-23 09:40:42 +02:00
lapb - > t1timer . function = lapb_t1timer_expiry ;
2005-04-16 15:20:36 -07:00
lapb - > t1timer . expires = jiffies + lapb - > t1 ;
add_timer ( & lapb - > t1timer ) ;
}
void lapb_start_t2timer ( struct lapb_cb * lapb )
{
del_timer ( & lapb - > t2timer ) ;
2017-10-23 09:40:42 +02:00
lapb - > t2timer . function = lapb_t2timer_expiry ;
2005-04-16 15:20:36 -07:00
lapb - > t2timer . expires = jiffies + lapb - > t2 ;
add_timer ( & lapb - > t2timer ) ;
}
void lapb_stop_t1timer ( struct lapb_cb * lapb )
{
del_timer ( & lapb - > t1timer ) ;
}
void lapb_stop_t2timer ( struct lapb_cb * lapb )
{
del_timer ( & lapb - > t2timer ) ;
}
int lapb_t1timer_running ( struct lapb_cb * lapb )
{
return timer_pending ( & lapb - > t1timer ) ;
}
2017-10-16 17:28:46 -07:00
static void lapb_t2timer_expiry ( struct timer_list * t )
2005-04-16 15:20:36 -07:00
{
2017-10-16 17:28:46 -07:00
struct lapb_cb * lapb = from_timer ( lapb , t , t2timer ) ;
2005-04-16 15:20:36 -07:00
if ( lapb - > condition & LAPB_ACK_PENDING_CONDITION ) {
lapb - > condition & = ~ LAPB_ACK_PENDING_CONDITION ;
lapb_timeout_response ( lapb ) ;
}
}
2017-10-16 17:28:46 -07:00
static void lapb_t1timer_expiry ( struct timer_list * t )
2005-04-16 15:20:36 -07:00
{
2017-10-16 17:28:46 -07:00
struct lapb_cb * lapb = from_timer ( lapb , t , t1timer ) ;
2005-04-16 15:20:36 -07:00
switch ( lapb - > state ) {
/*
* If we are a DCE , keep going DM . . DM . . DM
*/
case LAPB_STATE_0 :
if ( lapb - > mode & LAPB_DCE )
lapb_send_control ( lapb , LAPB_DM , LAPB_POLLOFF , LAPB_RESPONSE ) ;
break ;
/*
* Awaiting connection state , send SABM ( E ) , up to N2 times .
*/
2007-02-09 23:24:59 +09:00
case LAPB_STATE_1 :
2005-04-16 15:20:36 -07:00
if ( lapb - > n2count = = lapb - > n2 ) {
lapb_clear_queues ( lapb ) ;
lapb - > state = LAPB_STATE_0 ;
lapb_disconnect_indication ( lapb , LAPB_TIMEDOUT ) ;
2012-05-17 10:25:49 +00:00
lapb_dbg ( 0 , " (%p) S1 -> S0 \n " , lapb - > dev ) ;
2005-04-16 15:20:36 -07:00
return ;
} else {
lapb - > n2count + + ;
if ( lapb - > mode & LAPB_EXTENDED ) {
2012-05-17 10:25:49 +00:00
lapb_dbg ( 1 , " (%p) S1 TX SABME(1) \n " ,
lapb - > dev ) ;
2005-04-16 15:20:36 -07:00
lapb_send_control ( lapb , LAPB_SABME , LAPB_POLLON , LAPB_COMMAND ) ;
} else {
2012-05-17 10:25:49 +00:00
lapb_dbg ( 1 , " (%p) S1 TX SABM(1) \n " ,
lapb - > dev ) ;
2005-04-16 15:20:36 -07:00
lapb_send_control ( lapb , LAPB_SABM , LAPB_POLLON , LAPB_COMMAND ) ;
}
}
break ;
/*
* Awaiting disconnection state , send DISC , up to N2 times .
*/
case LAPB_STATE_2 :
if ( lapb - > n2count = = lapb - > n2 ) {
lapb_clear_queues ( lapb ) ;
lapb - > state = LAPB_STATE_0 ;
lapb_disconnect_confirmation ( lapb , LAPB_TIMEDOUT ) ;
2012-05-17 10:25:49 +00:00
lapb_dbg ( 0 , " (%p) S2 -> S0 \n " , lapb - > dev ) ;
2005-04-16 15:20:36 -07:00
return ;
} else {
lapb - > n2count + + ;
2012-05-17 10:25:49 +00:00
lapb_dbg ( 1 , " (%p) S2 TX DISC(1) \n " , lapb - > dev ) ;
2005-04-16 15:20:36 -07:00
lapb_send_control ( lapb , LAPB_DISC , LAPB_POLLON , LAPB_COMMAND ) ;
}
break ;
/*
* Data transfer state , restransmit I frames , up to N2 times .
*/
case LAPB_STATE_3 :
if ( lapb - > n2count = = lapb - > n2 ) {
lapb_clear_queues ( lapb ) ;
lapb - > state = LAPB_STATE_0 ;
lapb_stop_t2timer ( lapb ) ;
lapb_disconnect_indication ( lapb , LAPB_TIMEDOUT ) ;
2012-05-17 10:25:49 +00:00
lapb_dbg ( 0 , " (%p) S3 -> S0 \n " , lapb - > dev ) ;
2005-04-16 15:20:36 -07:00
return ;
} else {
lapb - > n2count + + ;
lapb_requeue_frames ( lapb ) ;
2013-09-18 12:00:35 +02:00
lapb_kick ( lapb ) ;
2005-04-16 15:20:36 -07:00
}
break ;
/*
* Frame reject state , restransmit FRMR frames , up to N2 times .
*/
case LAPB_STATE_4 :
if ( lapb - > n2count = = lapb - > n2 ) {
lapb_clear_queues ( lapb ) ;
lapb - > state = LAPB_STATE_0 ;
lapb_disconnect_indication ( lapb , LAPB_TIMEDOUT ) ;
2012-05-17 10:25:49 +00:00
lapb_dbg ( 0 , " (%p) S4 -> S0 \n " , lapb - > dev ) ;
2005-04-16 15:20:36 -07:00
return ;
} else {
lapb - > n2count + + ;
lapb_transmit_frmr ( lapb ) ;
}
break ;
}
lapb_start_t1timer ( lapb ) ;
}