# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.930.52.3+1.930.50.1 -> 1.930.52.4
#	            Makefile	1.190.1.15 -> 1.193.1.12
#	   drivers/net/tg3.c	1.56.1.1 -> 1.62   
#	arch/ia64/kernel/acpi.c	1.6.2.1 -> 1.6.1.7
#	   drivers/net/tg3.h	1.25.1.1 -> 1.27   
#	include/linux/highmem.h	1.10.1.1 -> 1.12   
#	drivers/char/Makefile	1.27.1.4 -> 1.31   
#
diff -Nru a/Makefile b/Makefile
--- a/Makefile	Wed Oct  8 09:08:32 2003
+++ b/Makefile	Wed Oct  8 09:08:32 2003
@@ -90,6 +90,7 @@
 
 CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \
 	  -fno-strict-aliasing -fno-common
+CFLAGS += -g
 ifndef CONFIG_FRAME_POINTER
 CFLAGS += -fomit-frame-pointer
 endif
@@ -300,8 +301,7 @@
 	$(CONFIG_SHELL) scripts/Configure -d arch/$(ARCH)/config.in
 
 xconfig: symlinks
-	$(MAKE) -C scripts kconfig.tk
-	wish -f scripts/kconfig.tk
+	@echo -e "***\n* Sorry, xconfig is broken; use \"make menuconfig\" instead.\n***"
 
 menuconfig: include/linux/version.h symlinks
 	$(MAKE) -C scripts/lxdialog all
diff -Nru a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
--- a/arch/ia64/kernel/acpi.c	Wed Oct  8 09:08:32 2003
+++ b/arch/ia64/kernel/acpi.c	Wed Oct  8 09:08:32 2003
@@ -443,9 +443,8 @@
 
 	if (iosapic_init) {
 #ifndef CONFIG_ITANIUM
-		/* PCAT_COMPAT flag indicates dual-8259 setup */
 		iosapic_init(iosapic->address, iosapic->global_irq_base,
-			     acpi_madt->flags.pcat_compat);
+			     has_8259);
 #else
 		/* Firmware on old Itanium systems is broken */
 		iosapic_init(iosapic->address, iosapic->global_irq_base, 1);
@@ -595,59 +594,6 @@
 }
 
 
