# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/03/04 08:33:48-03:00 marcelo@logos.cnet # Merge bk://gkernel.bkbits.net/net-drivers-2.4 # into logos.cnet:/home/marcelo/bk/linux-2.4 # TAG: MailDone # # ChangeSet # 2005/03/03 09:39:57-03:00 marcelo@logos.cnet # Allow lseek on SCSI tapes # # drivers/scsi/st.c # 2005/03/03 09:39:26-03:00 marcelo@logos.cnet +0 -1 # Allow lseek on SCSI tapes # # ChangeSet # 2005/03/02 14:12:47-08:00 davem@nuts.davemloft.net # [SPARC64]: Accept 'm5823' clock chip as seen on SB1500. # # Signed-off-by: David S. Miller # # arch/sparc64/kernel/time.c # 2005/03/02 14:12:26-08:00 davem@nuts.davemloft.net +5 -2 # [SPARC64]: Accept 'm5823' clock chip as seen on SB1500. # # ChangeSet # 2005/03/02 13:55:07-03:00 marcelo@logos.cnet # Cset exclude: solar@openwall.com|ChangeSet|20041125155150|65356 # # drivers/scsi/st.c # 2005/03/02 13:54:51-03:00 marcelo@logos.cnet +0 -0 # Exclude # # ChangeSet # 2005/02/27 11:33:05-08:00 davem@nuts.davemloft.net # [AF_UNIX]: Fix SIOCINQ for STREAM. # # We should report the total bytes in the whole receive # queue, not just the first packet, in these cases. # # Reported by Uwe Bonnes. # # Signed-off-by: David S. Miller # # net/unix/af_unix.c # 2005/02/27 11:32:47-08:00 davem@nuts.davemloft.net +7 -2 # [AF_UNIX]: Fix SIOCINQ for STREAM. # # ChangeSet # 2005/02/26 13:27:40-08:00 krzysztof.h1@wp.pl # [SPARC]: DBRI fixes and improvements # # - [audio.c] Added missing semicolon when debug information is enabled # (compilation bug). # # - [audio.c] Number of input and output 8KB buffers is now a module # parameter as previous authors requested. More buffers should help on # slower machines. # # - [audio.c] Fixes some debug strings, so compilation warnings are gone # (when debug is enabled). # # - [dbri.c] Added missing dbri_get_formats() function, so sox/play now # plays sound files without forcing it to Sun audio output interface (OSS # works). # # - [dbri.c] Enabled burst transfers for DBRI. # # - [dbri.c] Added a fix to not leave few bytes in a next memory chunk # when building chain of output data buffers for DBRI. It is really a # critical thing if the next change is applied. # # - [dbri.c] [the most important one] Writing an output data (playback) # returns immediately which allows audio player to prepare next data when # an audio codec is playing the previous. It removes clicking noise on # output signal. # # Signed-off-by: David S. Miller # # drivers/sbus/audio/dbri.c # 2005/02/26 13:27:00-08:00 krzysztof.h1@wp.pl +63 -29 # [SPARC]: DBRI fixes and improvements # # drivers/sbus/audio/audio.c # 2005/02/26 13:27:00-08:00 krzysztof.h1@wp.pl +14 -8 # [SPARC]: DBRI fixes and improvements # # ChangeSet # 2005/02/26 10:45:45-03:00 slee@netengine1.com # [PATCH] Fix units/partition count in sd.c # # Symptom: # When a scsi disk is removed other scsi disk with biggest minor # # disapears in /proc/partition at the same time. # # Cause and fix: # sd.c decreases nr_real on disk removal but because nr_real is not # real # of devices but max # of devices of a major #, # it doesn't need to be changed on disk add/remove. # # 2.6 has little different structure but it does like this # # sd.c:sd_probe() # gd->minors = 16; # TAG: MailDone # # drivers/scsi/sd.c # 2005/02/23 17:54:38-03:00 slee@netengine1.com +1 -3 # Fix units/partition count in sd.c # # ChangeSet # 2005/02/26 09:59:34-03:00 solar@openwall.com # [PATCH] Fix proc_tty.c comment typos # # TAG: MailDone # # fs/proc/proc_tty.c # 2005/01/22 20:53:36-02:00 solar@openwall.com +2 -2 # Fix proc_tty.c comment typos # # ChangeSet # 2005/02/26 09:28:54-03:00 solar@openwall.com # [PATCH] Fix for swapoff after re-creating device files # # $SUBJECT says it all - if device is recreated the current dentry-only # comparison in sys_swapoff() might have problems. # # mm/swapfile.c # 2005/01/22 20:53:36-02:00 solar@openwall.com +4 -2 # Fix for swapoff after re-creating device files # # ChangeSet # 2005/02/26 06:59:14-03:00 hifumi.hisashi@lab.ntt.co.jp # [PATCH] BUG on error handlings in Ext3 under I/O # # I found bugs on error handlings in the functions arround the file system, # which cause inadequate completions of synchronous write I/O operations # when disk I/O failures occur. # # I carried out following experiment: # # 1. Mount a ext3 file system on a SCSI disk with ordered mode. # 2. Open a file on the file system with O_SYNC|O_RDWR|O_TRUNC|O_CREAT flag. # 3. Write 512 bytes data to the file by calling write() every 5 seconds, and # examine return values from the syscall. # from write(). # 4. Disconnect the SCSI cable, and examine messages from the kernel. # # After the SCSI cable is disconnected, write() must fail. But write() # succeeded for a while even though messages of the kernel notified SCSI I/O error. # # By applying following modifications, the above problem was solved. # In fact I have send patch for both 2.4 and 2.6 to Andrew, but only 2.6 was # accepted. # So I send you my patch for the 2.4 kernel. # # Please consider applying this patch to the 2.4 mainline kernel. # # # Signed-off-by: Hisashi Hifumi # # mm/filemap.c # 2005/02/15 04:40:05-03:00 hifumi.hisashi@lab.ntt.co.jp +6 -1 # BUG on error handlings in Ext3 under I/O # # include/linux/jbd.h # 2005/02/15 04:40:05-03:00 hifumi.hisashi@lab.ntt.co.jp +1 -1 # BUG on error handlings in Ext3 under I/O # # fs/jbd/transaction.c # 2005/02/15 04:40:05-03:00 hifumi.hisashi@lab.ntt.co.jp +2 -2 # BUG on error handlings in Ext3 under I/O # # fs/jbd/journal.c # 2005/02/15 04:40:05-03:00 hifumi.hisashi@lab.ntt.co.jp +10 -2 # BUG on error handlings in Ext3 under I/O # # fs/jbd/commit.c # 2005/02/15 04:40:05-03:00 hifumi.hisashi@lab.ntt.co.jp +17 -1 # BUG on error handlings in Ext3 under I/O # # fs/ext3/super.c # 2005/02/15 04:40:05-03:00 hifumi.hisashi@lab.ntt.co.jp +3 -2 # BUG on error handlings in Ext3 under I/O # # fs/ext3/fsync.c # 2005/02/15 04:40:05-03:00 hifumi.hisashi@lab.ntt.co.jp +1 -1 # BUG on error handlings in Ext3 under I/O # # ChangeSet # 2005/02/26 04:19:29-05:00 linville@tuxdriver.com # [PATCH] tulip: make tulip_stop_rxtx() wait for DMA to fully stop # # tulip_stop_rxtx() doesn't wait for DMA to fully stop like the function # call name implies. # # Acked-by: Grant Grundler # Acked-by: Charlie Brett # Signed-off-by: John W. Linville # Signed-off-by: Jeff Garzik # # drivers/net/tulip/tulip_core.c # 2005/02/25 19:00:00-05:00 linville@tuxdriver.com +1 -1 # tulip: make tulip_stop_rxtx() wait for DMA to fully stop # # drivers/net/tulip/tulip.h # 2005/02/25 19:00:00-05:00 linville@tuxdriver.com +14 -1 # tulip: make tulip_stop_rxtx() wait for DMA to fully stop # # drivers/net/tulip/timer.c # 2005/02/25 19:00:00-05:00 linville@tuxdriver.com +1 -0 # tulip: make tulip_stop_rxtx() wait for DMA to fully stop # # drivers/net/tulip/pnic2.c # 2005/02/25 19:00:00-05:00 linville@tuxdriver.com +1 -1 # tulip: make tulip_stop_rxtx() wait for DMA to fully stop # # drivers/net/tulip/pnic.c # 2005/02/25 19:00:00-05:00 linville@tuxdriver.com +1 -0 # tulip: make tulip_stop_rxtx() wait for DMA to fully stop # # drivers/net/tulip/media.c # 2005/02/25 19:00:00-05:00 linville@tuxdriver.com +1 -0 # tulip: make tulip_stop_rxtx() wait for DMA to fully stop # # drivers/net/tulip/interrupt.c # 2005/02/25 19:00:00-05:00 linville@tuxdriver.com +1 -1 # tulip: make tulip_stop_rxtx() wait for DMA to fully stop # # drivers/net/tulip/eeprom.c # 2005/02/25 19:00:00-05:00 linville@tuxdriver.com +1 -0 # tulip: make tulip_stop_rxtx() wait for DMA to fully stop # # drivers/net/tulip/21142.c # 2005/02/25 19:00:00-05:00 linville@tuxdriver.com +1 -1 # tulip: make tulip_stop_rxtx() wait for DMA to fully stop # # ChangeSet # 2005/02/25 18:19:47-03:00 zwane@arm.linux.org.uk # [PATCH] Fix timer override on nforce # # Per our discussion, i've ported the 2.6 nforce skip timer override (and # early PCI access) code to 2.4. This fixes an issue whereupon nforce # systems have incorrect override values for irq0. Architectures affected # are i386 and x86_64 # # Signed-off-by: Zwane Mwaikambo # TAG: MailDone # # include/asm-i386/pci-direct.h # 2005/02/18 11:53:58-03:00 zwane@arm.linux.org.uk +1 -0 # Fix timer override on nforce # # arch/i386/kernel/earlyquirk.c # 2005/02/18 11:53:58-03:00 zwane@arm.linux.org.uk +53 -0 # Fix timer override on nforce # # include/asm-x86_64/acpi.h # 2005/02/18 11:53:58-03:00 zwane@arm.linux.org.uk +1 -0 # Fix timer override on nforce # # include/asm-i386/pci-direct.h # 2005/02/18 11:53:58-03:00 zwane@arm.linux.org.uk +0 -0 # BitKeeper file /home/marcelo/bk/linux-2.4/include/asm-i386/pci-direct.h # # include/asm-i386/acpi.h # 2005/02/18 11:53:58-03:00 zwane@arm.linux.org.uk +2 -0 # Fix timer override on nforce # # arch/x86_64/kernel/io_apic.c # 2005/02/18 11:53:58-03:00 zwane@arm.linux.org.uk +7 -3 # Fix timer override on nforce # # arch/x86_64/kernel/acpi.c # 2005/02/18 11:53:58-03:00 zwane@arm.linux.org.uk +7 -0 # Fix timer override on nforce # # arch/i386/kernel/earlyquirk.c # 2005/02/18 11:53:58-03:00 zwane@arm.linux.org.uk +0 -0 # BitKeeper file /home/marcelo/bk/linux-2.4/arch/i386/kernel/earlyquirk.c # # arch/i386/kernel/acpi.c # 2005/02/18 11:53:58-03:00 zwane@arm.linux.org.uk +9 -0 # Fix timer override on nforce # # arch/i386/kernel/Makefile # 2005/02/18 11:53:58-03:00 zwane@arm.linux.org.uk +1 -1 # Fix timer override on nforce # # ChangeSet # 2005/02/25 17:35:21-03:00 Matt_Domsch@dell.com # [PATCH] aic7xxx: don't reset chip on pause # # (resend) # Patch below taken from RHEL3 Update 4 kernel 2.4.21-27.EL, fixes a bug # in the aic79xx and aic7xxx drivers, where upon trying to pause the # controller chip, it is accidentally hard-reset. This causes PCI # Parity errors to appear on Dell PowerEdge 4600 servers as the inb() # immediately after accidental reset receives corrupted data. # # Patch was submitted by Justin Gibbs many moons ago, but never applied # to mainline 2.4. It's in mainline 2.6. Marcelo, please apply. # # Signed-off-by: Matt Domsch # # drivers/scsi/aic7xxx/aic7xxx_pci.c # 2004/12/01 18:49:28-02:00 Matt_Domsch@dell.com +3 -1 # aic7xxx: don't reset chip on pause # # drivers/scsi/aic7xxx/aic79xx_pci.c # 2004/12/01 18:49:28-02:00 Matt_Domsch@dell.com +3 -1 # aic7xxx: don't reset chip on pause # # ChangeSet # 2005/02/25 17:24:34-03:00 paulkf@microgate.com # [PATCH] fix synclinkmp register access typo # # Fix typo to correctly access # rx ready control (RRC) register instead of # the tx ready control (TRC0) register. # TAG: MailDone # # drivers/char/synclinkmp.c # 2005/02/23 18:55:30-03:00 paulkf@microgate.com +3 -3 # fix synclinkmp register access typo # # ChangeSet # 2005/02/25 17:19:51-03:00 marcelo@logos.cnet # Merge bk://kernel.bkbits.net/davem/sparc-2.4 # into logos.cnet:/home/marcelo/bk/linux-2.4 # # arch/sparc64/kernel/sys_sparc32.c # 2005/02/25 17:19:47-03:00 marcelo@logos.cnet +0 -0 # Auto merged # # ChangeSet # 2005/02/25 11:06:47-08:00 davem@nuts.davemloft.net # [SPARC64]: Fix 32bit compat layer bugs in sys_ipc() and sys_rt_sigtimedwait(). # # 1) sys_ipc() compat wrappers need to verify length # before allocating kernel data and performing copies. # 2) sys_rt_sigtimedwait() had one schedule_timeout() too # many. # # Signed-off-by: David S. Miller # # arch/sparc64/kernel/sys_sparc32.c # 2005/02/25 11:05:43-08:00 davem@nuts.davemloft.net +54 -33 # [SPARC64]: Fix 32bit compat layer bugs in sys_ipc() and sys_rt_sigtimedwait(). # # ChangeSet # 2005/02/24 14:53:59-05:00 jgarzik@pobox.com # [libata ahci] Print out port id on error messages # # Pointed out by Justin Cormack, Brett Russ, and others. # # drivers/scsi/ahci.c # 2005/02/24 14:53:37-05:00 jgarzik@pobox.com +1 -1 # [libata ahci] Print out port id on error messages # # Pointed out by Justin Cormack, Brett Russ, and others. # # ChangeSet # 2005/02/24 00:41:15-05:00 mallikarjuna.chilakala@intel.com # [PATCH] e1000: Driver version white space, # # 10 Driver version number, white space, comments, device id & other changes # Signed-off-by: Mallikarjuna R Chilakala # Signed-off-by: Ganesh Venkatesan # Signed-off-by: John Ronciak # Signed-off-by: Jeff Garzik # # drivers/net/e1000/e1000_main.c # 2005/02/02 02:21:51-05:00 mallikarjuna.chilakala@intel.com +16 -5 # e1000: Driver version white space, # # drivers/net/e1000/e1000_hw.h # 2005/02/02 02:21:50-05:00 mallikarjuna.chilakala@intel.com +9 -3 # e1000: Driver version white space, # # drivers/net/e1000/e1000_hw.c # 2005/02/02 02:21:50-05:00 mallikarjuna.chilakala@intel.com +4 -5 # e1000: Driver version white space, # # ChangeSet # 2005/02/24 00:41:10-05:00 mallikarjuna.chilakala@intel.com # [PATCH] e1000: Fixes related to Cable length # # 9 Fixes related to Cable length estimation # Signed-off-by: Mallikarjuna R Chilakala # Signed-off-by: Ganesh Venkatesan # Signed-off-by: John Ronciak # Signed-off-by: Jeff Garzik # # drivers/net/e1000/e1000_hw.c # 2005/02/02 02:21:50-05:00 mallikarjuna.chilakala@intel.com +42 -37 # e1000: Fixes related to Cable length # # ChangeSet # 2005/02/24 00:41:05-05:00 mallikarjuna.chilakala@intel.com # [PATCH] e1000: Report failure code when loopback # # 8 Report failure code when loopback test fails # Signed-off-by: Mallikarjuna R Chilakala # Signed-off-by: Ganesh Venkatesan # Signed-off-by: John Ronciak # Signed-off-by: Jeff Garzik # # drivers/net/e1000/e1000_ethtool.c # 2005/02/02 02:21:50-05:00 mallikarjuna.chilakala@intel.com +6 -5 # e1000: Report failure code when loopback # # ChangeSet # 2005/02/24 00:41:00-05:00 mallikarjuna.chilakala@intel.com # [PATCH] e1000: Checks for desc ring/rx data # # 7 Add checks for desc ring/rx data bufs spanning 64k address boundary # Signed-off-by: Mallikarjuna R Chilakala # Signed-off-by: Ganesh Venkatesan # Signed-off-by: John Ronciak # Signed-off-by: Jeff Garzik # # drivers/net/e1000/e1000_main.c # 2005/02/02 02:21:51-05:00 mallikarjuna.chilakala@intel.com +133 -3 # e1000: Checks for desc ring/rx data # # ChangeSet # 2005/02/24 00:40:56-05:00 mallikarjuna.chilakala@intel.com # [PATCH] e1000: Patch from Peter Kjellstroem -- # # 6 Patch from Peter Kjellstroem -- fix lockup with 82547 # Signed-off-by: Mallikarjuna R Chilakala # Signed-off-by: Ganesh Venkatesan # Signed-off-by: John Ronciak # Signed-off-by: Jeff Garzik # # drivers/net/e1000/e1000_main.c # 2005/02/02 02:21:51-05:00 mallikarjuna.chilakala@intel.com +18 -0 # e1000: Patch from Peter Kjellstroem -- # # ChangeSet # 2005/02/24 00:40:51-05:00 mallikarjuna.chilakala@intel.com # [PATCH] e1000: Fix WOL settings in 82544 based # # 5 Fix WOL settings in 82544 based adapters # Signed-off-by: Mallikarjuna R Chilakala # Signed-off-by: Ganesh Venkatesan # Signed-off-by: John Ronciak # Signed-off-by: Jeff Garzik # # drivers/net/e1000/e1000_main.c # 2005/02/02 02:21:51-05:00 mallikarjuna.chilakala@intel.com +7 -1 # e1000: Fix WOL settings in 82544 based # # drivers/net/e1000/e1000.h # 2005/02/02 02:21:50-05:00 mallikarjuna.chilakala@intel.com +1 -0 # e1000: Fix WOL settings in 82544 based # # ChangeSet # 2005/02/24 00:40:46-05:00 mallikarjuna.chilakala@intel.com # [PATCH] e1000: Delay clean-up of last Tx buffer # # 4 Delay clean-up of last Tx buffer to fix pre-mature writeback of Tx descriptors. # Signed-off-by: Mallikarjuna R Chilakala # Signed-off-by: Ganesh Venkatesan # Signed-off-by: John Ronciak # Signed-off-by: Jeff Garzik # # drivers/net/e1000/e1000_main.c # 2005/02/02 02:21:51-05:00 mallikarjuna.chilakala@intel.com +30 -1 # e1000: Delay clean-up of last Tx buffer # # drivers/net/e1000/e1000.h # 2005/02/02 02:21:50-05:00 mallikarjuna.chilakala@intel.com +1 -0 # e1000: Delay clean-up of last Tx buffer # # ChangeSet # 2005/02/24 00:40:41-05:00 mallikarjuna.chilakala@intel.com # [PATCH] e1000: Avoid race between e1000_watchdog # # 3 Avoid race condition between e1000_watchdog and e1000_clean_tx_irq # Signed-off-by: Mallikarjuna R Chilakala # Signed-off-by: Ganesh Venkatesan # Signed-off-by: John Ronciak # Signed-off-by: Jeff Garzik # # drivers/net/e1000/e1000_main.c # 2005/02/02 02:21:51-05:00 mallikarjuna.chilakala@intel.com +12 -7 # e1000: Avoid race between e1000_watchdog # # drivers/net/e1000/e1000.h # 2005/02/02 02:21:50-05:00 mallikarjuna.chilakala@intel.com +1 -0 # e1000: Avoid race between e1000_watchdog # # ChangeSet # 2005/02/24 00:40:36-05:00 mallikarjuna.chilakala@intel.com # [PATCH] e1000: 2 use netif_poll_{enable|disable} # # 2 use netif_poll_{enable|disable} to synchronize between poll and i/f down/up # Signed-off-by: Mallikarjuna R Chilakala # Signed-off-by: Ganesh Venkatesan # Signed-off-by: John Ronciak # Signed-off-by: Jeff Garzik # # drivers/net/e1000/e1000_main.c # 2005/02/02 02:21:51-05:00 mallikarjuna.chilakala@intel.com +7 -0 # e1000: 2 use netif_poll_{enable|disable} # # ChangeSet # 2005/02/24 00:40:31-05:00 mallikarjuna.chilakala@intel.com # [PATCH] e1000: 1 Robert Olsson's fix and # # 1 Rober Olsson's fix and refinement to the poll routine # Signed-off-by: Mallikarjuna R Chilakala # Signed-off-by: Ganesh Venkatesan # Signed-off-by: John Ronciak # Signed-off-by: Jeff Garzik # # drivers/net/e1000/e1000_main.c # 2005/02/02 02:21:51-05:00 mallikarjuna.chilakala@intel.com +4 -7 # e1000: 1 Robert Olsson's fix and # # ChangeSet # 2005/02/24 00:38:15-05:00 jgarzik@pobox.com # [libata] Use DMA_{32,64}BIT_MASK in ahci, sata_vsc drivers. # # Similar to a patch applied in 2.6.x by Tobias Klauser. # # drivers/scsi/sata_vsc.c # 2005/02/24 00:38:14-05:00 jgarzik@pobox.com +1 -1 # [libata] Use DMA_{32,64}BIT_MASK in ahci, sata_vsc drivers. # # Similar to a patch applied in 2.6.x by Tobias Klauser. # # drivers/scsi/ahci.c # 2005/02/24 00:38:14-05:00 jgarzik@pobox.com +2 -2 # [libata] Use DMA_{32,64}BIT_MASK in ahci, sata_vsc drivers. # # Similar to a patch applied in 2.6.x by Tobias Klauser. # # ChangeSet # 2005/02/24 00:32:06-05:00 mlord@pobox.com # [libata qstor] minor update per LKML comments # # * use __le{32,64} # * use DMA_{32,64}BIT_MASK # # Also, add these to linux/libata-compat.h since they are not # defined in 2.4.x. # # include/linux/libata-compat.h # 2005/02/24 00:32:04-05:00 mlord@pobox.com +7 -0 # [libata qstor] minor update per LKML comments # # * use __le{32,64} # * use DMA_{32,64}BIT_MASK # # Also, add these to linux/libata-compat.h since they are not # defined in 2.4.x. # # drivers/scsi/sata_qstor.c # 2005/02/24 00:32:04-05:00 mlord@pobox.com +7 -7 # [libata qstor] minor update per LKML comments # # * use __le{32,64} # * use DMA_{32,64}BIT_MASK # # Also, add these to linux/libata-compat.h since they are not # defined in 2.4.x. # # ChangeSet # 2005/02/23 15:10:27-05:00 jgarzik@pobox.com # [libata] Add missing hooks, to avoid oops in advanced SATA drivers # # Advanced SATA drivers should not (and cannot) use the basic # PCI IDE hooks for checking the Status and Error registers, as these # registers are either in non-standard locations, or simply don't # exist. # # In the error handling path, libata was unconditionally calling some # PCI IDE hardware bitbanging functions, which would cause an oops # in the AHCI driver and any other advanced libata driver. # # include/linux/libata.h # 2005/02/23 15:10:05-05:00 jgarzik@pobox.com +4 -15 # [libata] Add missing hooks, to avoid oops in advanced SATA drivers # # Advanced SATA drivers should not (and cannot) use the basic # PCI IDE hooks for checking the Status and Error registers, as these # registers are either in non-standard locations, or simply don't # exist. # # In the error handling path, libata was unconditionally calling some # PCI IDE hardware bitbanging functions, which would cause an oops # in the AHCI driver and any other advanced libata driver. # # drivers/scsi/libata-core.c # 2005/02/23 15:10:05-05:00 jgarzik@pobox.com +26 -3 # [libata] Add missing hooks, to avoid oops in advanced SATA drivers # # Advanced SATA drivers should not (and cannot) use the basic # PCI IDE hooks for checking the Status and Error registers, as these # registers are either in non-standard locations, or simply don't # exist. # # In the error handling path, libata was unconditionally calling some # PCI IDE hardware bitbanging functions, which would cause an oops # in the AHCI driver and any other advanced libata driver. # # drivers/scsi/ahci.c # 2005/02/23 15:10:05-05:00 jgarzik@pobox.com +10 -0 # [libata] Add missing hooks, to avoid oops in advanced SATA drivers # # Advanced SATA drivers should not (and cannot) use the basic # PCI IDE hooks for checking the Status and Error registers, as these # registers are either in non-standard locations, or simply don't # exist. # # In the error handling path, libata was unconditionally calling some # PCI IDE hardware bitbanging functions, which would cause an oops # in the AHCI driver and any other advanced libata driver. # # ChangeSet # 2005/02/18 15:50:12-05:00 linville@tuxdriver.com # [PATCH] libata: fix command queue leak when xlat_func fails # # ata_scsi_translate allocates from the libata command queue by calling # ata_scsi_qc_new. If xlat_func returns non-zero, control jumps to # err_out which fails to free the allocated command. Fix is to add a # new API to free unused commands. # # Signed-off-by: John W. Linville # Signed-off-by: Jeff Garzik # # drivers/scsi/libata.h # 2005/02/18 15:50:08-05:00 linville@tuxdriver.com +1 -0 # [PATCH] libata: fix command queue leak when xlat_func fails # # ata_scsi_translate allocates from the libata command queue by calling # ata_scsi_qc_new. If xlat_func returns non-zero, control jumps to # err_out which fails to free the allocated command. Fix is to add a # new API to free unused commands. # # Signed-off-by: John W. Linville # Signed-off-by: Jeff Garzik # # drivers/scsi/libata-scsi.c # 2005/02/18 15:50:08-05:00 linville@tuxdriver.com +1 -0 # [PATCH] libata: fix command queue leak when xlat_func fails # # ata_scsi_translate allocates from the libata command queue by calling # ata_scsi_qc_new. If xlat_func returns non-zero, control jumps to # err_out which fails to free the allocated command. Fix is to add a # new API to free unused commands. # # Signed-off-by: John W. Linville # Signed-off-by: Jeff Garzik # # drivers/scsi/libata-core.c # 2005/02/18 15:50:08-05:00 linville@tuxdriver.com +18 -0 # [PATCH] libata: fix command queue leak when xlat_func fails # # ata_scsi_translate allocates from the libata command queue by calling # ata_scsi_qc_new. If xlat_func returns non-zero, control jumps to # err_out which fails to free the allocated command. Fix is to add a # new API to free unused commands. # # Signed-off-by: John W. Linville # Signed-off-by: Jeff Garzik # # ChangeSet # 2005/02/17 20:45:52-05:00 lsml@rtr.ca # [PATCH] sata_qstor: new basic driver for Pacific Digital # # This is a new basic libata SATA driver # for the Pacific Digital QStor SATA/RAID card. # # It features ordinary per-drive SATA with single-request DMA # for R/W commands, and PIO for everything else. # # It currently does not implement any of the hardware RAID support, # nor hot-plug, nor the tagged/native command-queuing features. # # On the other hand, it is small and simple as a result. # # Signed-off-by: Mark Lord # Signed-off-by: Jeff Garzik # # drivers/scsi/sata_qstor.c # 2005/02/17 20:45:50-05:00 lsml@rtr.ca +699 -0 # # include/linux/libata-compat.h # 2005/02/17 20:45:50-05:00 lsml@rtr.ca +10 -0 # [PATCH] sata_qstor: new basic driver for Pacific Digital # # This is a new basic libata SATA driver # for the Pacific Digital QStor SATA/RAID card. # # It features ordinary per-drive SATA with single-request DMA # for R/W commands, and PIO for everything else. # # It currently does not implement any of the hardware RAID support, # nor hot-plug, nor the tagged/native command-queuing features. # # On the other hand, it is small and simple as a result. # # Signed-off-by: Mark Lord # Signed-off-by: Jeff Garzik # # drivers/scsi/sata_qstor.c # 2005/02/17 20:45:50-05:00 lsml@rtr.ca +0 -0 # BitKeeper file /garz/repo/libata-upstream-2.4/drivers/scsi/sata_qstor.c # # drivers/scsi/Makefile # 2005/02/17 20:45:50-05:00 lsml@rtr.ca +1 -0 # [PATCH] sata_qstor: new basic driver for Pacific Digital # # This is a new basic libata SATA driver # for the Pacific Digital QStor SATA/RAID card. # # It features ordinary per-drive SATA with single-request DMA # for R/W commands, and PIO for everything else. # # It currently does not implement any of the hardware RAID support, # nor hot-plug, nor the tagged/native command-queuing features. # # On the other hand, it is small and simple as a result. # # Signed-off-by: Mark Lord # Signed-off-by: Jeff Garzik # # drivers/scsi/Config.in # 2005/02/17 20:45:50-05:00 lsml@rtr.ca +1 -0 # [PATCH] sata_qstor: new basic driver for Pacific Digital # # This is a new basic libata SATA driver # for the Pacific Digital QStor SATA/RAID card. # # It features ordinary per-drive SATA with single-request DMA # for R/W commands, and PIO for everything else. # # It currently does not implement any of the hardware RAID support, # nor hot-plug, nor the tagged/native command-queuing features. # # On the other hand, it is small and simple as a result. # # Signed-off-by: Mark Lord # Signed-off-by: Jeff Garzik # # Documentation/Configure.help # 2005/02/17 20:45:50-05:00 lsml@rtr.ca +5 -0 # [PATCH] sata_qstor: new basic driver for Pacific Digital # # This is a new basic libata SATA driver # for the Pacific Digital QStor SATA/RAID card. # # It features ordinary per-drive SATA with single-request DMA # for R/W commands, and PIO for everything else. # # It currently does not implement any of the hardware RAID support, # nor hot-plug, nor the tagged/native command-queuing features. # # On the other hand, it is small and simple as a result. # # Signed-off-by: Mark Lord # Signed-off-by: Jeff Garzik # # ChangeSet # 2005/02/17 20:12:36-05:00 Mat.Loikkanen@synopsys.com # [libata] add ->bmdma_{stop,status} hooks # # The timeout/error handling path was assuming that the hardware in # question was PCI IDE BMDMA-like, which is incorrect in a few cases. # # Turn direct function calls into two new hooks. # # include/linux/libata.h # 2005/02/17 20:12:14-05:00 Mat.Loikkanen@synopsys.com +5 -40 # [libata] add ->bmdma_{stop,status} hooks # # The timeout/error handling path was assuming that the hardware in # question was PCI IDE BMDMA-like, which is incorrect in a few cases. # # Turn direct function calls into two new hooks. # # drivers/scsi/sata_vsc.c # 2005/02/17 20:12:14-05:00 Mat.Loikkanen@synopsys.com +2 -0 # [libata] add ->bmdma_{stop,status} hooks # # The timeout/error handling path was assuming that the hardware in # question was PCI IDE BMDMA-like, which is incorrect in a few cases. # # Turn direct function calls into two new hooks. # # drivers/scsi/sata_via.c # 2005/02/17 20:12:14-05:00 Mat.Loikkanen@synopsys.com +3 -0 # [libata] add ->bmdma_{stop,status} hooks # # The timeout/error handling path was assuming that the hardware in # question was PCI IDE BMDMA-like, which is incorrect in a few cases. # # Turn direct function calls into two new hooks. # # drivers/scsi/sata_uli.c # 2005/02/17 20:12:14-05:00 Mat.Loikkanen@synopsys.com +2 -0 # [libata] add ->bmdma_{stop,status} hooks # # The timeout/error handling path was assuming that the hardware in # question was PCI IDE BMDMA-like, which is incorrect in a few cases. # # Turn direct function calls into two new hooks. # # drivers/scsi/sata_svw.c # 2005/02/17 20:12:14-05:00 Mat.Loikkanen@synopsys.com +2 -0 # [libata] add ->bmdma_{stop,status} hooks # # The timeout/error handling path was assuming that the hardware in # question was PCI IDE BMDMA-like, which is incorrect in a few cases. # # Turn direct function calls into two new hooks. # # drivers/scsi/sata_sis.c # 2005/02/17 20:12:14-05:00 Mat.Loikkanen@synopsys.com +2 -0 # [libata] add ->bmdma_{stop,status} hooks # # The timeout/error handling path was assuming that the hardware in # question was PCI IDE BMDMA-like, which is incorrect in a few cases. # # Turn direct function calls into two new hooks. # # drivers/scsi/sata_sil.c # 2005/02/17 20:12:14-05:00 Mat.Loikkanen@synopsys.com +2 -0 # [libata] add ->bmdma_{stop,status} hooks # # The timeout/error handling path was assuming that the hardware in # question was PCI IDE BMDMA-like, which is incorrect in a few cases. # # Turn direct function calls into two new hooks. # # drivers/scsi/sata_nv.c # 2005/02/17 20:12:14-05:00 Mat.Loikkanen@synopsys.com +2 -0 # [libata] add ->bmdma_{stop,status} hooks # # The timeout/error handling path was assuming that the hardware in # question was PCI IDE BMDMA-like, which is incorrect in a few cases. # # Turn direct function calls into two new hooks. # # drivers/scsi/libata-core.c # 2005/02/17 20:12:14-05:00 Mat.Loikkanen@synopsys.com +45 -7 # [libata] add ->bmdma_{stop,status} hooks # # The timeout/error handling path was assuming that the hardware in # question was PCI IDE BMDMA-like, which is incorrect in a few cases. # # Turn direct function calls into two new hooks. # # drivers/scsi/ata_piix.c # 2005/02/17 20:12:14-05:00 Mat.Loikkanen@synopsys.com +4 -0 # [libata] add ->bmdma_{stop,status} hooks # # The timeout/error handling path was assuming that the hardware in # question was PCI IDE BMDMA-like, which is incorrect in a few cases. # # Turn direct function calls into two new hooks. # # ChangeSet # 2005/02/13 20:03:31-05:00 jgarzik@pobox.com # [libata] do not call pci_disable_device() for certain errors # # If PCI request regions fails, then someone else is using the # hardware we wish to use. For that one case, calling pci_disable_device() # is rather rude. # # drivers/scsi/sata_vsc.c # 2005/02/13 20:03:29-05:00 jgarzik@pobox.com +6 -2 # [libata] do not call pci_disable_device() for certain errors # # If PCI request regions fails, then someone else is using the # hardware we wish to use. For that one case, calling pci_disable_device() # is rather rude. # # drivers/scsi/sata_via.c # 2005/02/13 20:03:29-05:00 jgarzik@pobox.com +6 -2 # [libata] do not call pci_disable_device() for certain errors # # If PCI request regions fails, then someone else is using the # hardware we wish to use. For that one case, calling pci_disable_device() # is rather rude. # # drivers/scsi/sata_uli.c # 2005/02/13 20:03:29-05:00 jgarzik@pobox.com +6 -2 # [libata] do not call pci_disable_device() for certain errors # # If PCI request regions fails, then someone else is using the # hardware we wish to use. For that one case, calling pci_disable_device() # is rather rude. # # drivers/scsi/sata_sx4.c # 2005/02/13 20:03:29-05:00 jgarzik@pobox.com +6 -2 # [libata] do not call pci_disable_device() for certain errors # # If PCI request regions fails, then someone else is using the # hardware we wish to use. For that one case, calling pci_disable_device() # is rather rude. # # drivers/scsi/sata_svw.c # 2005/02/13 20:03:29-05:00 jgarzik@pobox.com +6 -2 # [libata] do not call pci_disable_device() for certain errors # # If PCI request regions fails, then someone else is using the # hardware we wish to use. For that one case, calling pci_disable_device() # is rather rude. # # drivers/scsi/sata_sis.c # 2005/02/13 20:03:29-05:00 jgarzik@pobox.com +6 -2 # [libata] do not call pci_disable_device() for certain errors # # If PCI request regions fails, then someone else is using the # hardware we wish to use. For that one case, calling pci_disable_device() # is rather rude. # # drivers/scsi/sata_sil.c # 2005/02/13 20:03:29-05:00 jgarzik@pobox.com +6 -2 # [libata] do not call pci_disable_device() for certain errors # # If PCI request regions fails, then someone else is using the # hardware we wish to use. For that one case, calling pci_disable_device() # is rather rude. # # drivers/scsi/sata_promise.c # 2005/02/13 20:03:29-05:00 jgarzik@pobox.com +6 -2 # [libata] do not call pci_disable_device() for certain errors # # If PCI request regions fails, then someone else is using the # hardware we wish to use. For that one case, calling pci_disable_device() # is rather rude. # # drivers/scsi/sata_nv.c # 2005/02/13 20:03:29-05:00 jgarzik@pobox.com +6 -2 # [libata] do not call pci_disable_device() for certain errors # # If PCI request regions fails, then someone else is using the # hardware we wish to use. For that one case, calling pci_disable_device() # is rather rude. # # drivers/scsi/libata-core.c # 2005/02/13 20:03:29-05:00 jgarzik@pobox.com +12 -6 # [libata] do not call pci_disable_device() for certain errors # # If PCI request regions fails, then someone else is using the # hardware we wish to use. For that one case, calling pci_disable_device() # is rather rude. # # drivers/scsi/ahci.c # 2005/02/13 20:03:29-05:00 jgarzik@pobox.com +6 -2 # [libata] do not call pci_disable_device() for certain errors # # If PCI request regions fails, then someone else is using the # hardware we wish to use. For that one case, calling pci_disable_device() # is rather rude. # # ChangeSet # 2005/02/13 15:23:36-05:00 jgarzik@pobox.com # [libata] trivial: whitespace sync with 2.6 # # drivers/scsi/libata-core.c # 2005/02/13 15:23:34-05:00 jgarzik@pobox.com +1 -1 # [libata] trivial: whitespace sync with 2.6 # # ChangeSet # 2005/02/13 15:15:55-05:00 jgarzik@pobox.com # [libata] resync with 2.6 msleep() updates # # Now that 2.4 has msleep, we can update the libata code to be closer # to the 2.6 code, reducing the maintenance burden on moi. # # include/linux/libata-compat.h # 2005/02/13 15:15:53-05:00 jgarzik@pobox.com +0 -5 # [libata] resync with 2.6 msleep() updates # # Now that 2.4 has msleep, we can update the libata code to be closer # to the 2.6 code, reducing the maintenance burden on moi. # # drivers/scsi/sata_sx4.c # 2005/02/13 15:15:53-05:00 jgarzik@pobox.com +2 -4 # [libata] resync with 2.6 msleep() updates # # Now that 2.4 has msleep, we can update the libata code to be closer # to the 2.6 code, reducing the maintenance burden on moi. # # drivers/scsi/sata_promise.c # 2005/02/13 15:15:53-05:00 jgarzik@pobox.com +0 -2 # [libata] resync with 2.6 msleep() updates # # Now that 2.4 has msleep, we can update the libata code to be closer # to the 2.6 code, reducing the maintenance burden on moi. # # drivers/scsi/libata-core.c # 2005/02/13 15:15:53-05:00 jgarzik@pobox.com +0 -1 # [libata] resync with 2.6 msleep() updates # # Now that 2.4 has msleep, we can update the libata code to be closer # to the 2.6 code, reducing the maintenance burden on moi. # # drivers/scsi/ahci.c # 2005/02/13 15:15:53-05:00 jgarzik@pobox.com +0 -2 # [libata] resync with 2.6 msleep() updates # # Now that 2.4 has msleep, we can update the libata code to be closer # to the 2.6 code, reducing the maintenance burden on moi. # # ChangeSet # 2005/02/13 13:27:08-05:00 jgarzik@pobox.com # [libata sata_via] add support for VT6421 SATA # # drivers/scsi/sata_via.c # 2005/02/13 13:27:02-05:00 jgarzik@pobox.com +84 -10 # [libata sata_via] add support for VT6421 SATA # # ChangeSet # 2005/02/13 13:26:12-05:00 jgarzik@pobox.com # [libata sata_via] minor cleanups # # Preparation for addition of VT6421 support. Mostly moving bits # of code into discrete functions. # # drivers/scsi/sata_via.c # 2005/02/13 13:25:43-05:00 jgarzik@pobox.com +67 -47 # [libata sata_via] minor cleanups # # Preparation for addition of VT6421 support. Mostly moving bits # of code into discrete functions. # diff -Nru a/Documentation/Configure.help b/Documentation/Configure.help --- a/Documentation/Configure.help 2005-03-04 12:03:50 -08:00 +++ b/Documentation/Configure.help 2005-03-04 12:03:50 -08:00 @@ -9345,6 +9345,11 @@ If unsure, say N. +CONFIG_SCSI_SATA_QSTOR + This option enables support for Pacific Digital Serial ATA QStor. + + If unsure, say N. + CONFIG_SCSI_SATA_SX4 This option enables support for Promise Serial ATA SX4. diff -Nru a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile --- a/arch/i386/kernel/Makefile 2005-03-04 12:03:50 -08:00 +++ b/arch/i386/kernel/Makefile 2005-03-04 12:03:50 -08:00 @@ -40,7 +40,7 @@ obj-$(CONFIG_ACPI_SLEEP) += acpi_wakeup.o obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o obj-$(CONFIG_X86_LOCAL_APIC) += mpparse.o apic.o nmi.o -obj-$(CONFIG_X86_IO_APIC) += io_apic.o +obj-$(CONFIG_X86_IO_APIC) += io_apic.o earlyquirk.o obj-$(CONFIG_X86_VISWS_APIC) += visws_apic.o obj-$(CONFIG_EDD) += edd.o diff -Nru a/arch/i386/kernel/acpi.c b/arch/i386/kernel/acpi.c --- a/arch/i386/kernel/acpi.c 2005-03-04 12:03:50 -08:00 +++ b/arch/i386/kernel/acpi.c 2005-03-04 12:03:50 -08:00 @@ -55,6 +55,7 @@ acpi_interrupt_flags acpi_sci_flags __initdata; int acpi_sci_override_gsi __initdata; +int acpi_skip_timer_override __initdata; /* -------------------------------------------------------------------------- Boot-time Configuration -------------------------------------------------------------------------- */ @@ -320,6 +321,12 @@ return 0; } + if (acpi_skip_timer_override && + intsrc->bus_irq == 0 && intsrc->global_irq == 2) { + printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n"); + return 0; + } + mp_override_legacy_irq ( intsrc->bus_irq, intsrc->flags.polarity, @@ -433,6 +440,8 @@ return result; } + check_acpi_pci(); + result = acpi_blacklisted(); if (result) { printk(KERN_NOTICE PREFIX "BIOS listed in blacklist, disabling ACPI support\n"); diff -Nru a/arch/i386/kernel/earlyquirk.c b/arch/i386/kernel/earlyquirk.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/i386/kernel/earlyquirk.c 2005-03-04 12:03:50 -08:00 @@ -0,0 +1,53 @@ +/* + * Do early PCI probing for bug detection when the main PCI subsystem is + * not up yet. + */ +#include +#include +#include +#include +#include + +#ifdef CONFIG_ACPI +static int __init check_bridge(int vendor, int device) +{ + /* According to Nvidia all timer overrides are bogus. Just ignore + them all. */ + if (vendor == PCI_VENDOR_ID_NVIDIA) { + acpi_skip_timer_override = 1; + } + return 0; +} + +void __init check_acpi_pci(void) +{ + int num,slot,func; + + /* Assume the machine supports type 1. If not it will + always read ffffffff and should not have any side effect. */ + + /* Poor man's PCI discovery */ + for (num = 0; num < 32; num++) { + for (slot = 0; slot < 32; slot++) { + for (func = 0; func < 8; func++) { + u32 class; + u32 vendor; + class = read_pci_config(num,slot,func, + PCI_CLASS_REVISION); + if (class == 0xffffffff) + break; + + if ((class >> 16) != PCI_CLASS_BRIDGE_PCI) + continue; + + vendor = read_pci_config(num, slot, func, + PCI_VENDOR_ID); + + if (check_bridge(vendor&0xffff, vendor >> 16)) + return; + } + + } + } +} +#endif /* CONFIG_ACPI */ diff -Nru a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c --- a/arch/sparc64/kernel/sys_sparc32.c 2005-03-04 12:03:50 -08:00 +++ b/arch/sparc64/kernel/sys_sparc32.c 2005-03-04 12:03:50 -08:00 @@ -505,25 +505,32 @@ return err; } -static int do_sys32_msgsnd (int first, int second, int third, void *uptr) +static int do_sys32_msgsnd(int first, int second, int third, void *uptr) { - struct msgbuf *p = kmalloc (second + sizeof (struct msgbuf), GFP_USER); - struct msgbuf32 *up = (struct msgbuf32 *)uptr; + struct msgbuf *p; + struct msgbuf32 *up; mm_segment_t old_fs; int err; + if (second < 0) + return -EINVAL; + + p = kmalloc(second + sizeof (struct msgbuf), GFP_USER); if (!p) return -ENOMEM; + + up = (struct msgbuf32 *)uptr; err = -EFAULT; - if (get_user (p->mtype, &up->mtype) || - __copy_from_user (p->mtext, &up->mtext, second)) + if (get_user(p->mtype, &up->mtype) || + __copy_from_user(p->mtext, up->mtext, second)) goto out; - old_fs = get_fs (); - set_fs (KERNEL_DS); - err = sys_msgsnd (first, p, second, third); - set_fs (old_fs); + + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = sys_msgsnd(first, p, second, third); + set_fs(old_fs); out: - kfree (p); + kfree(p); return err; } @@ -535,6 +542,9 @@ mm_segment_t old_fs; int err; + if (second < 0) + return -EINVAL; + if (!version) { struct ipc_kludge *uipck = (struct ipc_kludge *)uptr; struct ipc_kludge ipck; @@ -560,7 +570,7 @@ goto free_then_out; up = (struct msgbuf32 *)uptr; if (put_user (p->mtype, &up->mtype) || - __copy_to_user (&up->mtext, p->mtext, err)) + __copy_to_user (up->mtext, p->mtext, err)) err = -EFAULT; free_then_out: kfree (p); @@ -647,18 +657,18 @@ return err; } -static int do_sys32_shmat (int first, int second, int third, int version, void *uptr) +static int do_sys32_shmat(int first, int second, u32 third, int version, void *uptr) { unsigned long raddr; - u32 *uaddr = (u32 *)A((u32)third); + u32 *uaddr = (u32 *)A(third); int err = -EINVAL; if (version == 1) goto out; - err = sys_shmat (first, uptr, second, &raddr); + err = sys_shmat(first, uptr, second, &raddr); if (err) goto out; - err = put_user (raddr, uaddr); + err = put_user(raddr, uaddr); out: return err; } @@ -797,9 +807,11 @@ return sys_semtimedop(semid, tsems, nsems, t64); } -asmlinkage int sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) +asmlinkage int sys32_ipc (u32 call, u32 first, u32 second, u32 third, s32 __ptr, s32 __fifth) { int version, err; + u32 ptr = (u32) __ptr; + u32 fifth = (u32) __fifth; version = call >> 16; /* hack for backward compatibility */ call &= 0xffff; @@ -808,15 +820,23 @@ switch (call) { case SEMOP: /* struct sembuf is the same on 32 and 64bit :)) */ - err = sys_semtimedop (first, (struct sembuf *)AA(ptr), second, NULL); + err = sys_semtimedop((int)first, + (struct sembuf *)A(ptr), + second, NULL); goto out; case SEMTIMEDOP: - err = sys32_semtimedop (first, (struct sembuf *)AA(ptr), second, (const struct timespec32 *) AA(fifth)); + err = sys32_semtimedop((int)first, + (struct sembuf *)A(ptr), + second, + (const struct timespec32 *) + A(third)); case SEMGET: - err = sys_semget (first, second, third); + err = sys_semget((key_t)first, (int)second, + (int)third); goto out; case SEMCTL: - err = do_sys32_semctl (first, second, third, (void *)AA(ptr)); + err = do_sys32_semctl((int)first, (int)second, + (int)third, (void *) A(ptr)); goto out; default: err = -ENOSYS; @@ -825,17 +845,20 @@ if (call <= MSGCTL) switch (call) { case MSGSND: - err = do_sys32_msgsnd (first, second, third, (void *)AA(ptr)); + err = do_sys32_msgsnd((int)first, (int)second, + (int)third, (void *)A(ptr)); goto out; case MSGRCV: - err = do_sys32_msgrcv (first, second, fifth, third, - version, (void *)AA(ptr)); + err = do_sys32_msgrcv((int)first, (int)second, + (int)fifth, (int)third, + version, (void *)A(ptr)); goto out; case MSGGET: - err = sys_msgget ((key_t) first, second); + err = sys_msgget((key_t)first, (int)second); goto out; case MSGCTL: - err = do_sys32_msgctl (first, second, (void *)AA(ptr)); + err = do_sys32_msgctl((int)first, (int)second, + (void *)A(ptr)); goto out; default: err = -ENOSYS; @@ -844,17 +867,18 @@ if (call <= SHMCTL) switch (call) { case SHMAT: - err = do_sys32_shmat (first, second, third, - version, (void *)AA(ptr)); + err = do_sys32_shmat((int)first, (int)second, third, + version, (void *)A(ptr)); goto out; case SHMDT: - err = sys_shmdt ((char *)AA(ptr)); + err = sys_shmdt((char *)A(ptr)); goto out; case SHMGET: - err = sys_shmget (first, second, third); + err = sys_shmget((key_t)first, second, (int)third); goto out; case SHMCTL: - err = do_sys32_shmctl (first, second, (void *)AA(ptr)); + err = do_sys32_shmctl((int)first, (int)second, + (void *)A(ptr)); goto out; default: err = -ENOSYS; @@ -2158,9 +2182,6 @@ if (uts) timeout = (timespec_to_jiffies(&ts) + (ts.tv_sec || ts.tv_nsec)); - - current->state = TASK_INTERRUPTIBLE; - timeout = schedule_timeout(timeout); if (timeout) { /* None ready -- temporarily unblock those we're diff -Nru a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c --- a/arch/sparc64/kernel/time.c 2005-03-04 12:03:50 -08:00 +++ b/arch/sparc64/kernel/time.c 2005-03-04 12:03:50 -08:00 @@ -770,6 +770,7 @@ strcmp(model, "mk48t59") && strcmp(model, "m5819") && strcmp(model, "m5819p") && + strcmp(model, "m5823") && strcmp(model, "ds1287")) { if (cbus != NULL) { prom_printf("clock_probe: Central bus lacks timer chip.\n"); @@ -829,7 +830,8 @@ if (!strcmp(model, "ds1287") || !strcmp(model, "m5819") || - !strcmp(model, "m5819p")) { + !strcmp(model, "m5819p") || + !strcmp(model, "m5823")) { ds1287_regs = edev->resource[0].start; } else { mstk48t59_regs = edev->resource[0].start; @@ -850,7 +852,8 @@ } if (!strcmp(model, "ds1287") || !strcmp(model, "m5819") || - !strcmp(model, "m5819p")) { + !strcmp(model, "m5819p") || + !strcmp(model, "m5823")) { ds1287_regs = isadev->resource.start; } else { mstk48t59_regs = isadev->resource.start; diff -Nru a/arch/x86_64/kernel/acpi.c b/arch/x86_64/kernel/acpi.c --- a/arch/x86_64/kernel/acpi.c 2005-03-04 12:03:50 -08:00 +++ b/arch/x86_64/kernel/acpi.c 2005-03-04 12:03:50 -08:00 @@ -53,6 +53,7 @@ acpi_interrupt_flags acpi_sci_flags __initdata; int acpi_sci_override_gsi __initdata; +int acpi_skip_timer_override __initdata; /* -------------------------------------------------------------------------- Boot-time Configuration -------------------------------------------------------------------------- */ @@ -330,6 +331,12 @@ if (intsrc->bus_irq == acpi_fadt.sci_int) { acpi_sci_ioapic_setup(intsrc->global_irq, intsrc->flags.polarity, intsrc->flags.trigger); + return 0; + } + + if (acpi_skip_timer_override && + intsrc->bus_irq == 0 && intsrc->global_irq == 2) { + printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n"); return 0; } diff -Nru a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c --- a/arch/x86_64/kernel/io_apic.c 2005-03-04 12:03:50 -08:00 +++ b/arch/x86_64/kernel/io_apic.c 2005-03-04 12:03:50 -08:00 @@ -259,10 +259,14 @@ case PCI_VENDOR_ID_VIA: return; case PCI_VENDOR_ID_NVIDIA: +#ifdef CONFIG_ACPI + /* All timer overrides on Nvidia + seem to be wrong. Skip them. */ + acpi_skip_timer_override = 1; printk(KERN_INFO - "PCI bridge %02x:%02x from %x found. Setting \"noapic\". Overwrite with \"apic\"\n", - num,slot,vendor); - skip_ioapic_setup = 1; + "Nvidia board detected. Ignoring ACPI timer override.\n"); +#endif + /* RED-PEN skip them on mptables too? */ return; } diff -Nru a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c --- a/drivers/char/synclinkmp.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/char/synclinkmp.c 2005-03-04 12:03:50 -08:00 @@ -1,5 +1,5 @@ /* - * $Id: synclinkmp.c,v 3.23 2004/08/24 19:49:48 paulkf Exp $ + * $Id: synclinkmp.c,v 3.27 2005/02/15 21:29:09 paulkf Exp $ * * Device driver for Microgate SyncLink Multiport * high speed multiprotocol serial adapter. @@ -504,7 +504,7 @@ MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICES) "i"); static char *driver_name = "SyncLink MultiPort driver"; -static char *driver_version = "$Revision: 3.23 $"; +static char *driver_version = "$Revision: 3.27 $"; static int __devinit synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent); static void __devexit synclinkmp_remove_one(struct pci_dev *dev); @@ -4482,7 +4482,7 @@ * 07..05 Reserved, must be 0 * 04..00 RRC<4..0> Rx FIFO trigger active 0x00 = 1 byte */ - write_reg(info, TRC0, 0x00); + write_reg(info, RRC, 0x00); /* TRC0 Transmit Ready Control 0 * diff -Nru a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h --- a/drivers/net/e1000/e1000.h 2005-03-04 12:03:50 -08:00 +++ b/drivers/net/e1000/e1000.h 2005-03-04 12:03:50 -08:00 @@ -140,6 +140,7 @@ #define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */ #define AUTO_ALL_MODES 0 +#define E1000_EEPROM_82544_APM 0x0004 #define E1000_EEPROM_APME 0x0400 #ifndef E1000_MASTER_SLAVE @@ -211,6 +212,7 @@ /* TX */ struct e1000_desc_ring tx_ring; + struct e1000_buffer previous_buffer_info; spinlock_t tx_lock; uint32_t txd_cmd; uint32_t tx_int_delay; @@ -224,6 +226,7 @@ uint32_t tx_fifo_size; atomic_t tx_fifo_stall; boolean_t pcix_82544; + boolean_t detect_tx_hung; /* RX */ struct e1000_desc_ring rx_ring; diff -Nru a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c --- a/drivers/net/e1000/e1000_ethtool.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/net/e1000/e1000_ethtool.c 2005-03-04 12:03:50 -08:00 @@ -1309,7 +1309,7 @@ struct e1000_desc_ring *txdr = &adapter->test_tx_ring; struct e1000_desc_ring *rxdr = &adapter->test_rx_ring; struct pci_dev *pdev = adapter->pdev; - int i; + int i, ret_val; E1000_WRITE_REG(&adapter->hw, RDT, rxdr->count - 1); @@ -1329,11 +1329,12 @@ rxdr->buffer_info[i].length, PCI_DMA_FROMDEVICE); - if (!e1000_check_lbtest_frame(rxdr->buffer_info[i++].skb, 1024)) - return 0; - } while (i < 64); + ret_val = e1000_check_lbtest_frame(rxdr->buffer_info[i].skb, + 1024); + i++; + } while (ret_val != 0 && i < 64); - return 13; + return ret_val; } static int diff -Nru a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c --- a/drivers/net/e1000/e1000_hw.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/net/e1000/e1000_hw.c 2005-03-04 12:03:50 -08:00 @@ -1573,7 +1573,8 @@ if(mii_status_reg & MII_SR_LINK_STATUS) break; msec_delay(100); } - if((i == 0) && (hw->phy_type == e1000_phy_m88)) { + if((i == 0) && + (hw->phy_type == e1000_phy_m88)) { /* We didn't get link. Reset the DSP and wait again for link. */ ret_val = e1000_phy_reset_dsp(hw); if(ret_val) { @@ -2504,7 +2505,7 @@ } } - ret_val = e1000_read_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT & reg_addr, + ret_val = e1000_read_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr, phy_data); return ret_val; @@ -2610,7 +2611,7 @@ } } - ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT & reg_addr, + ret_val = e1000_write_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr, phy_data); return ret_val; @@ -2956,8 +2957,7 @@ /* Check polarity status */ ret_val = e1000_check_polarity(hw, &polarity); if(ret_val) - return ret_val; - + return ret_val; phy_info->cable_polarity = polarity; ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); @@ -2967,9 +2967,9 @@ phy_info->mdix_mode = (phy_data & M88E1000_PSSR_MDIX) >> M88E1000_PSSR_MDIX_SHIFT; - if(phy_data & M88E1000_PSSR_1000MBS) { - /* Cable Length Estimation and Local/Remote Receiver Informatoion - * are only valid at 1000 Mbps + if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) { + /* Cable Length Estimation and Local/Remote Receiver Information + * are only valid at 1000 Mbps. */ phy_info->cable_length = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> M88E1000_PSSR_CABLE_LENGTH_SHIFT); @@ -4641,41 +4641,44 @@ { uint32_t status; - if(hw->mac_type < e1000_82543) { + switch (hw->mac_type) { + case e1000_82542_rev2_0: + case e1000_82542_rev2_1: hw->bus_type = e1000_bus_type_unknown; hw->bus_speed = e1000_bus_speed_unknown; hw->bus_width = e1000_bus_width_unknown; - return; - } - - status = E1000_READ_REG(hw, STATUS); - hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ? - e1000_bus_type_pcix : e1000_bus_type_pci; + break; + default: + status = E1000_READ_REG(hw, STATUS); + hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ? + e1000_bus_type_pcix : e1000_bus_type_pci; - if(hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) { - hw->bus_speed = (hw->bus_type == e1000_bus_type_pci) ? - e1000_bus_speed_66 : e1000_bus_speed_120; - } else if(hw->bus_type == e1000_bus_type_pci) { - hw->bus_speed = (status & E1000_STATUS_PCI66) ? - e1000_bus_speed_66 : e1000_bus_speed_33; - } else { - switch (status & E1000_STATUS_PCIX_SPEED) { - case E1000_STATUS_PCIX_SPEED_66: - hw->bus_speed = e1000_bus_speed_66; - break; - case E1000_STATUS_PCIX_SPEED_100: - hw->bus_speed = e1000_bus_speed_100; - break; - case E1000_STATUS_PCIX_SPEED_133: - hw->bus_speed = e1000_bus_speed_133; - break; - default: - hw->bus_speed = e1000_bus_speed_reserved; - break; + if(hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) { + hw->bus_speed = (hw->bus_type == e1000_bus_type_pci) ? + e1000_bus_speed_66 : e1000_bus_speed_120; + } else if(hw->bus_type == e1000_bus_type_pci) { + hw->bus_speed = (status & E1000_STATUS_PCI66) ? + e1000_bus_speed_66 : e1000_bus_speed_33; + } else { + switch (status & E1000_STATUS_PCIX_SPEED) { + case E1000_STATUS_PCIX_SPEED_66: + hw->bus_speed = e1000_bus_speed_66; + break; + case E1000_STATUS_PCIX_SPEED_100: + hw->bus_speed = e1000_bus_speed_100; + break; + case E1000_STATUS_PCIX_SPEED_133: + hw->bus_speed = e1000_bus_speed_133; + break; + default: + hw->bus_speed = e1000_bus_speed_reserved; + break; + } } + hw->bus_width = (status & E1000_STATUS_BUS64) ? + e1000_bus_width_64 : e1000_bus_width_32; + break; } - hw->bus_width = (status & E1000_STATUS_BUS64) ? - e1000_bus_width_64 : e1000_bus_width_32; } /****************************************************************************** * Reads a value from one of the devices registers using port I/O (as opposed @@ -4740,6 +4743,7 @@ uint16_t agc_value = 0; uint16_t cur_agc, min_agc = IGP01E1000_AGC_LENGTH_TABLE_SIZE; uint16_t i, phy_data; + uint16_t cable_length; DEBUGFUNC("e1000_get_cable_length"); @@ -4751,10 +4755,11 @@ &phy_data); if(ret_val) return ret_val; + cable_length = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >> + M88E1000_PSSR_CABLE_LENGTH_SHIFT; /* Convert the enum value to ranged values */ - switch((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> - M88E1000_PSSR_CABLE_LENGTH_SHIFT) { + switch (cable_length) { case e1000_cable_length_50: *min_length = 0; *max_length = e1000_igp_cable_length_50; @@ -4921,8 +4926,7 @@ return ret_val; hw->speed_downgraded = (phy_data & IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0; - } - else if(hw->phy_type == e1000_phy_m88) { + } else if(hw->phy_type == e1000_phy_m88) { ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); if(ret_val) diff -Nru a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h --- a/drivers/net/e1000/e1000_hw.h 2005-03-04 12:03:50 -08:00 +++ b/drivers/net/e1000/e1000_hw.h 2005-03-04 12:03:50 -08:00 @@ -36,7 +36,6 @@ #include "e1000_osdep.h" - /* Forward declarations of structures used by the shared code */ struct e1000_hw; struct e1000_hw_stats; @@ -370,6 +369,7 @@ #define E1000_DEV_ID_82546GB_SERDES 0x107B #define E1000_DEV_ID_82546GB_PCIE 0x108A #define E1000_DEV_ID_82547EI 0x1019 + #define NODE_ADDRESS_SIZE 6 #define ETH_LENGTH_OF_ADDRESS 6 @@ -1735,6 +1735,9 @@ #define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */ #define PHY_EXT_STATUS 0x0F /* Extended Status Reg */ +#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ +#define MAX_PHY_MULTI_PAGE_REG 0xF /* Registers equal on all pages */ + /* M88E1000 Specific Registers */ #define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */ #define M88E1000_PHY_SPEC_STATUS 0x11 /* PHY Specific Status Register */ @@ -1795,8 +1798,7 @@ #define IGP01E1000_ANALOG_REGS_PAGE 0x20C0 -#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ -#define MAX_PHY_MULTI_PAGE_REG 0xF /*Registers that are equal on all pages*/ + /* PHY Control Register */ #define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */ #define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */ @@ -2099,7 +2101,11 @@ #define IGP01E1000_ANALOG_FUSE_FINE_1 0x0080 #define IGP01E1000_ANALOG_FUSE_FINE_10 0x0500 + /* Bit definitions for valid PHY IDs. */ +/* I = Integrated + * E = External + */ #define M88E1000_E_PHY_ID 0x01410C50 #define M88E1000_I_PHY_ID 0x01410C30 #define M88E1011_I_PHY_ID 0x01410C20 diff -Nru a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c --- a/drivers/net/e1000/e1000_main.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/net/e1000/e1000_main.c 2005-03-04 12:03:50 -08:00 @@ -34,6 +34,14 @@ * - if_mii support and associated kcompat for older kernels * - More errlogging support from Jon Mason * - Fix TSO issues on PPC64 machines -- Jon Mason + * 5.7.1 12/16/04 + * - Resurrect 82547EI/GI related fix in e1000_intr to avoid deadlocks. This + * fix was removed as it caused system instability. The suspected cause of + * this is the called to e1000_irq_disable in e1000_intr. Inlined the + * required piece of e1000_irq_disable into e1000_intr. + * 5.7.0 12/10/04 + * - include fix to the condition that determines when to quit NAPI - Robert Olsson + * - use netif_poll_{disable/enable} to synchronize between NAPI and i/f up/down * 5.6.5 11/01/04 * - Enabling NETIF_F_SG without checksum offload is illegal - John Mason @@ -41,8 +49,13 @@ * - Remove redundant initialization - Jamal Hadi * - Reset buffer_info->dma in tx resource cleanup logic * 5.6.2 10/12/04 + * - Avoid filling tx_ring completely - shemminger@osdl.org + * - Replace schedule_timeout() with msleep()/msleep_interruptible() - + * nacc@us.ibm.com * - Sparse cleanup - shemminger@osdl.org * - Fix tx resource cleanup logic + * - LLTX support - ak@suse.de and hadi@cyberus.ca + * - {set, get}_wol is now symmetric for 82545EM adapters */ char e1000_driver_name[] = "e1000"; @@ -52,7 +65,7 @@ #else #define DRIVERNAPI "-NAPI" #endif -char e1000_driver_version[] = "5.6.10.1-k1"DRIVERNAPI; +char e1000_driver_version[] = "5.7.6-k1"DRIVERNAPI; char e1000_copyright[] = "Copyright (c) 1999-2004 Intel Corporation."; /* e1000_pci_tbl - PCI Device ID Table @@ -76,6 +89,7 @@ INTEL_E1000_ETHERNET_DEVICE(0x1011), INTEL_E1000_ETHERNET_DEVICE(0x1012), INTEL_E1000_ETHERNET_DEVICE(0x1013), + INTEL_E1000_ETHERNET_DEVICE(0x1014), INTEL_E1000_ETHERNET_DEVICE(0x1015), INTEL_E1000_ETHERNET_DEVICE(0x1016), INTEL_E1000_ETHERNET_DEVICE(0x1017), @@ -303,6 +317,9 @@ mod_timer(&adapter->watchdog_timer, jiffies); e1000_irq_enable(adapter); +#ifdef CONFIG_E1000_NAPI + netif_poll_enable(netdev); +#endif return 0; } @@ -316,6 +333,10 @@ del_timer_sync(&adapter->tx_fifo_stall_timer); del_timer_sync(&adapter->watchdog_timer); del_timer_sync(&adapter->phy_info_timer); + +#ifdef CONFIG_E1000_NAPI + netif_poll_disable(netdev); +#endif adapter->link_speed = 0; adapter->link_duplex = 0; netif_carrier_off(netdev); @@ -409,6 +430,7 @@ int i; int err; uint16_t eeprom_data; + uint16_t eeprom_apme_mask = E1000_EEPROM_APME; if((err = pci_enable_device(pdev))) return err; @@ -505,9 +527,6 @@ } #ifdef NETIF_F_TSO - /* Disbaled for now until root-cause is found for - * hangs reported against non-IA archs. TSO can be - * enabled using ethtool -K eth tso on */ if((adapter->hw.mac_type >= e1000_82544) && (adapter->hw.mac_type != e1000_82547)) netdev->features |= NETIF_F_TSO; @@ -576,6 +595,11 @@ case e1000_82542_rev2_1: case e1000_82543: break; + case e1000_82544: + e1000_read_eeprom(&adapter->hw, + EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data); + eeprom_apme_mask = E1000_EEPROM_82544_APM; + break; case e1000_82546: case e1000_82546_rev_3: if((E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1) @@ -590,7 +614,7 @@ EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); break; } - if(eeprom_data & E1000_EEPROM_APME) + if(eeprom_data & eeprom_apme_mask) adapter->wol |= E1000_WUFC_MAG; /* reset the hardware with the new settings */ @@ -797,6 +821,31 @@ } /** + * e1000_check_64k_bound - check that memory doesn't cross 64kB boundary + * @adapter: address of board private structure + * @begin: address of beginning of memory + * @end: address of end of memory + **/ +static inline boolean_t +e1000_check_64k_bound(struct e1000_adapter *adapter, + void *start, unsigned long len) +{ + unsigned long begin = (unsigned long) start; + unsigned long end = begin + len; + + /* first rev 82545 and 82546 need to not allow any memory + * write location to cross a 64k boundary due to errata 23 */ + if (adapter->hw.mac_type == e1000_82545 || + adapter->hw.mac_type == e1000_82546 ) { + + /* check buffer doesn't cross 64kB */ + return ((begin ^ (end - 1)) >> 16) != 0 ? FALSE : TRUE; + } + + return TRUE; +} + +/** * e1000_setup_tx_resources - allocate Tx resources (Descriptors) * @adapter: board private structure * @@ -826,11 +875,42 @@ txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma); if(!txdr->desc) { +setup_tx_desc_die: DPRINTK(PROBE, ERR, "Unable to Allocate Memory for the Transmit descriptor ring\n"); vfree(txdr->buffer_info); return -ENOMEM; } + + /* fix for errata 23, cant cross 64kB boundary */ + if (!e1000_check_64k_bound(adapter, txdr->desc, txdr->size)) { + void *olddesc = txdr->desc; + dma_addr_t olddma = txdr->dma; + DPRINTK(TX_ERR,ERR,"txdr align check failed: %u bytes at %p\n", + txdr->size, txdr->desc); + /* try again, without freeing the previous */ + txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma); + /* failed allocation, critial failure */ + if(!txdr->desc) { + pci_free_consistent(pdev, txdr->size, olddesc, olddma); + goto setup_tx_desc_die; + } + + if (!e1000_check_64k_bound(adapter, txdr->desc, txdr->size)) { + /* give up */ + pci_free_consistent(pdev, txdr->size, + txdr->desc, txdr->dma); + pci_free_consistent(pdev, txdr->size, olddesc, olddma); + DPRINTK(PROBE, ERR, + "Unable to Allocate aligned Memory for the Transmit" + " descriptor ring\n"); + vfree(txdr->buffer_info); + return -ENOMEM; + } else { + /* free old, move on with the new one since its okay */ + pci_free_consistent(pdev, txdr->size, olddesc, olddma); + } + } memset(txdr->desc, 0, txdr->size); txdr->next_to_use = 0; @@ -948,11 +1028,43 @@ rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma); if(!rxdr->desc) { +setup_rx_desc_die: DPRINTK(PROBE, ERR, - "Unable to Allocate Memory for the Recieve descriptor ring\n"); + "Unble to Allocate Memory for the Recieve descriptor ring\n"); vfree(rxdr->buffer_info); return -ENOMEM; } + + /* fix for errata 23, cant cross 64kB boundary */ + if (!e1000_check_64k_bound(adapter, rxdr->desc, rxdr->size)) { + void *olddesc = rxdr->desc; + dma_addr_t olddma = rxdr->dma; + DPRINTK(RX_ERR,ERR, + "rxdr align check failed: %u bytes at %p\n", + rxdr->size, rxdr->desc); + /* try again, without freeing the previous */ + rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma); + /* failed allocation, critial failure */ + if(!rxdr->desc) { + pci_free_consistent(pdev, rxdr->size, olddesc, olddma); + goto setup_rx_desc_die; + } + + if (!e1000_check_64k_bound(adapter, rxdr->desc, rxdr->size)) { + /* give up */ + pci_free_consistent(pdev, rxdr->size, + rxdr->desc, rxdr->dma); + pci_free_consistent(pdev, rxdr->size, olddesc, olddma); + DPRINTK(PROBE, ERR, + "Unable to Allocate aligned Memory for the" + " Receive descriptor ring\n"); + vfree(rxdr->buffer_info); + return -ENOMEM; + } else { + /* free old, move on with the new one since its okay */ + pci_free_consistent(pdev, rxdr->size, olddesc, olddma); + } + } memset(rxdr->desc, 0, rxdr->size); rxdr->next_to_clean = 0; @@ -1086,6 +1198,7 @@ struct e1000_buffer *buffer_info) { struct pci_dev *pdev = adapter->pdev; + if(buffer_info->dma) { pci_unmap_page(pdev, buffer_info->dma, @@ -1114,6 +1227,11 @@ /* Free all the Tx ring sk_buffs */ + if (likely(adapter->previous_buffer_info.skb != NULL)) { + e1000_unmap_and_free_tx_resource(adapter, + &adapter->previous_buffer_info); + } + for(i = 0; i < tx_ring->count; i++) { buffer_info = &tx_ring->buffer_info[i]; e1000_unmap_and_free_tx_resource(adapter, buffer_info); @@ -1415,7 +1533,6 @@ struct e1000_adapter *adapter = (struct e1000_adapter *) data; struct net_device *netdev = adapter->netdev; struct e1000_desc_ring *txdr = &adapter->tx_ring; - unsigned int i; uint32_t link; e1000_check_for_link(&adapter->hw); @@ -1495,12 +1612,8 @@ /* Cause software interrupt to ensure rx ring is cleaned */ E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0); - /* Early detection of hung controller */ - i = txdr->next_to_clean; - if(txdr->buffer_info[i].dma && - time_after(jiffies, txdr->buffer_info[i].time_stamp + HZ) && - !(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_TXOFF)) - netif_stop_queue(netdev); + /* Force detection of hung controller every watchdog period*/ + adapter->detect_tx_hung = TRUE; /* Reset the timer */ mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); @@ -2132,10 +2245,28 @@ __netif_rx_schedule(netdev); } #else + /* Writing IMC and IMS is needed for 82547. + Due to Hub Link bus being occupied, an interrupt + de-assertion message is not able to be sent. + When an interrupt assertion message is generated later, + two messages are re-ordered and sent out. + That causes APIC to think 82547 is in de-assertion + state, while 82547 is in assertion state, resulting + in dead lock. Writing IMC forces 82547 into + de-assertion state. + */ + if(hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2){ + atomic_inc(&adapter->irq_sem); + E1000_WRITE_REG(&adapter->hw, IMC, ~0); + } + for(i = 0; i < E1000_MAX_INTR; i++) if(unlikely(!e1000_clean_rx_irq(adapter) & !e1000_clean_tx_irq(adapter))) break; + + if(hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2) + e1000_irq_enable(adapter); #endif return IRQ_HANDLED; @@ -2155,24 +2286,21 @@ int tx_cleaned; int work_done = 0; - if (!netif_carrier_ok(netdev)) - goto quit_polling; - tx_cleaned = e1000_clean_tx_irq(adapter); e1000_clean_rx_irq(adapter, &work_done, work_to_do); *budget -= work_done; netdev->quota -= work_done; - /* if no Rx and Tx cleanup work was done, exit the polling mode */ - if(!tx_cleaned || (work_done < work_to_do) || + /* if no Tx and not enough Rx work done, exit the polling mode */ + if((!tx_cleaned && (work_done < work_to_do)) || !netif_running(netdev)) { -quit_polling: netif_rx_complete(netdev); + netif_rx_complete(netdev); e1000_irq_enable(adapter); return 0; } - return (work_done >= work_to_do); + return 1; } #endif @@ -2196,11 +2324,34 @@ eop_desc = E1000_TX_DESC(*tx_ring, eop); while(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) { + /* pre-mature writeback of Tx descriptors */ + /* clear (free buffers and unmap pci_mapping) */ + /* previous_buffer_info */ + if (likely(adapter->previous_buffer_info.skb != NULL)) { + e1000_unmap_and_free_tx_resource(adapter, + &adapter->previous_buffer_info); + } + for(cleaned = FALSE; !cleaned; ) { tx_desc = E1000_TX_DESC(*tx_ring, i); buffer_info = &tx_ring->buffer_info[i]; + cleaned = (i == eop); + + /* pre-mature writeback of Tx descriptors */ + /* save the cleaning of the this for the */ + /* next iteration */ + if (cleaned) { + memcpy(&adapter->previous_buffer_info, + buffer_info, + sizeof(struct e1000_buffer)); + memset(buffer_info, + 0, + sizeof(struct e1000_buffer)); + } else { + e1000_unmap_and_free_tx_resource(adapter, + buffer_info); + } - e1000_unmap_and_free_tx_resource(adapter, buffer_info); tx_desc->buffer_addr = 0; tx_desc->lower.data = 0; tx_desc->upper.data = 0; @@ -2222,6 +2373,16 @@ netif_wake_queue(netdev); spin_unlock(&adapter->tx_lock); + + if(adapter->detect_tx_hung) { + /* detect a transmit hang in hardware, this serializes the + * check with the clearing of time_stamp and movement of i */ + adapter->detect_tx_hung = FALSE; + if(tx_ring->buffer_info[i].dma && + time_after(jiffies, tx_ring->buffer_info[i].time_stamp + HZ) && + !(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_TXOFF)) + netif_stop_queue(netdev); + } return cleaned; } @@ -2389,20 +2550,43 @@ struct e1000_buffer *buffer_info; struct sk_buff *skb; int reserve_len = 2; - unsigned int i; + unsigned int i, bufsz; i = rx_ring->next_to_use; buffer_info = &rx_ring->buffer_info[i]; while(!buffer_info->skb) { + bufsz = adapter->rx_buffer_len + reserve_len; - skb = dev_alloc_skb(adapter->rx_buffer_len + reserve_len); - + skb = dev_alloc_skb(bufsz); if(unlikely(!skb)) { /* Better luck next round */ break; } + /* fix for errata 23, cant cross 64kB boundary */ + if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) { + struct sk_buff *oldskb = skb; + DPRINTK(RX_ERR,ERR, + "skb align check failed: %u bytes at %p\n", + bufsz, skb->data); + /* try again, without freeing the previous */ + skb = dev_alloc_skb(bufsz); + if (!skb) { + dev_kfree_skb(oldskb); + break; + } + if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) { + /* give up */ + dev_kfree_skb(skb); + dev_kfree_skb(oldskb); + break; /* while !buffer_info->skb */ + } else { + /* move on with the new one */ + dev_kfree_skb(oldskb); + } + } + /* Make buffer alignment 2 beyond a 16 byte boundary * this will result in a 16 byte aligned IP header after * the 14 byte MAC header is removed @@ -2417,6 +2601,25 @@ skb->data, adapter->rx_buffer_len, PCI_DMA_FROMDEVICE); + + /* fix for errata 23, cant cross 64kB boundary */ + if(!e1000_check_64k_bound(adapter, + (void *)(unsigned long)buffer_info->dma, + adapter->rx_buffer_len)) { + DPRINTK(RX_ERR,ERR, + "dma align check failed: %u bytes at %ld\n", + adapter->rx_buffer_len, (unsigned long)buffer_info->dma); + + dev_kfree_skb(skb); + buffer_info->skb = NULL; + + pci_unmap_single(pdev, + buffer_info->dma, + adapter->rx_buffer_len, + PCI_DMA_FROMDEVICE); + + break; /* while !buffer_info->skb */ + } rx_desc = E1000_RX_DESC(*rx_ring, i); rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); diff -Nru a/drivers/net/tulip/21142.c b/drivers/net/tulip/21142.c --- a/drivers/net/tulip/21142.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/net/tulip/21142.c 2005-03-04 12:03:50 -08:00 @@ -14,8 +14,8 @@ */ -#include "tulip.h" #include +#include "tulip.h" #include diff -Nru a/drivers/net/tulip/eeprom.c b/drivers/net/tulip/eeprom.c --- a/drivers/net/tulip/eeprom.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/net/tulip/eeprom.c 2005-03-04 12:03:50 -08:00 @@ -14,6 +14,7 @@ */ +#include #include "tulip.h" #include #include diff -Nru a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c --- a/drivers/net/tulip/interrupt.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/net/tulip/interrupt.c 2005-03-04 12:03:50 -08:00 @@ -14,10 +14,10 @@ */ +#include #include "tulip.h" #include #include -#include int tulip_rx_copybreak; diff -Nru a/drivers/net/tulip/media.c b/drivers/net/tulip/media.c --- a/drivers/net/tulip/media.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/net/tulip/media.c 2005-03-04 12:03:50 -08:00 @@ -18,6 +18,7 @@ #include #include #include +#include #include "tulip.h" diff -Nru a/drivers/net/tulip/pnic.c b/drivers/net/tulip/pnic.c --- a/drivers/net/tulip/pnic.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/net/tulip/pnic.c 2005-03-04 12:03:50 -08:00 @@ -15,6 +15,7 @@ */ #include +#include #include "tulip.h" diff -Nru a/drivers/net/tulip/pnic2.c b/drivers/net/tulip/pnic2.c --- a/drivers/net/tulip/pnic2.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/net/tulip/pnic2.c 2005-03-04 12:03:50 -08:00 @@ -76,8 +76,8 @@ -#include "tulip.h" #include +#include "tulip.h" #include diff -Nru a/drivers/net/tulip/timer.c b/drivers/net/tulip/timer.c --- a/drivers/net/tulip/timer.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/net/tulip/timer.c 2005-03-04 12:03:50 -08:00 @@ -14,6 +14,7 @@ */ +#include #include "tulip.h" diff -Nru a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h --- a/drivers/net/tulip/tulip.h 2005-03-04 12:03:50 -08:00 +++ b/drivers/net/tulip/tulip.h 2005-03-04 12:03:50 -08:00 @@ -146,6 +146,9 @@ TxIntr = 0x01, }; +/* bit mask for CSR5 TX/RX process state */ +#define CSR5_TS 0x00700000 +#define CSR5_RS 0x000e0000 enum tulip_mode_bits { TxThreshold = (1 << 22), @@ -484,9 +487,19 @@ u32 csr6 = inl(ioaddr + CSR6); if (csr6 & RxTx) { + unsigned i=1300/10; outl(csr6 & ~RxTx, ioaddr + CSR6); barrier(); - (void) inl(ioaddr + CSR6); /* mmio sync */ + /* wait until in-flight frame completes. + * Max time @ 10BT: 1500*8b/10Mbps == 1200us (+ 100us margin) + * Typically expect this loop to end in < 50us on 100BT. + */ + while (--i && (inl(ioaddr + CSR5) & (CSR5_TS|CSR5_RS))) + udelay(10); + + if (!i) + printk (KERN_DEBUG "%s: tulip_stop_rxtx() failed\n", + tp->pdev->slot_name); } } diff -Nru a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c --- a/drivers/net/tulip/tulip_core.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/net/tulip/tulip_core.c 2005-03-04 12:03:50 -08:00 @@ -20,8 +20,8 @@ #include #include -#include "tulip.h" #include +#include "tulip.h" #include #include #include diff -Nru a/drivers/sbus/audio/audio.c b/drivers/sbus/audio/audio.c --- a/drivers/sbus/audio/audio.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/sbus/audio/audio.c 2005-03-04 12:03:50 -08:00 @@ -65,6 +65,14 @@ #define tprintk(x) #endif +static int audio_input_buffers = 8; +MODULE_PARM(audio_input_buffers, "i"); +MODULE_PARM_DESC(audio_input_buffers,"Number of input 8KB buffers."); + +static int audio_output_buffers = 8; +MODULE_PARM(audio_output_buffers, "i"); +MODULE_PARM_DESC(audio_output_buffers,"Number of output 8KB buffer."); + static short lis_get_elist_ent( strevent_t *list, pid_t pid ); static int lis_add_to_elist( strevent_t **list, pid_t pid, short events ); static int lis_del_from_elist( strevent_t **list, pid_t pid, short events ); @@ -438,7 +446,7 @@ m = drv->ops->get_input_balance(drv); i = OSS_TO_GAIN(k); j = OSS_TO_BAL(k); - oprintk((" for stereo to do %d (bal %d):", i, j)); + oprintk((" for stereo to do %ld (bal %ld):", i, j)); if (drv->ops->set_input_volume) drv->ops->set_input_volume(drv, i); if (drv->ops->set_input_balance) @@ -488,7 +496,7 @@ oprintk((" started as (0x%x)\n", BAL_TO_OSS(l,m))); i = OSS_TO_GAIN(k); j = OSS_TO_BAL(k); - oprintk((" for stereo to %d (bal %d)\n", i, j)); + oprintk((" for stereo to %ld (bal %ld)\n", i, j)); if (drv->ops->set_output_volume) drv->ops->set_output_volume(drv, i); if (drv->ops->set_output_balance) @@ -565,7 +573,7 @@ if (k & SOUND_MASK_CD) j = AUDIO_CD; if (k & SOUND_MASK_LINE) j = AUDIO_LINE_IN; if (k & SOUND_MASK_MIC) j = AUDIO_MICROPHONE; - oprintk(("setting inport to %d\n", j)); + oprintk(("setting inport to %ld\n", j)); i = drv->ops->set_input_port(drv, j); return put_user(i, (int *)arg); @@ -798,7 +806,7 @@ retval = -EINVAL; break; } - get_user(i, (int *)arg) + get_user(i, (int *)arg); tprintk(("setting speed to %d\n", i)); drv->ops->set_input_rate(drv, i); drv->ops->set_output_rate(drv, i); @@ -1955,8 +1963,6 @@ * Input buffers, on the other hand, always fill completely, * so we don't need input counts - each contains input_buffer_size * bytes of audio data. - * - * TODO: Make number of input/output buffers tunable parameters */ init_waitqueue_head(&drv->open_wait); @@ -1964,7 +1970,7 @@ init_waitqueue_head(&drv->output_drain_wait); init_waitqueue_head(&drv->input_read_wait); - drv->num_output_buffers = 8; + drv->num_output_buffers = audio_output_buffers; drv->output_buffer_size = (4096 * 2); drv->playing_count = 0; drv->output_offset = 0; @@ -1997,7 +2003,7 @@ } /* Setup the circular queue of input buffers. */ - drv->num_input_buffers = 8; + drv->num_input_buffers = audio_input_buffers; drv->input_buffer_size = (4096 * 2); drv->recording_count = 0; drv->input_front = 0; diff -Nru a/drivers/sbus/audio/dbri.c b/drivers/sbus/audio/dbri.c --- a/drivers/sbus/audio/dbri.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/sbus/audio/dbri.c 2005-03-04 12:03:50 -08:00 @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -161,7 +162,7 @@ static void dbri_process_interrupt_buffer(struct dbri *); -static void dbri_cmdsend(struct dbri *dbri, volatile s32 *cmd) +static void dbri_cmdsend(struct dbri *dbri, volatile s32 *cmd, int pause) { int MAXLOOPS = 1000000; int maxloops = MAXLOOPS; @@ -181,25 +182,30 @@ } else if ((cmd - &dbri->dma->cmd[0]) >= DBRI_NO_CMDS-1) { printk("DBRI: Command buffer overflow! (bug in driver)\n"); } else { - *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0); + if (pause) + *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0); *(cmd++) = DBRI_CMD(D_WAIT, 1, 0); dbri->wait_seen = 0; sbus_writel(dbri->dma_dvma, dbri->regs + REG8); - while ((--maxloops) > 0 && - (sbus_readl(dbri->regs + REG0) & D_P)) - barrier(); - if (maxloops == 0) { - printk("DBRI: Chip never completed command buffer\n"); - } else { - while ((--maxloops) > 0 && (! dbri->wait_seen)) - dbri_process_interrupt_buffer(dbri); + if (pause) { + while ((--maxloops) > 0 && + (sbus_readl(dbri->regs + REG0) & D_P)) + barrier(); if (maxloops == 0) { - printk("DBRI: Chip never acked WAIT\n"); + printk("DBRI: Chip never completed command buffer\n"); } else { - dprintk(D_INT, ("DBRI: Chip completed command " - "buffer (%d)\n", - MAXLOOPS - maxloops)); + while ((--maxloops) > 0 && (! dbri->wait_seen)) + dbri_process_interrupt_buffer(dbri); + if (maxloops == 0) { + printk("DBRI: Chip never acked WAIT\n"); + } else { + dprintk(D_INT, ("DBRI: Chip completed command " + "buffer (%d)\n", + MAXLOOPS - maxloops)); + } } + } else { + dprintk(D_INT, ("DBRI: NO PAUSE\n")); } } @@ -257,7 +263,10 @@ /* We should query the openprom to see what burst sizes this * SBus supports. For now, just disable all SBus bursts */ tmp = sbus_readl(dbri->regs + REG0); - tmp &= ~(D_G | D_S | D_E); + /* A brute approach - DBRI falls back to working burst size by itself + * On SS20 D_S does not work, so do not try so high. */ + tmp |= D_G | D_E; + tmp &= ~D_S; sbus_writel(tmp, dbri->regs + REG0); /* @@ -268,7 +277,7 @@ *(cmd++) = DBRI_CMD(D_IIQ, 0, 0); *(cmd++) = dma_addr; - dbri_cmdsend(dbri, cmd); + dbri_cmdsend(dbri, cmd, 1); } @@ -455,7 +464,7 @@ dbri->pipes[pipe].sdp | D_SDP_P | D_SDP_C | D_SDP_2SAME); *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, td); - dbri_cmdsend(dbri, cmd); + dbri_cmdsend(dbri, cmd, 1); } if (code == D_INTR_FXDT) { @@ -579,7 +588,7 @@ cmd = dbri_cmdlock(dbri); *(cmd++) = DBRI_CMD(D_SDP, 0, sdp | D_SDP_C | D_SDP_P); *(cmd++) = 0; - dbri_cmdsend(dbri, cmd); + dbri_cmdsend(dbri, cmd, 1); desc = dbri->pipes[pipe].desc; while (desc != -1) { @@ -722,7 +731,7 @@ *(cmd++) = D_TS_LEN(length) | D_TS_CYCLE(cycle) | D_TS_NEXT(nextpipe); } - dbri_cmdsend(dbri, cmd); + dbri_cmdsend(dbri, cmd, 1); } /* I don't use this function, so it's basically untested. */ @@ -752,7 +761,7 @@ *(cmd++) = D_TS_NEXT(nextpipe); } - dbri_cmdsend(dbri, cmd); + dbri_cmdsend(dbri, cmd, 1); } /* xmit_fixed() / recv_fixed() @@ -803,7 +812,7 @@ *(cmd++) = DBRI_CMD(D_SSP, 0, pipe); *(cmd++) = data; - dbri_cmdsend(dbri, cmd); + dbri_cmdsend(dbri, cmd, 1); } static void recv_fixed(struct dbri *dbri, int pipe, volatile __u32 *ptr) @@ -884,7 +893,9 @@ } if (len > ((1 << 13) - 1)) { - mylen = (1 << 13) - 1; + /* One should not leave a buffer shorter than */ + /* a single sample. Otherwise bad things happens.*/ + mylen = (1 << 13) - 4; } else { mylen = len; } @@ -954,7 +965,7 @@ cmd = dbri_cmdlock(dbri); *(cmd++) = DBRI_CMD(D_CDP, 0, pipe); - dbri_cmdsend(dbri,cmd); + dbri_cmdsend(dbri,cmd, 0); } else { /* Pipe isn't active - issue an SDP command to start * our chain of TDs running. @@ -965,7 +976,7 @@ dbri->pipes[pipe].sdp | D_SDP_P | D_SDP_EVERY | D_SDP_C); *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, first_td); - dbri_cmdsend(dbri, cmd); + dbri_cmdsend(dbri, cmd, 0); } restore_flags(flags); @@ -1083,7 +1094,7 @@ *(cmd++) = DBRI_CMD(D_SDP, 0, dbri->pipes[pipe].sdp | D_SDP_P | D_SDP_C); *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, first_rd); - dbri_cmdsend(dbri, cmd); + dbri_cmdsend(dbri, cmd, 1); } @@ -1191,7 +1202,7 @@ *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0); *(cmd++) = DBRI_CMD(D_CDM, 0, D_CDM_XCE|D_CDM_XEN|D_CDM_REN); - dbri_cmdsend(dbri, cmd); + dbri_cmdsend(dbri, cmd, 1); } /* @@ -1538,7 +1549,6 @@ xmit_on_pipe(dbri, 4, buffer, count, &dbri_audio_output_callback, drv); -#if 0 /* Notify midlevel that we're a DMA-capable driver that * can accept another buffer immediately. We should probably * check that we've got enough resources (i.e, descriptors) @@ -1551,9 +1561,14 @@ * DBRI with a chain of buffers, but the midlevel code is * so tricky that I really don't want to deal with it. */ + /* + * This must be enabled otherwise the output is noisy + * as return to user space is done when all buffers + * are already played, so user space player has no time + * to prepare next ones without a period of silence. - Krzysztof Helt + */ sparcaudio_output_done(drv, 2); -#endif } static void dbri_stop_output(struct sparcaudio_driver *drv) @@ -1842,6 +1857,12 @@ return dbri_get_output_rate(drv); } +static int dbri_get_formats(struct sparcaudio_driver *drv) +{ +/* 8-bit format is not working */ + return (AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE); +} + /******************* sparcaudio midlevel - ports ***********************/ static int dbri_set_output_port(struct sparcaudio_driver *drv, int port) @@ -1983,6 +2004,19 @@ dbri_get_input_ports, dbri_set_output_muted, dbri_get_output_muted, + NULL, /* dbri_set_output_pause, */ + NULL, /* dbri_get_output_pause, */ + NULL, /* dbri_set_input_pause, */ + NULL, /* dbri_get_input_pause, */ + NULL, /* dbri_set_output_samples, */ + NULL, /* dbri_get_output_samples, */ + NULL, /* dbri_set_input_samples, */ + NULL, /* dbri_get_input_samples, */ + NULL, /* dbri_set_output_error, */ + NULL, /* dbri_get_output_error, */ + NULL, /* dbri_set_input_error, */ + NULL, /* dbri_get_input_error, */ + dbri_get_formats }; @@ -2093,7 +2127,7 @@ #endif *(cmd++) = DBRI_CMD(D_TE, 0, val); - dbri_cmdsend(dbri, cmd); + dbri_cmdsend(dbri, cmd, 1); /* Activate the interface */ tmp = sbus_readl(dbri->regs + REG0); diff -Nru a/drivers/scsi/Config.in b/drivers/scsi/Config.in --- a/drivers/scsi/Config.in 2005-03-04 12:03:50 -08:00 +++ b/drivers/scsi/Config.in 2005-03-04 12:03:50 -08:00 @@ -73,6 +73,7 @@ dep_tristate ' ServerWorks Frodo / Apple K2 SATA support (EXPERIMENTAL)' CONFIG_SCSI_SATA_SVW $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL dep_tristate ' Intel PIIX/ICH SATA support' CONFIG_SCSI_ATA_PIIX $CONFIG_SCSI_SATA $CONFIG_PCI dep_tristate ' NVIDIA SATA support (EXPERIMENTAL)' CONFIG_SCSI_SATA_NV $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL +dep_tristate ' Pacific Digital SATA QStor support' CONFIG_SCSI_SATA_QSTOR $CONFIG_SCSI_SATA $CONFIG_PCI dep_tristate ' Promise SATA TX2/TX4 support (EXPERIMENTAL)' CONFIG_SCSI_SATA_PROMISE $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL dep_tristate ' Promise SATA SX4 support (EXPERIMENTAL)' CONFIG_SCSI_SATA_SX4 $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL dep_tristate ' Silicon Image SATA support (EXPERIMENTAL)' CONFIG_SCSI_SATA_SIL $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL diff -Nru a/drivers/scsi/Makefile b/drivers/scsi/Makefile --- a/drivers/scsi/Makefile 2005-03-04 12:03:50 -08:00 +++ b/drivers/scsi/Makefile 2005-03-04 12:03:50 -08:00 @@ -134,6 +134,7 @@ obj-$(CONFIG_SCSI_SATA_SVW) += libata.o sata_svw.o obj-$(CONFIG_SCSI_ATA_PIIX) += libata.o ata_piix.o obj-$(CONFIG_SCSI_SATA_PROMISE) += libata.o sata_promise.o +obj-$(CONFIG_SCSI_SATA_QSTOR) += libata.o sata_qstor.o obj-$(CONFIG_SCSI_SATA_SIL) += libata.o sata_sil.o obj-$(CONFIG_SCSI_SATA_VIA) += libata.o sata_via.o obj-$(CONFIG_SCSI_SATA_VITESSE) += libata.o sata_vsc.o diff -Nru a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c --- a/drivers/scsi/ahci.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/scsi/ahci.c 2005-03-04 12:03:50 -08:00 @@ -40,8 +40,6 @@ #define DRV_NAME "ahci" #define DRV_VERSION "1.00" -#define msleep libata_msleep /* 2.4-specific */ - enum { AHCI_PCI_BAR = 5, AHCI_MAX_SG = 168, /* hardware max is 64K */ @@ -180,6 +178,7 @@ static void ahci_host_stop(struct ata_host_set *host_set); static void ahci_qc_prep(struct ata_queued_cmd *qc); static u8 ahci_check_status(struct ata_port *ap); +static u8 ahci_check_err(struct ata_port *ap); static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); static Scsi_Host_Template ahci_sht = { @@ -206,6 +205,8 @@ .port_disable = ata_port_disable, .check_status = ahci_check_status, + .check_altstatus = ahci_check_status, + .check_err = ahci_check_err, .dev_select = ata_noop_dev_select, .phy_reset = ahci_phy_reset, @@ -454,6 +455,13 @@ return readl(mmio + PORT_TFDATA) & 0xFF; } +static u8 ahci_check_err(struct ata_port *ap) +{ + void *mmio = (void *) ap->ioaddr.cmd_addr; + + return (readl(mmio + PORT_TFDATA) >> 8) & 0xFF; +} + static void ahci_fill_sg(struct ata_queued_cmd *qc) { struct ahci_port_priv *pp = qc->ap->private_data; @@ -566,7 +574,7 @@ writel(tmp, port_mmio + PORT_CMD); readl(port_mmio + PORT_CMD); /* flush */ - printk(KERN_WARNING "ata%u: error occurred, port reset\n", ap->port_no); + printk(KERN_WARNING "ata%u: error occurred, port reset\n", ap->id); } static void ahci_eng_timeout(struct ata_port *ap) @@ -758,10 +766,10 @@ using_dac = hpriv->cap & HOST_CAP_64; if (using_dac && - !pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) { + !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { hpriv->flags |= HOST_CAP_64; } else { - rc = pci_set_dma_mask(pdev, 0xffffffffULL); + rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (rc) { printk(KERN_ERR DRV_NAME "(%s): 32-bit DMA enable failed\n", pci_name(pdev)); @@ -926,6 +934,7 @@ unsigned long base; void *mmio_base; unsigned int board_idx = (unsigned int) ent->driver_data; + int pci_dev_busy = 0; int rc; VPRINTK("ENTER\n"); @@ -938,8 +947,10 @@ return rc; rc = pci_request_regions(pdev, DRV_NAME); - if (rc) + if (rc) { + pci_dev_busy = 1; goto err_out; + } pci_enable_intx(pdev); @@ -999,7 +1010,8 @@ err_out_regions: pci_release_regions(pdev); err_out: - pci_disable_device(pdev); + if (!pci_dev_busy) + pci_disable_device(pdev); return rc; } diff -Nru a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c --- a/drivers/scsi/aic7xxx/aic79xx_pci.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/scsi/aic7xxx/aic79xx_pci.c 2005-03-04 12:03:50 -08:00 @@ -451,8 +451,10 @@ * or read prefetching could be initiated by the * CPU or host bridge. Our device does not support * either, so look for data corruption and/or flaged - * PCI errors. + * PCI errors. First pause without causing another + * chip reset. */ + hcntrl &= ~CHIPRST; ahd_outb(ahd, HCNTRL, hcntrl|PAUSE); while (ahd_is_paused(ahd) == 0) ; diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c --- a/drivers/scsi/aic7xxx/aic7xxx_pci.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c 2005-03-04 12:03:50 -08:00 @@ -1284,8 +1284,10 @@ * or read prefetching could be initiated by the * CPU or host bridge. Our device does not support * either, so look for data corruption and/or flagged - * PCI errors. + * PCI errors. First pause without causing another + * chip reset. */ + hcntrl &= ~CHIPRST; ahc_outb(ahc, HCNTRL, hcntrl|PAUSE); while (ahc_is_paused(ahc) == 0) ; diff -Nru a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c --- a/drivers/scsi/ata_piix.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/scsi/ata_piix.c 2005-03-04 12:03:50 -08:00 @@ -139,6 +139,8 @@ .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, + .bmdma_stop = ata_bmdma_stop, + .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, @@ -164,6 +166,8 @@ .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, + .bmdma_stop = ata_bmdma_stop, + .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, diff -Nru a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c --- a/drivers/scsi/libata-core.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/scsi/libata-core.c 2005-03-04 12:03:50 -08:00 @@ -376,7 +376,7 @@ } /** - * ata_check_status - Read device status reg & clear interrupt + * ata_check_status_pio - Read device status reg & clear interrupt * @ap: port where the device is * * Reads ATA taskfile status register for currently-selected device @@ -414,6 +414,27 @@ return ata_check_status_pio(ap); } +u8 ata_altstatus(struct ata_port *ap) +{ + if (ap->ops->check_altstatus) + return ap->ops->check_altstatus(ap); + + if (ap->flags & ATA_FLAG_MMIO) + return readb((void __iomem *)ap->ioaddr.altstatus_addr); + return inb(ap->ioaddr.altstatus_addr); +} + +u8 ata_chk_err(struct ata_port *ap) +{ + if (ap->ops->check_err) + return ap->ops->check_err(ap); + + if (ap->flags & ATA_FLAG_MMIO) { + return readb((void __iomem *) ap->ioaddr.error_addr); + } + return inb(ap->ioaddr.error_addr); +} + /** * ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure * @tf: Taskfile to convert @@ -1160,7 +1181,6 @@ printk(KERN_WARNING "ata%u: dev %u not supported, ignoring\n", ap->id, device); err_out: - ata_irq_on(ap); /* re-enable interrupts */ dev->class++; /* converts ATA_DEV_xxx into ATA_DEV_xxx_UNSUP */ DPRINTK("EXIT, err\n"); } @@ -1668,7 +1688,8 @@ ata_dev_try_classify(ap, 1); /* re-enable interrupts */ - ata_irq_on(ap); + if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */ + ata_irq_on(ap); /* is double-select really necessary? */ if (ap->device[1].class != ATA_DEV_NONE) @@ -2601,10 +2622,10 @@ case ATA_PROT_DMA: case ATA_PROT_ATAPI_DMA: - host_stat = ata_bmdma_status(ap); + host_stat = ap->ops->bmdma_status(ap); /* before we do anything else, clear DMA-Start bit */ - ata_bmdma_stop(ap); + ap->ops->bmdma_stop(ap); /* fall through */ @@ -2613,7 +2634,7 @@ drv_stat = ata_chk_status(ap); /* ack bmdma irq events */ - ata_bmdma_ack_irq(ap); + ap->ops->irq_clear(ap); printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n", ap->id, qc->tf.command, drv_stat, host_stat); @@ -2752,6 +2773,24 @@ } /** + * ata_qc_free - free unused ata_queued_cmd + * @qc: Command to complete + * + * Designed to free unused ata_queued_cmd object + * in case something prevents using it. + * + * LOCKING: + * + */ +void ata_qc_free(struct ata_queued_cmd *qc) +{ + assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */ + assert(qc->waiting == NULL); /* nothing should be waiting */ + + __ata_qc_complete(qc); +} + +/** * ata_qc_complete - Complete an active ATA command * @qc: Command to complete * @drv_stat: ATA status register contents @@ -2800,7 +2839,7 @@ return 1; /* fall through */ - + default: return 0; } @@ -3042,7 +3081,43 @@ void ata_bmdma_irq_clear(struct ata_port *ap) { - ata_bmdma_ack_irq(ap); + if (ap->flags & ATA_FLAG_MMIO) { + void __iomem *mmio = ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS; + writeb(readb(mmio), mmio); + } else { + unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS; + outb(inb(addr), addr); + } + +} + +u8 ata_bmdma_status(struct ata_port *ap) +{ + u8 host_stat; + if (ap->flags & ATA_FLAG_MMIO) { + void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr; + host_stat = readb(mmio + ATA_DMA_STATUS); + } else + host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); + return host_stat; +} + +void ata_bmdma_stop(struct ata_port *ap) +{ + if (ap->flags & ATA_FLAG_MMIO) { + void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr; + + /* clear start/stop bit */ + writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START, + mmio + ATA_DMA_CMD); + } else { + /* clear start/stop bit */ + outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START, + ap->ioaddr.bmdma_addr + ATA_DMA_CMD); + } + + /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ + ata_altstatus(ap); /* dummy read */ } /** @@ -3072,7 +3147,7 @@ case ATA_PROT_ATAPI_DMA: case ATA_PROT_ATAPI: /* check status of DMA engine */ - host_stat = ata_bmdma_status(ap); + host_stat = ap->ops->bmdma_status(ap); VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat); /* if it's not our irq... */ @@ -3080,7 +3155,7 @@ goto idle_irq; /* before we do anything else, clear DMA-Start bit */ - ata_bmdma_stop(ap); + ap->ops->bmdma_stop(ap); /* fall through */ @@ -3099,7 +3174,7 @@ ap->id, qc->tf.protocol, status); /* ack bmdma irq events */ - ata_bmdma_ack_irq(ap); + ap->ops->irq_clear(ap); /* complete taskfile transaction */ ata_qc_complete(qc, status); @@ -3674,6 +3749,7 @@ struct ata_port_info *port[2]; u8 tmp8, mask; unsigned int legacy_mode = 0; + int disable_dev_on_err = 1; int rc; DPRINTK("ENTER\n"); @@ -3704,18 +3780,22 @@ return rc; rc = pci_request_regions(pdev, DRV_NAME); - if (rc) + if (rc) { + disable_dev_on_err = 0; goto err_out; + } if (legacy_mode) { - if (!request_region(0x1f0, 8, "libata")) + if (!request_region(0x1f0, 8, "libata")) { + disable_dev_on_err = 0; printk(KERN_WARNING "ata: 0x1f0 IDE port busy\n"); - else + } else legacy_mode |= (1 << 0); - if (!request_region(0x170, 8, "libata")) + if (!request_region(0x170, 8, "libata")) { + disable_dev_on_err = 0; printk(KERN_WARNING "ata: 0x170 IDE port busy\n"); - else + } else legacy_mode |= (1 << 1); } @@ -3764,7 +3844,8 @@ release_region(0x170, 8); pci_release_regions(pdev); err_out: - pci_disable_device(pdev); + if (disable_dev_on_err) + pci_disable_device(pdev); return rc; } @@ -3922,6 +4003,8 @@ EXPORT_SYMBOL_GPL(ata_tf_to_fis); EXPORT_SYMBOL_GPL(ata_tf_from_fis); EXPORT_SYMBOL_GPL(ata_check_status); +EXPORT_SYMBOL_GPL(ata_altstatus); +EXPORT_SYMBOL_GPL(ata_chk_err); EXPORT_SYMBOL_GPL(ata_exec_command); EXPORT_SYMBOL_GPL(ata_port_start); EXPORT_SYMBOL_GPL(ata_port_stop); @@ -3930,6 +4013,8 @@ EXPORT_SYMBOL_GPL(ata_bmdma_setup); EXPORT_SYMBOL_GPL(ata_bmdma_start); EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear); +EXPORT_SYMBOL_GPL(ata_bmdma_status); +EXPORT_SYMBOL_GPL(ata_bmdma_stop); EXPORT_SYMBOL_GPL(ata_port_probe); EXPORT_SYMBOL_GPL(sata_phy_reset); EXPORT_SYMBOL_GPL(__sata_phy_reset); @@ -3940,7 +4025,6 @@ EXPORT_SYMBOL_GPL(ata_scsi_error); EXPORT_SYMBOL_GPL(ata_scsi_detect); EXPORT_SYMBOL_GPL(ata_add_to_probe_list); -EXPORT_SYMBOL_GPL(libata_msleep); EXPORT_SYMBOL_GPL(ssleep); EXPORT_SYMBOL_GPL(ata_scsi_release); EXPORT_SYMBOL_GPL(ata_host_intr); diff -Nru a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c --- a/drivers/scsi/libata-scsi.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/scsi/libata-scsi.c 2005-03-04 12:03:50 -08:00 @@ -663,6 +663,7 @@ return; err_out: + ata_qc_free(qc); ata_bad_cdb(cmd, done); DPRINTK("EXIT - badcmd\n"); } diff -Nru a/drivers/scsi/libata.h b/drivers/scsi/libata.h --- a/drivers/scsi/libata.h 2005-03-04 12:03:50 -08:00 +++ b/drivers/scsi/libata.h 2005-03-04 12:03:50 -08:00 @@ -37,6 +37,7 @@ /* libata-core.c */ extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, struct ata_device *dev); +extern void ata_qc_free(struct ata_queued_cmd *qc); extern int ata_qc_issue(struct ata_queued_cmd *qc); extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); extern void ata_dev_select(struct ata_port *ap, unsigned int device, diff -Nru a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c --- a/drivers/scsi/sata_nv.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/scsi/sata_nv.c 2005-03-04 12:03:50 -08:00 @@ -218,6 +218,8 @@ .phy_reset = sata_phy_reset, .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, + .bmdma_stop = ata_bmdma_stop, + .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, .eng_timeout = ata_eng_timeout, @@ -333,6 +335,7 @@ struct nv_host *host; struct ata_port_info *ppi; struct ata_probe_ent *probe_ent; + int pci_dev_busy = 0; int rc; u32 bar; @@ -351,8 +354,10 @@ goto err_out; rc = pci_request_regions(pdev, DRV_NAME); - if (rc) + if (rc) { + pci_dev_busy = 1; goto err_out_disable; + } rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); if (rc) @@ -418,7 +423,8 @@ err_out_regions: pci_release_regions(pdev); err_out_disable: - pci_disable_device(pdev); + if (!pci_dev_busy) + pci_disable_device(pdev); err_out: return rc; } diff -Nru a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c --- a/drivers/scsi/sata_promise.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/scsi/sata_promise.c 2005-03-04 12:03:50 -08:00 @@ -42,8 +42,6 @@ #define DRV_NAME "sata_promise" #define DRV_VERSION "1.01" -#define msleep libata_msleep /* 2.4-specific */ - enum { PDC_PKT_SUBMIT = 0x40, /* Command packet pointer addr */ PDC_INT_SEQMASK = 0x40, /* Mask of asserted SEQ INTs */ @@ -558,6 +556,7 @@ unsigned long base; void *mmio_base; unsigned int board_idx = (unsigned int) ent->driver_data; + int pci_dev_busy = 0; int rc; if (!printed_version++) @@ -572,8 +571,10 @@ return rc; rc = pci_request_regions(pdev, DRV_NAME); - if (rc) + if (rc) { + pci_dev_busy = 1; goto err_out; + } rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); if (rc) @@ -647,7 +648,8 @@ err_out_regions: pci_release_regions(pdev); err_out: - pci_disable_device(pdev); + if (!pci_dev_busy) + pci_disable_device(pdev); return rc; } diff -Nru a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/scsi/sata_qstor.c 2005-03-04 12:03:50 -08:00 @@ -0,0 +1,699 @@ +/* + * sata_qstor.c - Pacific Digital Corporation QStor SATA + * + * Maintained by: Mark Lord + * + * Copyright 2005 Pacific Digital Corporation. + * (OSL/GPL code release authorized by Jalil Fadavi). + * + * The contents of this file are subject to the Open + * Software License version 1.1 that can be found at + * http://www.opensource.org/licenses/osl-1.1.txt and is included herein + * by reference. + * + * Alternatively, the contents of this file may be used under the terms + * of the GNU General Public License version 2 (the "GPL") as distributed + * in the kernel source COPYING file, in which case the provisions of + * the GPL are applicable instead of the above. If you wish to allow + * the use of your version of this file only under the terms of the + * GPL and not to allow others to use your version of this file under + * the OSL, indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by the GPL. + * If you do not delete the provisions above, a recipient may use your + * version of this file under either the OSL or the GPL. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "scsi.h" +#include +#include +#include + +#define DRV_NAME "sata_qstor" +#define DRV_VERSION "0.03" + +enum { + QS_PORTS = 4, + QS_MAX_PRD = LIBATA_MAX_PRD, + QS_CPB_ORDER = 6, + QS_CPB_BYTES = (1 << QS_CPB_ORDER), + QS_PRD_BYTES = QS_MAX_PRD * 16, + QS_PKT_BYTES = QS_CPB_BYTES + QS_PRD_BYTES, + + QS_DMA_BOUNDARY = ~0UL, + + /* global register offsets */ + QS_HCF_CNFG3 = 0x0003, /* host configuration offset */ + QS_HID_HPHY = 0x0004, /* host physical interface info */ + QS_HCT_CTRL = 0x00e4, /* global interrupt mask offset */ + QS_HST_SFF = 0x0100, /* host status fifo offset */ + QS_HVS_SERD3 = 0x0393, /* PHY enable offset */ + + /* global control bits */ + QS_HPHY_64BIT = (1 << 1), /* 64-bit bus detected */ + QS_CNFG3_GSRST = 0x01, /* global chip reset */ + QS_SERD3_PHY_ENA = 0xf0, /* PHY detection ENAble*/ + + /* per-channel register offsets */ + QS_CCF_CPBA = 0x0710, /* chan CPB base address */ + QS_CCF_CSEP = 0x0718, /* chan CPB separation factor */ + QS_CFC_HUFT = 0x0800, /* host upstream fifo threshold */ + QS_CFC_HDFT = 0x0804, /* host downstream fifo threshold */ + QS_CFC_DUFT = 0x0808, /* dev upstream fifo threshold */ + QS_CFC_DDFT = 0x080c, /* dev downstream fifo threshold */ + QS_CCT_CTR0 = 0x0900, /* chan control-0 offset */ + QS_CCT_CTR1 = 0x0901, /* chan control-1 offset */ + QS_CCT_CFF = 0x0a00, /* chan command fifo offset */ + + /* channel control bits */ + QS_CTR0_REG = (1 << 1), /* register mode (vs. pkt mode) */ + QS_CTR0_CLER = (1 << 2), /* clear channel errors */ + QS_CTR1_RDEV = (1 << 1), /* sata phy/comms reset */ + QS_CTR1_RCHN = (1 << 4), /* reset channel logic */ + QS_CCF_RUN_PKT = 0x107, /* RUN a new dma PKT */ + + /* pkt sub-field headers */ + QS_HCB_HDR = 0x01, /* Host Control Block header */ + QS_DCB_HDR = 0x02, /* Device Control Block header */ + + /* pkt HCB flag bits */ + QS_HF_DIRO = (1 << 0), /* data DIRection Out */ + QS_HF_DAT = (1 << 3), /* DATa pkt */ + QS_HF_IEN = (1 << 4), /* Interrupt ENable */ + QS_HF_VLD = (1 << 5), /* VaLiD pkt */ + + /* pkt DCB flag bits */ + QS_DF_PORD = (1 << 2), /* Pio OR Dma */ + QS_DF_ELBA = (1 << 3), /* Extended LBA (lba48) */ + + /* PCI device IDs */ + board_2068_idx = 0, /* QStor 4-port SATA/RAID */ +}; + +typedef enum { qs_state_idle, qs_state_pkt, qs_state_mmio } qs_state_t; + +struct qs_port_priv { + u8 *pkt; + dma_addr_t pkt_dma; + qs_state_t state; +}; + +static u32 qs_scr_read (struct ata_port *ap, unsigned int sc_reg); +static void qs_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); +static int qs_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); +static irqreturn_t qs_intr (int irq, void *dev_instance, struct pt_regs *regs); +static int qs_port_start(struct ata_port *ap); +static void qs_host_stop(struct ata_host_set *host_set); +static void qs_port_stop(struct ata_port *ap); +static void qs_phy_reset(struct ata_port *ap); +static void qs_qc_prep(struct ata_queued_cmd *qc); +static int qs_qc_issue(struct ata_queued_cmd *qc); +static int qs_check_atapi_dma(struct ata_queued_cmd *qc); +static void qs_bmdma_stop(struct ata_port *ap); +static u8 qs_bmdma_status(struct ata_port *ap); +static void qs_irq_clear(struct ata_port *ap); + +static Scsi_Host_Template qs_ata_sht = { + .module = THIS_MODULE, + .name = DRV_NAME, + .detect = ata_scsi_detect, + .release = ata_scsi_release, + .ioctl = ata_scsi_ioctl, + .queuecommand = ata_scsi_queuecmd, + .eh_strategy_handler = ata_scsi_error, + .can_queue = ATA_DEF_QUEUE, + .this_id = ATA_SHT_THIS_ID, + .sg_tablesize = QS_MAX_PRD, + .max_sectors = ATA_MAX_SECTORS, + .cmd_per_lun = ATA_SHT_CMD_PER_LUN, + .use_new_eh_code = ATA_SHT_NEW_EH_CODE, + .emulated = ATA_SHT_EMULATED, + //FIXME .use_clustering = ATA_SHT_USE_CLUSTERING, + .use_clustering = ENABLE_CLUSTERING, + .proc_name = DRV_NAME, + .bios_param = ata_std_bios_param, +}; + +static struct ata_port_operations qs_ata_ops = { + .port_disable = ata_port_disable, + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + .check_status = ata_check_status, + .check_atapi_dma = qs_check_atapi_dma, + .exec_command = ata_exec_command, + .dev_select = ata_std_dev_select, + .phy_reset = qs_phy_reset, + .qc_prep = qs_qc_prep, + .qc_issue = qs_qc_issue, + .eng_timeout = ata_eng_timeout, + .irq_handler = qs_intr, + .irq_clear = qs_irq_clear, + .scr_read = qs_scr_read, + .scr_write = qs_scr_write, + .port_start = qs_port_start, + .port_stop = qs_port_stop, + .host_stop = qs_host_stop, + .bmdma_stop = qs_bmdma_stop, + .bmdma_status = qs_bmdma_status, +}; + +static struct ata_port_info qs_port_info[] = { + /* board_2068_idx */ + { + .sht = &qs_ata_sht, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_SATA_RESET | + //FIXME ATA_FLAG_SRST | + ATA_FLAG_MMIO, + .pio_mask = 0x10, /* pio4 */ + .udma_mask = 0x7f, /* udma0-6 */ + .port_ops = &qs_ata_ops, + }, +}; + +static struct pci_device_id qs_ata_pci_tbl[] = { + { PCI_VENDOR_ID_PDC, 0x2068, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_2068_idx }, + + { } /* terminate list */ +}; + +static struct pci_driver qs_ata_pci_driver = { + .name = DRV_NAME, + .id_table = qs_ata_pci_tbl, + .probe = qs_ata_init_one, + .remove = ata_pci_remove_one, +}; + +static int qs_check_atapi_dma(struct ata_queued_cmd *qc) +{ + return 1; /* ATAPI DMA not supported */ +} + +static void qs_bmdma_stop(struct ata_port *ap) +{ + /* nothing */ +} + +static u8 qs_bmdma_status(struct ata_port *ap) +{ + return 0; +} + +static void qs_irq_clear(struct ata_port *ap) +{ + /* nothing */ +} + +static void qs_enter_reg_mode(struct ata_port *ap) +{ + u8 __iomem *chan = ap->host_set->mmio_base + (ap->port_no * 0x4000); + + writeb(QS_CTR0_REG, chan + QS_CCT_CTR0); + readb(chan + QS_CCT_CTR0); /* flush */ +} + +static void qs_phy_reset(struct ata_port *ap) +{ + u8 __iomem *chan = ap->host_set->mmio_base + (ap->port_no * 0x4000); + struct qs_port_priv *pp = ap->private_data; + + pp->state = qs_state_idle; + writeb(QS_CTR1_RCHN, chan + QS_CCT_CTR1); + qs_enter_reg_mode(ap); + sata_phy_reset(ap); +} + +static u32 qs_scr_read (struct ata_port *ap, unsigned int sc_reg) +{ + if (sc_reg > SCR_CONTROL) + return ~0U; + return readl((void __iomem *)(ap->ioaddr.scr_addr + (sc_reg * 8))); +} + +static void qs_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) +{ + if (sc_reg > SCR_CONTROL) + return; + writel(val, (void __iomem *)(ap->ioaddr.scr_addr + (sc_reg * 8))); +} + +static void qs_fill_sg(struct ata_queued_cmd *qc) +{ + struct scatterlist *sg = qc->sg; + struct ata_port *ap = qc->ap; + struct qs_port_priv *pp = ap->private_data; + unsigned int nelem; + u8 *prd = pp->pkt + QS_CPB_BYTES; + + assert(sg != NULL); + assert(qc->n_elem > 0); + + for (nelem = 0; nelem < qc->n_elem; nelem++,sg++) { + u64 addr; + u32 len; + + addr = sg_dma_address(sg); + *(__le64 *)prd = cpu_to_le64(addr); + prd += sizeof(u64); + + len = sg_dma_len(sg); + *(__le32 *)prd = cpu_to_le32(len); + prd += sizeof(u64); + + VPRINTK("PRD[%u] = (0x%llX, 0x%X)\n", nelem, + (unsigned long long)addr, len); + } +} + +static void qs_qc_prep(struct ata_queued_cmd *qc) +{ + struct qs_port_priv *pp = qc->ap->private_data; + u8 dflags = QS_DF_PORD, *buf = pp->pkt; + u8 hflags = QS_HF_DAT | QS_HF_IEN | QS_HF_VLD; + u64 addr; + + VPRINTK("ENTER\n"); + + qs_enter_reg_mode(qc->ap); + if (qc->tf.protocol != ATA_PROT_DMA) { + ata_qc_prep(qc); + return; + } + + qs_fill_sg(qc); + + if ((qc->tf.flags & ATA_TFLAG_WRITE)) + hflags |= QS_HF_DIRO; + if ((qc->tf.flags & ATA_TFLAG_LBA48)) + dflags |= QS_DF_ELBA; + + /* host control block (HCB) */ + buf[ 0] = QS_HCB_HDR; + buf[ 1] = hflags; + *(__le32 *)(&buf[ 4]) = cpu_to_le32(qc->nsect * ATA_SECT_SIZE); + *(__le32 *)(&buf[ 8]) = cpu_to_le32(qc->n_elem); + addr = ((u64)pp->pkt_dma) + QS_CPB_BYTES; + *(__le64 *)(&buf[16]) = cpu_to_le64(addr); + + /* device control block (DCB) */ + buf[24] = QS_DCB_HDR; + buf[28] = dflags; + + /* frame information structure (FIS) */ + ata_tf_to_fis(&qc->tf, &buf[32], 0); +} + +static inline void qs_packet_start(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + u8 __iomem *chan = ap->host_set->mmio_base + (ap->port_no * 0x4000); + + VPRINTK("ENTER, ap %p\n", ap); + + writeb(QS_CTR0_CLER, chan + QS_CCT_CTR0); + wmb(); /* flush PRDs and pkt to memory */ + writel(QS_CCF_RUN_PKT, chan + QS_CCT_CFF); + readl(chan + QS_CCT_CFF); /* flush */ +} + +static int qs_qc_issue(struct ata_queued_cmd *qc) +{ + struct qs_port_priv *pp = qc->ap->private_data; + + switch (qc->tf.protocol) { + case ATA_PROT_DMA: + + pp->state = qs_state_pkt; + qs_packet_start(qc); + return 0; + + case ATA_PROT_ATAPI_DMA: + BUG(); + break; + + default: + break; + } + + pp->state = qs_state_mmio; + return ata_qc_issue_prot(qc); +} + +static inline unsigned int qs_intr_pkt(struct ata_host_set *host_set) +{ + unsigned int handled = 0; + u8 sFFE; + u8 __iomem *mmio_base = host_set->mmio_base; + + do { + u32 sff0 = readl(mmio_base + QS_HST_SFF); + u32 sff1 = readl(mmio_base + QS_HST_SFF + 4); + u8 sEVLD = (sff1 >> 30) & 0x01; /* valid flag */ + sFFE = sff1 >> 31; /* empty flag */ + + if (sEVLD) { + u8 sDST = sff0 >> 16; /* dev status */ + u8 sHST = sff1 & 0x3f; /* host status */ + unsigned int port_no = (sff1 >> 8) & 0x03; + struct ata_port *ap = host_set->ports[port_no]; + + DPRINTK("SFF=%08x%08x: sCHAN=%u sHST=%d sDST=%02x\n", + sff1, sff0, port_no, sHST, sDST); + handled = 1; + if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) { + struct ata_queued_cmd *qc; + struct qs_port_priv *pp = ap->private_data; + if (!pp || pp->state != qs_state_pkt) + continue; + qc = ata_qc_from_tag(ap, ap->active_tag); + if (qc && (!(qc->tf.ctl & ATA_NIEN))) { + switch (sHST) { + case 0: /* sucessful CPB */ + case 3: /* device error */ + pp->state = qs_state_idle; + qs_enter_reg_mode(qc->ap); + ata_qc_complete(qc, sDST); + break; + default: + break; + } + } + } + } + } while (!sFFE); + return handled; +} + +static inline unsigned int qs_intr_mmio(struct ata_host_set *host_set) +{ + unsigned int handled = 0, port_no; + + for (port_no = 0; port_no < host_set->n_ports; ++port_no) { + struct ata_port *ap; + ap = host_set->ports[port_no]; + if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) { + struct ata_queued_cmd *qc; + struct qs_port_priv *pp = ap->private_data; + if (!pp || pp->state != qs_state_mmio) + continue; + qc = ata_qc_from_tag(ap, ap->active_tag); + if (qc && (!(qc->tf.ctl & ATA_NIEN))) { + + /* check main status, clearing INTRQ */ + u8 status = ata_chk_status(ap); + if ((status & ATA_BUSY)) + continue; + DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n", + ap->id, qc->tf.protocol, status); + + /* complete taskfile transaction */ + pp->state = qs_state_idle; + ata_qc_complete(qc, status); + handled = 1; + } + } + } + return handled; +} + +static irqreturn_t qs_intr(int irq, void *dev_instance, struct pt_regs *regs) +{ + struct ata_host_set *host_set = dev_instance; + unsigned int handled = 0; + + VPRINTK("ENTER\n"); + + spin_lock(&host_set->lock); + handled = qs_intr_pkt(host_set) | qs_intr_mmio(host_set); + spin_unlock(&host_set->lock); + + VPRINTK("EXIT\n"); + + return IRQ_RETVAL(handled); +} + +static void qs_ata_setup_port(struct ata_ioports *port, unsigned long base) +{ + port->cmd_addr = + port->data_addr = base + 0x400; + port->error_addr = + port->feature_addr = base + 0x408; /* hob_feature = 0x409 */ + port->nsect_addr = base + 0x410; /* hob_nsect = 0x411 */ + port->lbal_addr = base + 0x418; /* hob_lbal = 0x419 */ + port->lbam_addr = base + 0x420; /* hob_lbam = 0x421 */ + port->lbah_addr = base + 0x428; /* hob_lbah = 0x429 */ + port->device_addr = base + 0x430; + port->status_addr = + port->command_addr = base + 0x438; + port->altstatus_addr = + port->ctl_addr = base + 0x440; + port->scr_addr = base + 0xc00; +} + +static int qs_port_start(struct ata_port *ap) +{ + struct device *dev = ap->host_set->dev; + struct qs_port_priv *pp; + void __iomem *mmio_base = ap->host_set->mmio_base; + void __iomem *chan = mmio_base + (ap->port_no * 0x4000); + u64 addr; + int rc; + + rc = ata_port_start(ap); + if (rc) + return rc; + qs_enter_reg_mode(ap); + pp = kcalloc(1, sizeof(*pp), GFP_KERNEL); + if (!pp) { + rc = -ENOMEM; + goto err_out; + } + pp->pkt = dma_alloc_coherent(dev, QS_PKT_BYTES, &pp->pkt_dma, + GFP_KERNEL); + if (!pp->pkt) { + rc = -ENOMEM; + goto err_out_kfree; + } + memset(pp->pkt, 0, QS_PKT_BYTES); + ap->private_data = pp; + + addr = (u64)pp->pkt_dma; + writel((u32) addr, chan + QS_CCF_CPBA); + writel((u32)(addr >> 32), chan + QS_CCF_CPBA + 4); + return 0; + +err_out_kfree: + kfree(pp); +err_out: + ata_port_stop(ap); + return rc; +} + +static void qs_port_stop(struct ata_port *ap) +{ + struct device *dev = ap->host_set->dev; + struct qs_port_priv *pp = ap->private_data; + + if (pp != NULL) { + ap->private_data = NULL; + if (pp->pkt != NULL) + dma_free_coherent(dev, QS_PKT_BYTES, pp->pkt, + pp->pkt_dma); + kfree(pp); + } + ata_port_stop(ap); +} + +static void qs_host_stop(struct ata_host_set *host_set) +{ + void __iomem *mmio_base = host_set->mmio_base; + + writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */ + writeb(QS_CNFG3_GSRST, mmio_base + QS_HCF_CNFG3); /* global reset */ +} + +static void qs_host_init(unsigned int chip_id, struct ata_probe_ent *pe) +{ + void __iomem *mmio_base = pe->mmio_base; + unsigned int port_no; + + writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */ + writeb(QS_CNFG3_GSRST, mmio_base + QS_HCF_CNFG3); /* global reset */ + + /* reset each channel in turn */ + for (port_no = 0; port_no < pe->n_ports; ++port_no) { + u8 __iomem *chan = mmio_base + (port_no * 0x4000); + writeb(QS_CTR1_RDEV|QS_CTR1_RCHN, chan + QS_CCT_CTR1); + writeb(QS_CTR0_REG, chan + QS_CCT_CTR0); + readb(chan + QS_CCT_CTR0); /* flush */ + } + writeb(QS_SERD3_PHY_ENA, mmio_base + QS_HVS_SERD3); /* enable phy */ + + for (port_no = 0; port_no < pe->n_ports; ++port_no) { + u8 __iomem *chan = mmio_base + (port_no * 0x4000); + /* set FIFO depths to same settings as Windows driver */ + writew(32, chan + QS_CFC_HUFT); + writew(32, chan + QS_CFC_HDFT); + writew(10, chan + QS_CFC_DUFT); + writew( 8, chan + QS_CFC_DDFT); + /* set CPB size in bytes, as a power of two */ + writeb(QS_CPB_ORDER, chan + QS_CCF_CSEP); + } + writeb(1, mmio_base + QS_HCT_CTRL); /* enable host interrupts */ +} + +/* + * The QStor understands 64-bit buses, and uses 64-bit fields + * for DMA pointers regardless of bus width. We just have to + * make sure our DMA masks are set appropriately for whatever + * bridge lies between us and the QStor, and then the DMA mapping + * code will ensure we only ever "see" appropriate buffer addresses. + * If we're 32-bit limited somewhere, then our 64-bit fields will + * just end up with zeros in the upper 32-bits, without any special + * logic required outside of this routine (below). + */ +static int qs_set_dma_masks(struct pci_dev *pdev, void __iomem *mmio_base) +{ + u32 bus_info = readl(mmio_base + QS_HID_HPHY); + int rc, have_64bit_bus = (bus_info & QS_HPHY_64BIT); + + if (have_64bit_bus && + !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { + /* do nothing */ + } else { + rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + if (rc) { + printk(KERN_ERR DRV_NAME + "(%s): 32-bit DMA enable failed\n", + pci_name(pdev)); + return rc; + } + } + return 0; +} + +static int qs_ata_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + static int printed_version; + struct ata_probe_ent *probe_ent = NULL; + void __iomem *mmio_base; + unsigned int board_idx = (unsigned int) ent->driver_data; + int rc, port_no; + + if (!printed_version++) + printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); + + rc = pci_enable_device(pdev); + if (rc) + return rc; + + rc = pci_request_regions(pdev, DRV_NAME); + if (rc) + goto err_out; + + if ((pci_resource_flags(pdev, 4) & IORESOURCE_MEM) == 0) { + rc = -ENODEV; + goto err_out_regions; + } + + mmio_base = ioremap(pci_resource_start(pdev, 4), + pci_resource_len(pdev, 4)); + if (mmio_base == NULL) { + rc = -ENOMEM; + goto err_out_regions; + } + + rc = qs_set_dma_masks(pdev, mmio_base); + if (rc) + goto err_out_iounmap; + + probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); + if (probe_ent == NULL) { + rc = -ENOMEM; + goto err_out_iounmap; + } + + memset(probe_ent, 0, sizeof(*probe_ent)); + probe_ent->dev = pci_dev_to_dev(pdev); + INIT_LIST_HEAD(&probe_ent->node); + + probe_ent->sht = qs_port_info[board_idx].sht; + probe_ent->host_flags = qs_port_info[board_idx].host_flags; + probe_ent->pio_mask = qs_port_info[board_idx].pio_mask; + probe_ent->mwdma_mask = qs_port_info[board_idx].mwdma_mask; + probe_ent->udma_mask = qs_port_info[board_idx].udma_mask; + probe_ent->port_ops = qs_port_info[board_idx].port_ops; + + probe_ent->irq = pdev->irq; + probe_ent->irq_flags = SA_SHIRQ; + probe_ent->mmio_base = mmio_base; + probe_ent->n_ports = QS_PORTS; + + for (port_no = 0; port_no < probe_ent->n_ports; ++port_no) { + unsigned long chan = (unsigned long)mmio_base + + (port_no * 0x4000); + qs_ata_setup_port(&probe_ent->port[port_no], chan); + } + + pci_set_master(pdev); + + /* initialize adapter */ + qs_host_init(board_idx, probe_ent); + + ata_add_to_probe_list(probe_ent); + return 0; + +err_out_iounmap: + iounmap(mmio_base); +err_out_regions: + pci_release_regions(pdev); +err_out: + pci_disable_device(pdev); + return rc; +} + +static int __init qs_ata_init(void) +{ + int rc; + + rc = pci_module_init(&qs_ata_pci_driver); + if (rc) + return rc; + + rc = scsi_register_module(MODULE_SCSI_HA, &qs_ata_sht); + if (rc) { + rc = -ENODEV; + goto err_out; + } + + return 0; + +err_out: + pci_unregister_driver(&qs_ata_pci_driver); + return rc; +} + +static void __exit qs_ata_exit(void) +{ + scsi_unregister_module(MODULE_SCSI_HA, &qs_ata_sht); + pci_unregister_driver(&qs_ata_pci_driver); +} + +MODULE_AUTHOR("Mark Lord"); +MODULE_DESCRIPTION("Pacific Digital Corporation QStor SATA low-level driver"); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(pci, qs_ata_pci_tbl); +MODULE_VERSION(DRV_VERSION); + +module_init(qs_ata_init); +module_exit(qs_ata_exit); diff -Nru a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c --- a/drivers/scsi/sata_sil.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/scsi/sata_sil.c 2005-03-04 12:03:50 -08:00 @@ -140,6 +140,8 @@ .post_set_mode = sil_post_set_mode, .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, + .bmdma_stop = ata_bmdma_stop, + .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, .eng_timeout = ata_eng_timeout, @@ -337,6 +339,7 @@ void *mmio_base; int rc; unsigned int i; + int pci_dev_busy = 0; u32 tmp, irq_mask; if (!printed_version++) @@ -351,8 +354,10 @@ return rc; rc = pci_request_regions(pdev, DRV_NAME); - if (rc) + if (rc) { + pci_dev_busy = 1; goto err_out; + } rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); if (rc) @@ -434,7 +439,8 @@ err_out_regions: pci_release_regions(pdev); err_out: - pci_disable_device(pdev); + if (!pci_dev_busy) + pci_disable_device(pdev); return rc; } diff -Nru a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c --- a/drivers/scsi/sata_sis.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/scsi/sata_sis.c 2005-03-04 12:03:50 -08:00 @@ -103,6 +103,8 @@ .phy_reset = sata_phy_reset, .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, + .bmdma_stop = ata_bmdma_stop, + .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, .eng_timeout = ata_eng_timeout, @@ -201,14 +203,17 @@ int rc; u32 genctl; struct ata_port_info *ppi; + int pci_dev_busy = 0; rc = pci_enable_device(pdev); if (rc) return rc; rc = pci_request_regions(pdev, DRV_NAME); - if (rc) + if (rc) { + pci_dev_busy = 1; goto err_out; + } rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); if (rc) @@ -255,7 +260,8 @@ pci_release_regions(pdev); err_out: - pci_disable_device(pdev); + if (!pci_dev_busy) + pci_disable_device(pdev); return rc; } diff -Nru a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c --- a/drivers/scsi/sata_svw.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/scsi/sata_svw.c 2005-03-04 12:03:50 -08:00 @@ -302,6 +302,8 @@ .phy_reset = sata_phy_reset, .bmdma_setup = k2_bmdma_setup_mmio, .bmdma_start = k2_bmdma_start_mmio, + .bmdma_stop = ata_bmdma_stop, + .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, .eng_timeout = ata_eng_timeout, @@ -339,6 +341,7 @@ struct ata_probe_ent *probe_ent = NULL; unsigned long base; void *mmio_base; + int pci_dev_busy = 0; int rc; if (!printed_version++) @@ -360,8 +363,10 @@ /* Request PCI regions */ rc = pci_request_regions(pdev, DRV_NAME); - if (rc) + if (rc) { + pci_dev_busy = 1; goto err_out; + } rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); if (rc) @@ -429,7 +434,8 @@ err_out_regions: pci_release_regions(pdev); err_out: - pci_disable_device(pdev); + if (!pci_dev_busy) + pci_disable_device(pdev); return rc; } diff -Nru a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c --- a/drivers/scsi/sata_sx4.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/scsi/sata_sx4.c 2005-03-04 12:03:50 -08:00 @@ -1191,8 +1191,7 @@ error = 0; break; } - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((i * 100) * HZ / 1000 + 1); + msleep(i*100); } return error; } @@ -1225,8 +1224,7 @@ readl(mmio + PDC_TIME_CONTROL); /* Wait 3 seconds */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(3 * HZ); + msleep(3000); /* When timer is enabled, counter is decreased every internal @@ -1369,6 +1367,7 @@ void *mmio_base, *dimm_mmio = NULL; struct pdc_host_priv *hpriv = NULL; unsigned int board_idx = (unsigned int) ent->driver_data; + int pci_dev_busy = 0; int rc; if (!printed_version++) @@ -1383,8 +1382,10 @@ return rc; rc = pci_request_regions(pdev, DRV_NAME); - if (rc) + if (rc) { + pci_dev_busy = 1; goto err_out; + } rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); if (rc) @@ -1469,7 +1470,8 @@ err_out_regions: pci_release_regions(pdev); err_out: - pci_disable_device(pdev); + if (!pci_dev_busy) + pci_disable_device(pdev); return rc; } diff -Nru a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c --- a/drivers/scsi/sata_uli.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/scsi/sata_uli.c 2005-03-04 12:03:50 -08:00 @@ -98,6 +98,8 @@ .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, + .bmdma_stop = ata_bmdma_stop, + .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, @@ -186,14 +188,17 @@ struct ata_port_info *ppi; int rc; unsigned int board_idx = (unsigned int) ent->driver_data; + int pci_dev_busy = 0; rc = pci_enable_device(pdev); if (rc) return rc; rc = pci_request_regions(pdev, DRV_NAME); - if (rc) + if (rc) { + pci_dev_busy = 1; goto err_out; + } rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); if (rc) @@ -256,7 +261,8 @@ pci_release_regions(pdev); err_out: - pci_disable_device(pdev); + if (!pci_dev_busy) + pci_disable_device(pdev); return rc; } diff -Nru a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c --- a/drivers/scsi/sata_via.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/scsi/sata_via.c 2005-03-04 12:03:50 -08:00 @@ -24,6 +24,11 @@ If you do not delete the provisions above, a recipient may use your version of this file under either the OSL or the GPL. + ---------------------------------------------------------------------- + + To-do list: + * VT6421 PATA support + */ #include @@ -38,11 +43,14 @@ #include #define DRV_NAME "sata_via" -#define DRV_VERSION "1.0" +#define DRV_VERSION "1.1" -enum { - via_sata = 0, +enum board_ids_enum { + vt6420, + vt6421, +}; +enum { SATA_CHAN_ENAB = 0x40, /* SATA channel enable */ SATA_INT_GATE = 0x41, /* SATA interrupt gating */ SATA_NATIVE_MODE = 0x42, /* Native mode enable */ @@ -50,10 +58,8 @@ PORT0 = (1 << 1), PORT1 = (1 << 0), - - ENAB_ALL = PORT0 | PORT1, - - INT_GATE_ALL = PORT0 | PORT1, + ALL_PORTS = PORT0 | PORT1, + N_PORTS = 2, NATIVE_MODE_ALL = (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4), @@ -66,7 +72,8 @@ static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); static struct pci_device_id svia_pci_tbl[] = { - { 0x1106, 0x3149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, via_sata }, + { 0x1106, 0x3149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6420 }, + { 0x1106, 0x3249, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6421 }, { } /* terminate list */ }; @@ -111,6 +118,9 @@ .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, + .bmdma_stop = ata_bmdma_stop, + .bmdma_status = ata_bmdma_status, + .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, @@ -159,18 +169,132 @@ 8, 4, 8, 4, 16, 256 }; +static const unsigned int vt6421_bar_sizes[] = { + 16, 16, 16, 16, 32, 128 +}; + static unsigned long svia_scr_addr(unsigned long addr, unsigned int port) { return addr + (port * 128); } +static unsigned long vt6421_scr_addr(unsigned long addr, unsigned int port) +{ + return addr + (port * 64); +} + +static void vt6421_init_addrs(struct ata_probe_ent *probe_ent, + struct pci_dev *pdev, + unsigned int port) +{ + unsigned long reg_addr = pci_resource_start(pdev, port); + unsigned long bmdma_addr = pci_resource_start(pdev, 4) + (port * 8); + unsigned long scr_addr; + + probe_ent->port[port].cmd_addr = reg_addr; + probe_ent->port[port].altstatus_addr = + probe_ent->port[port].ctl_addr = (reg_addr + 8) | ATA_PCI_CTL_OFS; + probe_ent->port[port].bmdma_addr = bmdma_addr; + + scr_addr = vt6421_scr_addr(pci_resource_start(pdev, 5), port); + probe_ent->port[port].scr_addr = scr_addr; + + ata_std_ports(&probe_ent->port[port]); +} + +static struct ata_probe_ent *vt6420_init_probe_ent(struct pci_dev *pdev) +{ + struct ata_probe_ent *probe_ent; + struct ata_port_info *ppi = &svia_port_info; + + probe_ent = ata_pci_init_native_mode(pdev, &ppi); + if (!probe_ent) + return NULL; + + probe_ent->port[0].scr_addr = + svia_scr_addr(pci_resource_start(pdev, 5), 0); + probe_ent->port[1].scr_addr = + svia_scr_addr(pci_resource_start(pdev, 5), 1); + + return probe_ent; +} + +static struct ata_probe_ent *vt6421_init_probe_ent(struct pci_dev *pdev) +{ + struct ata_probe_ent *probe_ent; + unsigned int i; + + probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); + if (!probe_ent) + return NULL; + + memset(probe_ent, 0, sizeof(*probe_ent)); + probe_ent->dev = pci_dev_to_dev(pdev); + INIT_LIST_HEAD(&probe_ent->node); + + probe_ent->sht = &svia_sht; + probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET | + ATA_FLAG_NO_LEGACY; + probe_ent->port_ops = &svia_sata_ops; + probe_ent->n_ports = N_PORTS; + probe_ent->irq = pdev->irq; + probe_ent->irq_flags = SA_SHIRQ; + probe_ent->pio_mask = 0x1f; + probe_ent->mwdma_mask = 0x07; + probe_ent->udma_mask = 0x7f; + + for (i = 0; i < N_PORTS; i++) + vt6421_init_addrs(probe_ent, pdev, i); + + return probe_ent; +} + +static void svia_configure(struct pci_dev *pdev) +{ + u8 tmp8; + + pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tmp8); + printk(KERN_INFO DRV_NAME "(%s): routed to hard irq line %d\n", + pci_name(pdev), + (int) (tmp8 & 0xf0) == 0xf0 ? 0 : tmp8 & 0x0f); + + /* make sure SATA channels are enabled */ + pci_read_config_byte(pdev, SATA_CHAN_ENAB, &tmp8); + if ((tmp8 & ALL_PORTS) != ALL_PORTS) { + printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channels (0x%x)\n", + pci_name(pdev), (int) tmp8); + tmp8 |= ALL_PORTS; + pci_write_config_byte(pdev, SATA_CHAN_ENAB, tmp8); + } + + /* make sure interrupts for each channel sent to us */ + pci_read_config_byte(pdev, SATA_INT_GATE, &tmp8); + if ((tmp8 & ALL_PORTS) != ALL_PORTS) { + printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel interrupts (0x%x)\n", + pci_name(pdev), (int) tmp8); + tmp8 |= ALL_PORTS; + pci_write_config_byte(pdev, SATA_INT_GATE, tmp8); + } + + /* make sure native mode is enabled */ + pci_read_config_byte(pdev, SATA_NATIVE_MODE, &tmp8); + if ((tmp8 & NATIVE_MODE_ALL) != NATIVE_MODE_ALL) { + printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel native mode (0x%x)\n", + pci_name(pdev), (int) tmp8); + tmp8 |= NATIVE_MODE_ALL; + pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8); + } +} + static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; unsigned int i; int rc; - struct ata_port_info *ppi; struct ata_probe_ent *probe_ent; + int board_id = (int) ent->driver_data; + const int *bar_sizes; + int pci_dev_busy = 0; u8 tmp8; if (!printed_version++) @@ -181,20 +305,28 @@ return rc; rc = pci_request_regions(pdev, DRV_NAME); - if (rc) + if (rc) { + pci_dev_busy = 1; goto err_out; + } - pci_read_config_byte(pdev, SATA_PATA_SHARING, &tmp8); - if (tmp8 & SATA_2DEV) { - printk(KERN_ERR DRV_NAME "(%s): SATA master/slave not supported (0x%x)\n", - pci_name(pdev), (int) tmp8); - rc = -EIO; - goto err_out_regions; + if (board_id == vt6420) { + pci_read_config_byte(pdev, SATA_PATA_SHARING, &tmp8); + if (tmp8 & SATA_2DEV) { + printk(KERN_ERR DRV_NAME "(%s): SATA master/slave not supported (0x%x)\n", + pci_name(pdev), (int) tmp8); + rc = -EIO; + goto err_out_regions; + } + + bar_sizes = &svia_bar_sizes[0]; + } else { + bar_sizes = &vt6421_bar_sizes[0]; } for (i = 0; i < ARRAY_SIZE(svia_bar_sizes); i++) if ((pci_resource_start(pdev, i) == 0) || - (pci_resource_len(pdev, i) < svia_bar_sizes[i])) { + (pci_resource_len(pdev, i) < bar_sizes[i])) { printk(KERN_ERR DRV_NAME "(%s): invalid PCI BAR %u (sz 0x%lx, val 0x%lx)\n", pci_name(pdev), i, pci_resource_start(pdev, i), @@ -207,8 +339,11 @@ if (rc) goto err_out_regions; - ppi = &svia_port_info; - probe_ent = ata_pci_init_native_mode(pdev, &ppi); + if (board_id == vt6420) + probe_ent = vt6420_init_probe_ent(pdev); + else + probe_ent = vt6421_init_probe_ent(pdev); + if (!probe_ent) { printk(KERN_ERR DRV_NAME "(%s): out of memory\n", pci_name(pdev)); @@ -216,42 +351,7 @@ goto err_out_regions; } - probe_ent->port[0].scr_addr = - svia_scr_addr(pci_resource_start(pdev, 5), 0); - probe_ent->port[1].scr_addr = - svia_scr_addr(pci_resource_start(pdev, 5), 1); - - pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tmp8); - printk(KERN_INFO DRV_NAME "(%s): routed to hard irq line %d\n", - pci_name(pdev), - (int) (tmp8 & 0xf0) == 0xf0 ? 0 : tmp8 & 0x0f); - - /* make sure SATA channels are enabled */ - pci_read_config_byte(pdev, SATA_CHAN_ENAB, &tmp8); - if ((tmp8 & ENAB_ALL) != ENAB_ALL) { - printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channels (0x%x)\n", - pci_name(pdev), (int) tmp8); - tmp8 |= ENAB_ALL; - pci_write_config_byte(pdev, SATA_CHAN_ENAB, tmp8); - } - - /* make sure interrupts for each channel sent to us */ - pci_read_config_byte(pdev, SATA_INT_GATE, &tmp8); - if ((tmp8 & INT_GATE_ALL) != INT_GATE_ALL) { - printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel interrupts (0x%x)\n", - pci_name(pdev), (int) tmp8); - tmp8 |= INT_GATE_ALL; - pci_write_config_byte(pdev, SATA_INT_GATE, tmp8); - } - - /* make sure native mode is enabled */ - pci_read_config_byte(pdev, SATA_NATIVE_MODE, &tmp8); - if ((tmp8 & NATIVE_MODE_ALL) != NATIVE_MODE_ALL) { - printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel native mode (0x%x)\n", - pci_name(pdev), (int) tmp8); - tmp8 |= NATIVE_MODE_ALL; - pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8); - } + svia_configure(pdev); pci_set_master(pdev); @@ -262,7 +362,8 @@ err_out_regions: pci_release_regions(pdev); err_out: - pci_disable_device(pdev); + if (!pci_dev_busy) + pci_disable_device(pdev); return rc; } diff -Nru a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c --- a/drivers/scsi/sata_vsc.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/scsi/sata_vsc.c 2005-03-04 12:03:50 -08:00 @@ -218,6 +218,8 @@ .phy_reset = sata_phy_reset, .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, + .bmdma_stop = ata_bmdma_stop, + .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, .eng_timeout = ata_eng_timeout, @@ -256,6 +258,7 @@ static int printed_version; struct ata_probe_ent *probe_ent = NULL; unsigned long base; + int pci_dev_busy = 0; void *mmio_base; int rc; @@ -275,13 +278,15 @@ } rc = pci_request_regions(pdev, DRV_NAME); - if (rc) + if (rc) { + pci_dev_busy = 1; goto err_out; + } /* * Use 32 bit DMA mask, because 64 bit address support is poor. */ - rc = pci_set_dma_mask(pdev, 0xFFFFFFFFULL); + rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (rc) goto err_out_regions; @@ -348,7 +353,8 @@ err_out_regions: pci_release_regions(pdev); err_out: - pci_disable_device(pdev); + if (!pci_dev_busy) + pci_disable_device(pdev); return rc; } diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c --- a/drivers/scsi/sd.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/scsi/sd.c 2005-03-04 12:03:50 -08:00 @@ -1220,7 +1220,7 @@ goto cleanup_gendisks_part; memset(sd_gendisks[i].part, 0, (SCSI_DISKS_PER_MAJOR << 4) * sizeof(struct hd_struct)); sd_gendisks[i].sizes = sd_sizes + (i * SCSI_DISKS_PER_MAJOR << 4); - sd_gendisks[i].nr_real = 0; + sd_gendisks[i].nr_real = SCSI_DISKS_PER_MAJOR; sd_gendisks[i].real_devices = (void *) (rscsi_disks + i * SCSI_DISKS_PER_MAJOR); } @@ -1333,7 +1333,6 @@ rscsi_disks[i].device = SDp; rscsi_disks[i].has_part_table = 0; sd_template.nr_dev++; - SD_GENDISK(i).nr_real++; devnum = i % SCSI_DISKS_PER_MAJOR; SD_GENDISK(i).de_arr[devnum] = SDp->de; if (SDp->removable) @@ -1447,7 +1446,6 @@ SDp->attached--; sd_template.dev_noticed--; sd_template.nr_dev--; - SD_GENDISK(i).nr_real--; return; } return; diff -Nru a/drivers/scsi/st.c b/drivers/scsi/st.c --- a/drivers/scsi/st.c 2005-03-04 12:03:50 -08:00 +++ b/drivers/scsi/st.c 2005-03-04 12:03:50 -08:00 @@ -1641,7 +1641,7 @@ if (STps->drv_block >= 0) STps->drv_block += 1; (STp->buffer)->buffer_bytes = 0; - return (-EIO); + return (-ENOMEM); } (STp->buffer)->buffer_bytes = bytes - transfer; } else { @@ -3778,7 +3778,6 @@ read: st_read, write: st_write, ioctl: st_ioctl, - llseek: no_llseek, open: st_open, flush: st_flush, release: st_release, diff -Nru a/fs/ext3/fsync.c b/fs/ext3/fsync.c --- a/fs/ext3/fsync.c 2005-03-04 12:03:50 -08:00 +++ b/fs/ext3/fsync.c 2005-03-04 12:03:50 -08:00 @@ -69,7 +69,7 @@ if (test_opt(inode->i_sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA) ret |= fsync_inode_data_buffers(inode); - ext3_force_commit(inode->i_sb); + ret |= ext3_force_commit(inode->i_sb); return ret; } diff -Nru a/fs/ext3/super.c b/fs/ext3/super.c --- a/fs/ext3/super.c 2005-03-04 12:03:50 -08:00 +++ b/fs/ext3/super.c 2005-03-04 12:03:50 -08:00 @@ -1608,12 +1608,13 @@ static int ext3_sync_fs(struct super_block *sb) { + int err; tid_t target; sb->s_dirt = 0; target = log_start_commit(EXT3_SB(sb)->s_journal, NULL); - log_wait_commit(EXT3_SB(sb)->s_journal, target); - return 0; + err = log_wait_commit(EXT3_SB(sb)->s_journal, target); + return err; } /* diff -Nru a/fs/jbd/commit.c b/fs/jbd/commit.c --- a/fs/jbd/commit.c 2005-03-04 12:03:50 -08:00 +++ b/fs/jbd/commit.c 2005-03-04 12:03:50 -08:00 @@ -92,7 +92,7 @@ struct buffer_head *wbuf[64]; int bufs; int flags; - int err; + int err = 0; unsigned long blocknr; char *tagp = NULL; journal_header_t *header; @@ -299,6 +299,8 @@ spin_unlock(&journal_datalist_lock); unlock_journal(journal); wait_on_buffer(bh); + if (unlikely(!buffer_uptodate(bh))) + err = -EIO; /* the journal_head may have been removed now */ lock_journal(journal); goto write_out_data; @@ -326,6 +328,8 @@ spin_unlock(&journal_datalist_lock); unlock_journal(journal); wait_on_buffer(bh); + if (unlikely(!buffer_uptodate(bh))) + err = -EIO; lock_journal(journal); spin_lock(&journal_datalist_lock); continue; /* List may have changed */ @@ -351,6 +355,9 @@ } spin_unlock(&journal_datalist_lock); + if (err) + __journal_abort_hard(journal); + /* * If we found any dirty or locked buffers, then we should have * looped back up to the write_out_data label. If there weren't @@ -541,6 +548,8 @@ if (buffer_locked(bh)) { unlock_journal(journal); wait_on_buffer(bh); + if (unlikely(!buffer_uptodate(bh))) + err = -EIO; lock_journal(journal); goto wait_for_iobuf; } @@ -602,6 +611,8 @@ if (buffer_locked(bh)) { unlock_journal(journal); wait_on_buffer(bh); + if (unlikely(!buffer_uptodate(bh))) + err = -EIO; lock_journal(journal); goto wait_for_ctlbuf; } @@ -650,6 +661,8 @@ bh->b_end_io = journal_end_buffer_io_sync; submit_bh(WRITE, bh); wait_on_buffer(bh); + if (unlikely(!buffer_uptodate(bh))) + err = -EIO; put_bh(bh); /* One for getblk() */ journal_unlock_journal_head(descriptor); } @@ -661,6 +674,9 @@ skip_commit: /* The journal should be unlocked by now. */ + if (err) + __journal_abort_hard(journal); + /* Call any callbacks that had been registered for handles in this * transaction. It is up to the callback to free any allocated * memory. diff -Nru a/fs/jbd/journal.c b/fs/jbd/journal.c --- a/fs/jbd/journal.c 2005-03-04 12:03:50 -08:00 +++ b/fs/jbd/journal.c 2005-03-04 12:03:50 -08:00 @@ -582,8 +582,10 @@ * Wait for a specified commit to complete. * The caller may not hold the journal lock. */ -void log_wait_commit (journal_t *journal, tid_t tid) +int log_wait_commit (journal_t *journal, tid_t tid) { + int err = 0; + lock_kernel(); #ifdef CONFIG_JBD_DEBUG lock_journal(journal); @@ -600,6 +602,12 @@ sleep_on(&journal->j_wait_done_commit); } unlock_kernel(); + + if (unlikely(is_journal_aborted(journal))) { + printk(KERN_EMERG "journal commit I/O error\n"); + err = -EIO; + } + return err; } /* @@ -1326,7 +1334,7 @@ /* Wait for the log commit to complete... */ if (transaction) - log_wait_commit(journal, transaction->t_tid); + err = log_wait_commit(journal, transaction->t_tid); /* ...and flush everything in the log out to disk. */ lock_journal(journal); diff -Nru a/fs/jbd/transaction.c b/fs/jbd/transaction.c --- a/fs/jbd/transaction.c 2005-03-04 12:03:50 -08:00 +++ b/fs/jbd/transaction.c 2005-03-04 12:03:50 -08:00 @@ -1484,7 +1484,7 @@ * to wait for the commit to complete. */ if (handle->h_sync && !(current->flags & PF_MEMALLOC)) - log_wait_commit(journal, tid); + err = log_wait_commit(journal, tid); } kfree(handle); return err; @@ -1509,7 +1509,7 @@ goto out; } handle->h_sync = 1; - journal_stop(handle); + ret = journal_stop(handle); out: unlock_kernel(); return ret; diff -Nru a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c --- a/fs/proc/proc_tty.c 2005-03-04 12:03:50 -08:00 +++ b/fs/proc/proc_tty.c 2005-03-04 12:03:50 -08:00 @@ -129,7 +129,7 @@ } /* - * Thsi function is called by register_tty_driver() to handle + * This function is called by tty_register_driver() to handle * registering the driver's /proc handler into /proc/tty/driver/ */ void proc_tty_register_driver(struct tty_driver *driver) @@ -152,7 +152,7 @@ } /* - * This function is called by unregister_tty_driver() + * This function is called by tty_unregister_driver() */ void proc_tty_unregister_driver(struct tty_driver *driver) { diff -Nru a/include/asm-i386/acpi.h b/include/asm-i386/acpi.h --- a/include/asm-i386/acpi.h 2005-03-04 12:03:50 -08:00 +++ b/include/asm-i386/acpi.h 2005-03-04 12:03:50 -08:00 @@ -121,6 +121,8 @@ extern int acpi_strict; extern int acpi_disabled; extern int acpi_ht; +extern int acpi_skip_timer_override; +void __init check_acpi_pci(void); static inline void disable_acpi(void) { acpi_disabled = 1; diff -Nru a/include/asm-i386/pci-direct.h b/include/asm-i386/pci-direct.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/include/asm-i386/pci-direct.h 2005-03-04 12:03:50 -08:00 @@ -0,0 +1 @@ +#include "asm-x86_64/pci-direct.h" diff -Nru a/include/asm-x86_64/acpi.h b/include/asm-x86_64/acpi.h --- a/include/asm-x86_64/acpi.h 2005-03-04 12:03:50 -08:00 +++ b/include/asm-x86_64/acpi.h 2005-03-04 12:03:50 -08:00 @@ -118,6 +118,7 @@ extern int acpi_strict; extern int acpi_disabled; extern int acpi_ht; +extern int acpi_skip_timer_override; static inline void disable_acpi(void) { acpi_disabled = 1; diff -Nru a/include/linux/jbd.h b/include/linux/jbd.h --- a/include/linux/jbd.h 2005-03-04 12:03:50 -08:00 +++ b/include/linux/jbd.h 2005-03-04 12:03:50 -08:00 @@ -848,7 +848,7 @@ extern int log_space_left (journal_t *); /* Called with journal locked */ extern tid_t log_start_commit (journal_t *, transaction_t *); -extern void log_wait_commit (journal_t *, tid_t); +extern int log_wait_commit (journal_t *, tid_t); extern int log_do_checkpoint (journal_t *, int); extern void log_wait_for_space(journal_t *, int nblocks); diff -Nru a/include/linux/libata-compat.h b/include/linux/libata-compat.h --- a/include/linux/libata-compat.h 2005-03-04 12:03:50 -08:00 +++ b/include/linux/libata-compat.h 2005-03-04 12:03:50 -08:00 @@ -1,8 +1,16 @@ #ifndef __LIBATA_COMPAT_H__ #define __LIBATA_COMPAT_H__ +#include #include #include +#include + +typedef u32 __le32; +typedef u64 __le64; + +#define DMA_64BIT_MASK 0xffffffffffffffffULL +#define DMA_32BIT_MASK 0x00000000ffffffffULL #define MODULE_VERSION(ver_str) @@ -10,11 +18,6 @@ struct pci_dev pdev; }; -static inline void libata_msleep(unsigned long msecs) -{ - msleep(msecs); -} - static inline struct pci_dev *to_pci_dev(struct device *dev) { return (struct pci_dev *) dev; @@ -46,5 +49,14 @@ pci_get_drvdata(to_pci_dev(dev)) #define dev_set_drvdata(dev,ptr) \ pci_set_drvdata(to_pci_dev(dev),(ptr)) + +static inline void *kcalloc(size_t nmemb, size_t size, int flags) +{ + size_t total = nmemb * size; + void *mem = kmalloc(total, flags); + if (mem) + memset(mem, 0, total); + return mem; +} #endif /* __LIBATA_COMPAT_H__ */ diff -Nru a/include/linux/libata.h b/include/linux/libata.h --- a/include/linux/libata.h 2005-03-04 12:03:50 -08:00 +++ b/include/linux/libata.h 2005-03-04 12:03:50 -08:00 @@ -335,6 +335,8 @@ void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf); u8 (*check_status)(struct ata_port *ap); + u8 (*check_altstatus)(struct ata_port *ap); + u8 (*check_err)(struct ata_port *ap); void (*dev_select)(struct ata_port *ap, unsigned int device); void (*phy_reset) (struct ata_port *ap); @@ -361,6 +363,9 @@ void (*port_stop) (struct ata_port *ap); void (*host_stop) (struct ata_host_set *host_set); + + void (*bmdma_stop) (struct ata_port *ap); + u8 (*bmdma_status) (struct ata_port *ap); }; struct ata_port_info { @@ -401,6 +406,8 @@ extern void ata_noop_dev_select (struct ata_port *ap, unsigned int device); extern void ata_std_dev_select (struct ata_port *ap, unsigned int device); extern u8 ata_check_status(struct ata_port *ap); +extern u8 ata_altstatus(struct ata_port *ap); +extern u8 ata_chk_err(struct ata_port *ap); extern void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf); extern int ata_port_start (struct ata_port *ap); extern void ata_port_stop (struct ata_port *ap); @@ -416,6 +423,8 @@ unsigned int ofs, unsigned int len); extern void ata_bmdma_setup (struct ata_queued_cmd *qc); extern void ata_bmdma_start (struct ata_queued_cmd *qc); +extern void ata_bmdma_stop(struct ata_port *ap); +extern u8 ata_bmdma_status(struct ata_port *ap); extern void ata_bmdma_irq_clear(struct ata_port *ap); extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat); extern void ata_eng_timeout(struct ata_port *ap); @@ -451,26 +460,11 @@ (dev->class == ATA_DEV_ATAPI)); } -static inline u8 ata_chk_err(struct ata_port *ap) -{ - if (ap->flags & ATA_FLAG_MMIO) { - return readb((void __iomem *) ap->ioaddr.error_addr); - } - return inb(ap->ioaddr.error_addr); -} - static inline u8 ata_chk_status(struct ata_port *ap) { return ap->ops->check_status(ap); } -static inline u8 ata_altstatus(struct ata_port *ap) -{ - if (ap->flags & ATA_FLAG_MMIO) - return readb((void __iomem *)ap->ioaddr.altstatus_addr); - return inb(ap->ioaddr.altstatus_addr); -} - static inline void ata_pause(struct ata_port *ap) { ata_altstatus(ap); @@ -592,46 +586,6 @@ static inline unsigned int sata_dev_present(struct ata_port *ap) { return ((scr_read(ap, SCR_STATUS) & 0xf) == 0x3) ? 1 : 0; -} - -static inline void ata_bmdma_stop(struct ata_port *ap) -{ - if (ap->flags & ATA_FLAG_MMIO) { - void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr; - - /* clear start/stop bit */ - writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START, - mmio + ATA_DMA_CMD); - } else { - /* clear start/stop bit */ - outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START, - ap->ioaddr.bmdma_addr + ATA_DMA_CMD); - } - - /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ - ata_altstatus(ap); /* dummy read */ -} - -static inline void ata_bmdma_ack_irq(struct ata_port *ap) -{ - if (ap->flags & ATA_FLAG_MMIO) { - void __iomem *mmio = ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS; - writeb(readb(mmio), mmio); - } else { - unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS; - outb(inb(addr), addr); - } -} - -static inline u8 ata_bmdma_status(struct ata_port *ap) -{ - u8 host_stat; - if (ap->flags & ATA_FLAG_MMIO) { - void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr; - host_stat = readb(mmio + ATA_DMA_STATUS); - } else - host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); - return host_stat; } static inline int ata_try_flush_cache(struct ata_device *dev) diff -Nru a/mm/filemap.c b/mm/filemap.c --- a/mm/filemap.c 2005-03-04 12:03:50 -08:00 +++ b/mm/filemap.c 2005-03-04 12:03:50 -08:00 @@ -3261,7 +3261,12 @@ status = generic_osync_inode(inode, OSYNC_METADATA|OSYNC_DATA); } - err = written ? written : status; + /* + * generic_osync_inode always returns 0 or negative value. + * So 'status < written' is always true, and written should + * be returned if status >= 0. + */ + err = (status < 0) ? status : written; out: return err; diff -Nru a/mm/swapfile.c b/mm/swapfile.c --- a/mm/swapfile.c 2005-03-04 12:03:50 -08:00 +++ b/mm/swapfile.c 2005-03-04 12:03:50 -08:00 @@ -738,8 +738,10 @@ for (type = swap_list.head; type >= 0; type = swap_info[type].next) { p = swap_info + type; if ((p->flags & SWP_WRITEOK) == SWP_WRITEOK) { - if (p->swap_file == nd.dentry) - break; + if (p->swap_file == nd.dentry || + (S_ISBLK(nd.dentry->d_inode->i_mode) && + p->swap_device == nd.dentry->d_inode->i_rdev)) + break; } prev = type; } diff -Nru a/net/unix/af_unix.c b/net/unix/af_unix.c --- a/net/unix/af_unix.c 2005-03-04 12:03:50 -08:00 +++ b/net/unix/af_unix.c 2005-03-04 12:03:50 -08:00 @@ -1686,8 +1686,13 @@ } spin_lock(&sk->receive_queue.lock); - if((skb=skb_peek(&sk->receive_queue))!=NULL) - amount=skb->len; + if (sk->type == SOCK_STREAM) { + skb_queue_walk(&sk->receive_queue, skb) + amount += skb->len; + } else { + if((skb=skb_peek(&sk->receive_queue))!=NULL) + amount=skb->len; + } spin_unlock(&sk->receive_queue.lock); err = put_user(amount, (int *)arg); break;