diff -urN linux-2.4.22.orig/Documentation/computone.txt linux-2.4.22/Documentation/computone.txt --- linux-2.4.22.orig/Documentation/computone.txt Fri Nov 2 20:26:17 2001 +++ linux-2.4.22/Documentation/computone.txt Wed Nov 5 21:38:18 2003 @@ -6,8 +6,8 @@ These notes are for the drivers which have already been integrated into the kernel and have been tested on Linux kernels 2.0, 2.2, 2.3, and 2.4. -Version: 1.2.14 -Date: 11/01/2001 +Version: 1.2.16 +Date: 11/05/2003 Historical Author: Andrew Manison Primary Author: Doug McNash Support: support@computone.com @@ -26,7 +26,7 @@ products previous to the Intelliport II. This driver was developed on the v2.0.x Linux tree and has been tested up -to v2.4.14; it will probably not work with earlier v1.X kernels,. +to v2.4.22; it will probably not work with earlier v1.X kernels,. 2. QUICK INSTALLATION diff -urN linux-2.4.22.orig/drivers/char/ip2/i2ellis.h linux-2.4.22/drivers/char/ip2/i2ellis.h --- linux-2.4.22.orig/drivers/char/ip2/i2ellis.h Wed Oct 24 15:05:18 2001 +++ linux-2.4.22/drivers/char/ip2/i2ellis.h Wed Nov 5 21:36:12 2003 @@ -403,7 +403,7 @@ // For queuing interupt bottom half handlers. /\/\|=mhw=|\/\/ struct tq_struct tqueue_interrupt; - struct timer_list SendPendingTimer; // Used by iiSendPending +// struct timer_list SendPendingTimer; // Used by iiSendPending unsigned int SendPendingRetry; #ifdef CONFIG_DEVFS_FS diff -urN linux-2.4.22.orig/drivers/char/ip2/i2lib.c linux-2.4.22/drivers/char/ip2/i2lib.c --- linux-2.4.22.orig/drivers/char/ip2/i2lib.c Fri Aug 2 20:39:43 2002 +++ linux-2.4.22/drivers/char/ip2/i2lib.c Wed Nov 5 21:36:12 2003 @@ -164,6 +164,7 @@ { if (pB->i2eOutMailWaiting && (!pB->i2eWaitingForEmptyFifo) ) { +// while( pB->SendPendingRetry < 32 ) { if (iiTrySendMail(pB, pB->i2eOutMailWaiting)) { /* If we were already waiting for fifo to empty, @@ -174,8 +175,13 @@ pB->i2eWaitingForEmptyFifo |= (pB->i2eOutMailWaiting & MB_OUT_STUFFED); pB->i2eOutMailWaiting = 0; + if( pB->SendPendingRetry ) { + printk( KERN_DEBUG "IP2: iiSendPendingMail: busy board pickup on %d\n", pB->SendPendingRetry ); + } pB->SendPendingRetry = 0; +// break; } else { +#ifdef IP2_USE_TIMER_WAIT /* The only time we hit this area is when "iiTrySendMail" has failed. That only occurs when the outbound mailbox is still busy with the last message. We take a short breather @@ -193,7 +199,13 @@ } else { printk( KERN_ERR "IP2: iiSendPendingMail unable to queue outbound mail\n" ); } +#endif + pB->SendPendingRetry++; + if( 0 == ( pB->SendPendingRetry % 8 ) ) { + printk( KERN_ERR "IP2: iiSendPendingMail: board busy, retry %d\n", pB->SendPendingRetry ); + } } +// } } } @@ -1329,8 +1341,9 @@ remove_wait_queue(&(pCh->pBookmarkWait), &wait); // if expires == 0 then timer poped, then do not need to del_timer + // jiffy wrap per Tim Schmielau (tim@physik3.uni-rostock.de) if ((timeout > 0) && pCh->BookmarkTimer.expires && - time_before(jiffies, pCh->BookmarkTimer.expires)) { + time_before(jiffies, pCh->BookmarkTimer.expires)) { del_timer( &(pCh->BookmarkTimer) ); pCh->BookmarkTimer.expires = 0; diff -urN linux-2.4.22.orig/drivers/char/ip2main.c linux-2.4.22/drivers/char/ip2main.c --- linux-2.4.22.orig/drivers/char/ip2main.c Thu Nov 28 18:53:12 2002 +++ linux-2.4.22/drivers/char/ip2main.c Wed Nov 5 21:36:12 2003 @@ -19,6 +19,15 @@ // // Done: // +// 1.2.16 /\/\|=mhw=|\/\/ +// Yet another shot at the busy board timing window (use the poll timer). +// Because of this, the poll timer is always enabled... +// Cleaned up some comments on immediate interrupt mode (ppp code elsewhere +// has been fixed and the new busy board logic won't throw a hairball). +// +// 1.2.15 dmc +// Fixed jiffy wrap, PCI card may now be set to poll. +// // 1.2.14 /\/\|=mhw=|\/\/ // Added bounds checking to ip2_ipl_ioctl to avoid potential terroristic acts. // Changed the definition of ip2trace to be more consistant with kernel style @@ -227,7 +236,7 @@ /* String constants to identify ourselves */ static char *pcName = "Computone IntelliPort Plus multiport driver"; -static char *pcVersion = "1.2.14"; +static char *pcVersion = "1.2.16"; /* String constants for port names */ static char *pcDriver_name = "ip2"; @@ -437,7 +446,7 @@ } return 0; } -#endif +#endif /* MODULE */ static int __init have_requested_irq( char irq ) @@ -604,17 +613,12 @@ if (iop) { ip2config.addr[i] = iop[i]; if (irqp) { - if( irqp[i] >= 0 ) { - ip2config.irq[i] = irqp[i]; - } else { - ip2config.irq[i] = 0; - } + ip2config.irq[i] = irqp[i]; // This is a little bit of a hack. If poll_only=1 on command // line back in ip2.c OR all IRQs on all specified boards are // explicitly set to 0, then drop to poll only mode and override // PCI or EISA interrupts. This superceeds the old hack of // triggering if all interrupts were zero (like da default). - // Still a hack but less prone to random acts of terrorism. // // What we really should do, now that the IRQ default is set // to -1, is to use 0 as a hard coded, do not probe. @@ -700,17 +704,12 @@ } else { printk( KERN_ERR "IP2: PCI I/O address error\n"); } - pcibios_read_config_byte(pci_bus, pci_devfn, + if (ip2config.irq[i] != 0) { + pcibios_read_config_byte(pci_bus, pci_devfn, PCI_INTERRUPT_LINE, &pci_irq); -// If the PCI BIOS assigned it, lets try and use it. If we -// can't acquire it or it screws up, deal with it then. - -// if (!is_valid_irq(pci_irq)) { -// printk( KERN_ERR "IP2: Bad PCI BIOS IRQ(%d)\n",pci_irq); -// pci_irq = 0; -// } - ip2config.irq[i] = pci_irq; + ip2config.irq[i] = pci_irq; + } } else { // ann error ip2config.addr[i] = 0; if (status == PCIBIOS_DEVICE_NOT_FOUND) { @@ -737,17 +736,12 @@ } else { printk( KERN_ERR "IP2: PCI I/O address error\n"); } - status = - pci_read_config_byte(pci_dev_i, PCI_INTERRUPT_LINE, &pci_irq); + if (ip2config.irq[i] != 0) { + status = + pci_read_config_byte(pci_dev_i, PCI_INTERRUPT_LINE, &pci_irq); -// If the PCI BIOS assigned it, lets try and use it. If we -// can't acquire it or it screws up, deal with it then. - -// if (!is_valid_irq(pci_irq)) { -// printk( KERN_ERR "IP2: Bad PCI BIOS IRQ(%d)\n",pci_irq); -// pci_irq = 0; -// } - ip2config.irq[i] = pci_irq; + ip2config.irq[i] = pci_irq; + } } else { // ann error ip2config.addr[i] = 0; if (status == PCIBIOS_DEVICE_NOT_FOUND) { @@ -934,6 +928,11 @@ } #endif +// Kick the timer on for stuck board safeties... + PollTimer.expires = POLL_TIMEOUT; + add_timer ( &PollTimer ); + TimerOn = 1; + if (poll_only) { // Poll only forces driver to only use polling and // to ignore the probed PCI or EISA interrupts. @@ -988,7 +987,7 @@ static void __init ip2_init_board( int boardnum ) { - int i,rc; + int i, rc=0; int nports = 0, nboxes = 0; i2ChanStrPtr pCh; i2eBordStrPtr pB = i2BoardPtrTable[boardnum]; @@ -1375,8 +1374,10 @@ // Only process those boards which match our IRQ. // IRQ = 0 for polled boards, we won't poll "IRQ" boards +// Add an additional "check" if the irq is zero for boards +// which are "stuck" - if ( pB && (pB->i2eUsingIrq == irq) ) { + if ( pB && ( pB->i2eUsingIrq == irq || ( 0 == irq && 0 != pB->SendPendingRetry ) ) ) { #ifdef USE_IQI if (NO_MAIL_HERE != ( pB->i2eStartMail = iiGetMail(pB))) { @@ -1391,9 +1392,8 @@ mark_bh(IMMEDIATE_BH); } #else -// We are using immediate servicing here. This sucks and can -// cause all sorts of havoc with ppp and others. The failsafe -// check on iiSendPendingMail could also throw a hairball. +// We are using immediate servicing here. Suboptimal +// to say the least... i2ServiceBoard( pB ); #endif /* USE_IQI */ } @@ -1417,6 +1417,9 @@ static void ip2_poll(unsigned long arg) { + int i; + i2eBordStrPtr pB; + ip2trace (ITRC_NO_PORT, ITRC_INTR, 100, 0 ); TimerOn = 0; // it's the truth but not checked in service @@ -1424,7 +1427,15 @@ // Just polled boards, IRQ = 0 will hit all non-interrupt boards. // It will NOT poll boards handled by hard interrupts. // The issue of queued BH interrups is handled in ip2_interrupt(). - ip2_interrupt(0, NULL, NULL); + + for( i = 0; i < i2nBoards; ++i ) { + pB = i2BoardPtrTable[i]; + // Service the board if the irq indicates a polled board + // OR if the SendPendingRetry indicates a retry state in the board + if ( pB && ( 0 == pB->i2eUsingIrq || 0 != pB->SendPendingRetry ) ) { + i2ServiceBoard( pB ); + } + } PollTimer.expires = POLL_TIMEOUT; add_timer( &PollTimer );