-#ifdef CONFIG_SERIAL_ACPI
-
-#include <linux/acpi_serial.h>
-
-static int __init
-acpi_parse_spcr (unsigned long phys_addr, unsigned long size)
-{
-	acpi_ser_t *spcr;
-	u32 gsi, gsi_base;
-	char *iosapic_address;
-
-	if (!phys_addr || !size)
-		return -EINVAL;
-
-	if (!iosapic_register_intr)
-		return -ENODEV;
-
-	/*
-	 * ACPI is able to describe serial ports that live at non-standard
-	 * memory addresses and use non-standard interrupts, either via
-	 * direct SAPIC mappings or via PCI interrupts.  We handle interrupt
-	 * routing for SAPIC-based (non-PCI) devices here.  Interrupt routing
-	 * for PCI devices will be handled when processing the PCI Interrupt
-	 * Routing Table (PRT).
-	 */
-
-	spcr = (acpi_ser_t *) __va(phys_addr);
-	setup_serial_acpi(spcr);
-
-	if (spcr->length < sizeof(acpi_ser_t))
-		/* Table not long enough for full info, thus no interrupt */
-		return -ENODEV;
-
-	if ((spcr->base_addr.space_id != ACPI_SERIAL_PCICONF_SPACE) &&
-	    (spcr->int_type == ACPI_SERIAL_INT_SAPIC)) {
-
-		/* We have a UART in memory space with an SAPIC interrupt */
-
-		gsi = (spcr->global_int[3] << 24) |
-		      (spcr->global_int[2] << 16) |
-		      (spcr->global_int[1] << 8)  |
-		      (spcr->global_int[0]);
-
-		if (!acpi_find_iosapic(gsi, &gsi_base, &iosapic_address))
-			iosapic_register_intr(gsi, 1, 1,
-					      gsi_base, iosapic_address);
-	}
-	return 0;
-}
-
-#endif /*CONFIG_SERIAL_ACPI*/
-
-
 unsigned long __init
 acpi_find_rsdp (void)
 {
@@ -727,10 +673,6 @@
 	 */
 	if (acpi_table_parse(ACPI_FACP, acpi_parse_fadt) < 1)
 		printk(KERN_ERR PREFIX "Can't find FADT\n");
-
-#ifdef CONFIG_SERIAL_ACPI
-	acpi_table_parse(ACPI_SPCR, acpi_parse_spcr);
-#endif
 
 #ifdef CONFIG_SMP
 	if (available_cpus == 0) {
diff -Nru a/drivers/char/Makefile b/drivers/char/Makefile
--- a/drivers/char/Makefile	Wed Oct  8 09:08:32 2003
+++ b/drivers/char/Makefile	Wed Oct  8 09:08:32 2003
@@ -182,6 +182,7 @@
 obj-$(CONFIG_HIL) += hp_keyb.o
 obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o
 obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o
+obj-$(CONFIG_HP_SIMSERIAL) += simserial.o
 obj-$(CONFIG_ROCKETPORT) += rocket.o
 obj-$(CONFIG_MOXA_SMARTIO) += mxser.o
 obj-$(CONFIG_MOXA_INTELLIO) += moxa.o
diff -Nru a/drivers/net/tg3.c b/drivers/net/tg3.c
--- a/drivers/net/tg3.c	Wed Oct  8 09:08:32 2003
+++ b/drivers/net/tg3.c	Wed Oct  8 09:08:32 2003
@@ -50,8 +50,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"1.4"
-#define DRV_MODULE_RELDATE	"Feb 1, 2003"
+#define DRV_MODULE_VERSION	"1.4c"
+#define DRV_MODULE_RELDATE	"Feb 18, 2003"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -210,6 +210,12 @@
 	tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
 }
 
+static inline void tg3_cond_int(struct tg3 *tp)
+{
+	if (tp->hw_status->status & SD_STATUS_UPDATED)
+		tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
+}
+
 static void tg3_enable_ints(struct tg3 *tp)
 {
 	tw32(TG3PCI_MISC_HOST_CTRL,
@@ -217,9 +223,55 @@
 	tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000000);
 	tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
 
-	if (tp->hw_status->status & SD_STATUS_UPDATED)
-		tw32(GRC_LOCAL_CTRL,
-		     tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
+	tg3_cond_int(tp);
+}
+
+/* these netif_xxx funcs should be moved into generic net layer */
+static void netif_poll_disable(struct net_device *dev)
+{
+	while (test_and_set_bit(__LINK_STATE_RX_SCHED, &dev->state)) {
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(1);
+	}
+}
+
+static inline void netif_poll_enable(struct net_device *dev)
+{
+	clear_bit(__LINK_STATE_RX_SCHED, &dev->state);
+}
+
+/* same as netif_rx_complete, except that local_irq_save(flags)
+ * has already been issued
+ */
+static inline void __netif_rx_complete(struct net_device *dev)
+{
+	if (!test_bit(__LINK_STATE_RX_SCHED, &dev->state)) BUG();
+	list_del(&dev->poll_list);
+	clear_bit(__LINK_STATE_RX_SCHED, &dev->state);
+}
+
+static inline void netif_tx_disable(struct net_device *dev)
+{
+	spin_lock_bh(&dev->xmit_lock);
+	netif_stop_queue(dev);
+	spin_unlock_bh(&dev->xmit_lock);
+}
+
+static inline void tg3_netif_stop(struct tg3 *tp)
+{
+	netif_poll_disable(tp->dev);
+	netif_tx_disable(tp->dev);
+}
+
+static inline void tg3_netif_start(struct tg3 *tp)
+{
+	netif_wake_queue(tp->dev);
+	/* NOTE: unconditional netif_wake_queue is only appropriate
+	 * so long as all callers are assured to have free tx slots
+	 * (such as after tg3_init_hw)
+	 */
+	netif_poll_enable(tp->dev);
+	tg3_cond_int(tp);
 }
 
 static void tg3_switch_clocks(struct tg3 *tp)
@@ -381,7 +433,6 @@
 }
 
 static int tg3_setup_phy(struct tg3 *);
-static int tg3_halt(struct tg3 *);
 
 static int tg3_set_power_state(struct tg3 *tp, int state)
 {
@@ -452,8 +503,6 @@
 		tg3_setup_phy(tp);
 	}
 
-	tg3_halt(tp);
-
 	pci_read_config_word(tp->pdev, pm + PCI_PM_PMC, &power_caps);
 
 	if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) {
@@ -2038,7 +2087,12 @@
 		spin_unlock(&tp->tx_lock);
 	}
 
