diff options
-rw-r--r-- | xhfc/xhfc.c | 4 | ||||
-rw-r--r-- | xhfc/xhfc.h | 12 | ||||
-rw-r--r-- | xhfc/xhfc_st_state.c | 53 |
3 files changed, 51 insertions, 18 deletions
diff --git a/xhfc/xhfc.c b/xhfc/xhfc.c index fcf9488..cb442ca 100644 --- a/xhfc/xhfc.c +++ b/xhfc/xhfc.c @@ -620,8 +620,8 @@ irqreturn_t xhfc_interrupt(int irq, void *dev_id, struct pt_regs* ptregs) r_su_irq = read_xhfc(xhfc, R_SU_IRQ); for (i = 0; i < ARRAY_SIZE(xhfc->spans); i++) - if (r_su_irq & (1 << i) || 2 == xhfc->ticks /* bootstrap XXX*/) - hfc_handle_state(&xhfc->spans[i]); // BOOM (recursion + GFP_KERNEL allocs there) + if (r_su_irq & (1 << i)/* || 2 == xhfc->ticks /* bootstrap XXX WTF*/) + handle_state_change(&xhfc->spans[i]); hfc_update_st_timers(xhfc); } diff --git a/xhfc/xhfc.h b/xhfc/xhfc.h index 793cf05..0b4fe00 100644 --- a/xhfc/xhfc.h +++ b/xhfc/xhfc.h @@ -85,6 +85,8 @@ enum { XHFC_T1, XHFC_T2, XHFC_T3, XHFC_T4 }; # define MIN(a, b) (((a) < (b))? (a) : (b)) #endif +#define NOT_RUNNING UINT_MAX + enum data_dir { TRANSMIT = 0, RECEIVE = 1 }; #define xhfc_info(x, format, arg...) \ @@ -114,16 +116,14 @@ struct xhfc_span { int port; /* (physical) S/T port number */ int nt; /* 1 if the port is nt, 0 if it's TE */ + /* Got the following from DAHDI */ - int oldstate; - int state, previous_state; - int newalarm; - unsigned long alarmtimer; + u8 state, prev_state; + struct dahdi_chan* sigchan; int sigactive; - unsigned long hfc_timers[4]; /* T1, T2, T3, T4 */ - int hfc_timer_on[4]; /* 1=timer active */ + unsigned int t1, t3, f6_f7_transition; unsigned long non_rx_cnt; }; diff --git a/xhfc/xhfc_st_state.c b/xhfc/xhfc_st_state.c index ca4ade6..3cd1cbf 100644 --- a/xhfc/xhfc_st_state.c +++ b/xhfc/xhfc_st_state.c @@ -12,6 +12,12 @@ according to I.430 "the value depends on the subscriber loop transmission technique. The worst case value is 30s." */ +#define F6_F7_MS 2 /* Wait before signalling the change to F7. + This is done because the XHFC might go to F7 + for a short time during a F6->F3 transition when + receiving INFO0. The wait time should be + "about 1ms", this set to 2 to guarantee that the + wait will be long enough. */ enum te_state { F0, F1, F2, F3, F4, F5, F6, F7, F8 }; enum nt_state { G0, G1, G2, G3 }; @@ -19,6 +25,7 @@ enum nt_state { G0, G1, G2, G3 }; void activate_request(struct xhfc_span* s); void deactivate_request(struct xhfc_span* s); void handle_state_change(struct xhfc_span* s); +void handle_timers(struct xhfc_span* s) static void expiry_T1(struct xhfc_span* s); static void expiry_T3(struct xhfc_span* s); @@ -44,7 +51,7 @@ void handle_state_change(struct xhfc_span* s) if(debug & DEBUG_ST_STATE) //XXX only place where this is used print_state(s); - if(s->prev_state = s->state) { + if(s->prev_state == s->state) { printk(KERN_WARNING DRIVER_NAME ": a state change has been " "reported on port %d but it looks like the " "state has not changed?", s->port + 1); @@ -59,7 +66,7 @@ void handle_state_change(struct xhfc_span* s) static void handle_state_change_nt(struct xhfc_span* s) { - switch (s->state) { + switch (GET_V_SU_STA(s->state)) { case G0: case G1: case G4: @@ -75,18 +82,19 @@ static void handle_state_change_nt(struct xhfc_span* s) * implemented in hardware. */ - /* Start T1 */ ; + s->t1 = T1_TICKS; break; case G3: s->span.alarms = DAHDI_ALARM_NONE; - /* Stop T1 */ + + s->t1 = NOT_RUNNING; break; } } static void handle_state_change_te(struct xhfc_span* s) { - switch(s->state) { + switch(GET_V_SU_STA(s->state)) { case F0: case F1: case F2: @@ -111,7 +119,7 @@ static void handle_state_change_te(struct xhfc_span* s) * hard) is assumed. */ - /* Start T3 */ + s->t3 = T3_TICKS; /* Fall through */ case F5: @@ -119,20 +127,44 @@ static void handle_state_change_te(struct xhfc_span* s) s->span.alarms = DAHDI_ALARM_YELLOW; break; case F7: - s->span.alarms = DAHDI_ALARM_NONE; - /* Stop T3 */ + s->t3 = NOT_RUNNING; + + if ( GET_V_SU_STA(s->prev_state) == F6 && + GET_V_SU_INFO0(s->state)) { + s->f6_f7_transition = F6_F7_MS; + break; + } + + signal_f7_transition(s); + s->f6_f7_transition = NOT_RUNNING; + break; } } +void handle_st_timers(struct xhfc_span* s) +{ + if(s->t1 != NOT_RUNNING && !--t1) expiry_T1(s); + if(s->t3 != NOT_RUNNING && !--t3) expiry_T3(s); + if(s->f6_f7_transition != NOT_RUNNING && !--f6_f7_transition) + signal_f7_transition(s); +} + +static void signal_f7_transition(struct xhfc_span* s) +{ + s->span.alarms = DAHDI_ALARM_NONE; +} + static void expiry_T1(struct xhfc_span* s) { set_st_state(s, G4); + s->t1 = NOT_RUNNING; } static void expiry_T3(struct xhfc_span* s); { set_st_state(s, F3); + s->t3 = NOT_RUNNING; } static void set_st_state(struct xhfc_span* s, int state) @@ -173,11 +205,12 @@ static char *state_descriptions[2][16] = { static void print_state(struct xhfc_span* s) { + int sta = GET_V_SU_STA(s->state); printk(KERN_DEBUG DRIVER_NAME "port %d: %s state %c%d (%s)\n", s->port + 1, (s->nt ? "NT" : "TE"), (s->nt ? 'G' : 'F'), - s->state, - state_description[s->nt][s->state]); + sta, + state_description[s->nt][sta]); } |