From 61cc6e4ac8324b1e38a5c3bb543d1d262552bb78 Mon Sep 17 00:00:00 2001 From: tzafrir Date: Fri, 1 Dec 2006 05:22:55 +0000 Subject: Merging from 1.2: * Removing -DSOFT_RING: unused, useless code. * Register init scripts are not as noisy by default. * Register init scripts read configuration from a standard location. * Fixed a FXO spinlock race. (Log was lost on previos merge) git-svn-id: http://svn.digium.com/svn/zaptel/trunk@1680 5390a7c7-147a-4af0-8ec9-7488f05a26cb --- xpp/Makefile | 2 +- xpp/README.Astribank | 28 +++++++++++++ xpp/calibrate_slics | 42 ++++++++++++------- xpp/card_fxo.c | 115 ++++++--------------------------------------------- xpp/card_fxs.c | 6 +-- xpp/card_global.c | 41 +++++++++++------- xpp/init_card_3_23 | 19 ++++++--- xpp/init_card_4_23 | 22 +++++++--- xpp/utils/Makefile | 6 +-- xpp/xbus-core.c | 32 ++++++++++---- 10 files changed, 153 insertions(+), 160 deletions(-) diff --git a/xpp/Makefile b/xpp/Makefile index bef84cf..e0a9152 100644 --- a/xpp/Makefile +++ b/xpp/Makefile @@ -1,4 +1,4 @@ -EXTRA_CFLAGS = -g3 -I$(SUBDIRS) -DDEBUG -DPOLL_DIGITAL_INPUTS -DWITH_ECHO_SUPPRESSION # -DSOFT_RING +EXTRA_CFLAGS = -g3 -I$(SUBDIRS) -DDEBUG -DPOLL_DIGITAL_INPUTS -DWITH_ECHO_SUPPRESSION obj-m += xpp.o xpd_fxs.o xpd_fxo.o diff --git a/xpp/README.Astribank b/xpp/README.Astribank index e45bde9..f0f93b5 100644 --- a/xpp/README.Astribank +++ b/xpp/README.Astribank @@ -329,6 +329,34 @@ file. (There are a bunch of other status files under /proc/xpp/ ) +Zaptel Init Configuration File +"""""""""""""""""""""""""""""" +The zaptel init.d script, genzaptelconf and the XPD init scripts source +the file /etc/init.d/zaptel (on Debian) or /etc/sysconfig/zaptel (on +RedHats). A number of useful values for there: + +############################### +# Lines beginning with '#' are considered comments and ignored. + +# A two-letter country code. genzaptelconf uses it to better guess +# the configuration it generates. E.g: the signalling of E1 spans, and +# a few other country-specific settings. +lc_country=us + +# See genzaptelconf(8) and the script itself for a longer list of +# variables. + +# Equivalent to the parameter opermode to the module wctdm: country-specific +# settings to the FXO lines. For a complete list of possible values, see +# /usr/share/zaptel/init_fxo_mode . +#opermode=FCC +#opermode=FRANCE + +# If you feel like flooding your logs with debug output of the calibration +# process: +#DEBUG_CALIBRATION=1 +############################### + Useful Module Parameters: """""""""""""""""""""""" zap_autoreg: (xpp) diff --git a/xpp/calibrate_slics b/xpp/calibrate_slics index 72ca202..c639832 100755 --- a/xpp/calibrate_slics +++ b/xpp/calibrate_slics @@ -15,11 +15,21 @@ if ( ! -f $SlicsFile ) { exit 1 } +my $debug = 0; +# set DEBUG_CALIBRATION in /etc/default/zaptel or similar +if (exists $ENV{DEBUG_CALIBRATION}) { + $debug = 1; +} + sub logger($) { print STDERR "LOG: @_\n"; system("logger @_"); } +sub debug($) { + logger(@_) if ($debug); +} + sub write_to_slic_file($) { my $write_str = shift; @@ -45,11 +55,11 @@ sub read_reg($$$) { my @reply = (); while(){ #if (/^ /) { - # print STDERR "answer line: $_"; + # debug "answer line: $_"; #} if (/^ \d*\s+[RW][DIS]\s+[[:xdigit:]]+\s+([[:xdigit:]]+)\s+([[:xdigit:]]+)/){ @reply = (hex($1), hex($2)); - #print STDERR "got [$reply]\n"; + #debug "got [$reply]\n"; last; } } @@ -83,7 +93,7 @@ sub log_calib_params() { for my $slic (@SlicNums) { $line .= " ".read_reg($slic, $i, 'D'); } - logger($line); + debug($line); } } @@ -209,17 +219,17 @@ sub manual_calibrate_loop($$) { # wait until all slics have finished calibration, or for timeout while ($calibration_in_progress) { $calibration_in_progress = 0; # until proven otherwise - print STDERR "ManualCalib:: "; + my $debug_calib_str = "ManualCalib:: "; for my $slic(@SlicNums) { my $value = read_reg($slic, $read_reg, 'D'); - print STDERR " [$slic_counters[$slic]:$value]"; + $debug_calib_str .= " [$slic_counters[$slic]:$value]"; if ($value != 0 && $slic_counters[$slic] >= 0) { $calibration_in_progress = 1; $slic_counters[$slic]--; write_reg($slic,$write_reg,'D',$slic_counters[$slic]); } } - print STDERR "\n"; + debug($debug_calib_str); # TODO: unnecessary sleep in the last round: sleep $ManualCalibrationSleepTime; } @@ -247,20 +257,20 @@ sub auto_calibrate($$) { my $end_time=time() + 2; my $timeout=0; CALIB_LOOP: for my $slic (@SlicNums) { - logger("checking slic $slic"); + debug("checking slic $slic"); while(1) { if ((read_reg($slic, 60, 'D')) == 0) { # move to next register - logger("slic $slic calibrated"); + debug("slic $slic calibrated"); last; } my $time=time(); if ( $time > $end_time) { $timeout=1; - logger("Exiting on timeout: $end_time < $time."); + debug("Exiting on timeout: $end_time < $time."); last CALIB_LOOP; } - logger("auto_calibrate not done yet: slic #$slic\n"); + debug("auto_calibrate not done yet: slic #$slic\n"); sleep(0.1); } } @@ -277,17 +287,17 @@ sub auto_calibrate($$) { #read_reg($slic, 0x0B, 'D'): 0x33 #read_reg($slic, 0x40, 'D'): 0x00 (?) -print STDERR "starting\n"; +debug "starting\n"; init_indirect_registers(); -print STDERR "after init_indirect_registers\n"; +debug "after init_indirect_registers\n"; init_early_direct_regs(); -print STDERR "after init_early_direct_regs\n"; +debug "after init_early_direct_regs\n"; auto_calibrate(0x47, 0x1E); -print STDERR "after auto_calibrate\n"; +debug "after auto_calibrate\n"; manual_calibrate(); -print STDERR "after manul_calibrate\n"; +debug "after manul_calibrate\n"; auto_calibrate(0x40, 0x01); -print STDERR "after auto_calibrate 2\n"; +debug "after auto_calibrate 2\n"; diff --git a/xpp/card_fxo.c b/xpp/card_fxo.c index 7672db3..d3e7637 100644 --- a/xpp/card_fxo.c +++ b/xpp/card_fxo.c @@ -80,11 +80,6 @@ static int handle_register_command(xpd_t *xpd, char *cmdline); #define PROC_REGISTER_FNAME "slics" #define PROC_FXO_INFO_FNAME "fxo_info" -#ifdef SOFT_RING -#define POLL_RING_INTERVAL 2 -#define RING_THRESHOLD 3 -#define NORING_THRESHOLD 10 -#endif #define DAA_RING_REGISTER 0x05 struct FXO_priv_data { @@ -96,15 +91,6 @@ struct FXO_priv_data { xpp_line_t ledstate[NUM_LEDS]; /* 0 - OFF, 1 - ON */ xpp_line_t ledcontrol[NUM_LEDS]; /* 0 - OFF, 1 - ON */ int blinking[NUM_LEDS][CHANNELS_PERXPD]; -#ifdef SOFT_RING - ushort ring_thresh[CHANNELS_PERXPD]; - ushort noring_thresh[CHANNELS_PERXPD]; - /* ring_sig is set when Reg5, bit 2 (Ring Detect) is set. - * While ring_sig=1 we check R5 bit 20H and 40H for ringing. - * When it drops to 0 that's the end of the ring sequence and - * we clear the ring detection variables */ - ushort ring_sig[CHANNELS_PERXPD]; -#endif }; /*---------------- FXO: Static functions ----------------------------------*/ @@ -187,7 +173,7 @@ static void handle_fxo_leds(xpd_t *xpd) spin_unlock_irqrestore(&xpd->lock, flags); } -static void mark_ring(xpd_t *xpd, lineno_t pos, bool on) +static void mark_ring(xpd_t *xpd, lineno_t pos, bool on, bool update_zap) { struct FXO_priv_data *priv; @@ -197,13 +183,15 @@ static void mark_ring(xpd_t *xpd, lineno_t pos, bool on) DBG("%s/%s/%d: START\n", xpd->xbus->busname, xpd->xpdname, pos); xpd->ringing[pos] = 1; MARK_BLINK(priv, pos, LED_GREEN, LED_BLINK); - update_zap_ring(xpd, pos, 1); + if(update_zap) + update_zap_ring(xpd, pos, on); } else if(!on && xpd->ringing[pos]) { DBG("%s/%s/%d: STOP\n", xpd->xbus->busname, xpd->xpdname, pos); xpd->ringing[pos] = 0; if(IS_BLINKING(priv, pos, LED_GREEN)) MARK_BLINK(priv, pos, LED_GREEN, 0); - update_zap_ring(xpd, pos, 0); + if(update_zap) + update_zap_ring(xpd, pos, on); } } @@ -224,14 +212,11 @@ static int do_sethook(xpd_t *xpd, int pos, bool to_offhook) NOTICE("%s/%s/%d: WARNING: called while battery is off\n", xbus->busname, xpd->xpdname, pos); } spin_lock_irqsave(&xpd->lock, flags); - mark_ring(xpd, pos, 0); // No more rings + mark_ring(xpd, pos, 0, 0); // No more rings value = (to_offhook) ? 0x09 : 0x08; /* Bit 3 is for CID */ DBG("%s/%s/%d: SETHOOK: value=0x%02X %s\n", xbus->busname, xpd->xpdname, pos, value, (to_offhook)?"OFFHOOK":"ONHOOK"); MARK_LED(xpd, pos, LED_GREEN, (to_offhook)?LED_ON:LED_OFF); ret = DAA_DIRECT_REQUEST(xbus, xpd, pos, DAA_WRITE, DAA_RING_REGISTER, value); -#ifdef SOFT_RING - priv->ring_sig[pos] = 0; -#endif if(to_offhook) { BIT_SET(xpd->offhook, pos); } else { @@ -362,7 +347,7 @@ static int FXO_card_zaptel_preregistration(xpd_t *xpd, bool on) MARK_LED(xpd, ALL_LINES, LED_GREEN, LED_OFF); for_each_line(xpd, i) { MARK_LED(xpd, i, LED_GREEN, LED_ON); - mdelay(50); + msleep(50); } return 0; } @@ -381,7 +366,7 @@ static int FXO_card_zaptel_postregistration(xpd_t *xpd, bool on) DBG("%s/%s (%d)\n", xbus->busname, xpd->xpdname, on); for_each_line(xpd, i) { MARK_LED(xpd, i, LED_GREEN, LED_OFF); - mdelay(50); + msleep(50); } return 0; } @@ -420,21 +405,6 @@ static void poll_battery(xbus_t *xbus, xpd_t *xpd) } } -#ifdef SOFT_RING -static void poll_ring(xbus_t *xbus, xpd_t *xpd) -{ - int i; - struct FXO_priv_data *priv; - - priv = xpd->priv; - BUG_ON(!priv); - for_each_line(xpd, i) { - if(priv->ring_sig[i]) - DAA_DIRECT_REQUEST(xbus, xpd, i, DAA_READ, DAA_RING_REGISTER, 0); - } -} -#endif - static int FXO_card_tick(xbus_t *xbus, xpd_t *xpd) { struct FXO_priv_data *priv; @@ -445,10 +415,6 @@ static int FXO_card_tick(xbus_t *xbus, xpd_t *xpd) if(poll_battery_interval != 0 && (priv->poll_counter % poll_battery_interval) == 0) { poll_battery(xbus, xpd); } -#ifdef SOFT_RING - if((priv->poll_counter % POLL_RING_INTERVAL) == 0) - poll_ring(xbus, xpd); -#endif handle_fxo_leds(xpd); priv->poll_counter++; return 0; @@ -489,7 +455,7 @@ static int FXO_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long a ret = handle_register_command(xpd, buf); if(ret < 0) return ret; - mdelay(1); + msleep(1); } DBG("-- Set echo registers successfully\n"); @@ -546,11 +512,11 @@ static /* 0x0F */ HOSTCMD(FXO, XPD_STATE, bool on) if(on) { for_each_line(xpd, i) { MARK_LED(xpd, i, LED_GREEN, LED_ON); - mdelay(20); + msleep(20); } for_each_line(xpd, i) { MARK_LED(xpd, i, LED_GREEN, LED_OFF); - mdelay(20); + msleep(20); } } return ret; @@ -606,21 +572,7 @@ HANDLER_DEF(FXO, SIG_CHANGED) xbus->busname, xpd->xpdname, i); continue; } - if(IS_SET(sig_status, i)) { -#ifdef SOFT_RING - priv->ring_sig[i]=1; /* trigger register polling */ - /* reset ring check counters */ - priv->ring_thresh[i] = 0; - priv->noring_thresh[i] = 0; -#else - mark_ring(xpd, i, 1); -#endif - } else { -#ifdef SOFT_RING - priv->ring_sig[i] = 0; -#endif - mark_ring(xpd, i, 0); - } + mark_ring(xpd, i, IS_SET(sig_status, i), 1); } } spin_unlock_irqrestore(&xpd->lock, flags); @@ -667,25 +619,6 @@ HANDLER_DEF(FXO, DAA_REPLY) } } } -#ifdef SOFT_RING - if(REG_FIELD(info, regnum) == DAA_RING_REGISTER && priv->ring_sig[chipsel]) { - bool ringit = (REG_FIELD(info, data_low) & (0x20 | 0x40)) ? 1 : 0; /* Ring positive | Ring negative */ - - if(ringit) { - if(priv->ring_thresh[chipsel] > RING_THRESHOLD) { - mark_ring(xpd, chipsel, 1); - priv->noring_thresh[chipsel] = 0; - } else - priv->ring_thresh[chipsel]++; - } else { - if(priv->noring_thresh[chipsel] > NORING_THRESHOLD) { - mark_ring(xpd, chipsel, 0); - priv->ring_thresh[chipsel] = 0; - } else - priv->noring_thresh[chipsel]++; - } - } -#endif #if 0 DBG("DAA_REPLY: xpd #%d %s reg_num=0x%X, dataL=0x%X dataH=0x%X\n", xpd->id, (info->size == 3)?"I":"D", @@ -779,23 +712,6 @@ static int proc_fxo_info_read(char *page, char **start, off_t off, int count, in if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i)) len += sprintf(page + len, "%2d ", IS_BLINKING(priv,i,LED_GREEN)); } -#ifdef SOFT_RING - len += sprintf(page + len, "\n\t%-17s: ", "ring_thresh"); - for_each_line(xpd, i) { - if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i)) - len += sprintf(page + len, "%2d ", priv->ring_thresh[i]); - } - len += sprintf(page + len, "\n\t%-17s: ", "noring_thresh"); - for_each_line(xpd, i) { - if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i)) - len += sprintf(page + len, "%2d ", priv->noring_thresh[i]); - } - len += sprintf(page + len, "\n\t%-17s: ", "ring_sig"); - for_each_line(xpd, i) { - if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i)) - len += sprintf(page + len, "%2d ", priv->ring_sig[i]); - } -#endif len += sprintf(page + len, "\n\t%-17s: ", "battery"); for_each_line(xpd, i) { len += sprintf(page + len, "%2d ", IS_SET(priv->battery, i)); @@ -942,7 +858,7 @@ static int proc_xpd_register_write(struct file *file, const char __user *buffer, ret = handle_register_command(xpd, buf); if(ret < 0) return ret; - mdelay(1); + msleep(1); } return count; } @@ -982,11 +898,6 @@ static int proc_xpd_register_read(char *page, char **start, off_t off, int count int __init card_fxo_startup(void) { INFO("%s revision %s\n", THIS_MODULE->name, ZAPTEL_VERSION); -#ifdef SOFT_RING - INFO("FEATURE: %s with SOFT_RING\n", THIS_MODULE->name); -#else - INFO("FEATURE: %s without SOFT_RING\n", THIS_MODULE->name); -#endif xproto_register(&PROTO_TABLE(FXO)); return 0; } diff --git a/xpp/card_fxs.c b/xpp/card_fxs.c index 3d659fa..b5c6538 100644 --- a/xpp/card_fxs.c +++ b/xpp/card_fxs.c @@ -343,7 +343,7 @@ static int FXS_card_zaptel_preregistration(xpd_t *xpd, bool on) spin_unlock_irqrestore(&xpd->lock, flags); for_each_line(xpd, i) { MARK_LED(priv, i, color, LED_ON); - mdelay(50); + msleep(50); } return 0; } @@ -363,7 +363,7 @@ static int FXS_card_zaptel_postregistration(xpd_t *xpd, bool on) DBG("%s/%s (%d)\n", xbus->busname, xpd->xpdname, on); for_each_line(xpd, i) { MARK_LED(priv, i, color, LED_OFF); - mdelay(50); + msleep(50); } return 0; } @@ -946,7 +946,7 @@ static int proc_xpd_register_write(struct file *file, const char __user *buffer, ret = handle_register_command(xpd, buf); if(ret < 0) return ret; - mdelay(1); + msleep(1); } return count; } diff --git a/xpp/card_global.c b/xpp/card_global.c index 4740eab..22456bc 100644 --- a/xpp/card_global.c +++ b/xpp/card_global.c @@ -30,15 +30,6 @@ static const char rcsid[] = "$Id$"; DEF_PARM(charp,initdir, "/usr/share/zaptel", "The directory of card initialization scripts"); -/* - * BRI: Temporary software workaround for firmware limitation: - * - The BRI firmware count PCM channel number globally across subunits. - * - The module parameter 'bri_pcmshift' enables us to cheat and shift - * each B-channel, 4 bits for each subsequent subunit. - * - Eventually, this should be fixed in the firmware, otherwise we won't - * handle PRI (all the space we have is 32bits). - */ -DEF_PARM(bool,bri_pcmshift, 1, "TESTING: shift bri PCM bits by subunit number"); extern int print_dbg; static bool pcm_valid(xpd_t *xpd, xpacket_t *pack); @@ -94,7 +85,11 @@ static void global_packet_dump(const char *msg, xpacket_t *pack); } buf += ZT_CHUNKSIZE; } - if(bri_pcmshift) { /* workaround for pcm problem in BRI */ + /* + * BRI: Software workaround for firmware limitation. + * The BRI firmware count PCM channel number globally across subunits. + */ + if(xpd->type == XPD_TYPE_BRI_NT || xpd->type == XPD_TYPE_BRI_TE) { lines = lines << (xpd->addr.subunit * 4); RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines) = lines; } @@ -153,17 +148,22 @@ HANDLER_DEF(GLOBAL, DEV_DESC) card_desc->type = type; card_desc->rev = rev; card_desc->xpd_addr = xpd_addr; + DBG("%s: xpd=%d-%d type=%d rev=%d line_status=0x%04X\n", + xbus->busname, xpd_addr.unit, xpd_addr.subunit, type, rev, line_status); spin_lock_irqsave(&xbus->lock, flags); - DBG("xpd=%d-%d type=%d rev=%d line_status=0x%04X\n", - xpd_addr.unit, xpd_addr.subunit, type, rev, line_status); if(type == XPD_TYPE_NOMODULE) XBUS_COUNTER(xbus, DEV_DESC_EMPTY)++; else XBUS_COUNTER(xbus, DEV_DESC_FULL)++; atomic_inc(&xbus->count_poll_answers); - wake_up(&xbus->wait_for_polls); list_add_tail(&card_desc->card_list, &xbus->poll_results); spin_unlock_irqrestore(&xbus->lock, flags); + /* + * wake_up only after exiting our critical section. + * We suspect that otherwise a spinlock nesting may occur + * and cause a panic (if spinlock debugging is compiled in). + */ + wake_up(&xbus->wait_for_polls); return 0; } @@ -176,6 +176,7 @@ HANDLER_DEF(GLOBAL, PCM_READ) volatile u_char *r; unsigned long flags; int i; + xpp_line_t old_lines = lines; BUG_ON(!xbus); if(!xpd) { @@ -188,11 +189,20 @@ HANDLER_DEF(GLOBAL, PCM_READ) } // DBG("lines=0x%04X\n", lines); - if(bri_pcmshift) { /* workaround for pcm problem in BRI */ + /* + * BRI: Software workaround for firmware limitation. + * The BRI firmware count PCM channel number globally across subunits. + */ + if(xpd->type == XPD_TYPE_BRI_NT || xpd->type == XPD_TYPE_BRI_TE) { lines = (lines >> (xpd->addr.subunit * 4)) & 0x7; RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines) = lines; } if(!pcm_valid(xpd, pack)) { + static int rate_limit; + + if((rate_limit++ % 5001) == 0) + ERR("%s/%s: old_lines=0x%04X lines=0x%04X subunit=%d\n", + xpd->xbus->busname, xpd->xpdname, old_lines, lines, xpd->addr.subunit); return -EPROTO; } spin_lock_irqsave(&xpd->lock, flags); @@ -313,7 +323,8 @@ static bool pcm_valid(xpd_t *xpd, xpacket_t *pack) XPD_COUNTER(xpd, RECV_ERRORS)++; if((rate_limit++ % 1000) <= 10) { - ERR("BAD PCM REPLY: pack->datalen=%d, count=%d\n", pack->datalen, count); + ERR("%s/%s: BAD PCM REPLY: pack->datalen=%d, count=%d\n", + xpd->xbus->busname, xpd->xpdname, pack->datalen, count); dump_packet("BAD PCM REPLY", pack, 1); } return 0; diff --git a/xpp/init_card_3_23 b/xpp/init_card_3_23 index 5698484..3f07578 100755 --- a/xpp/init_card_3_23 +++ b/xpp/init_card_3_23 @@ -46,10 +46,21 @@ XPP_BASE=/proc/xpp export XPP_BASE LOGGER="logger -s -t $me" +ZAPTEL_BOOT_DEBIAN=${ZAPTEL_BOOT_DEBIAN:-/etc/default/zaptel} +ZAPTEL_BOOT_FEDORA=${ZAPTEL_BOOT_FEDORA:-/etc/sysconfig/zaptel} + +# read default configuration from /etc/default/zaptel +if [ -r $ZAPTEL_BOOT_DEBIAN ]; then . $ZAPTEL_BOOT_DEBIAN; fi +if [ -r $ZAPTEL_BOOT_FEDORA ]; then . $ZAPTEL_BOOT_FEDORA; fi + +if [ "$DEBUG_CALIBRATION"=1 ]; then + LOGGER=":" +fi + # Always redirect stderr somewhere, otherwise the shell script will die # when it tries to do I/O related stuff on closed file descriptor. # Our default is to throw it down the bit-bucket. -exec 2> /dev/null +exec 2> /dev/console ## If you wish to trace this script: #exec 2> /tmp/xpp_init_$XPD_NAME ## Altenativly, if you have multiple XBUS'es: @@ -65,8 +76,7 @@ $LOGGER -p kern.info "$XPD_BUS/$XPD_NAME: Calibrating '$0'" $LOGGER -p kern.info "$XPD_BUS/$XPD_NAME: Continue '$0'" -sed -e 's/[;#].*$//' -e '/^[ ]*$/d' < /dev/null +exec 2> /dev/console ## If you wish to trace this script: #exec 2> /tmp/xpp_init_$XPD_NAME ## Altenativly, if you have multiple XBUS'es: @@ -69,12 +80,12 @@ set_daa_country_params() { . $INIT_DIR/init_fxo_modes fi # Our register numbers are HEXADECIMAL! - cat <$@ init_fxo_modes: print_modes - ./$^ >$@ + ./$< >$@ clean: $(RM) *.o $(TARGETS) diff --git a/xpp/xbus-core.c b/xpp/xbus-core.c index 9f73a86..59db079 100644 --- a/xpp/xbus-core.c +++ b/xpp/xbus-core.c @@ -33,7 +33,7 @@ #include #endif #include -#include /* for mdelay() to debug */ +#include /* for msleep() to debug */ #include "xpd.h" #include "xpp_zap.h" #include "xbus-core.h" @@ -42,7 +42,7 @@ static const char rcsid[] = "$Id$"; /* Defines */ -#define POLL_TIMEOUT (MAX_XPDS) /* in jiffies */ +#define POLL_TIMEOUT (2*MAX_XPDS) /* in jiffies */ #define INITIALIZATION_TIMEOUT (40*HZ) /* in jiffies */ #define PROC_XBUSES "xbuses" #define PROC_XBUS_SUMMARY "summary" @@ -55,6 +55,7 @@ static int proc_xbus_command_write(struct file *file, const char __user *buffer, /* Command line parameters */ extern int print_dbg; +DEF_PARM(uint, poll_timeout, POLL_TIMEOUT,"Timeout (in jiffies) waiting for units to reply (default " __stringify(POLL_TIMEOUT) ")"); /* Forward declarations */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14) @@ -226,7 +227,7 @@ static int xbus_poll(void *data) ERR("%s is being removed...\n", xbus->busname); return -EBUSY; } - mdelay(2); /* roundtrip for older polls */ + msleep(2); /* roundtrip for older polls */ spin_lock_irqsave(&xbus->lock, flags); DBG("%s\n", xbus->busname); @@ -250,16 +251,18 @@ static int xbus_poll(void *data) /* * Wait for replies */ - DBG("%s: Polled %d XPD's. Waiting for replies max %d jiffies\n", xbus->busname, MAX_XPDS, POLL_TIMEOUT); - ret = wait_event_interruptible_timeout(xbus->wait_for_polls, atomic_read(&xbus->count_poll_answers) >= MAX_XPDS, POLL_TIMEOUT); + DBG("%s: Polled %d XPD's. Waiting for replies max %d jiffies\n", xbus->busname, MAX_XPDS, poll_timeout); + ret = wait_event_interruptible_timeout(xbus->wait_for_polls, atomic_read(&xbus->count_poll_answers) >= MAX_XPDS, poll_timeout); if(ret == 0) { - ERR("%s: Poll timeout\n", xbus->busname); - goto out; + ERR("%s: Poll timeout. Continuing anyway.\n", xbus->busname); + /* + * Continue processing. Maybe some units did reply. + */ } else if(ret < 0) { ERR("%s: Poll interrupted %d\n", xbus->busname, ret); goto out; - } - DBG("%s: Poll finished in %d jiffies. Start processing.\n", xbus->busname, POLL_TIMEOUT - ret); + } else + DBG("%s: Poll finished in %d jiffies.\n", xbus->busname, poll_timeout - ret); /* * Build removals/additions lists */ @@ -288,6 +291,10 @@ static int xbus_poll(void *data) kfree(card_desc); } } + /* + * We set this *after* poll is finished, so wait_for_xpd_initialization can + * tell we already know how many units we have. + */ atomic_set(&xbus->count_xpds_to_initialize, count_added); spin_unlock_irqrestore(&xbus->lock, flags); INFO("%s: Poll results: removals=%d additions=%d\n", xbus->busname, count_removed, count_added); @@ -659,7 +666,14 @@ static int xbus_read_waitfor_xpds(char *page, char **start, off_t off, int count if(!xbus) goto out; DBG("%s: Waiting for card initialization of %d XPD's max %d seconds\n", xbus->busname, MAX_XPDS, INITIALIZATION_TIMEOUT/HZ); + /* + * xbus_poll sets count_xpds_to_initialize only when polling is finished. + * To prevent race conditions we test both: + * - It is none zero -- meaning we already have the poll results. + * - And all units have finished initialization. + */ ret = wait_event_interruptible_timeout(xbus->wait_for_xpd_initialization, + atomic_read(&xbus->count_xpds_to_initialize) && atomic_read(&xbus->count_xpds_initialized) >= atomic_read(&xbus->count_xpds_to_initialize), INITIALIZATION_TIMEOUT); if(ret == 0) { -- cgit v1.2.3