-	/* run RX thread, within the bounds set by NAPI */
+	spin_unlock_irqrestore(&tp->lock, flags);
+
+	/* run RX thread, within the bounds set by NAPI.
+	 * All RX "locking" is done by ensuring outside
+	 * code synchronizes with dev->poll()
+	 */
 	done = 1;
 	if (sblk->idx[0].rx_producer != tp->rx_rcb_ptr) {
 		int orig_budget = *budget;
@@ -2058,12 +2112,12 @@
 
 	/* if no more work, tell net stack and NIC we're done */
 	if (done) {
-		netif_rx_complete(netdev);
+		spin_lock_irqsave(&tp->lock, flags);
+		__netif_rx_complete(netdev);
 		tg3_enable_ints(tp);
+		spin_unlock_irqrestore(&tp->lock, flags);
 	}
 
-	spin_unlock_irqrestore(&tp->lock, flags);
-
 	return (done ? 0 : 1);
 }
 
@@ -2130,17 +2184,21 @@
 
 static void tg3_init_rings(struct tg3 *);
 static int tg3_init_hw(struct tg3 *);
+static int tg3_halt(struct tg3 *);
 
-static void tg3_tx_timeout(struct net_device *dev)
+static void tg3_reset_task(void *_data)
 {
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = _data;
+	unsigned int restart_timer;
 
-	printk(KERN_ERR PFX "%s: transmit timed out, resetting\n",
-	       dev->name);
+	tg3_netif_stop(tp);
 
 	spin_lock_irq(&tp->lock);
 	spin_lock(&tp->tx_lock);
 
+	restart_timer = tp->tg3_flags2 & TG3_FLG2_RESTART_TIMER;
+	tp->tg3_flags2 &= ~TG3_FLG2_RESTART_TIMER;
+
 	tg3_halt(tp);
 	tg3_init_rings(tp);
 	tg3_init_hw(tp);
@@ -2148,7 +2206,20 @@
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
 
-	netif_wake_queue(dev);
+	tg3_netif_start(tp);
+
+	if (restart_timer)
+		mod_timer(&tp->timer, jiffies + 1);
+}
+
+static void tg3_tx_timeout(struct net_device *dev)
+{
+	struct tg3 *tp = dev->priv;
+
+	printk(KERN_ERR PFX "%s: transmit timed out, resetting\n",
+	       dev->name);
+
+	schedule_task(&tp->reset_task);
 }
 
 #if !PCI_DMA_BUS_IS_PHYS
@@ -2654,6 +2725,7 @@
 		return 0;
 	}
 
+	tg3_netif_stop(tp);
 	spin_lock_irq(&tp->lock);
 	spin_lock(&tp->tx_lock);
 
@@ -2666,6 +2738,7 @@
 
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
+	tg3_netif_start(tp);
 
 	return 0;
 }
@@ -3041,6 +3114,7 @@
 static void tg3_chip_reset(struct tg3 *tp)
 {
 	u32 val;
+	u32 flags_save;
 
 	/* Force NVRAM to settle.
 	 * This deals with a chip bug which can result in EEPROM
@@ -3057,8 +3131,21 @@
 		}
 	}
 
+	/*
+	 * We must avoid the readl() that normally takes place.
+	 * It locks machines, causes machine checks, and other
+	 * fun things.  So, temporarily disable the 5701
+	 * hardware workaround, while we do the reset.
+	 */
+	flags_save = tp->tg3_flags;
+	tp->tg3_flags &= ~TG3_FLAG_5701_REG_WRITE_BUG;
+
+	/* do the reset */
 	tw32(GRC_MISC_CFG, GRC_MISC_CFG_CORECLK_RESET);
 
+	/* restore 5701 hardware bug workaround flag */
+	tp->tg3_flags = flags_save;
+
 	/* Flush PCI posted writes.  The normal MMIO registers
 	 * are inaccessible at this time so this is the only
 	 * way to make this reliably.  I tried to use indirect
@@ -4360,9 +4447,11 @@
 	}
 
 	if (!(tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
-		tg3_halt(tp);
-		tg3_init_rings(tp);
-		tg3_init_hw(tp);
+		tp->tg3_flags2 |= TG3_FLG2_RESTART_TIMER;
+		spin_unlock(&tp->tx_lock);
+		spin_unlock_irqrestore(&tp->lock, flags);
+		schedule_task(&tp->reset_task);
+		return;
 	}
 
 	/* This part only runs once per second. */
@@ -4493,8 +4582,6 @@
 		return err;
 	}
 
