All of lore.kernel.org
 help / color / mirror / Atom feed
From: Paul Fulghum <paulkf@microgate.com>
To: linux-kernel <linux-kernel@vger.kernel.org>
Cc: Andrew Morton <akpm@osdl.org>
Subject: [PATCH] 2.6.9-rc1-bk3 synclinkmp transmit eom fix
Date: 27 Aug 2004 15:56:34 -0500	[thread overview]
Message-ID: <1093640193.2640.5.camel@deimos.microgate.com> (raw)

Bug Fixes:

* Fix transmit end of message (EOM) processing to
  work correctly with hardware auto CTS feature

* Fix oops in error path if hardware diags fail
  during device initialization

Cosmetic change:

* Use existing macros for address space size
  instead of hardcoded values

Signed-off-by: Paul Fulghum <paulkf@microgate.com>

Please apply.

--
Paul Fulghum
paulkf@microgate.com


--- linux-2.6.9-rc1-bk3/drivers/char/synclinkmp.c	2004-08-27 14:54:10.761161575 -0500
+++ linux-2.6.9-rc1-bk3-mg/drivers/char/synclinkmp.c	2004-08-27 15:54:23.818985480 -0500
@@ -1,5 +1,5 @@
 /*
- * $Id: synclinkmp.c,v 4.26 2004/08/11 19:30:02 paulkf Exp $
+ * $Id: synclinkmp.c,v 4.29 2004/08/27 20:06:41 paulkf Exp $
  *
  * Device driver for Microgate SyncLink Multiport
  * high speed multiprotocol serial adapter.
@@ -489,7 +489,7 @@
 MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICES) "i");
 
 static char *driver_name = "SyncLink MultiPort driver";
-static char *driver_version = "$Revision: 4.26 $";
+static char *driver_version = "$Revision: 4.29 $";
 
 static int synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent);
 static void synclinkmp_remove_one(struct pci_dev *dev);
@@ -651,7 +651,7 @@
 static unsigned char tx_negate_fifo_level = 32;	// tx request FIFO negation level in bytes
 
 static u32 misc_ctrl_value = 0x007e4040;
-static u32 lcr1_brdr_value = 0x0080002d;
+static u32 lcr1_brdr_value = 0x00800029;
 
 static u32 read_ahead_count = 8;
 
@@ -2182,16 +2182,15 @@
 {
  	struct tty_struct *tty = info->tty;
  	struct	mgsl_icount *icount = &info->icount;
-	unsigned char status = read_reg(info, SR1);
-	unsigned char status2 = read_reg(info, SR2);
+	unsigned char status = read_reg(info, SR1) & info->ie1_value & (FLGD + IDLD + CDCD + BRKD);
+	unsigned char status2 = read_reg(info, SR2) & info->ie2_value & OVRN;
 
 	/* clear status bits */
-	if ( status & (FLGD + IDLD + CDCD + BRKD) )
-		write_reg(info, SR1, 
-				(unsigned char)(status & (FLGD + IDLD + CDCD + BRKD)));
+	if (status)
+		write_reg(info, SR1, status);
 
