summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--xhfc/xhfc.c4
-rw-r--r--xhfc/xhfc.h12
-rw-r--r--xhfc/xhfc_st_state.c53
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]);
}