-	netif_start_queue(dev);
-
 	spin_lock_irq(&tp->lock);
 	spin_lock(&tp->tx_lock);
 
@@ -4503,6 +4590,8 @@
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
 
+	netif_start_queue(dev);
+
 	return 0;
 }
 
@@ -5268,6 +5357,7 @@
 		    (ering.tx_pending > TG3_TX_RING_SIZE - 1))
 			return -EINVAL;
 
+		tg3_netif_stop(tp);
 		spin_lock_irq(&tp->lock);
 		spin_lock(&tp->tx_lock);
 
@@ -5281,6 +5371,7 @@
 		netif_wake_queue(tp->dev);
 		spin_unlock(&tp->tx_lock);
 		spin_unlock_irq(&tp->lock);
+		tg3_netif_start(tp);
 
 		return 0;
 	}
@@ -5303,6 +5394,7 @@
 		if (copy_from_user(&epause, useraddr, sizeof(epause)))
 			return -EFAULT;
 
+		tg3_netif_stop(tp);
 		spin_lock_irq(&tp->lock);
 		spin_lock(&tp->tx_lock);
 		if (epause.autoneg)
@@ -5322,6 +5414,7 @@
 		tg3_init_hw(tp);
 		spin_unlock(&tp->tx_lock);
 		spin_unlock_irq(&tp->lock);
+		tg3_netif_start(tp);
 
 		return 0;
 	}
@@ -6671,6 +6764,7 @@
 	spin_lock_init(&tp->lock);
 	spin_lock_init(&tp->tx_lock);
 	spin_lock_init(&tp->indirect_lock);
+	PREPARE_TQUEUE(&tp->reset_task, tg3_reset_task, tp);
 
 	tp->regs = (unsigned long) ioremap(tg3reg_base, tg3reg_len);
 	if (tp->regs == 0UL) {
@@ -6801,6 +6895,8 @@
 	if (!netif_running(dev))
 		return 0;
 
+	tg3_netif_stop(tp);
+
 	spin_lock_irq(&tp->lock);
 	spin_lock(&tp->tx_lock);
 	tg3_disable_ints(tp);
@@ -6827,6 +6923,7 @@
 		spin_unlock_irq(&tp->lock);
 
 		netif_device_attach(dev);
+		tg3_netif_start(tp);
 	}
 
 	return err;
@@ -6856,6 +6953,8 @@
 
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
+
+	tg3_netif_start(tp);
 
 	return 0;
 }
diff -Nru a/drivers/net/tg3.h b/drivers/net/tg3.h
--- a/drivers/net/tg3.h	Wed Oct  8 09:08:32 2003
+++ b/drivers/net/tg3.h	Wed Oct  8 09:08:32 2003
@@ -1795,7 +1795,6 @@
 #define TG3_FLAG_USE_LINKCHG_REG	0x00000008
 #define TG3_FLAG_USE_MI_INTERRUPT	0x00000010
 #define TG3_FLAG_ENABLE_ASF		0x00000020
-#define TG3_FLAG_5701_REG_WRITE_BUG	0x00000040
 #define TG3_FLAG_POLL_SERDES		0x00000080
 #define TG3_FLAG_MBOX_WRITE_REORDER	0x00000100
 #define TG3_FLAG_PCIX_TARGET_HWBUG	0x00000200
diff -Nru a/include/linux/highmem.h b/include/linux/highmem.h
--- a/include/linux/highmem.h	Wed Oct  8 09:08:32 2003
+++ b/include/linux/highmem.h	Wed Oct  8 09:08:32 2003
@@ -84,7 +84,7 @@
 static inline void clear_user_highpage(struct page *page, unsigned long vaddr)
 {
 	void *addr = kmap_atomic(page, KM_USER0);
-	clear_user_page(addr, vaddr);
+	clear_user_page(addr, vaddr, page);
 	kunmap_atomic(addr, KM_USER0);
 }
 
@@ -116,7 +116,7 @@
 
 	vfrom = kmap_atomic(from, KM_USER0);
 	vto = kmap_atomic(to, KM_USER1);
-	copy_user_page(vto, vfrom, vaddr);
+	copy_user_page(vto, vfrom, vaddr, to);
 	kunmap_atomic(vfrom, KM_USER0);
 	kunmap_atomic(vto, KM_USER1);
 }