-	if ( status2 & OVRN )
-		write_reg(info, SR2, (unsigned char)(status2 & OVRN));
+	if (status2)
+		write_reg(info, SR2, status2);
 	
 	if ( debug_level >= DEBUG_LEVEL_ISR )
 		printk("%s(%d):%s isr_rxint status=%02X %02x\n",
@@ -2328,15 +2327,22 @@
 		printk("%s(%d):%s isr_txeom status=%02x\n",
 			__FILE__,__LINE__,info->device_name,status);
 
-	/* disable and clear MSCI interrupts */
-	info->ie1_value &= ~(IDLE + UDRN);
-	write_reg(info, IE1, info->ie1_value);
-	write_reg(info, SR1, (unsigned char)(UDRN + IDLE));
-
 	write_reg(info, TXDMA + DIR, 0x00); /* disable Tx DMA IRQs */
 	write_reg(info, TXDMA + DSR, 0xc0); /* clear IRQs and disable DMA */
 	write_reg(info, TXDMA + DCMD, SWABORT);	/* reset/init DMA channel */
 
+	if (status & UDRN) {
+		write_reg(info, CMD, TXRESET);
+		write_reg(info, CMD, TXENABLE);
+	} else
+		write_reg(info, CMD, TXBUFCLR);
+
+	/* disable and clear tx interrupts */
+	info->ie0_value &= ~TXRDYE;
+	info->ie1_value &= ~(IDLE + UDRN);
+	write_reg16(info, IE0, (unsigned short)((info->ie1_value << 8) + info->ie0_value));
+	write_reg(info, SR1, (unsigned char)(UDRN + IDLE));
+
 	if ( info->tx_active ) {
 		if (info->params.mode != MGSL_MODE_ASYNC) {
 			if (status & UDRN)
@@ -2377,10 +2383,10 @@
  */
 void isr_txint(SLMP_INFO * info)
 {
-	unsigned char status = read_reg(info, SR1);
+	unsigned char status = read_reg(info, SR1) & info->ie1_value & (UDRN + IDLE + CCTS);
 
 	/* clear status bits */
-	write_reg(info, SR1, (unsigned char)(status & (UDRN + IDLE + CCTS)));
+	write_reg(info, SR1, status);
 
 	if ( debug_level >= DEBUG_LEVEL_ISR )
 		printk("%s(%d):%s isr_txint status=%02x\n",
@@ -2409,6 +2415,14 @@
 		printk("%s(%d):%s isr_txrdy() tx_count=%d\n",
 			__FILE__,__LINE__,info->device_name,info->tx_count);
 
+	if (info->params.mode != MGSL_MODE_ASYNC) {
+		/* disable TXRDY IRQ, enable IDLE IRQ */
+		info->ie0_value &= ~TXRDYE;
+		info->ie1_value |= IDLE;
+		write_reg16(info, IE0, (unsigned short)((info->ie1_value << 8) + info->ie0_value));
+		return;
+	}
+
 	if (info->tty && (info->tty->stopped || info->tty->hw_stopped)) {
 		tx_stop(info);
 		return;
@@ -2463,13 +2477,6 @@
 
 void isr_txdmaok(SLMP_INFO * info)
 {
-	/* BIT7 = EOT (end of transfer, used for async mode)
-	 * BIT6 = EOM (end of message/frame, used for sync mode)
-	 *
-	 * We don't look at DMA status because only EOT is enabled
-	 * and we always clear and disable all tx DMA IRQs.
-	 */
-//	unsigned char dma_status = read_reg(info,TXDMA + DSR) & 0xc0;
 	unsigned char status_reg1 = read_reg(info, SR1);
 
 	write_reg(info, TXDMA + DIR, 0x00);	/* disable Tx DMA IRQs */
@@ -2480,19 +2487,10 @@
 		printk("%s(%d):%s isr_txdmaok(), status=%02x\n",
 			__FILE__,__LINE__,info->device_name,status_reg1);
 
-	/* If transmitter already idle, do end of frame processing,
-	 * otherwise enable interrupt for tx IDLE.
-	 */
-	if (status_reg1 & IDLE)
-		isr_txeom(info, IDLE);
-	else {
-		/* disable and clear underrun IRQ, enable IDLE interrupt */
-		info->ie1_value |= IDLE;
-		info->ie1_value &= ~UDRN;
-		write_reg(info, IE1, info->ie1_value);
-
-		write_reg(info, SR1, UDRN);
-	}
+	/* program TXRDY as FIFO empty flag, enable TXRDY IRQ */
+	write_reg16(info, TRC0, 0);
+	info->ie0_value |= TXRDYE;
+	write_reg(info, IE0, info->ie0_value);
 }
 
 void isr_txdmaerror(SLMP_INFO * info)
@@ -3176,7 +3174,7 @@
 		unsigned char oldval = info->ie1_value;
 		unsigned char newval = oldval +
 			 (mask & MgslEvent_ExitHuntMode ? FLGD:0) +
-			 (mask & MgslEvent_IdleReceived ? IDLE:0);
+			 (mask & MgslEvent_IdleReceived ? IDLD:0);
 		if ( oldval != newval ) {
 			info->ie1_value = newval;
 			write_reg(info, IE1, info->ie1_value);
@@ -3243,7 +3241,7 @@
 		spin_lock_irqsave(&info->lock,flags);
 		if (!waitqueue_active(&info->event_wait_q)) {
 			/* disable enable exit hunt mode/idle rcvd IRQs */
-			info->ie1_value &= ~(FLGD|IDLE);
+			info->ie1_value &= ~(FLGD|IDLD);
 			write_reg(info, IE1, info->ie1_value);
 		}
 		spin_unlock_irqrestore(&info->lock,flags);
@@ -3637,9 +3635,10 @@
 
 int claim_resources(SLMP_INFO *info)
 {
-	if (request_mem_region(info->phys_memory_base,0x40000,"synclinkmp") == NULL) {
+	if (request_mem_region(info->phys_memory_base,SCA_MEM_SIZE,"synclinkmp") == NULL) {
 		printk( "%s(%d):%s mem addr conflict, Addr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_memory_base);
+		info->init_error = DiagStatus_AddressConflict;
 		goto errout;
 	}
 	else
@@ -3648,22 +3647,25 @@
 	if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclinkmp") == NULL) {
 		printk( "%s(%d):%s lcr mem addr conflict, Addr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_lcr_base);
+		info->init_error = DiagStatus_AddressConflict;
 		goto errout;
 	}
 	else
 		info->lcr_mem_requested = 1;
 
-	if (request_mem_region(info->phys_sca_base + info->sca_offset,512,"synclinkmp") == NULL) {
+	if (request_mem_region(info->phys_sca_base + info->sca_offset,SCA_BASE_SIZE,"synclinkmp") == NULL) {
 		printk( "%s(%d):%s sca mem addr conflict, Addr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_sca_base);
+		info->init_error = DiagStatus_AddressConflict;
 		goto errout;
 	}
 	else
 		info->sca_base_requested = 1;
 
-	if (request_mem_region(info->phys_statctrl_base + info->statctrl_offset,16,"synclinkmp") == NULL) {
+	if (request_mem_region(info->phys_statctrl_base + info->statctrl_offset,SCA_REG_SIZE,"synclinkmp") == NULL) {
 		printk( "%s(%d):%s stat/ctrl mem addr conflict, Addr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_statctrl_base);
+		info->init_error = DiagStatus_AddressConflict;
 		goto errout;
 	}
 	else
@@ -3673,33 +3675,41 @@
 	if (!info->memory_base) {
 		printk( "%s(%d):%s Cant map shared memory, MemAddr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_memory_base );
+		info->init_error = DiagStatus_CantAssignPciResources;
 		goto errout;
 	}
 
-	if ( !memory_test(info) ) {
-		printk( "%s(%d):Shared Memory Test failed for device %s MemAddr=%08X\n",
-			__FILE__,__LINE__,info->device_name, info->phys_memory_base );
-		goto errout;
-	}
-
-	info->lcr_base = ioremap(info->phys_lcr_base,PAGE_SIZE) + info->lcr_offset;
+	info->lcr_base = ioremap(info->phys_lcr_base,PAGE_SIZE);
 	if (!info->lcr_base) {
 		printk( "%s(%d):%s Cant map LCR memory, MemAddr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_lcr_base );
+		info->init_error = DiagStatus_CantAssignPciResources;
 		goto errout;
 	}
+	info->lcr_base += info->lcr_offset;
 
-	info->sca_base = ioremap(info->phys_sca_base,PAGE_SIZE) + info->sca_offset;
+	info->sca_base = ioremap(info->phys_sca_base,PAGE_SIZE);
 	if (!info->sca_base) {
 		printk( "%s(%d):%s Cant map SCA memory, MemAddr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_sca_base );
+		info->init_error = DiagStatus_CantAssignPciResources;
 		goto errout;
 	}
+	info->sca_base += info->sca_offset;
 
-	info->statctrl_base = ioremap(info->phys_statctrl_base,PAGE_SIZE) + info->statctrl_offset;
+	info->statctrl_base = ioremap(info->phys_statctrl_base,PAGE_SIZE);
 	if (!info->statctrl_base) {
 		printk( "%s(%d):%s Cant map SCA Status/Control memory, MemAddr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_statctrl_base );
+		info->init_error = DiagStatus_CantAssignPciResources;
+		goto errout;
+	}
+	info->statctrl_base += info->statctrl_offset;
+
+	if ( !memory_test(info) ) {
+		printk( "%s(%d):Shared Memory Test failed for device %s MemAddr=%08X\n",
+			__FILE__,__LINE__,info->device_name, info->phys_memory_base );
+		info->init_error = DiagStatus_MemoryError;
 		goto errout;
 	}
 
@@ -3722,7 +3732,7 @@
 	}
 
 	if ( info->shared_mem_requested ) {
-		release_mem_region(info->phys_memory_base,0x40000);
+		release_mem_region(info->phys_memory_base,SCA_MEM_SIZE);
 		info->shared_mem_requested = 0;
 	}
 	if ( info->lcr_mem_requested ) {
@@ -3730,11 +3740,11 @@
 		info->lcr_mem_requested = 0;
 	}
 	if ( info->sca_base_requested ) {
-		release_mem_region(info->phys_sca_base + info->sca_offset,512);
+		release_mem_region(info->phys_sca_base + info->sca_offset,SCA_BASE_SIZE);
 		info->sca_base_requested = 0;
 	}
 	if ( info->sca_statctrl_requested ) {
-		release_mem_region(info->phys_statctrl_base + info->statctrl_offset,16);
+		release_mem_region(info->phys_statctrl_base + info->statctrl_offset,SCA_REG_SIZE);
 		info->sca_statctrl_requested = 0;
 	}
 
@@ -3975,7 +3985,6 @@
 
 static void synclinkmp_cleanup(void)
 {
-	unsigned long flags;
 	int rc;
 	SLMP_INFO *info;
 	SLMP_INFO *tmp;
@@ -3989,33 +3998,24 @@
 		put_tty_driver(serial_driver);
 	}
 
+	/* reset devices */
 	info = synclinkmp_device_list;
 	while(info) {
-#ifdef CONFIG_HDLC
-		hdlcdev_exit(info);
-#endif
 		reset_port(info);
-		if ( info->port_num == 0 ) {
-			if ( info->irq_requested ) {
-				free_irq(info->irq_level, info);
-				info->irq_requested = 0;
-			}
-		}
 		info = info->next_device;
 	}
 
-	/* port 0 of each adapter originally claimed
-	 * all resources, release those now
-	 */
+	/* release devices */
 	info = synclinkmp_device_list;
 	while(info) {
+#ifdef CONFIG_HDLC
+		hdlcdev_exit(info);
+#endif
 		free_dma_bufs(info);
 		free_tmp_rx_buf(info);
 		if ( info->port_num == 0 ) {
-			spin_lock_irqsave(&info->lock,flags);
-			reset_adapter(info);
-			write_reg(info, LPR, 1);		/* set low power mode */
-			spin_unlock_irqrestore(&info->lock,flags);
+			if (info->sca_base)
+				write_reg(info, LPR, 1); /* set low power mode */
 			release_resources(info);
 		}
 		tmp = info;
@@ -4298,6 +4298,9 @@
 				}
 			}
 
+			write_reg16(info, TRC0,
+				(unsigned short)(((tx_negate_fifo_level-1)<<8) + tx_active_fifo_level));
+
 			write_reg(info, TXDMA + DSR, 0); 		/* disable DMA channel */
 			write_reg(info, TXDMA + DCMD, SWABORT);	/* reset/init DMA channel */
 	
@@ -4309,11 +4312,10 @@
 			write_reg16(info, TXDMA + EDA,
 				info->tx_buf_list_ex[info->last_tx_buf].phys_entry);
 	
-			/* clear IDLE and UDRN status bit */
-			info->ie1_value &= ~(IDLE + UDRN);
-			if (info->params.mode != MGSL_MODE_ASYNC)
-				info->ie1_value |= UDRN;     		/* HDLC, IRQ on underrun */
-			write_reg(info, IE1, info->ie1_value);	/* enable MSCI interrupts */
+			/* enable underrun IRQ */
+			info->ie1_value &= ~IDLE;
+			info->ie1_value |= UDRN;
+			write_reg(info, IE1, info->ie1_value);
 			write_reg(info, SR1, (unsigned char)(IDLE + UDRN));
 	
 			write_reg(info, TXDMA + DIR, 0x40);		/* enable Tx DMA interrupts (EOM) */




                 reply	other threads:[~2004-08-27 21:02 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1093640193.2640.5.camel@deimos.microgate.com \
    --to=paulkf@microgate.com \
    --cc=akpm@osdl.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.