[kernel] r8062 - in dists/sid/linux-2.6/debian: . patches
patches/series
Christian T. Steigies
cts at alioth.debian.org
Sun Dec 31 16:31:00 UTC 2006
Author: cts
Date: Sun Dec 31 17:30:59 2006
New Revision: 8062
Added:
dists/sid/linux-2.6/debian/patches/m68k-atari-scsi2.patch
dists/sid/linux-2.6/debian/patches/m68k-mac-cuda.patch
dists/sid/linux-2.6/debian/patches/m68k-mac-mace.patch
Modified:
dists/sid/linux-2.6/debian/changelog
dists/sid/linux-2.6/debian/patches/series/9-extra
Log:
atari scsi driver fixes by Michael and mac mace and cuda fixes by Finn
Modified: dists/sid/linux-2.6/debian/changelog
==============================================================================
--- dists/sid/linux-2.6/debian/changelog (original)
+++ dists/sid/linux-2.6/debian/changelog Sun Dec 31 17:30:59 2006
@@ -49,6 +49,8 @@
[ Christian T. Steigies ]
* m68k/atari: enable keyboard, mouse and fb drivers
* m68k/atari: fixes for ethernec and video driver by Michael Schmitz
+ * m68k/atari: fixes for scsi driver by Michael Schmitz
+ * m68k/mac: fixes for mace and cuda driver by Finn Thain
[ maximilian attems ]
* Add stable release 2.6.18.6:
@@ -110,7 +112,7 @@
- r8169: more magic during initialization of the hardware
- r8169: perform a PHY reset before any other operation at boot time
- r8169: Fix iteration variable sign
- - r8169: remove extraneous Cmd{Tx/Rx}Enb write
+ - r8169: remove extraneous Cmd{Tx/Rx}Enb write
[ Jurij Smakov ]
* Add bugfix/sparc/isa-dev-no-reg.patch to make sure that
@@ -122,7 +124,7 @@
memory accesses in ehci-hub-control() by adding an alignment attribute
to the tbuf array declaration. Thanks to David Miller for the patch.
- -- maximilian attems <maks at sternwelten.at> Sun, 31 Dec 2006 17:07:53 +0100
+ -- Christian T. Steigies <cts at debian.org> Sun, 31 Dec 2006 17:29:17 +0100
linux-2.6 (2.6.18-8) unstable; urgency=low
Added: dists/sid/linux-2.6/debian/patches/m68k-atari-scsi2.patch
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/m68k-atari-scsi2.patch Sun Dec 31 17:30:59 2006
@@ -0,0 +1,349 @@
+I've looked at the SCSI situation in more detail, and updated the Atari
+SCSI code to cope with the changes in 2.6 (scsi_error expect different
+return codes; queuecmnd called from softirq and cannot sleep). I get no
+more lockups, but writing to a ZIP drive corrupts data on the drive. May
+just be a broken ZIP drive, who knows. I need to try with a real SCSI
+disk...
+
+Christian, please apply this on top of my other 2.6.18 patch.
+
+
+diff -u source-m68k-none/drivers/scsi/atari_scsi.c source-m68k-msch/drivers/scsi/atari_scsi.c
+--- source-m68k-none/drivers/scsi/atari_scsi.c 2006-12-31 14:06:09.000000000 +0100
++++ source-m68k-msch/drivers/scsi/atari_scsi.c 2006-12-31 16:29:46.000000000 +0100
+@@ -67,12 +67,40 @@
+
+ #include <linux/module.h>
+
+-#define NDEBUG (0)
++#define NDEBUG_ARBITRATION 0x1
++#define NDEBUG_AUTOSENSE 0x2
++#define NDEBUG_DMA 0x4
++#define NDEBUG_HANDSHAKE 0x8
++#define NDEBUG_INFORMATION 0x10
++#define NDEBUG_INIT 0x20
++#define NDEBUG_INTR 0x40
++#define NDEBUG_LINKED 0x80
++#define NDEBUG_MAIN 0x100
++#define NDEBUG_NO_DATAOUT 0x200
++#define NDEBUG_NO_WRITE 0x400
++#define NDEBUG_PIO 0x800
++#define NDEBUG_PSEUDO_DMA 0x1000
++#define NDEBUG_QUEUES 0x2000
++#define NDEBUG_RESELECTION 0x4000
++#define NDEBUG_SELECTION 0x8000
++#define NDEBUG_USLEEP 0x10000
++#define NDEBUG_LAST_BYTE_SENT 0x20000
++#define NDEBUG_RESTART_SELECT 0x40000
++#define NDEBUG_EXTENDED 0x80000
++#define NDEBUG_C400_PREAD 0x100000
++#define NDEBUG_C400_PWRITE 0x200000
++#define NDEBUG_LISTS 0x400000
+
+ #define NDEBUG_ABORT 0x800000
+ #define NDEBUG_TAGS 0x1000000
+ #define NDEBUG_MERGING 0x2000000
+
++#define NDEBUG_ANY 0xFFFFFFFFUL
++
++#define NDEBUG (0)
++//#define NDEBUG (NDEBUG_MAIN)
++
++
+ #define AUTOSENSE
+ /* For the Atari version, use only polled IO or REAL_DMA */
+ #define REAL_DMA
+@@ -506,6 +534,15 @@
+ * again (but others waiting longer more probably will win).
+ */
+
++/* MSch 20061228: in 2.6, the fairness wait appears to open a race with
++* the IDE driver's use of the lock, resulting in scheduling_in_interrupt
++* level BUG() messages.
++* The low level queuecmd function now appears to be called from soft
++* interrupt context (block queue task??) and cannot sleep on the lock
++* anymore once IDE has stolen the lock.
++* Can we return 'please retry later' to the block queue task or mid level??
++* MSch 20061229: the race persists regardless ... leave it off for now.
++*/
+ static void
+ falcon_release_lock_if_possible( struct NCR5380_hostdata * hostdata )
+ {
+@@ -529,7 +566,9 @@
+ }
+ falcon_got_lock = 0;
+ stdma_release();
++#if defined(FALCON_FAIRNESS_WAIT)
+ wake_up( &falcon_fairness_wait );
++#endif
+ }
+
+ local_irq_restore(flags);
+@@ -550,20 +589,38 @@
+ * Complicated, complicated.... Sigh...
+ */
+
+-static void falcon_get_lock( void )
++/* MSch 20061229: atari_queue_command gets called from softirq context quite
++ * heavily in the 2.6 kernel series. Since atari_queue_command might need to
++ * sleep in order to grab the ST-DMA lock, I have modified falcon_get_lock to
++ * immediately return with error status if called in softirq context with the
++ * lock not currently held by the SCSI driver, and the ST-DMA locked by some
++ * other driver. atari_queue_command then returns SCSI_MLQUEUE_HOST_BUSY and
++ * prevents further commands from issueing.
++ */
++
++static int falcon_get_lock( void )
+ {
+ unsigned long flags;
+
+- if (IS_A_TT()) return;
++ if (IS_A_TT()) return 0;
+
+ local_irq_save(flags);
+
++#if defined (FALCON_FAIRNESS_WAIT)
+ while( !in_interrupt() && falcon_got_lock && stdma_others_waiting() )
+ sleep_on( &falcon_fairness_wait );
++#endif
+
+ while (!falcon_got_lock) {
+- if (in_interrupt())
++ if (in_irq())
+ panic( "Falcon SCSI hasn't ST-DMA lock in interrupt" );
++ /* we may not sleep in soft interrupts neither, so bail out */
++ if (in_softirq() && stdma_islocked()) {
++ printk(KERN_INFO "Falcon SCSI does not hold ST-DMA lock in softirq!\n" );
++ local_irq_restore(flags);
++ return 1;
++ }
++
+ if (!falcon_trying_lock) {
+ falcon_trying_lock = 1;
+ stdma_lock(scsi_falcon_intr, NULL);
+@@ -579,6 +636,8 @@
+ local_irq_restore(flags);
+ if (!falcon_got_lock)
+ panic("Falcon SCSI: someone stole the lock :-(\n");
++
++ return 0;
+ }
+
+
+@@ -826,6 +885,8 @@
+ struct NCR5380_hostdata *hostdata =
+ (struct NCR5380_hostdata *)cmd->device->host->hostdata;
+
++ printk( "scsi%d: resetting the SCSI bus!\n", (cmd)->device->host->host_no);
++
+ /* For doing the reset, SCSI interrupts must be disabled first,
+ * since the 5380 raises its IRQ line while _RST is active and we
+ * can't disable interrupts completely, since we need the timer.
+@@ -855,8 +916,10 @@
+ else {
+ atari_turnon_irq( IRQ_MFP_FSCSI );
+ }
+- if ((rv & SCSI_RESET_ACTION) == SCSI_RESET_SUCCESS)
++ if (rv == SUCCESS) {
+ falcon_release_lock_if_possible(hostdata);
++ }
++ printk( "scsi%d: bus reset done!\n", (cmd)->device->host->host_no);
+
+ return( rv );
+ }
+
+diff -u source-m68k-none/drivers/scsi/atari_NCR5380.c source-m68k-msch/drivers/scsi/atari_NCR5380.c
+--- source-m68k-none/drivers/scsi/atari_NCR5380.c 2006-12-31 14:06:09.000000000 +0100
++++ source-m68k-msch/drivers/scsi/atari_NCR5380.c 2006-12-31 16:39:34.000000000 +0100
+@@ -474,7 +474,8 @@
+ virt_to_phys(page_address(cmd->SCp.buffer[1].page)+
+ cmd->SCp.buffer[1].offset) == endaddr; ) {
+ MER_PRINTK("VTOP(%p) == %08lx -> merging\n",
+- cmd->SCp.buffer[1].address, endaddr);
++ page_address(cmd->SCp.buffer[1].page)+cmd->SCp.buffer[1].offset,
++ endaddr);
+ #if (NDEBUG & NDEBUG_MERGING)
+ ++cnt;
+ #endif
+@@ -947,17 +948,6 @@
+ #endif
+
+ /*
+- * We use the host_scribble field as a pointer to the next command
+- * in a queue
+- */
+-
+- NEXT(cmd) = NULL;
+- cmd->scsi_done = done;
+-
+- cmd->result = 0;
+-
+-
+- /*
+ * Insert the cmd into the issue queue. Note that REQUEST SENSE
+ * commands are added to the head of the queue since any command will
+ * clear the contingent allegiance condition that exists and the
+@@ -978,10 +968,32 @@
+ * alter queues and touch the lock.
+ */
+ if (!IS_A_TT()) {
++ int rv;
++ /* MSch: since we get called from softirq context here, and cannot
++ * sleep safely, the return status of falcon_get_lock is now used to
++ * figure out if we could successfully lock, or need to bail out.
++ * Signal the midlevel we're unable to queue the command in this case.
++ */
++
+ oldto = update_timeout(cmd, 0);
+- falcon_get_lock();
+- update_timeout(cmd, oldto);
++ rv = falcon_get_lock();
++ atari_scsi_update_timeout(cmd, oldto);
++ if (rv) {
++ local_irq_restore(flags);
++ return SCSI_MLQUEUE_HOST_BUSY;
++ }
+ }
++
++ /*
++ * We use the host_scribble field as a pointer to the next command
++ * in a queue
++ */
++
++ NEXT(cmd) = NULL;
++ cmd->scsi_done = done;
++
++ cmd->result = 0;
++
+ if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
+ LIST(cmd, hostdata->issue_queue);
+ NEXT(cmd) = hostdata->issue_queue;
+@@ -1005,10 +1017,13 @@
+ * If we're not in an interrupt, we can call NCR5380_main()
+ * unconditionally, because it cannot be already running.
+ */
+- if (in_interrupt() || ((flags >> 8) & 7) >= 6)
++
++ /* MSch: in 2.6.19, we need to unconditionally use the task queue
++ * instead of directly starting main. Yet another side effect of
++ * the softirq business, I bet. */
++
+ queue_main();
+- else
+- NCR5380_main(NULL);
++
+ return 0;
+ }
+
+@@ -2630,7 +2645,7 @@
+ * host byte of the result field to, if zero DID_ABORTED is
+ * used.
+ *
+- * Returns : 0 - success, -1 on failure.
++ * Returns : SUCCESS - success, FAILED on failure.
+ *
+ * XXX - there is no way to abort the command that is currently
+ * connected, you have to wait for it to complete. If this is
+@@ -2700,11 +2715,12 @@
+ local_irq_restore(flags);
+ cmd->scsi_done(cmd);
+ falcon_release_lock_if_possible( hostdata );
+- return SCSI_ABORT_SUCCESS;
++ return SUCCESS;
+ } else {
++ /* Why is this not restoring IRQs?? */
+ /* local_irq_restore(flags); */
+ printk("scsi%d: abort of connected command failed!\n", HOSTNO);
+- return SCSI_ABORT_ERROR;
++ return FAILED;
+ }
+ }
+ #endif
+@@ -2728,7 +2744,7 @@
+ * yet... */
+ tmp->scsi_done(tmp);
+ falcon_release_lock_if_possible( hostdata );
+- return SCSI_ABORT_SUCCESS;
++ return SUCCESS;
+ }
+
+ /*
+@@ -2745,7 +2761,7 @@
+ if (hostdata->connected) {
+ local_irq_restore(flags);
+ ABRT_PRINTK("scsi%d: abort failed, command connected.\n", HOSTNO);
+- return SCSI_ABORT_SNOOZE;
++ return FAILED;
+ }
+
+ /*
+@@ -2807,7 +2823,7 @@
+ local_irq_restore(flags);
+ tmp->scsi_done(tmp);
+ falcon_release_lock_if_possible( hostdata );
+- return SCSI_ABORT_SUCCESS;
++ return SUCCESS;
+ }
+ }
+
+@@ -2831,7 +2847,7 @@
+ */
+ falcon_release_lock_if_possible( hostdata );
+
+- return SCSI_ABORT_NOT_RUNNING;
++ return SUCCESS;
+ }
+
+
+@@ -2840,7 +2856,7 @@
+ *
+ * Purpose : reset the SCSI bus.
+ *
+- * Returns : SCSI_RESET_WAKEUP
++ * Returns : SUCCESS
+ *
+ */
+
+@@ -2905,15 +2921,15 @@
+ */
+
+ if ((cmd = connected)) {
+- ABRT_PRINTK("scsi%d: reset aborted a connected command\n", H_NO(cmd));
+- cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
+- cmd->scsi_done( cmd );
++ ABRT_PRINTK("scsi%d: reset aborted a connected command, calling scsi_done() ...\n", H_NO(cmd));
++ cmd->result = (DID_RESET << 16);
++ cmd->scsi_done( cmd );
+ }
+
+ for (i = 0; (cmd = disconnected_queue); ++i) {
+ disconnected_queue = NEXT(cmd);
+ NEXT(cmd) = NULL;
+- cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
++ cmd->result = (DID_RESET << 16);
+ cmd->scsi_done( cmd );
+ }
+ if (i > 0)
+@@ -2930,7 +2946,7 @@
+ * the midlevel code that the reset was SUCCESSFUL, and there is no
+ * need to 'wake up' the commands by a request_sense
+ */
+- return SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET;
++ return SUCCESS;
+ #else /* 1 */
+
+ /* MSch: new-style reset handling: let the mid-level do what it can */
+@@ -2978,7 +2994,9 @@
+ local_irq_restore(flags);
+
+ /* we did no complete reset of all commands, so a wakeup is required */
+- return SCSI_RESET_WAKEUP | SCSI_RESET_BUS_RESET;
++ /* The new error handler code implicitly does this for us anyway */
++ return SUCCESS;
++
+ #endif /* 1 */
+ }
+
+Signed-Off-By: schmitz at debian.org
+
+ Michael
Added: dists/sid/linux-2.6/debian/patches/m68k-mac-cuda.patch
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/m68k-mac-cuda.patch Sun Dec 31 17:30:59 2006
@@ -0,0 +1,87 @@
+
+Fix the flakiness in the CUDA ADB driver (keypresses getting wedged down
+or ADB just going AWOL altogether). Stops lost VIA1 interrupts.
+
+Tested on Quadra 840av & 660av, LC630 and LC475. (This does not address
+the problems with the other m68k Mac ADB drivers.)
+
+Signed-off-by: Finn Thain <fthain at telegraphics.com.au>
+
+ arch/m68k/mac/via.c | 2 +-
+ drivers/macintosh/via-cuda.c | 26 +++++++++++++++++++++-----
+ 2 files changed, 22 insertions(+), 6 deletions(-)
+
+Index: linux-2.6.18/drivers/macintosh/via-cuda.c
+===================================================================
+--- linux-2.6.18.orig/drivers/macintosh/via-cuda.c 2006-12-26 13:48:02.000000000 +1100
++++ linux-2.6.18/drivers/macintosh/via-cuda.c 2006-12-26 14:11:43.000000000 +1100
+@@ -429,16 +429,19 @@ cuda_start(void)
+ void
+ cuda_poll(void)
+ {
+- unsigned long flags;
+-
+ /* cuda_interrupt only takes a normal lock, we disable
+ * interrupts here to avoid re-entering and thus deadlocking.
+- * An option would be to disable only the IRQ source with
+- * disable_irq(), would that work on m68k ? --BenH
+ */
++#ifdef CONFIG_MAC
++ disable_irq(IRQ_MAC_ADB);
++ cuda_interrupt(0, NULL, NULL);
++ enable_irq(IRQ_MAC_ADB);
++#else
++ unsigned long flags;
+ local_irq_save(flags);
+ cuda_interrupt(0, NULL, NULL);
+ local_irq_restore(flags);
++#endif
+ }
+
+ static irqreturn_t
+@@ -453,13 +456,26 @@ cuda_interrupt(int irq, void *arg, struc
+
+ spin_lock(&cuda_lock);
+
++#ifdef CONFIG_MAC
++ /* only do this when polling */
++ if (!arg) {
++ virq = in_8(&via[IFR]) & 0x7f;
++ if ((virq & SR_INT) == 0) {
++ spin_unlock(&cuda_lock);
++ return IRQ_NONE;
++ }
++ out_8(&via[IFR], SR_INT);
++ }
++#else
++ /* it would appear that powermacs don't use the other VIA interrupts */
+ virq = in_8(&via[IFR]) & 0x7f;
+ out_8(&via[IFR], virq);
+ if ((virq & SR_INT) == 0) {
+ spin_unlock(&cuda_lock);
+ return IRQ_NONE;
+ }
+-
++#endif
++
+ status = (~in_8(&via[B]) & (TIP|TREQ)) | (in_8(&via[ACR]) & SR_OUT);
+ /* printk("cuda_interrupt: state=%d status=%x\n", cuda_state, status); */
+ switch (cuda_state) {
+Index: linux-2.6.18/arch/m68k/mac/via.c
+===================================================================
+--- linux-2.6.18.orig/arch/m68k/mac/via.c 2006-12-26 13:48:02.000000000 +1100
++++ linux-2.6.18/arch/m68k/mac/via.c 2006-12-26 14:11:43.000000000 +1100
+@@ -431,8 +431,8 @@ irqreturn_t via1_irq(int irq, void *dev_
+ for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1)
+ if (events & irq_bit) {
+ via1[vIER] = irq_bit;
+- m68k_handle_int(VIA1_SOURCE_BASE + i, regs);
+ via1[vIFR] = irq_bit;
++ m68k_handle_int(VIA1_SOURCE_BASE + i, regs);
+ via1[vIER] = irq_bit | 0x80;
+ }
+
+-
+To unsubscribe from this list: send the line "unsubscribe linux-m68k" in
+the body of a message to majordomo at vger.kernel.org
+More majordomo info at http://vger.kernel.org/majordomo-info.html
Added: dists/sid/linux-2.6/debian/patches/m68k-mac-mace.patch
==============================================================================
--- (empty file)
+++ dists/sid/linux-2.6/debian/patches/m68k-mac-mace.patch Sun Dec 31 17:30:59 2006
@@ -0,0 +1,649 @@
+Fix a race condition in the transmit code, where the dma interrupt could
+update the free tx buffer count concurrently and wedge the tx queue.
+
+Fix the misuse of the rx frame status and rx frame length registers: no
+more "fifo overrun" errors caused by the OFLOW bit being tested in the
+frame length register, and no more missed packets due to incorrect length
+taken from status register.
+
+Fix a panic (skb_over_panic BUG) caused by allocating and then copying an
+incoming packet while the packet length register was changing.
+
+Cut-and-paste reset code from the powermac mace driver (mace.c), so the
+NIC functions when MacOS does not initialise it (important for anyone
+wanting to use the Emile boot loader).
+
+Cut-and-paste error counting and timeout recovery code from the powermac
+mace driver (mace.c).
+
+Fix a race condition in the PSC interrupt dispatch code where the
+interrupt flag was cleared after the handler ran (same bug that was fixed
+recently in the VIA2 interrupt dispatcher).
+
+Since I've run out of ways to make it fail, and since it performs well
+now, promote the driver from EXPERIMENTAL status. Tested on both quadra
+840av and 660av.
+
+Signed-off-by: Finn Thain <fthain at telegraphics.com.au>
+
+--- source-m68k-none/arch/m68k/mac/psc.c 2006-09-20 05:42:06.000000000 +0200
++++ source-m68k-finn/arch/m68k/mac/psc.c 2006-12-31 16:48:50.000000000 +0100
+@@ -149,8 +149,8 @@
+ for (i = 0, irq_bit = 1 ; i < 4 ; i++, irq_bit <<= 1) {
+ if (events & irq_bit) {
+ psc_write_byte(pIER, irq_bit);
+- m68k_handle_int(base_irq + i, regs);
+ psc_write_byte(pIFR, irq_bit);
++ m68k_handle_int(base_irq + i, regs);
+ psc_write_byte(pIER, irq_bit | 0x80);
+ }
+ }
+--- source-m68k-none/drivers/net/Kconfig 2006-12-31 16:45:54.000000000 +0100
++++ source-m68k-finn/drivers/net/Kconfig 2006-12-31 16:49:28.000000000 +0100
+@@ -335,8 +335,8 @@
+ be called macsonic.
+
+ config MACMACE
+- bool "Macintosh (AV) onboard MACE ethernet (EXPERIMENTAL)"
+- depends on NET_ETHERNET && MAC && EXPERIMENTAL
++ bool "Macintosh (AV) onboard MACE ethernet"
++ depends on NET_ETHERNET && MAC
+ select CRC32
+ help
+ Support for the onboard AMD 79C940 MACE Ethernet controller used in
+--- source-m68k-none/drivers/net/macmace.c 2006-12-31 16:45:54.000000000 +0100
++++ source-m68k-finn/drivers/net/macmace.c 2006-12-31 17:12:38.000000000 +0100
+@@ -36,6 +36,9 @@
+ #define N_RX_PAGES ((N_RX_RING * 0x0800 + PAGE_SIZE - 1) / PAGE_SIZE)
+ #define TX_TIMEOUT HZ
+
++/* Chip rev needs workaround on HW & multicast addr change */
++#define BROKEN_ADDRCHG_REV 0x0941
++
+ /* Bits in transmit DMA status */
+ #define TX_DMA_ERR 0x80
+
+@@ -54,15 +57,20 @@
+ struct net_device_stats stats;
+ int rx_slot, rx_tail;
+ int tx_slot, tx_sloti, tx_count;
++ int chipid;
+ };
+
+ struct mace_frame {
+- u16 len;
+- u16 status;
+- u16 rntpc;
+- u16 rcvcc;
+- u32 pad1;
+- u32 pad2;
++ u8 rcvcnt;
++ u8 pad1;
++ u8 rcvsts;
++ u8 pad2;
++ u8 rntpc;
++ u8 pad3;
++ u8 rcvcc;
++ u8 pad4;
++ u32 pad5;
++ u32 pad6;
+ u8 data[1];
+ /* And frame continues.. */
+ };
+@@ -77,9 +85,11 @@
+ static struct net_device_stats *mace_stats(struct net_device *dev);
+ static void mace_set_multicast(struct net_device *dev);
+ static int mace_set_address(struct net_device *dev, void *addr);
++static void mace_reset(struct net_device *dev);
+ static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+ static irqreturn_t mace_dma_intr(int irq, void *dev_id, struct pt_regs *regs);
+ static void mace_tx_timeout(struct net_device *dev);
++static void __mace_set_address(struct net_device *dev, void *addr);
+
+ /* Bit-reverse one byte of an ethernet hardware address. */
+
+@@ -209,6 +219,8 @@
+ dev->irq = IRQ_MAC_MACE;
+ mp->dma_intr = IRQ_MAC_MACE_DMA;
+
++ mp->chipid = mp->mace->chipid_hi << 8 | mp->mace->chipid_lo;
++
+ /*
+ * The PROM contains 8 bytes which total 0xFF when XOR'd
+ * together. Due to the usual peculiar apple brain damage
+@@ -256,15 +268,92 @@
+ }
+
+ /*
++ * Reset the chip.
++ */
++
++static void mace_reset(struct net_device *dev)
++{
++ struct mace_data *mp = (struct mace_data *) dev->priv;
++ volatile struct mace *mb = mp->mace;
++ int i;
++
++ /* soft-reset the chip */
++ i = 200;
++ while (--i) {
++ mb->biucc = SWRST;
++ if (mb->biucc & SWRST) {
++ udelay(10);
++ continue;
++ }
++ break;
++ }
++ if (!i) {
++ printk(KERN_ERR "macmace: cannot reset chip!\n");
++ return;
++ }
++
++ mb->maccc = 0; /* turn off tx, rx */
++ mb->imr = 0xFF; /* disable all intrs for now */
++ i = mb->ir;
++
++ mb->biucc = XMTSP_64;
++ mb->utr = RTRD;
++ mb->fifocc = XMTFW_16 | RCVFW_64 | XMTFWU | RCVFWU | XMTBRST | RCVBRST;
++ mb->xmtfc = AUTO_PAD_XMIT; /* auto-pad short frames */
++ mb->rcvfc = 0;
++
++ /* load up the hardware address */
++ __mace_set_address(dev, dev->dev_addr);
++
++ /* clear the multicast filter */
++ if (mp->chipid == BROKEN_ADDRCHG_REV)
++ mb->iac = LOGADDR;
++ else {
++ mb->iac = ADDRCHG | LOGADDR;
++ while ((mb->iac & ADDRCHG) != 0)
++ ;
++ }
++ for (i = 0; i < 8; ++i)
++ mb->ladrf = 0;
++
++ /* done changing address */
++ if (mp->chipid != BROKEN_ADDRCHG_REV)
++ mb->iac = 0;
++
++ mb->plscc = PORTSEL_AUI;
++}
++
++
++/*
+ * Load the address on a mace controller.
+ */
+
+-static int mace_set_address(struct net_device *dev, void *addr)
++static void __mace_set_address(struct net_device *dev, void *addr)
+ {
+- unsigned char *p = addr;
+ struct mace_data *mp = (struct mace_data *) dev->priv;
+ volatile struct mace *mb = mp->mace;
++ unsigned char *p = addr;
+ int i;
++
++ /* load up the hardware address */
++ if (mp->chipid == BROKEN_ADDRCHG_REV)
++ mb->iac = PHYADDR;
++ else {
++ mb->iac = ADDRCHG | PHYADDR;
++ while ((mb->iac & ADDRCHG) != 0)
++ ;
++ }
++ for (i = 0; i < 6; ++i)
++ mb->padr = dev->dev_addr[i] = p[i];
++ if (mp->chipid != BROKEN_ADDRCHG_REV)
++ mb->iac = 0;
++}
++
++static int mace_set_address(struct net_device *dev, void *addr)
++{
++ struct mace_data *mp = (struct mace_data *) dev->priv;
++ volatile struct mace *mb = mp->mace;
++
+ unsigned long flags;
+ u8 maccc;
+
+@@ -272,15 +361,10 @@
+
+ maccc = mb->maccc;
+
+- /* load up the hardware address */
+- mb->iac = ADDRCHG | PHYADDR;
+- while ((mb->iac & ADDRCHG) != 0);
+-
+- for (i = 0; i < 6; ++i) {
+- mb->padr = dev->dev_addr[i] = p[i];
+- }
++ __mace_set_address(dev, addr);
+
+ mb->maccc = maccc;
++
+ local_irq_restore(flags);
+
+ return 0;
+@@ -295,29 +379,9 @@
+ {
+ struct mace_data *mp = (struct mace_data *) dev->priv;
+ volatile struct mace *mb = mp->mace;
+-#if 0
+- int i;
+
+- i = 200;
+- while (--i) {
+- mb->biucc = SWRST;
+- if (mb->biucc & SWRST) {
+- udelay(10);
+- continue;
+- }
+- break;
+- }
+- if (!i) {
+- printk(KERN_ERR "%s: software reset failed!!\n", dev->name);
+- return -EAGAIN;
+- }
+-#endif
+-
+- mb->biucc = XMTSP_64;
+- mb->fifocc = XMTFW_16 | RCVFW_64 | XMTFWU | RCVFWU | XMTBRST | RCVBRST;
+- mb->xmtfc = AUTO_PAD_XMIT;
+- mb->plscc = PORTSEL_AUI;
+- /* mb->utr = RTRD; */
++ /* reset the chip */
++ mace_reset(dev);
+
+ if (request_irq(dev->irq, mace_interrupt, 0, dev->name, dev)) {
+ printk(KERN_ERR "%s: can't get irq %d\n", dev->name, dev->irq);
+@@ -360,33 +424,14 @@
+ psc_write_word(PSC_ENETWR_CTL, 0x0400);
+ psc_write_word(PSC_ENETRD_CTL, 0x0400);
+
+-#if 0
+- /* load up the hardware address */
+-
+- mb->iac = ADDRCHG | PHYADDR;
+-
+- while ((mb->iac & ADDRCHG) != 0);
+-
+- for (i = 0; i < 6; ++i)
+- mb->padr = dev->dev_addr[i];
+-
+- /* clear the multicast filter */
+- mb->iac = ADDRCHG | LOGADDR;
+-
+- while ((mb->iac & ADDRCHG) != 0);
+-
+- for (i = 0; i < 8; ++i)
+- mb->ladrf = 0;
+-
+- mb->plscc = PORTSEL_GPSI + ENPLSIO;
++ mace_rxdma_reset(dev);
++ mace_txdma_reset(dev);
+
++ /* turn it on! */
+ mb->maccc = ENXMT | ENRCV;
++ /* enable all interrupts except receive interrupts */
+ mb->imr = RCVINT;
+-#endif
+
+- mace_rxdma_reset(dev);
+- mace_txdma_reset(dev);
+-
+ return 0;
+ }
+
+@@ -419,15 +464,20 @@
+ static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev)
+ {
+ struct mace_data *mp = (struct mace_data *) dev->priv;
++ unsigned long flags;
+
+ /* Stop the queue if the buffer is full */
+
++ local_irq_save(flags);
+ if (!mp->tx_count) {
+ netif_stop_queue(dev);
+- return 1;
++ local_irq_restore(flags);
++ return NETDEV_TX_BUSY;
++
+ }
+ mp->tx_count--;
+-
++ local_irq_restore(flags);
++
+ mp->stats.tx_packets++;
+ mp->stats.tx_bytes += skb->len;
+
+@@ -461,7 +511,9 @@
+ int i, j;
+ u32 crc;
+ u8 maccc;
++ unsigned long flags;
+
++ local_irq_save(flags);
+ maccc = mb->maccc;
+ mb->maccc &= ~PROM;
+
+@@ -486,109 +538,96 @@
+ }
+ }
+
+- mb->iac = ADDRCHG | LOGADDR;
+- while (mb->iac & ADDRCHG);
+-
+- for (i = 0; i < 8; ++i) {
+- mb->ladrf = multicast_filter[i];
++ if (mp->chipid == BROKEN_ADDRCHG_REV)
++ mb->iac = LOGADDR;
++ else {
++ mb->iac = ADDRCHG | LOGADDR;
++ while ((mb->iac & ADDRCHG) != 0)
++ ;
++ }
++ for (i = 0; i < 8; ++i)
++ mb->ladrf = multicast_filter[i];
++ if (mp->chipid != BROKEN_ADDRCHG_REV)
++ mb->iac = 0;
+ }
+ }
+
+ mb->maccc = maccc;
++ local_irq_restore(flags);
+ }
+
+-/*
+- * Miscellaneous interrupts are handled here. We may end up
+- * having to bash the chip on the head for bad errors
+- */
+-
+ static void mace_handle_misc_intrs(struct mace_data *mp, int intr)
+ {
+ volatile struct mace *mb = mp->mace;
+ static int mace_babbles, mace_jabbers;
+
+- if (intr & MPCO) {
++ if (intr & MPCO)
+ mp->stats.rx_missed_errors += 256;
+- }
+- mp->stats.rx_missed_errors += mb->mpc; /* reading clears it */
+-
+- if (intr & RNTPCO) {
++ mp->stats.rx_missed_errors += mb->mpc; /* reading clears it */
++ if (intr & RNTPCO)
+ mp->stats.rx_length_errors += 256;
+- }
+ mp->stats.rx_length_errors += mb->rntpc; /* reading clears it */
+-
+- if (intr & CERR) {
++ if (intr & CERR)
+ ++mp->stats.tx_heartbeat_errors;
+- }
+- if (intr & BABBLE) {
+- if (mace_babbles++ < 4) {
+- printk(KERN_DEBUG "mace: babbling transmitter\n");
+- }
+- }
+- if (intr & JABBER) {
+- if (mace_jabbers++ < 4) {
+- printk(KERN_DEBUG "mace: jabbering transceiver\n");
+- }
+- }
++
++ if (intr & BABBLE)
++ if (mace_babbles++ < 4)
++ printk(KERN_DEBUG "macmace: babbling transmitter\n");
++ if (intr & JABBER)
++ if (mace_jabbers++ < 4)
++ printk(KERN_DEBUG "macmace: jabbering transceiver\n");
++
+ }
+
+-/*
+- * A transmit error has occurred. (We kick the transmit side from
+- * the DMA completion)
+- */
+-
+-static void mace_xmit_error(struct net_device *dev)
++static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+ {
++ struct net_device *dev = (struct net_device *) dev_id;
+ struct mace_data *mp = (struct mace_data *) dev->priv;
+ volatile struct mace *mb = mp->mace;
+- u8 xmtfs, xmtrc;
+-
+- xmtfs = mb->xmtfs;
+- xmtrc = mb->xmtrc;
+-
+- if (xmtfs & XMTSV) {
+- if (xmtfs & UFLO) {
+- printk("%s: DMA underrun.\n", dev->name);
+- mp->stats.tx_errors++;
+- mp->stats.tx_fifo_errors++;
+- mace_txdma_reset(dev);
++ int intr, fs;
++ unsigned int flags;
++
++ /* don't want the dma interrupt handler to fire */
++ local_irq_save(flags);
++
++ intr = mb->ir; /* read interrupt register */
++ mace_handle_misc_intrs(mp, intr);
++
++ if (mb->pr & XMTSV) {
++ fs = mb->xmtfs;
++ if ((fs & XMTSV) == 0) {
++ printk(KERN_ERR "macmace: xmtfs not valid! (fs=%x)\n", fs);
++ mace_reset(dev);
++ /*
++ * XXX mace likes to hang the machine after a xmtfs error.
++ * This is hard to reproduce, reseting *may* help
++ */
+ }
+- if (xmtfs & RTRY) {
+- mp->stats.collisions++;
++ /* dma should have finished */
++ if (!mp->tx_count) {
++ printk(KERN_DEBUG "macmace: tx ring ran out? (fs=%x)\n", fs);
+ }
+- }
+-}
++ /* Update stats */
++ if (fs & (UFLO|LCOL|LCAR|RTRY)) {
++ ++mp->stats.tx_errors;
++ if (fs & LCAR)
++ ++mp->stats.tx_carrier_errors;
++ else if (fs & (UFLO|LCOL|RTRY)) {
++ ++mp->stats.tx_aborted_errors;
++ if (mb->xmtfs & UFLO) {
++ printk(KERN_ERR "%s: DMA underrun.\n", dev->name);
++ mp->stats.tx_fifo_errors++;
++ mace_txdma_reset(dev);
++ }
++ }
++ }
++ }
+
+-/*
+- * A receive interrupt occurred.
+- */
++ if (mp->tx_count)
++ netif_wake_queue(dev);
+
+-static void mace_recv_interrupt(struct net_device *dev)
+-{
+-/* struct mace_data *mp = (struct mace_data *) dev->priv; */
+-// volatile struct mace *mb = mp->mace;
+-}
++ local_irq_restore(flags);
+
+-/*
+- * Process the chip interrupt
+- */
+-
+-static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+-{
+- struct net_device *dev = (struct net_device *) dev_id;
+- struct mace_data *mp = (struct mace_data *) dev->priv;
+- volatile struct mace *mb = mp->mace;
+- u8 ir;
+-
+- ir = mb->ir;
+- mace_handle_misc_intrs(mp, ir);
+-
+- if (ir & XMTINT) {
+- mace_xmit_error(dev);
+- }
+- if (ir & RCVINT) {
+- mace_recv_interrupt(dev);
+- }
+ return IRQ_HANDLED;
+ }
+
+@@ -598,51 +637,30 @@
+
+ static void mace_tx_timeout(struct net_device *dev)
+ {
+- struct mace_data *mp = (struct mace_data *) dev->priv;
+- volatile struct mace *mb = mp->mace;
+- unsigned long flags;
+- u8 maccc, imr;
+-
+- local_irq_save(flags);
+-
+- // save state
+- maccc = mb->maccc;
+- imr = mb->imr;
+-
+- // stop card
+- mb->maccc = 0; /* disable rx and tx */
+- mb->imr = 0xFF; /* disable all irqs */
+- mace_dma_off(dev);
+-
+- // reset card
+- mb->biucc = XMTSP_64;
+- mb->fifocc = XMTFW_16 | RCVFW_64 | XMTFWU | RCVFWU | XMTBRST | RCVBRST;
+- mb->xmtfc = AUTO_PAD_XMIT;
+- mb->plscc = PORTSEL_AUI;
+-
+- /* Not sure what these do - perhaps reset the PSC ??? */
+-
+- psc_write_word(PSC_ENETWR_CTL, 0x9000);
+- psc_write_word(PSC_ENETRD_CTL, 0x9000);
+- psc_write_word(PSC_ENETWR_CTL, 0x0400);
+- psc_write_word(PSC_ENETRD_CTL, 0x0400);
+-
+- // reset both DMAs
+- mace_rxdma_reset(dev);
+- mace_txdma_reset(dev);
+-
+- // free skb's - not necessary, already done in mace_xmit_start
+- // ring buffer pointers reset in txdma_reset, so just log error
+- mp->stats.tx_errors++;
+-
+- // re-kick upper level
+- netif_wake_queue(dev);
+-
+- // re-enable card, using saved imr/maccc (where is this ever set?)
+- mb->maccc = maccc;
+- mb->imr = imr;
+-
+- local_irq_restore(flags);
++ struct mace_data *mp = (struct mace_data *) dev->priv;
++ volatile struct mace *mb = mp->mace;
++ unsigned long flags;
++
++ local_irq_save(flags);
++
++ /* turn off both tx and rx and reset the chip */
++ mb->maccc = 0;
++ printk(KERN_ERR "macmace: transmit timeout - resetting\n");
++ mace_txdma_reset(dev);
++ mace_reset(dev);
++
++ /* restart rx dma */
++ mace_rxdma_reset(dev);
++
++ mp->tx_count = N_TX_RING;
++ netif_wake_queue(dev);
++
++ /* turn it on! */
++ mb->maccc = ENXMT | ENRCV;
++ /* enable all interrupts except receive interrupts */
++ mb->imr = RCVINT;
++
++ local_irq_restore(flags);
+ }
+
+ /*
+@@ -653,39 +671,39 @@
+ {
+ struct mace_data *mp = (struct mace_data *) dev->priv;
+ struct sk_buff *skb;
++ unsigned int frame_status = mf->rcvsts;
+
+- if (mf->status & RS_OFLO) {
+- printk("%s: fifo overflow.\n", dev->name);
+- mp->stats.rx_errors++;
+- mp->stats.rx_fifo_errors++;
+- }
+- if (mf->status&(RS_CLSN|RS_FRAMERR|RS_FCSERR))
++ if (frame_status & (RS_OFLO | RS_CLSN | RS_FRAMERR | RS_FCSERR)) {
+ mp->stats.rx_errors++;
+
+- if (mf->status&RS_CLSN) {
+- mp->stats.collisions++;
+- }
+- if (mf->status&RS_FRAMERR) {
+- mp->stats.rx_frame_errors++;
+- }
+- if (mf->status&RS_FCSERR) {
+- mp->stats.rx_crc_errors++;
++ if (frame_status & RS_OFLO) {
++ printk(KERN_DEBUG "%s: fifo overflow.\n", dev->name);
++ mp->stats.rx_fifo_errors++;
++ }
++ if (frame_status & RS_CLSN)
++ mp->stats.collisions++;
++ if (frame_status & RS_FRAMERR)
++ mp->stats.rx_frame_errors++;
++ if (frame_status & RS_FCSERR)
++ mp->stats.rx_crc_errors++;
++ } else {
++ unsigned int frame_length = mf->rcvcnt + ((frame_status & 0x0F) << 8 );
++
++ skb = dev_alloc_skb(frame_length + 2);
++ if (!skb) {
++ mp->stats.rx_dropped++;
++ return;
++ }
++ skb_reserve(skb, 2);
++ memcpy(skb_put(skb, frame_length), mf->data, frame_length);
++
++ skb->dev = dev;
++ skb->protocol = eth_type_trans(skb, dev);
++ netif_rx(skb);
++ dev->last_rx = jiffies;
++ mp->stats.rx_packets++;
++ mp->stats.rx_bytes += frame_length;
+ }
+-
+- skb = dev_alloc_skb(mf->len+2);
+- if (!skb) {
+- mp->stats.rx_dropped++;
+- return;
+- }
+- skb_reserve(skb,2);
+- memcpy(skb_put(skb, mf->len), mf->data, mf->len);
+-
+- skb->dev = dev;
+- skb->protocol = eth_type_trans(skb, dev);
+- netif_rx(skb);
+- dev->last_rx = jiffies;
+- mp->stats.rx_packets++;
+- mp->stats.rx_bytes += mf->len;
+ }
+
+ /*
Modified: dists/sid/linux-2.6/debian/patches/series/9-extra
==============================================================================
--- dists/sid/linux-2.6/debian/patches/series/9-extra (original)
+++ dists/sid/linux-2.6/debian/patches/series/9-extra Sun Dec 31 17:30:59 2006
@@ -5,3 +5,7 @@
+ features/all/xen/vserver-update.patch *_xen-vserver
+ m68k-atari-net.patch m68k
+ m68k-atari-video2.patch m68k
+- m68k-atari-scsi.patch m68k
++ m68k-atari-scsi2.patch m68k
++ m68k-mac-mace.patch m68k
++ m68k-mac-cuda.patch m68k
More information about the Kernel-svn-changes
mailing list