ftp://ftp.kernel.org/pub/linux/kernel/people/alan/2.4/
Intermediate diffs are available from
http://www.bzimage.org
You may well need to 'make clean' before building -ac8 as the GDT layout
has changed a little.
2.4.3-ac10
o Merge Linus 2.4.4pre4
o Apply the i960 quirk to the DPT I2O controllers (me)
o Etrax100 updates (Bjorn Wesen)
o Fix skge memory leak (Jes Sorensen)
o Handle reiserfs log overflow error (Chris Mason)
o Merge JFFS2 (compressing log flash file system) (David Woodhouse)
o Merge contributed help texts for options (Eric Raymond,
Steven Cole)
o Further screen blanking fixes (Mikael Pettersson)
o Further binfmt elf DLINFO fixes/alignment (Benjamin Herrenschmidt)
o Fix reboot notifier unregister in aic7xxx (Arjan van de Ven)
o Fix orinoco_cs build on powerpc (David Gibson)
o Neomagic audio didn't call pci_enable_device (Marcus Meissner)
o Remove superblock file size setting for 2Gb (Al Viro)
default size file systems
o Merge UML gprof support (Jeff Dike)
o Clean up UML slip code (Jeff Dike)
o Allow UML attach to already running debuggers (Jeff Dike)
o Reorder frame buffer probes (Geert Uytterhoeven)
o Add __init calls to bluesmoke.c (Dave Jones)
o Add missing pci_enable_device to toshoboe (Marcus Meissner)
o Updated AFFS file system (Roman Zippel)
o DVD-RAM fixes (Jens Axboe)
o Further sundance driver fixes (Jeff Garzik)
o Fix qlogicfc warning (Dave Miller)
o Fix sign handling error in scsi_ioctl (me)
| Found by the Stanford validator
o Fix sign handling error in af_decnet (me)
| Found by the Stanford validator
o Fixed i2o posts to be uninterruptible (me)
o Stop I2O layer eating Supertrak slave PDC20265 (me)
o Work around the DPT I2O controller exploding
when asked to quiesce. (me)
2.4.3-ac9
o Fix ac8 pnpbios build bug (me)
o Fix ac8 sysrq build bug (me)
o Fix uml for new semaphores (Jeff Dike)
o Attempt to flush low memory buffers when short
of bounce space on highmem machines (Marcelo Tosatti)
o Kill old filesystem_setup function (Al Viro)
o Small pnp bios tidy up (me)
2.4.3-ac8
o Restore wan router features backed out by the (me)
sangoma stuff Linus merged
o Clean up #ifdefs in Sangoma code a bit (me)
o Fix missing kmalloc return checks in Sangoma (me)
o Fix d_flags bit setting in knfsd (Mikael Pettersson)
o Turn on winchip MCE (Dave Jones)
o IRDA USB driver fixups (Dag Brattli,
Philipp Rumpf, Jean Tourrilhes)
o Tidy up cpu capability mask reporting (Rogier Wolff)
o Refix icmp gcc warnings (Andrzej M. Krzysztofowicz)
o Remove 2.0 ioremap hacks from ISDN layer (Kai Germaschewski)
o Fix request_region ranges on hisax/bkm_a8 (Roland Klabunde)
o Add rx fifo overlfow handling to pci hisax (Werner Cornelius)
o Hysdn driver updates (Ulrich Albrecht)
o Rewrite cisco hdlc keepalive code (Bjoern Zeeb,
Kai Germaschewski)
o Document CONFIG_TMSISA (Jochen Friedrich)
o Fix emu10k memory leak (Hugh Dickins)
o Fix i810 audio SMP lockups (Doug Ledford)
o Merge binfmt_elf changes for PPC (Benjamin Herrenschmidt)
o Make sysrq keybindings a clean API (Crutcher Dunvant)
| I think I caught all the sysrq updates from after
| the patch was written and got them right - please check
o Merge PnP bios enumeration and PnP BIOS (Christian Schmidt,
parport support (Tom Lees, David Hinds, Gunther Mayer)
o Bit more experimental work on fixing bounce (Marcelo Tosatti, me)
buffers
2.4.3-ac7
o Updated VIA quirk handling for the chipset (Andre Hedrick,
flaws George Breese)
| Experimental version removed
| VIA users should check this kernel -carefully-!!!!
o Remove KT7 dma kill (me)
| See above note
o Merge Linus 2.4.4pre3
o Fix winchip1 oops in mtrr from previous change (me)
o Add winchip3 support to mtrr/oostore (me)
o Fix the Zoran driver build (me)
| This is still not up to date with the master copy
| that is intentional - first things first.
o Fix CONFIG_WINCHIP kernel crash on cpu with (me)
fxsave
o Fix UML options help bug (Jeff Dike)
o Fix pte corruption in user mode linux (Jeff Dike)
o Fix gdb and terminal initialisation in UML (Jeff Dike)
o UML code cleanup (Jeff Dike)
o Fix saved register corruption in UML (Jeff Dike)
o Add pci_disable_device (Jeff Garzik)
o Fix a slight bug in the parport help (Tim Waugh)
o Hopefully fix the sb1000 driver irq support (James Anderson)
o Fix missing signal lock in keventd (Manfred Spraul)
o Fix module build with io debugging on (Markus Kossmann)
o Fix dcache flag atomicty (Al Viro)
o Make cs4281 use pci_set_dma_mask, clean up (Jeff Garzik)
wrappers
o Use pci_set_dma_mask on maestro3 (Jeff Garzik)
o Fix 3270 driver build bug (Dick Hitt)
o Fix accidental sb driver bug revert (Jeff Garzik)
o Clean up PCI dependancies in sound drivers (Jeff Garzik)
o Update synclink driver (Paul Fulghum)
o rtl8139 driver update (Jeff Garzik)
o Update ps/2 esdi fixes to correct DMA access (Hal Duston)
o More aha1542 code marked __init (Matthias Hanisch)
o More random.c code marked __init (Matthias Hanisch)
2.4.3-ac6
o Remove tables.h include from fatfs_syms (OGAWA Hirofumi)
o Update UML (Jeff Dike)
o Protect more __KERNEL__ only stuff from (Phil Copeland)
asm-alpha/io.h
o Fix sound/Config.in bug with ARM (Russell King)
o Update network drivers for ARM bits (Russell King)
| 8390, pcnet_cs, tulip
o Fix umount cleanups (Al Viro)
o Merge aic7xxx driver 6.11 (Justin Gibbs)
o Added support for the pentium machine check (me)
| Also including thermal check
o Add support for the winchip machine check (me)
o Fix mtrr support of the WinChip2 (me)
| Existing code set uncachable not write gathering on winchip2
o Support weak ordering mode on winchip cpus (me)
2.4.3-ac5
o Merge Linus 2.4.4pre1
o New rwsem implementation (David Howells)
o Fix rwsem compile problem (me)
o Fix bust_spinlocks build fail if !CONFIG_VT (me)
o Merge Linus 2.4.4pre2 except for ipv6
o Fix the corner case non zeroing bug in (me)
copy_from_user for x86
2.4.3-ac4
o Fix corruption case in ext2 inode handling (Ingo Molnar, Al Viro)
o Merge user mode linux port (Jeff Dike)
o Remove some surplus ifdefs from init/main.c (me)
o Update nwfpe (Russell King)
o Fix ps2esdi driver (Hal Duston)
o Update ARM documentation (Russell King)
o Update Symbios 53c8xx driver (G?rard Roudier)
o ARM frame buffer update (Russell King)
o Update ARM bootstrap code (Russell King)
o Eicon driver fix (Armin Schindler)
o Update S/390 Documentation (Utz Bacher, Carsten
o Update S/390 math emulation Otte, Holger Smolinski
o S/390 tape driver Martin Schwidefsky
o PAGEX support for Linux/390 under VM and probably others)
o General S/390 fixes
o Update S/390 tty drivers
o Update S/390 irq handling
o Update S/390 channel driver
o Update S/390 include files
o Update S/390 networking drivers
o Update S/390 DASD drivers
o Update S/390 mm to match generic mm changes
o Update S/390 makefiles
o Catch another subspecies of misidentifying CD (Bob Mende Pie)
o Fix bluesmoke formatting (Solar Designer)
o Fix rx error handling in rtl8139 (Jeff Garzik)
o Update paths to e2fsprogs (Steven Cole)
o Fix proc alloc map locking (Tom Leete)
o Console blanking fix (continued..) (Mikael Pettersson)
o ARM tools update (Russell King)
o Update ARM includes (Russell King)
o Update ARM sound drivers (Russell King)
o Update the shark ARM support (Alexander Schulz)
o Update SA1100 support (Russell King,
Nicolas Pitre)
o Update ARM make and config files (Russell King)
o Update ARM mm/fault handling (Russell King)
o Update ARM network driver config (Russell King)
o Misc ARM updates (Russell King)
o Update ARM footbridge code (Russell King)
o EBSA ISA bus fixups (Russell King)
o Fix agp copy_from_user bug (Dawson Engler)
o Correct devfs docs on /dev/sg (Herbert Xu)
o /dev/sg doc update (Douglas Gilbert)
2.4.3-ac3
o Fix console unblank from suspend bug (Mikael Pettersson)
o Fix unmap_buffer() race (Al Viro)
o Add a proper dmi blacklist (me)
o Fix alpha build for new mm changes (Ivan Kokshaysky)
o Resync setup-bus.c to pick up Alpha Noritake (Ivan Kokshaysky)
fixes
o Fix swap accounting for major faults (Marcelo Tosatti)
o Add some bigendian support and voodoo5 support (Ani Joshi)
to tdfxfb
o Fix failing build with CONFIG_VT=n (Jason McMullan)
o Fix some corner cases in iso9660 support (Andreas Eckleder)
for symlinks and XA attriubtes
o Fix NTFS and quota sparc build problems on -ac (Steve Ralston)
o Resync to the Linus serial.c + B9600 fix (me)
o Avoid nasties with OHCI controller gets no IRQ (Arjan van de Ven)
assigned
o Pull problem lance change (Jeff Garzik)
o Fix SMP lockup in usbdevfs (Tony Hoyle)
o Firestream atm update (Patrick van de Lageweg)
2.4.3-ac2
o Add the VIA C3 to the mtrr/setup code (Dave Jones)
o Report PAE mode oopses better (Ingo Molnar)
o Fix zap_low_mappings on PAE (Hugh Dickins)
o Tidy up parport resource handling, fix bug (Tim Waugh)
o Add series 6 backpack driver support (Tim Waugh)
o Make lockd use daemonize() (Paul Mundt)
o Fix aicasm to specify -I flags needed on some (Mads J?rgensen)
distributions
o Add docbook manual on bus independant I/O (Matthew Wilcox)
| + a few additional notes I added
o Make the VIA superIO driver honour the (Tim Waugh)
irq/dma settings passed
o Update mpt fusion drivers (Steve Ralston)
o Add reiserfs maintainer entries (Steven Cole)
o Experimental driver for communcation class USB (Brad Hards)
| eg Broadcom and Ericsson USB cable modems
o I2O updates, report SMART errors on i2o_block (Boji Kannanthanam)
o Fix shm locking, races on swapping, accounting (Stephen Tweedie)
and swapout of already mapped pages
o Clean up REPORTING-BUGS (Steven Cole)
o Fix ACM handling of CLOCAL (Vojtech Pavlik)
o Fix sparc64 module_map/vfree bug (Hugh Dickins)
o Fix scsi race on requeued requests (Mark Hemment)
o Tulip driver update (Jeff Garzik)
o Update bmac and gmac driver (Cort Dougan)
o Winbond w9966cf webcam parport driver (Jakob Kemi)
2.4.3-ac1
o Merge Linus 2.4.3 final, diff versus 2.4.3 (me)
2.4.2-ac28
o Fix another modules race (me)
o Add basic PM hooks to agpgart (me)
o Update new xircom_cb driver (Arjan van de Ven)
o Fix missing lock_kernel on truncate path (Al Viro)
o Update klsi usb ethernet ids (Brad Hards)
o Fix missing permission check in shm code (Matthew Klahn)
o Add extra doupdate() calls to menuconfig (Moritz Schulte)
o Update wireless extensions (Jean Tourrilhes)
o Fix cdda reading problem (Jens Axboe)
o Fix potential oops in usb-uhci (David Brownell)
2.4.2-ac27
o Rely on BIOS to setup apic bits on OSB4 (me)
o Disable events when unloading cardbus yenta (me)
| Fixes shared irq unload hang
o Fix x86 IPI replay problems (Stephen Tweedie)
o Add ALS100 gameport support (Vojtech Pavlik)
o Fix wrong path in comment in vesafb (Andres Salomon)
o Allow slab caches to force alignment always (Ingo Molnar)
and thus fix PAE+ slab poisoning
o Fix problems in faulting raw I/O pages (Stephen Tweedie)
o Fix rawio error handling for raw I/O (Stephen Tweedie)
| + other oddments
o Change default max printer ports to 8 (Tim Waugh)
o Parport soft control state fixes (Tim Waugh)
o Fix cpu info compile (Constantine Gavrilov)
o Set warning levels on reiserfs warn etc (Paul Mundt)
o Fix duplicate IOVIRT debug config help (Steven Cole)
o Revert mmap change that broke assumptions (and (Martin Diehl)
it seems SuS)
o Clean up fpu emu warnings on gcc 3.0cvs a bit (me)
2.4.2-ac26
o Fix es1370 build bug (me)
o Fix sbpcd compile warnings (me)
o Update usbnet driver (Oleg Drokin)
o Update Alpha to pre8 vm changes (Ivan Kokshaysky)
o Fix radeonfb config selections (Chris Lawrence)
o Fix vmalloc mismerge (Various)
o Fix n_r3964 console panic (Andrew Morton)
o Update ibm camera drivers
o Support 701b toshoboe fir
o New xircom_cb driver (Arjan van de Ven, Jeff Garzik,
Don Becker, Doug Ledford)
o Fix procfs mount point for binfmt_misc (Al Viro)
o Update hpt366 ide blacklist
o Further ide blacklist updates
o Smooth vm balancing (Marcelo Tosatti)
o Fix irda assert (Arjan van de Ven)
o Keep contrack cache sizes sane (Ben LaHaise)
o Fix possible file truncate/write race (Ben LaHaise)
o Make bootmem panic sanely on out of memory (Ben LaHaise)
o Fix unload crash in pci_socket (me)
o Revert previous wrong bootmem change (Ben LaHaise)
2.4.2-ac25
o Handle PCI/ISA simple MP tables via ELCR (John William)
o Fix get_sb_single (Al Viro)
o Update es1370, es1371,esssolo (Thomas Sailer,
Tjeerd Mulder,
Nathanial Daw)
o Update orinoco_cs (Jean Tourilhes)
o Fix races found in the new kbd/console code (Andrew Morton)
o Remove dead timer.h docs (Tim Wright)
o Update ppc to new generic mm changes (Paul Mackerras)
o Clean up mdacon (Paul Gortmaker)
o Remove duplicate configure.help texts (Steven Cole)
o Fix symbol export for shm_file_open (Keith Owens)
o First batch of pointer reference bug fixes (Andrew Morton)
from Stanford report
o Fix de4x5 oops on Alpha XP1000 (George France)
o Chipsfb update (Paul Mackerras)
o Fix higmem block_prepare_write crash (Stephen Tweedie)
o Bring PAE36 back up to date, handle x86 errata (Ingo Molnar)
o Fix ov511 crash if opened while loading (Pete Zaitcev)
o Merge Linus 2.4.3pre8
o Update Advansys scsi driver (Bob Frey)
2.4.2-ac24
o Fix build bug with tsc in ac23 (me)
o Update contact info for Phil Blundell (Phil Blundell)
o Update mm locking comments/rss locking (Andrew Morton)
o Update toshiba SMM driver (Jonathan Buzzard)
o Update old adaptec driver to 5.2.4 (Doug Ledford)
o CS46xx updates (Tom Woller)
o Quieten input layer printks a bit (me)
o Turn off APIC_DEBUG by default to cut noise down(me)
o Add Orinoco PCMCIA wireless support (David Gibson)
o Go back to 2.4.3pre6 tulip (Jeff Garzik)
o Fix double accounting of cpu time bug (Kevin Buhr)
o Drop ppp patch (me)
2.4.2-ac23
o Fix a nasty shared memory locking bug (Stephen Tweedie)
o Fix off by one bootmem memory corruptor (Ben LaHaise)
o Fix avmb1 oops on init (Carsten Paeth)
o Fix isdn makefile bugs (Kai Germaschewski)
o Clean up isdn minor checks (Julien Gaulmin)
o Workaround PPP CCP negotiation bugs (Kai Germaschewski)
o Fix timer handling bug in ISDN (Henk-Jan Slotboom)
o Fix i386 #ifdef bug with notsc disable (Anton Blanchard)
o Fix NMI docs (Keith Owens)
o Fix oops on out of memory in proc_symlink (me)
| Found by Stanford tools
o Fix oops caused by devfs changes to soundcore (me)
| Found by Stanford tools
o Fix rmmod crash on sundance alta (me)
| Found by Stanford tools
o Fix potential crash in nsc-ircc.c (me)
| Found by Stanford tools
o Fix memory leak in i810 audio (Doug Ledford)
o Fix several compile warnings with gcc 3.0 cvs (J Magallon)
o Mark 60Hz modes in mac fb modes (Geert Uytterhoeven)
o Chkconfig and ver_linux updates (Niels Jensen)
o Fix ctrlfb dac timing (Takashi Oe)
o Add vesa powerdown support for ctrlfb (Takashi Oe)
o Back out problem via bridge change (me)
o Fix bug in aironet4500_cs changes (Arjan van de Ven)
2.4.2-ac22
o Fix dereference after free in megaraid driver (me)
o Fix crash if we run out of memory during a link (me)
follow [found by Stanford tools]
o Fix crash if we run out of memory during
block_truncate_page [found by Stanford tools] (me)
o Update Alpha to pre6 style pte/pmd_alloc (Ivan Kokshaysky)
o Fix ppp memory corruption (Kevin Buhr)
| Bizzarely enough a direct re-invention of a 1.2 ppp bug
o Fix heavy stack usage in tty_foo_devfs() (Jeff Dike)
o Make alloc_tty_struct always use kmalloc (Andrew Morton)
o Document task struct locking rules (Andrew Morton)
o Document SAK properly (Andrew Morton)
o Fix SAK deadlocks (Andrew Morton)
o Fix inline/type order for picky compiler tools (Dave Jones)
o Fix printk levels for various fs printks that (Andrey Panin)
lacked them
o Next incarnation of the i810 audio driver (Doug Ledford)
o Add __init stuff to 3c515 driver (Andrzej Krzysztofowicz)
o Add __init stuff to ppp layer (Andrzej Krzysztofowicz)
o Remove duplicate NF_TARGET_TCPMSS config text (Steven Cole)
o Fix missing unlock_kernel in pcwd (me)
| Found by Stanford tools
o Fix missing unlock_kernels in es1371 (me)
| Found by Stanford tools
o Fix missing unlock_kernels in es1370 (me)
| Found by Stanford tools
o Fix missing unlock_kernels in esssolo1 (me)
| Found by Stanford tools
o Fix missing unlock kernels in sonicvibes (me)
| Found by Stanford tools
o Fix missing unlock kernels in fb mmap (me)
| Found by Stanford tools
o Fix missing unlock_super in UFS code (me)
| Found by Stanford tools
2.4.2-ac21
o Merge with Linus 2.4.3pre6
o Close last known reiserfs tail bug (Chris Mason)
o Fix link order bug with iso8859_8 and cp1255 (Dan Aloni)
o Generate generic CPU namings for 386/486 (Cesar Eduardo Barros)
o First set of ISDN fixes from Stanford code (Kai Germaschewski)
analyser
o Allow up to 16 parallel ports by default (Tim Waugh)
o Use long delays on low speed usb hub ports (Pete Zaitcev)
o Update credits for assorted Australians (Stephen Rothwell)
o Fix ali_restore_regs thinko (Pavel Roskin)
o Fix whiteheat usb driver bugs (Greg Kroah-Hartman)
o Fix kfree in belkin_sa (Greg Kroah-Hartman)
o Fix omninet copy*user bug (Greg Kroah-Hartman)
o Fix modular atyfb (Geert Uytterhoeven)
o Update joystick and input drivers (Vojtech Pavlik)
o Relax checksum enforcement on ISAPnP CSN (Gunther Mayer)
o Resync ids/comments with ISDN cvs (Kai Germaschewski)
o Update Harald Hoyer Credits entry (Harald Hoyer)
o Fix off by 2* mtrr handling bug (David Wragg)
o Fix irda hang on boot (Dag Brattli)
o FB device init updates (Geert Uytterhoeven)
o Add it8712 misp eval board support (P. Popov)
o Update NEC DDB5476 eval board support (Jun Sun)
o Update NEC DDB5074 eval board support (Ralf Baechle)
o Add Karsten Merker and Michael Engel to credits (Ralf Baechle)
o Update Baget port (Vladimir Roganov,
Gleb Raiko)
o Add LVM ioctls to sparc64 ioctl32 convertor (Patrick Caulfield)
o Powerpc updates for openfirmware mm, python etc (Cort Dougan)
o Add the casio qv digitalcamera to the usb
unusual devices list (Harald Schreiber)
o atyfb mode updates for powermac (Olaf Hering)
o Fix khubd locking (Pete Zaitcev)
o More on the great aic7xxx libdb game (Nathan Dabney)
o Further console handling updates (Andrew Morton)
o Fix i2o build problem when half modular (Michael Mueller)
o Fix off by one in prink <foo> check (Mitchell Blank Jr)
o Fix do_swap_page hang (Linus Torvalds)
2.4.2-ac20
o Add support for the GoHubs GO-COM232 (Greg Kroah-Hartman)
o Remove cobalt remnants (Ralf Baechle)
o First block of mm documentation (Rik van Riel)
o Replace ancient Zoran driver with new one (Serguei Miridonov,
Wolfgang Scherr, Rainer Johanni, Dave Perks)
o Fix Alpha build (Jeff Garzik)
o Fix K7 mtrr breakage (Dave Jones)
o Fix pcnet32 touching resources before enable (Dave Jones)
o Merge with Linus 2.4.3pre4
2.4.2-ac19
o Typo fixes (David Weinehall)
o Merge first block of OHCI non x86 support (Greg Kroah-Hartman)
o Add Edgeport USB serial support (David Iacovelli,
Greg Kroah-Hartman)
o Fix doorlock on scsi removables (Alex Davies)
o Fix hang when usb storage thread died (me)
o Change watchdog disable setup (Ingo Molnar)
o Fix bluetooth close and error bugs (Narayan Mohanram)
o mpt now has an assigned minor (me)
| Remember to fix your /dev/mptctl if using MPT
o Clean up 3270 ifdefs/printk a little (me)
o Fix NBD deadlocks and update it (Steve Whitehouse)
o Fix sercon printk divide by zero bug (Roger Gammans)
o Remove cosine support from MIPS tree (Ralf Baechle)
o bust_spinlocks for Alpha (Jeff Garzik)
o Hopefully fix the buslogic corruptions (me)
| This is a 'test if they went away' release not a 'its fixed' one.
o Some mips makefile fixes (Ralf Baechle)
| except mips/kernel/Makefile (I got .rej Ralf)
o ARC firmware interface fixes (Harald Koerfgen)
o DECstation console drivers (Michael Engel,
Karsten Merker,
Harald Koerfgen)
o Fix ipx build bug (Anton Altaparmakov)
o Fix ptrace race (Stephen Tweedie)
o Update include/config.h stuff, ver_linux (Niels Jensen)
o Add missing pci_enable_device to cs4281 (Marcus Meissner,
Thomas Woller)
o Fix non PPC build of clgenfb (Andrew Morton)
o Update CPU docs (Dave Jones)
o Add mips atlas/malta reference boards (Carsten Langgaard)
o Add gt91600 ethernet support (SteveL)
o Add philips SAA9730 ethernet (Carsten Langgaard)
o PCnet32 driver fixes (Carsten Langgaard)
o MIPS fpu emulator (Algorithmics, Ralf Baechle, Kevin Kissell,
Carsten Langgaard, Harald Koerfgen, Maciej Rozycki)
o mips network driver updates (Ralf Baechle)
o Fix FC920 workarounds in i2o (me)
o Fix i2o_block hang on exit, 0 event race (me)
o FIx i2o_core thread kill wakeup race (me)
o Backport 2.2 VIA 686a clock reset workaround (Arjan van de Ven)
o Further documentation updates (Matthew Wilcox)
2.4.2-ac18
o Debian has another location for db3 (Marc Volovic)
o Remove duplicated flush_tlb_page export on (Elliot Lee)
Alpha
o Fix SB Live! build on SMP Alpha (Elliot Lee)
o Fix disk corruption on qlogicisp and qlogicpti (Arjan van de Ven)
o Fix reporting of >4Gig of swap (Hugh Dickins)
o Fix sign issues in mpt fusion (Andrew Morton)
o CMS minidisk file system (read only) (Rick Troth)
2.4 port (me)
o Disable nmi watchdog by default (Andrew Morton)
o Fix elsa_cs eject problems (Klaus Lichtenwalder)
o Remove duplicate config entries (Steven Cole)
o Fix further wrong license references (Andrzej Krzysztofowicz)
o Add nmi watchdog disable for sysrq (Andrew Morton)
o Experimental test for serverworks/intel AGP (me)
comptability
o Fix ipx reference counting for routes (Arnaldo Carvalho
de Melo)
2.4.2-ac17
o Make the aic7xxx code handle multiple db3 paths (me)
o Small further via updates (Vojtech Pavlik)
o IDE tape updates for Onstream tape drives (Marcel Mol)
o Remove some bits of module.c that cant get (Keith Owens
executed Andrew Morton)
o Configure.help fixups (Steven Cole)
o Add Cyrix MTRR data (Dave Jones)
o Fix a slight bogon in the i386 Makefile (Dave Jones)
o Kill an escaped modversions.h (Keith Owens)
o Further controlfb fixes (Takashi Oe)
o Fix console driver oops in new locking (Andrew Morton)
o Add 'broken-psr' so you can command line tell (Neale Banks)
APM your BIOS is crap
o Fix serial console (Dave Jones)
o Fix megaraid kernel_version string (Arjan van de Ven)
o Fix off by one error in cpia (Andrew Morton)
o Fix lost dmfe typo fix (Torsten Duwe)
o Take kernel_lock for i_truncate method in (Al Viro)
vmtruncate
o Fix i2c sign check bug (Andrew Morton)
2.4.2-ac16
o Uniprocessor APIC fixes for misdetect (Mikael Pettersso)
o Small ymf_pci fixes/updates (Pete Zaitcev)
o Fix break support on sx serial (Rogier Wolff)
o Kill another dead config.in entry (Steven Cole)
o Add bust spinlocks logic to S/390 (Neale Ferguson)
o Fix ramdisk buffer only page bug (Philipp Rumpf)
o Mark ips scsi experimental until IBM ship a (Adam Lackorzynski)
proper 2.4 driver
o Update lanstreamer to use module_init and more (Mike Sullivan)
o Switch to the updated irda fixes (Jean Tourrilhes)
o Vaio kaweth ethernet apparently has its own id (Sven Anders)
o d_validate clean ups (Petr Vandrovec)
o Network further fixes from DaveM and co (Dave Miller
| This might fix the reported masuqerade crashes Alexey Kuznetsov
Werner Almesberger)
o Acenic updates (Jes Sorensen)
2.4.2-ac15
o Add CyrixIII specific kernel configuration (me)
| Note there are CyrixIII problems with some distribution installers
| because -m686 gcc output will not run on a model 6 cpu with no
| cmov.
o Fix aic Makefile for older gnu make (Keith Owens)
o Assorted i2o updates/partition handling fixes (Boji Kannanthanam)
o Fix dcache problems with ncpfs (Petr Vandrovec)
o Update via drivers to 3.22 (Vojtech Pavlik)
o Account for packet bytes on lmc driver (Ernst Lehmann)
o Atyfb rearrange (Geert Uytterhoeven)
o Fix sedlbauer_cs build bug add elsa_cs (Than Ngo)
| elsa_cs driver by (Klaus Lichtenwalder)
o Add support for the Fuji FinePix 1400Zoon (Nate)
o EISA initialisation changes for 3c59x (Andrzej Krzysztofowicz)
o Assorted small net protocol updates (Dave Miller)
o Fix dvd physical read bug (Jens Axboe)
o Fix ATM hang on SMP (Mike Westall)
| more work left to do on atm_ioctl for someone
o Changed get_addr and friends to atm_get_addr (me)
o Merge Linus 2.4.3pre3
o Fix do_BUG for both cases this time (me)
o Fix prefetch for Athlon build
o Fix an lvm oops case (Pete Zaitcev)
o Remove dead config.in entry (Steven Cole)
o Update reiserfs recommended tool revision (Steven Cole)
o Kill a few warnings (Keith Owens)
2.4.2-ac14
o Fix the non build problem with do_BUG (Andrew Morton)
o Fix interface autocreation bug in ipx (Arnaldo Carvalho
Also fix pprop routing bugs, tctrl handling de Melo)
Fix wrong comments, fix ipx sysctl handling
clean up code
o Updated i810_audio.c (Doug Ledford)
o Fix up printer status readback (Tim Waugh)
o Add support for "ide=nodma" on command line (Arjan van de Ven)
o More spelling fixes (Dag Wieers)
o Add pci vendor table to lanstreamer (Mike Sullivan)
o Do extra sanity checks on ext2 mount (Andreas Dilger)
o Multithreaded core dump handling (Don Dugger)
| This is fairly experimental so the more eyes
| the better but it does sort out a very annoying weakness
o Prefetch on lists for parisc and x86 (Arjan Van de Ven,
| Work about 4% on scheduler performance on PIII Matthew Wilcox)
o Natsemi power management changes (Tjeerd Mulder)
o Fix assorted smb bugs (Urban Widmark)
o Fix a sisfb build problem (Andrew Morton)
2.4.2-ac13
o Clean up mad16 detection stuff (Pavel Rabel)
o Fix epca unload (Andrey Panin)
o Change null apic handling (Maciej Rozycki)
o aicasm now uses db3 (Sergey Kubushin)
o Fix aic7xxx cross compile (Cort Dougan)
o Merge small net driver fixups/config fixes (Jeff Garzik)
o Update symbios drivers (G?rard Roudier)
o Rusty has moved (Rusty Russell)
o 3c509/3c515 compile fixes (Jeff Garzik)
o Console locking updates - should fix vesafb (Andrew Morton)
clock problems
o Merge the serial.c 5.0.5 update (Jeff Garzik,
Ted Ts'o)
o Merge SiS framebuffer updates (Can-Ru Yeou)
o Update ctrlfb (Takashi Oe,
Michel Lanners)
o Add epson 640U scanner to the usb scanner list (Patrick Dreker)
2.4.2-ac12
o Move the pci_enable_device for cardbus (David Hinds)
o Add Sony MSC-U01N to the unusual devices (Marcel Holtmann)
o Final smc-mca fixups - should now work (James Bottomley)
o Document kernel string/mem* functions (Matthew Wilcox)
| and I added a memcpy warning
o Update VIA IDE driver to 3.21 (Vojtech Pavlik)
|No UDMA66 on 82c686, fix /proc and udma on
|686b, fix dma disables
o Allow sleeping in ctrl-alt-del callbacks (Andrew Morton)
|Fix i2o, dac960, watchdog, gdth hangs on exit
o Fix binfmt_misc (and make the proc handling (Al Viro)
|a filesystem -
|mount -t binfmt_misc none /proc/sys/fs/binfmt_misc
o Update the ACI support for sound/radio stuff (Robert Siemer)
o Add RDS support to miroRadio (Robert Siemer)
o Remove serverworks handling. The BIOS is our (me)
best (and right now only) hope for that chip
o Tune the vm behavioru a bit more (Mike Galbraith)
o Update PAS16 documentation (Thomas Molina)
o Reiserfs tools recommended are now 0d not 0b (Steven Cole)
o Wan driver small fixes (Jeff Garzik)
o Net driver fixes for 3c503, 3c509, 3c515, (Jeff Garzik)
8139too, de4x5, defxx, dgrs, dmfe, eth16i,
ewrk3, natsemi, ni5010, pci-skeleton, rcpci45,
sis900, sk_g16, smc-ultra, sundance, tlan,
via-rhine, winbond-840, yellowfin, wavelan_cs
tms380tr
o Trim 3K off the aha1542 driver size (Andrzej Krzysztofowicz)
o Trim 1K off qlogicfas (Andrzej Krzysztofowicz)
o Fix openfirmware/mm boot on ppc (Cort Dougan)
o Fix topdir handling in Makefile (Keith Owens)
o Minor fusion driver updates (Steve Ralston)
o Merge Etrax cris updates (Bjorn Wesen)
o Clgen fb copyright update (Jeff Garzik)
o AGP linkage fix (Jeff Garzik)
o Update visor driver to work with minijam (Arnim Laeuger)
o Fix a usb devio return code (Dan Streetman)
o Resync a few other net device changes with the
submits Jeff sent to Linus (Jeff Garzik)
o Add missing md export symbol (Mohammad Haque)
2.4.2-ac11
o Fix NLS Config.in (David Weinehall)
o Sort out one escaped revert from the megaraid (me)
update
o Resync with Linux 2.4.3pre1
| Except tulip the network driver changes have
| been used to replace the existing ones
o Fix parport case where a reader could get stuck (Tim Waugh)
o Add ALi15x3 to the list of isa dma hangs (Angelo Di Filippo)
o Fix nasty bug in IPX routing of netbios frames (Arnaldo Carvalho
de Melo)
o Misc code cleanups (Keith Owens)
o Updated 3c527 driver (Richard Proctor)
o Further tulip updates (Jeff Garzik)
o i810_rng fixes (FIPS test, regions) (Jeff Garzik)
o Further cs89x0 cleanups (Andrew Morton)
o Further USB hub updates (Dave Brownell)
o Mall USB resource cleanup (Jeff Garzik)
o Resync hp100 changes from Jeff Garzik (Jeff Garzik)
o PCI documentation update (Tim Waugh)
o Fix irda crash (Jean Tourrilhes)
o PPC updates (Cort Dougan)
o Resync dmfe, hamachi, pci-skeleton and winbond (Jeff Garzik)
2.4.2-ac10
o Add ZF-Logic watchdog driver (Fernando Fuganti)
o Add devfs support to USB printers (Mark McClelland)
o Fix baud rate handling on keyspan (Paul Mackerras)
o USB documentation update (Dave Brownell)
o Fix disconnect leak (Randy Dunlap)
o ARM constants/fixes (Russell King)
o Includes for integrator ARM architecture (Russell King)
o Update NLS descriptions to be clearer (Pablo Saratxaga)
o Add iso-8859-13 (latvian/lithuanian) (Pablo Saratxaga)
iso-8859-4, cp1251 (windows cyrillic), cp1255
(windows hebrew), and some alises
o Merge 1.14 Megaraid driver (Venkatesh Ramamurthy)
o Reapply other fixes this version dropped (me)
o Reformat and clean up ifdefs in 1.14 Megaraid (me)
o I/O apic locking fixes (Maciej Rozycki)
o Print ioapic id to help debugging (Maciej Rozycki)
o Make the tpqic driver work (Hugh Dickins)
o USB scanner updates (David Nelson)
o Fix usbdevfs multimount (Al Viro)
o Fix wrong calculation of path buffer size (Hugh Dickins)
o cs89x0 allocated far too much memory (Hugh Dickins)
2.4.2-ac9
o misc device fix (ps/2 and drm are now back) (Tachino Nobuhiro)
| Believe it or not my main test box used no misc
| device files..
o Radeon build without 8bit (Cha Young-Ho)
o Fix oops in scc driver (Andrew Morton)
o Add __setup for ISAPnP, update docs (Jaroslav Kysela)
o Update E820 table sanitizer (Brian Moyle)
o i810 audio updates/mmap fixes (Doug Ledford)
o Be paranoid about VIA chipset configurations (Arjan van de Ven)
| Fixing VIA disk corruption bugs take 2
o Fix PPC request_irq problems, some fpu emu (Cort Dougan)
and timers
o Allow scsi drivers to limit request sizes (Jens Axboe,
(and fixed by Tim) Tim Waugh)
o Configure.help cleanups (Steve Cole)
o Loop device fix of the day (Jens Axboe)
o CDROM fixes (Jens Axboe)
o Reiserfs crash on fsync of dir fix (Alexander Zarochentcev)
2.4.2-ac8
o Fix loop over loop crash (Jens Axboe)
o Fix radeon build problems (ISHIKAWA Mutsumi)
o Stop two people claiming the same misc dev id (Philipp Rumpf)
o capable not suser on sx.c (Rob Radez)
o Fix an ixj build combination bug (Andrzej Krzysztofowicz)
o Add integrator to ARM machines (Russell King)
o ARM include/constant cleanups (Russell King)
o Update ARM vmlinuz.in (Russell King)
o ARM i2c fixes (Russell King)
o ARM scsi updates (Russell King)
o ARM header updates (Russell King)
o Handle E820 bios returns with overlaps (Brian Moyle)
o Fix a sparc64 include build bug (Andrzej Krzysztofowicz)
o Loop race fix (Jens Axboe)
o s_maxbytes wasnt set for old style compat (Chris Dukes)
mounts in reiserfs
o Fix the fact we dont see all busses on some (Don Dupuis)
Compaq machines
o Fix missing watchdog configure.help (Jakob Ostergaard)
o Fix oom deadlock (hopefully) (Rik van Riel)
o Fix binfmt_aout sign handling bug (Andrew Morton)
2.4.2-ac7
o Fusion driver updates (Steve Ralston)
o Olympic fix (Andrew Morton)
o Work around hardware bug in older Rage128 (Gareth Hughes)
o Handle broken PIV MP tables with a NULL ioapic
o Use capable in esp serial driver (Rob Radez)
o Use capable not suser in console (Rob Radez)
o Small networking fixups (Dave Miller)
o Fix make menuconfig breakage (Keith Owens)
o Enable cmpxchg8 on Rise P6 (Dave Jones)
o Fix wakeup losses on cpu_allowed using tasks (Manfred Spraul)
o Maestro3 now works with > 256Mb of ram (Zach Brown)
o Opl3sa2 isapnp=0 handling was wrong (J?r?me Aug?)
| I've fixed it a little differently however
o Turn off slow kmem chain check if not doing (Ingo Molnar, me)
slab debugging
o Fix cpu speed checking code (Mikael Pettersson)
o Make bus computation more accurate (me)
o Advantech watchdog driver (Marek Michalkiewicz)
o dz.c serial clean up (Rob Radez)
o Fix MSG_TRUNC for OOB TCP (Ingo Molnar)
o Fix oops on unconfigured loop (Arjan van de Ven)
o Drop nbd ll_rw_blk change (Linus has spoken ;))
o pci resource api (Jeff Garzik)
o Further Natsemi updates (Don Becker,
Jeff Garzik)
o Switch aurora serial to capable() (Rob Radez)
o Radeon frame buffer (Ani Joshi)
2.4.2-ac6
o Remove incorrect modules doc changes (Keith Owens)
o Fix elf.h defines (Keith Owens)
o Add 0x2B mtrr decode for intel/cyrix III (me)
o Make bigmem balancing somewhat saner (Mark Hemment)
o Update irda (Dag Brattli)
o New FIR dongle support (Dag Brattli)
o 3ware driver updates (Adam Radford)
o Further reiserfs tail conversion fixes (Chris Mason)
o Fix tpqic02 to use capable (Rob Radez)
o Set last_rx on comtrol hostess driver (Arnaldo Carvalho
de Melo)
o Raid Oops fix (Neil Brown)
o Fix last_rx/skb refs on cyc_x25 (Arnaldo Carvalho
de Melo)
o Fix last_rx/skb refs on 3c589 (Arnaldo Carvalho
de Melo)
o Highmem fixes for deadlock (Andrea Arcangeli,
Ingo Molnar)
o Another minor tulip fix (Jeff Garzik)
o Fix hinote and maybe other ps/aux hangs (me, Mark Clegg)
o Fix resource handling on 53c7xxx (Rasmus Andersen)
o Fix scsi_register failure handling on AMD scsi (Rasmus Andersen)
o Fix resource handling on aha1740 (Rasmus Andersen)
o Fix resource handling on blz1230 (Rasmus Andersen)
o Fix resource handling for dec_esp driver (Rasmus Andersen)
o Fix resource handling for fastlane scsi (Rasmus Andersen)
o Fix scsi_register failure on qlogic_fas (Rasmus Andersen)
o Fix scsi_register failure on qlogicfc (Rasmus Andersen)
o Fix irq alloc failure leak on sun3x_esp (Rasmus Andersen)
o Fix wd7000 init failures (Rasmus Andersen)
o Fix nbd device (Steve Whitehouse)
o Fix try_atomic_semop (Manfred Spraul)
o Parport fixes (Tim Waugh)
o Starfire start/stop if fix (Ion Badulescu)
o Fix raw.c off by one bug (Tigran Aivazian)
o USB hub kmalloc wrong size corruption fix (Peter Zaitcev)
2.4.2-ac5
o Add Epson 1240U scanners to usb scanner (Joel Becker)
o Fix eth= compatibility (Andrew Morton)
| Should fix 3c509 problems for one
o Add Pnp table to opl3sa2 (Bill Nottingham)
o Update loop driver fixes (Jens Axboe, Andrea
Arcangeli, Al Viro)
o Fix busy loop in usb storage (Arjan van de Ven)
o Add cardbus support to olympic (Mike Phillips)
o Make BUG() configurable to save space (Arjan van de Ven)
o Add configurability to most kernel debugging (various people)
functions on x86
o Richard G?nther/binfmt_misc page move (Richard G?nther)
o Fix de4x5 crash (Nikita Schmidt)
o Hopefully fix the smc-mca driver (me)
o Don't run the disk queue if we didnt launder (Marcelo Tosatti)
any pages
o ALi 6 channel audio and sp/dif updates (Matt Wu)
o Fix USB thread wakeup scheduling (Arjan van de Ven)
o Fix alignment problems with uni16_to_x8 (Ivan Kokshaysky)
2.4.2-ac4
o Fix Make xconfig failure (J Magallon)
o Fix a typo in the ISDN docs (Jim Freeman)
o Fix the 3ware driver a bit more (Ben LaHaise)
| should now be usable
o Update Dave Jones contact info (Dave Jones)
o Revert wavelan inline->macro change (Jean Tourillhes)
| CVS gcc and 2.96-74 don't accidentally unline it now
o Zerocopy TCP/IP patches (Dave Miller,
Alexey Kuznetsov,
and many more)
o Fix up command line options to old ncr driver (Martin Storsj?)
o NFS locking should call fs layer locking if (Brian Dixon)
present
o Fix cs46xx wakeup/poll problem (David Huggins-Daines)
o Add some missing MTD config help texts (Steven Cole,
David Woodhouse)
o Fix Alpha build bug (Sven Koch)
o Final i386/ptrace bit
o Finish off the vmalloc/WP fixup (me)
o Include file config.h fixes (Niels Jensen)
o More dscc4 updates (Francois Romieu)
2.4.2-ac3
o Add documentation for the fb interfaces (Brad Douglas)
o Work around apic disable_irq hardware bugs (Maciej Rozycki)
o Rage128 not "Rage 128" (Brad Douglas)
o Make ioremap debugging conditional (J Magallon)
o Merge Ninja pcmcia scsi driver (YOKOTA Hiroshi)
o Update 8139too docs (Jeff Garzik)
o Tulip updates, merge bits from 0.92 (Jeff Garzik,
Don Becker)
o Epic100 update (Jeff Garzik)
o Clean up Ariadne driver (Jeff Garzik)
o Remove dead wavelan prototype (Jeff Garzik)
o Remove unused arlan variable (Jeff Garzik)
o Clean up lance public symbols (Jeff Garzik)
o Switch fmv18x to spinlocks, fix other bits (Jeff Garzik)
o Clean up acenic global symbols (Jeff Garzik)
o Fix IDE blocking kmalloc with irqs off (Arjan van de Ven)
| I've redone the code a bit so it might be wrong again 8)
2.4.2-ac2
o Merge the loop device fixes (Jens Axboe)
o Fix af_unix SYSCTL=n build failure (Russell King)
o Adjust the throttling point for write (Jens Axboe)
throttles
o Fix sunhme ioremap (Andrey Panin)
o Fix disk change handling with removable sd (Alex Davis)
o Update/fix irq docs (Matthew Wilcox)
o Update PPC gmac and ncr885e drivers (Cort Dougan)
| bmac patch dropped as it loses other fixes
o Kai Petzke has moved (Kai Petzke)
o Fix starfire driver so pump doesnt kill it (Ion Badulescu)
2.4.2-ac1
o Merge Linus 2.4.2 tree
| We now have disagreeing ymfpci fixes. I've kept the ones
| I tested for now.
o Back out sr.c change (me)
o Fix moxa smartio driver (Tom Mraz)
o Hugh Blemings change of address (Hugh Blemings)
o Allow more i2o config time for slow calls
o Aty128fb updates (Brad Douglas,
Benjamin Herrenschmidt,
Michel Danzer,
Andreas Hundt)
o Add "loop" name to the root dev names (Barry Nathan)
o Further spelling cleanups (Dag Wieers)
o Remove bogus warning emissions from aha1740 (Nick Holloway)
o Remove surplus assignment in vmalloc (Francis Galiegue)
o Remove unneeded ifdef in i386/kernel/irq.c (Francis Galiegue)
o Add door locking ioctl to ide-floppy (Francis Galiegue)
o Allow scsi disk opening O_NDELAY for removables (me)
o Fix cosa compile warnings (me)
o Clean up dumpable/setuid write ordering (me)
o Hopefully fix the 3ware crashes (me)
---
Alan Cox <[email protected]>
Red Hat Kernel Hacker
& Linux 2.2 Maintainer Brainbench MVP for TCP/IP
http://www.linux.org.uk/diary http://www.brainbench.com
On Thu, 19 Apr 2001 21:14:32 +0100 (BST), Alan Cox <[email protected]> wrote:
> 2.4.3-ac10
> o Merge Linus 2.4.4pre4
Well, it seems you have backed out my starfire changes when you merged
Jeff Garzik's changes from 2.4.4pre4. So here's a new version, diff'ed
against 2.4.3-ac10, which includes all of Jeff's changes from 2.4.3pre[45].
BTW Jeff, do you want me to send these updates to you instead of Alan,
diff'ed against 2.4.x-pre_latest? Right now we're just wasting each
other's time by making conflicting changes to different trees.
Thanks,
Ion
--
It is better to keep your mouth shut and be thought a fool,
than to open it and remove all doubt.
--------------------------
--- /mnt/3/linux-2.4-ac/drivers/net/starfire.c Thu Apr 19 15:58:57 2001
+++ linux-2.4/drivers/net/starfire.c Thu Apr 19 17:41:01 2001
@@ -20,7 +20,7 @@
-----------------------------------------------------------
Linux kernel-specific changes:
-
+
LK1.1.1 (jgarzik):
- Use PCI driver interface
- Fix MOD_xxx races
@@ -31,9 +31,45 @@
LK1.1.3 (Andrew Morton)
- Timer cleanups
-
+
LK1.1.4 (jgarzik):
- Merge Becker version 1.03
+
+ LK1.2.1 (Ion Badulescu <[email protected]>)
+ - Support hardware Rx/Tx checksumming
+ - Use the GFP firmware taken from Adaptec's Netware driver
+
+ LK1.2.2 (Ion Badulescu)
+ - Backported to 2.2.x
+
+ LK1.2.3 (Ion Badulescu)
+ - Fix the flaky mdio interface
+ - More compat clean-ups
+
+ LK1.2.4 (Ion Badulescu)
+ - More 2.2.x initialization fixes
+
+ LK1.2.5 (Ion Badulescu)
+ - Several fixes from Manfred Spraul
+
+ LK1.2.6 (Ion Badulescu)
+ - Fixed ifup/ifdown/ifup problem in 2.4.x
+
+ LK1.2.7 (Ion Badulescu)
+ - Removed unused code
+ - Made more functions static and __init
+
+ LK1.2.8 (Ion Badulescu)
+ - Quell bogus error messages, inform about the Tx threshold
+ - Removed #ifdef CONFIG_PCI, this driver is PCI only
+
+ LK1.2.9 (Ion Badulescu)
+ - Merged Jeff Garzik's changes from 2.4.4-pre5
+ - Added 2.2.x compatibility stuff required by the above changes
+
+TODO:
+ - implement tx_timeout() properly
+ - support ethtool
*/
/* These identify the driver base version and may not be removed. */
@@ -43,24 +79,60 @@
" Updates and info at http://www.scyld.com/network/starfire.html\n";
static const char version3[] =
-" (unofficial 2.4.x kernel port, version 1.1.4, August 10, 2000)\n";
+" (unofficial 2.4.x kernel port, version 1.2.9, April 19, 2001)\n";
+
+/*
+ * Adaptec's license for their Novell drivers (which is where I got the
+ * firmware files) does not allow one to redistribute them. Thus, we can't
+ * include the firmware with this driver.
+ *
+ * However, an end-user is allowed to download and use it, after
+ * converting it to C header files using starfire_firmware.pl.
+ * Once that's done, the #undef must be changed into a #define
+ * for this driver to really use the firmware. Note that Rx/Tx
+ * hardware TCP checksumming is not possible without the firmware.
+ *
+ * I'm currently [Feb 2001] talking to Adaptec about this redistribution
+ * issue. Stay tuned...
+ */
+#undef HAS_FIRMWARE
+/*
+ * The current frame processor firmware fails to checksum a fragment
+ * of length 1. If and when this is fixed, the #define below can be removed.
+ */
+#define HAS_BROKEN_FIRMWARE
/* The user-configurable values.
These may be modified when a driver module is loaded.*/
/* Used for tuning interrupt latency vs. overhead. */
-static int interrupt_mitigation = 0x0;
+static int interrupt_mitigation;
static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */
static int max_interrupt_work = 20;
-static int mtu = 0;
+static int mtu;
/* Maximum number of multicast addresses to filter (vs. rx-all-multicast).
- The Starfire has a 512 element hash table based on the Ethernet CRC. */
-static int multicast_filter_limit = 32;
+ The Starfire has a 512 element hash table based on the Ethernet CRC. */
+static int multicast_filter_limit = 512;
-/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
- Setting to > 1518 effectively disables this feature. */
+#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
+/*
+ * Set the copy breakpoint for the copy-only-tiny-frames scheme.
+ * Setting to > 1518 effectively disables this feature.
+ *
+ * NOTE:
+ * The ia64 doesn't allow for unaligned loads even of integers being
+ * misaligned on a 2 byte boundary. Thus always force copying of
+ * packets as the starfire doesn't allow for misaligned DMAs ;-(
+ * 23/10/2000 - Jes
+ *
+ * The Alpha and the Sparc don't allow unaligned loads, either. -Ion
+ */
+#if defined(__ia64__) || defined(__alpha__) || defined(__sparc__)
+static int rx_copybreak = PKT_BUF_SZ;
+#else
static int rx_copybreak = 0;
+#endif
/* Used to pass the media type, etc.
Both 'options[]' and 'full_duplex[]' exist for driver interoperability.
@@ -84,9 +156,9 @@
/* Operational parameters that usually are not changed. */
/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT (2*HZ)
+#define TX_TIMEOUT (2*HZ)
-#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
+#define skb_first_frag_len(skb) (skb->len)
#if !defined(__OPTIMIZE__)
#warning You must compile this file with the correct options!
@@ -94,32 +166,36 @@
#error You must compile this driver with "-O".
#endif
-/* Include files, designed to support most kernel versions 2.0.0 and later. */
#include <linux/version.h>
#include <linux/module.h>
-
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/errno.h>
#include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/init.h>
+#include <linux/delay.h>
#include <asm/processor.h> /* Processor type for cache alignment. */
#include <asm/bitops.h>
#include <asm/io.h>
+#ifdef HAS_FIRMWARE
+#include "starfire_firmware.h"
+#endif /* HAS_FIRMWARE */
+
MODULE_AUTHOR("Donald Becker <[email protected]>");
MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver");
MODULE_PARM(max_interrupt_work, "i");
MODULE_PARM(mtu, "i");
MODULE_PARM(debug, "i");
MODULE_PARM(rx_copybreak, "i");
+MODULE_PARM(interrupt_mitigation, "i");
MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
@@ -152,8 +228,9 @@
See the Adaptec manual for the many possible structures, and options for
each structure. There are far too many to document here.
-For transmit this driver uses type 1 transmit descriptors, and relies on
-automatic minimum-length padding. It does not use the completion queue
+For transmit this driver uses type 0/1 transmit descriptors (depending
+on the presence of the zerocopy patches), and relies on automatic
+minimum-length padding. It does not use the completion queue
consumer index, but instead checks for non-zero status entries.
For receive this driver uses type 0 receive descriptors. The driver
@@ -170,8 +247,9 @@
A notable aspect of operation is that unaligned buffers are not permitted by
the Starfire hardware. The IP header at offset 14 in an ethernet frame thus
isn't longword aligned, which may cause problems on some machine
-e.g. Alphas. Copied frames are put into the skbuff at an offset of "+2",
-16-byte aligning the IP header.
+e.g. Alphas and IA64. For these architectures, the driver is forced to copy
+the frame into a new skbuff unconditionally. Copied frames are put into the
+skbuff at an offset of "+2", thus 16-byte aligning the IP header.
IIId. Synchronization
@@ -204,6 +282,235 @@
+/* 2.2.x compatibility code */
+#if LINUX_VERSION_CODE < 0x20300
+#include <linux/kcomp.h>
+
+static LIST_HEAD(pci_drivers);
+
+struct pci_driver_mapping {
+ struct pci_dev *dev;
+ struct pci_driver *drv;
+ void *driver_data;
+};
+
+struct pci_device_id {
+ unsigned int vendor, device;
+ unsigned int subvendor, subdevice;
+ unsigned int class, class_mask;
+ unsigned long driver_data;
+};
+
+struct pci_driver {
+ struct list_head node;
+ struct pci_dev *dev;
+ char *name;
+ const struct pci_device_id *id_table; /* NULL if wants all devices */
+ int (*probe)(struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */
+ void (*remove)(struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */
+ void (*suspend)(struct pci_dev *dev); /* Device suspended */
+ void (*resume)(struct pci_dev *dev); /* Device woken up */
+};
+
+#define PCI_MAX_MAPPINGS 16
+static struct pci_driver_mapping drvmap [PCI_MAX_MAPPINGS] = { { NULL, } , };
+
+#define __devinit __init
+#define __devinitdata __initdata
+#define __devexit
+#define MODULE_DEVICE_TABLE(foo,bar)
+#define SET_MODULE_OWNER(dev)
+#define COMPAT_MOD_INC_USE_COUNT MOD_INC_USE_COUNT
+#define COMPAT_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT
+#define PCI_ANY_ID (~0)
+#define IORESOURCE_MEM 2
+#define PCI_DMA_FROMDEVICE 0
+#define PCI_DMA_TODEVICE 0
+
+#define pci_request_regions(pdev, name) 0
+#define pci_release_regions(pdev) do {} while(0)
+#define del_timer_sync(timer) del_timer(timer)
+#define alloc_etherdev(size) init_etherdev(NULL, size)
+#define register_netdev(dev) 0
+
+static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
+ dma_addr_t *dma_handle)
+{
+ void *virt_ptr;
+
+ virt_ptr = kmalloc(size, GFP_KERNEL);
+ *dma_handle = virt_to_bus(virt_ptr);
+ return virt_ptr;
+}
+#define pci_free_consistent(cookie, size, ptr, dma_ptr) kfree(ptr)
+#define pci_map_single(cookie, address, size, dir) virt_to_bus(address)
+#define pci_unmap_single(cookie, address, size, dir)
+#define pci_dma_sync_single(cookie, address, size, dir)
+#undef pci_resource_flags
+#define pci_resource_flags(dev, i) \
+ ((dev->base_address[i] & IORESOURCE_IO) ? IORESOURCE_IO : IORESOURCE_MEM)
+
+static void * pci_get_drvdata (struct pci_dev *dev)
+{
+ int i;
+
+ for (i = 0; i < PCI_MAX_MAPPINGS; i++)
+ if (drvmap[i].dev == dev)
+ return drvmap[i].driver_data;
+
+ return NULL;
+}
+
+static void pci_set_drvdata (struct pci_dev *dev, void *driver_data)
+{
+ int i;
+
+ for (i = 0; i < PCI_MAX_MAPPINGS; i++)
+ if (drvmap[i].dev == dev) {
+ drvmap[i].driver_data = driver_data;
+ return;
+ }
+}
+
+static const struct pci_device_id * __init
+pci_compat_match_device(const struct pci_device_id *ids, struct pci_dev *dev)
+{
+ u16 subsystem_vendor, subsystem_device;
+
+ pci_read_config_word(dev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
+ pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &subsystem_device);
+
+ while (ids->vendor || ids->subvendor || ids->class_mask) {
+ if ((ids->vendor == PCI_ANY_ID || ids->vendor == dev->vendor) &&
+ (ids->device == PCI_ANY_ID || ids->device == dev->device) &&
+ (ids->subvendor == PCI_ANY_ID || ids->subvendor == subsystem_vendor) &&
+ (ids->subdevice == PCI_ANY_ID || ids->subdevice == subsystem_device) &&
+ !((ids->class ^ dev->class) & ids->class_mask))
+ return ids;
+ ids++;
+ }
+ return NULL;
+}
+
+static int __init
+pci_announce_device(struct pci_driver *drv, struct pci_dev *dev)
+{
+ const struct pci_device_id *id;
+ int found, i;
+
+ if (drv->id_table) {
+ id = pci_compat_match_device(drv->id_table, dev);
+ if (!id)
+ return 0;
+ } else
+ id = NULL;
+
+ found = 0;
+ for (i = 0; i < PCI_MAX_MAPPINGS; i++)
+ if (!drvmap[i].dev) {
+ drvmap[i].dev = dev;
+ drvmap[i].drv = drv;
+ found = 1;
+ break;
+ }
+
+ if (!found)
+ return 0;
+
+ if (drv->probe(dev, id) >= 0)
+ return 1;
+
+ /* clean up */
+ drvmap[i].dev = NULL;
+ return 0;
+}
+
+static int __init
+pci_register_driver(struct pci_driver *drv)
+{
+ struct pci_dev *dev;
+ int count = 0, found, i;
+ list_add_tail(&drv->node, &pci_drivers);
+ for (dev = pci_devices; dev; dev = dev->next) {
+ found = 0;
+ for (i = 0; i < PCI_MAX_MAPPINGS && !found; i++)
+ if (drvmap[i].dev == dev)
+ found = 1;
+ if (!found)
+ count += pci_announce_device(drv, dev);
+ }
+ return count;
+}
+
+static void
+pci_unregister_driver(struct pci_driver *drv)
+{
+ struct pci_dev *dev;
+ int i, found;
+ list_del(&drv->node);
+ for (dev = pci_devices; dev; dev = dev->next) {
+ found = 0;
+ for (i = 0; i < PCI_MAX_MAPPINGS; i++)
+ if (drvmap[i].dev == dev) {
+ found = 1;
+ break;
+ }
+ if (found) {
+ if (drv->remove)
+ drv->remove(dev);
+ drvmap[i].dev = NULL;
+ }
+ }
+}
+
+static inline int pci_module_init(struct pci_driver *drv)
+{
+ if (pci_register_driver(drv))
+ return 0;
+ return -ENODEV;
+}
+
+static struct pci_driver starfire_driver;
+
+int __init starfire_probe(struct net_device *dev)
+{
+ static int __initdata probed = 0;
+
+ if (probed)
+ return -ENODEV;
+ probed++;
+
+ return pci_module_init(&starfire_driver);
+}
+
+#define init_tx_timer(dev, func, timeout)
+#define kick_tx_timer(dev, func, timeout) \
+ if (netif_queue_stopped(dev)) { \
+ /* If this happens network layer tells us we're broken. */ \
+ if (jiffies - dev->trans_start > timeout) \
+ func(dev); \
+ }
+
+#define netif_start_if(dev) dev->start = 1
+#define netif_stop_if(dev) dev->start = 0
+
+#else /* LINUX_VERSION_CODE > 0x20300 */
+
+#define COMPAT_MOD_INC_USE_COUNT
+#define COMPAT_MOD_DEC_USE_COUNT
+
+#define init_tx_timer(dev, func, timeout) \
+ dev->tx_timeout = func; \
+ dev->watchdog_timeo = timeout;
+#define kick_tx_timer(dev, func, timeout)
+
+#define netif_start_if(dev)
+#define netif_stop_if(dev)
+
+#endif /* LINUX_VERSION_CODE > 0x20300 */
+/* end of compatibility code */
+
+
enum chip_capability_flags {CanHaveMII=1, };
#define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_MEM | PCI_ADDR0)
#define MEM_ADDR_SZ 0x80000 /* And maps in 0.5MB(!). */
@@ -253,19 +560,32 @@
TxThreshold=0x500B0,
CompletionHiAddr=0x500B4, TxCompletionAddr=0x500B8,
RxCompletionAddr=0x500BC, RxCompletionQ2Addr=0x500C0,
- CompletionQConsumerIdx=0x500C4,
+ CompletionQConsumerIdx=0x500C4, RxDMACtrl=0x500D0,
RxDescQCtrl=0x500D4, RxDescQHiAddr=0x500DC, RxDescQAddr=0x500E0,
RxDescQIdx=0x500E8, RxDMAStatus=0x500F0, RxFilterMode=0x500F4,
- TxMode=0x55000,
+ TxMode=0x55000, TxGfpMem=0x58000, RxGfpMem=0x5a000,
};
/* Bits in the interrupt status/mask registers. */
enum intr_status_bits {
- IntrNormalSummary=0x8000, IntrAbnormalSummary=0x02000000,
- IntrRxDone=0x0300, IntrRxEmpty=0x10040, IntrRxPCIErr=0x80000,
- IntrTxDone=0x4000, IntrTxEmpty=0x1000, IntrTxPCIErr=0x80000,
- StatsMax=0x08000000, LinkChange=0xf0000000,
- IntrTxDataLow=0x00040000,
+ IntrLinkChange=0xf0000000, IntrStatsMax=0x08000000,
+ IntrAbnormalSummary=0x02000000, IntrGeneralTimer=0x01000000,
+ IntrSoftware=0x800000, IntrRxComplQ1Low=0x400000,
+ IntrTxComplQLow=0x200000, IntrPCI=0x100000,
+ IntrDMAErr=0x080000, IntrTxDataLow=0x040000,
+ IntrRxComplQ2Low=0x020000, IntrRxDescQ1Low=0x010000,
+ IntrNormalSummary=0x8000, IntrTxDone=0x4000,
+ IntrTxDMADone=0x2000, IntrTxEmpty=0x1000,
+ IntrEarlyRxQ2=0x0800, IntrEarlyRxQ1=0x0400,
+ IntrRxQ2Done=0x0200, IntrRxQ1Done=0x0100,
+ IntrRxGFPDead=0x80, IntrRxDescQ2Low=0x40,
+ IntrNoTxCsum=0x20, IntrTxBadID=0x10,
+ IntrHiPriTxBadID=0x08, IntrRxGfp=0x04,
+ IntrTxGfp=0x02, IntrPCIPad=0x01,
+ /* not quite bits */
+ IntrRxDone=IntrRxQ2Done | IntrRxQ1Done,
+ IntrRxEmpty=IntrRxDescQ1Low | IntrRxDescQ2Low,
+ IntrNormalMask=0xf0, IntrAbnormalMask=0x3f0e,
};
/* Bits in the RxFilterMode register. */
@@ -274,9 +594,40 @@
AcceptMulticast=0x10, AcceptMyPhys=0xE040,
};
+/* Bits in the TxDescCtrl register. */
+enum tx_ctrl_bits {
+ TxDescSpaceUnlim=0x00, TxDescSpace32=0x10, TxDescSpace64=0x20,
+ TxDescSpace128=0x30, TxDescSpace256=0x40,
+ TxDescType0=0x00, TxDescType1=0x01, TxDescType2=0x02,
+ TxDescType3=0x03, TxDescType4=0x04,
+ TxNoDMACompletion=0x08, TxDescQ64bit=0x80,
+ TxHiPriFIFOThreshShift=24, TxPadLenShift=16,
+ TxDMABurstSizeShift=8,
+};
+
+/* Bits in the RxDescQCtrl register. */
+enum rx_ctrl_bits {
+ RxBufferLenShift=16, RxMinDescrThreshShift=0,
+ RxPrefetchMode=0x8000, Rx2048QEntries=0x4000,
+ RxVariableQ=0x2000, RxDesc64bit=0x1000,
+ RxDescQAddr64bit=0x0100,
+ RxDescSpace4=0x000, RxDescSpace8=0x100,
+ RxDescSpace16=0x200, RxDescSpace32=0x300,
+ RxDescSpace64=0x400, RxDescSpace128=0x500,
+ RxConsumerWrEn=0x80,
+};
+
+/* Bits in the RxCompletionAddr register */
+enum rx_compl_bits {
+ RxComplQAddr64bit=0x80, TxComplProducerWrEn=0x40,
+ RxComplType0=0x00, RxComplType1=0x10,
+ RxComplType2=0x20, RxComplType3=0x30,
+ RxComplThreshShift=0,
+};
+
/* The Rx and Tx buffer descriptors. */
struct starfire_rx_desc {
- u32 rxaddr; /* Optionally 64 bits. */
+ u32 rxaddr; /* Optionally 64 bits. */
};
enum rx_desc_bits {
RxDescValid=1, RxDescEndRing=2,
@@ -285,14 +636,20 @@
/* Completion queue entry.
You must update the page allocation, init_ring and the shift count in rx()
if using a larger format. */
+#ifdef HAS_FIRMWARE
+#define csum_rx_status
+#endif /* HAS_FIRMWARE */
struct rx_done_desc {
- u32 status; /* Low 16 bits is length. */
+ u32 status; /* Low 16 bits is length. */
+#ifdef csum_rx_status
+ u32 status2; /* Low 16 bits is csum */
+#endif /* csum_rx_status */
#ifdef full_rx_status
u32 status2;
u16 vlanid;
- u16 csum; /* partial checksum */
+ u16 csum; /* partial checksum */
u32 timestamp;
-#endif
+#endif /* full_rx_status */
};
enum rx_done_bits {
RxOK=0x20000000, RxFIFOErr=0x10000000, RxBufQ2=0x08000000,
@@ -300,26 +657,31 @@
/* Type 1 Tx descriptor. */
struct starfire_tx_desc {
- u32 status; /* Upper bits are status, lower 16 length. */
- u32 addr;
+ u32 status; /* Upper bits are status, lower 16 length. */
+ u32 first_addr;
};
enum tx_desc_bits {
- TxDescID=0xB1010000, /* Also marks single fragment, add CRC. */
- TxDescIntr=0x08000000, TxRingWrap=0x04000000,
+ TxDescID=0xB0000000,
+ TxCRCEn=0x01000000, TxDescIntr=0x08000000,
+ TxRingWrap=0x04000000, TxCalTCP=0x02000000,
};
struct tx_done_report {
- u32 status; /* timestamp, index. */
+ u32 status; /* timestamp, index. */
#if 0
- u32 intrstatus; /* interrupt status */
+ u32 intrstatus; /* interrupt status */
#endif
};
-#define PRIV_ALIGN 15 /* Required alignment mask */
-struct ring_info {
+struct rx_ring_info {
struct sk_buff *skb;
dma_addr_t mapping;
};
+struct tx_ring_info {
+ struct sk_buff *skb;
+ dma_addr_t first_mapping;
+};
+#define MII_CNT 2
struct netdev_private {
/* Descriptor rings first for alignment. */
struct starfire_rx_desc *rx_ring;
@@ -327,8 +689,8 @@
dma_addr_t rx_ring_dma;
dma_addr_t tx_ring_dma;
/* The addresses of rx/tx-in-place skbuffs. */
- struct ring_info rx_info[RX_RING_SIZE];
- struct ring_info tx_info[TX_RING_SIZE];
+ struct rx_ring_info rx_info[RX_RING_SIZE];
+ struct tx_ring_info tx_info[TX_RING_SIZE];
/* Pointers to completion queues (full pages). I should cache line pad..*/
u8 pad0[100];
struct rx_done_desc *rx_done_q;
@@ -341,84 +703,86 @@
struct timer_list timer; /* Media monitoring timer. */
struct pci_dev *pci_dev;
/* Frequently used values: keep some adjacent for cache effect. */
- unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */
+ unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */
unsigned int cur_tx, dirty_tx;
- unsigned int rx_buf_sz; /* Based on MTU+slack. */
- unsigned int tx_full:1; /* The Tx queue is full. */
+ unsigned int rx_buf_sz; /* Based on MTU+slack. */
+ unsigned int tx_full:1; /* The Tx queue is full. */
/* These values are keep track of the transceiver/media in use. */
- unsigned int full_duplex:1, /* Full-duplex operation requested. */
- medialock:1, /* Xcvr set to fixed speed/duplex. */
+ unsigned int full_duplex:1, /* Full-duplex operation requested. */
+ medialock:1, /* Xcvr set to fixed speed/duplex. */
rx_flowctrl:1,
- tx_flowctrl:1; /* Use 802.3x flow control. */
- unsigned int default_port:4; /* Last dev->if_port value. */
+ tx_flowctrl:1; /* Use 802.3x flow control. */
+ unsigned int default_port:4; /* Last dev->if_port value. */
u32 tx_mode;
u8 tx_threshold;
/* MII transceiver section. */
- int mii_cnt; /* MII device addresses. */
- u16 advertising; /* NWay media advertisement */
- unsigned char phys[2]; /* MII device addresses. */
-};
-
-static int mdio_read(struct net_device *dev, int phy_id, int location);
-static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
-static int netdev_open(struct net_device *dev);
-static void check_duplex(struct net_device *dev, int startup);
-static void netdev_timer(unsigned long data);
-static void tx_timeout(struct net_device *dev);
-static void init_ring(struct net_device *dev);
-static int start_tx(struct sk_buff *skb, struct net_device *dev);
-static void intr_handler(int irq, void *dev_instance, struct pt_regs *regs);
-static void netdev_error(struct net_device *dev, int intr_status);
-static int netdev_rx(struct net_device *dev);
-static void netdev_error(struct net_device *dev, int intr_status);
-static void set_rx_mode(struct net_device *dev);
+ int mii_cnt; /* MII device addresses. */
+ u16 advertising; /* NWay media advertisement */
+ unsigned char phys[MII_CNT]; /* MII device addresses. */
+};
+
+static int mdio_read(struct net_device *dev, int phy_id, int location);
+static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
+static int netdev_open(struct net_device *dev);
+static void check_duplex(struct net_device *dev, int startup);
+static void netdev_timer(unsigned long data);
+static void tx_timeout(struct net_device *dev);
+static void init_ring(struct net_device *dev);
+static int start_tx(struct sk_buff *skb, struct net_device *dev);
+static void intr_handler(int irq, void *dev_instance, struct pt_regs *regs);
+static void netdev_error(struct net_device *dev, int intr_status);
+static int netdev_rx(struct net_device *dev);
+static void netdev_error(struct net_device *dev, int intr_status);
+static void set_rx_mode(struct net_device *dev);
static struct net_device_stats *get_stats(struct net_device *dev);
-static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static int netdev_close(struct net_device *dev);
+static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static int netdev_close(struct net_device *dev);
-static int __devinit starfire_init_one (struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int __devinit starfire_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct netdev_private *np;
int i, irq, option, chip_idx = ent->driver_data;
struct net_device *dev;
static int card_idx = -1;
- static int printed_version = 0;
+ static int printed_version;
long ioaddr;
- int drv_flags, io_size = netdrv_tbl[chip_idx].io_size;
+ int drv_flags, io_size;
+ int boguscnt;
card_idx++;
option = card_idx < MAX_UNITS ? options[card_idx] : 0;
-
+
if (!printed_version++)
printk(KERN_INFO "%s" KERN_INFO "%s" KERN_INFO "%s",
- version1, version2, version3);
+ version1, version2, version3);
+
+ if (pci_enable_device (pdev))
+ return -EIO;
ioaddr = pci_resource_start (pdev, 0);
+ io_size = pci_resource_len (pdev, 0);
if (!ioaddr || ((pci_resource_flags (pdev, 0) & IORESOURCE_MEM) == 0)) {
printk (KERN_ERR "starfire %d: no PCI MEM resources, aborting\n", card_idx);
return -ENODEV;
}
-
- dev = init_etherdev(NULL, sizeof(*np));
+
+ dev = alloc_etherdev(sizeof(*np));
if (!dev) {
printk (KERN_ERR "starfire %d: cannot alloc etherdev, aborting\n", card_idx);
return -ENOMEM;
}
-
- irq = pdev->irq;
+ SET_MODULE_OWNER(dev);
- if (request_mem_region (ioaddr, io_size, dev->name) == NULL) {
- printk (KERN_ERR "starfire %d: resource 0x%x @ 0x%lx busy, aborting\n",
- card_idx, io_size, ioaddr);
+ irq = pdev->irq;
+
+ if (pci_request_regions (pdev, dev->name)) {
+ printk (KERN_ERR "starfire %d: cannot reserve PCI resources, aborting\n", card_idx);
goto err_out_free_netdev;
}
-
- if (pci_enable_device (pdev))
- goto err_out_free_res;
-
+
ioaddr = (long) ioremap (ioaddr, io_size);
if (!ioaddr) {
printk (KERN_ERR "starfire %d: cannot remap 0x%x @ 0x%lx, aborting\n",
@@ -427,32 +791,42 @@
}
pci_set_master (pdev);
-
- printk(KERN_INFO "%s: %s at 0x%lx, ",
- dev->name, netdrv_tbl[chip_idx].name, ioaddr);
/* Serial EEPROM reads are hidden by the hardware. */
for (i = 0; i < 6; i++)
dev->dev_addr[i] = readb(ioaddr + EEPROMCtrl + 20-i);
- for (i = 0; i < 5; i++)
- printk("%2.2x:", dev->dev_addr[i]);
- printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);
#if ! defined(final_version) /* Dump the EEPROM contents during development. */
if (debug > 4)
for (i = 0; i < 0x20; i++)
- printk("%2.2x%s", (unsigned int)readb(ioaddr + EEPROMCtrl + i),
- i % 16 != 15 ? " " : "\n");
+ printk("%2.2x%s",
+ (unsigned int)readb(ioaddr + EEPROMCtrl + i),
+ i % 16 != 15 ? " " : "\n");
#endif
+ /* Issue soft reset */
+ writel(0x8000, ioaddr + TxMode);
+ udelay(1000);
+ writel(0, ioaddr + TxMode);
+
/* Reset the chip to erase previous misconfiguration. */
writel(1, ioaddr + PCIDeviceConfig);
+ boguscnt = 1000;
+ while (--boguscnt > 0) {
+ udelay(10);
+ if ((readl(ioaddr + PCIDeviceConfig) & 1) == 0)
+ break;
+ }
+ if (boguscnt == 0)
+ printk("%s: chipset reset never completed!\n", dev->name);
+ /* wait a little longer */
+ udelay(1000);
dev->base_addr = ioaddr;
dev->irq = irq;
np = dev->priv;
- pdev->driver_data = dev;
+ pci_set_drvdata(pdev, dev);
np->pci_dev = pdev;
drv_flags = netdrv_tbl[chip_idx].drv_flags;
@@ -468,7 +842,7 @@
if (np->default_port)
np->medialock = 1;
}
- if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0)
+ if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0)
np->full_duplex = 1;
if (np->full_duplex)
@@ -477,8 +851,7 @@
/* The chip-specific entries in the device structure. */
dev->open = &netdev_open;
dev->hard_start_xmit = &start_tx;
- dev->tx_timeout = &tx_timeout;
- dev->watchdog_timeo = TX_TIMEOUT;
+ init_tx_timer(dev, tx_timeout, TX_TIMEOUT);
dev->stop = &netdev_close;
dev->get_stats = &get_stats;
dev->set_multicast_list = &set_rx_mode;
@@ -487,16 +860,39 @@
if (mtu)
dev->mtu = mtu;
+ i = register_netdev(dev);
+ if (i)
+ goto err_out_cleardev;
+
+ printk(KERN_INFO "%s: %s at 0x%lx, ",
+ dev->name, netdrv_tbl[chip_idx].name, ioaddr);
+ for (i = 0; i < 5; i++)
+ printk("%2.2x:", dev->dev_addr[i]);
+ printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);
+
if (drv_flags & CanHaveMII) {
int phy, phy_idx = 0;
- for (phy = 0; phy < 32 && phy_idx < 4; phy++) {
- int mii_status = mdio_read(dev, phy, 1);
- if (mii_status != 0xffff && mii_status != 0x0000) {
+ int mii_status;
+ for (phy = 0; phy < 32 && phy_idx < MII_CNT; phy++) {
+ mdio_write(dev, phy, 0, 0x8000);
+ udelay(500);
+ boguscnt = 1000;
+ while (--boguscnt > 0)
+ if ((mdio_read(dev, phy, 0) & 0x8000) == 0)
+ break;
+ if (boguscnt == 0) {
+ printk("%s: PHY reset never completed!\n", dev->name);
+ continue;
+ }
+ mii_status = mdio_read(dev, phy, 1);
+ if (mii_status != 0x0000) {
np->phys[phy_idx++] = phy;
np->advertising = mdio_read(dev, phy, 4);
printk(KERN_INFO "%s: MII PHY found at address %d, status "
"0x%4.4x advertising %4.4x.\n",
dev->name, phy, mii_status, np->advertising);
+ /* there can be only one PHY on-board */
+ break;
}
}
np->mii_cnt = phy_idx;
@@ -504,8 +900,11 @@
return 0;
+err_out_cleardev:
+ pci_set_drvdata(pdev, NULL);
+ iounmap((void *)ioaddr);
err_out_free_res:
- release_mem_region (ioaddr, io_size);
+ pci_release_regions (pdev);
err_out_free_netdev:
unregister_netdev (dev);
kfree (dev);
@@ -522,7 +921,11 @@
/* ??? Should we add a busy-wait here? */
do
result = readl(mdio_addr);
- while ((result & 0xC0000000) != 0x80000000 && --boguscnt >= 0);
+ while ((result & 0xC0000000) != 0x80000000 && --boguscnt > 0);
+ if (boguscnt == 0)
+ return 0;
+ if ((result & 0xffff) == 0xffff)
+ return 0;
return result & 0xffff;
}
@@ -537,17 +940,17 @@
static int netdev_open(struct net_device *dev)
{
- struct netdev_private *np = (struct netdev_private *)dev->priv;
+ struct netdev_private *np = dev->priv;
long ioaddr = dev->base_addr;
int i, retval;
/* Do we ever need to reset the chip??? */
- MOD_INC_USE_COUNT;
+ COMPAT_MOD_INC_USE_COUNT;
retval = request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev);
if (retval) {
- MOD_DEC_USE_COUNT;
+ COMPAT_MOD_DEC_USE_COUNT;
return retval;
}
@@ -556,40 +959,48 @@
writel(1, ioaddr + PCIDeviceConfig);
if (debug > 1)
printk(KERN_DEBUG "%s: netdev_open() irq %d.\n",
- dev->name, dev->irq);
+ dev->name, dev->irq);
/* Allocate the various queues, failing gracefully. */
if (np->tx_done_q == 0)
np->tx_done_q = pci_alloc_consistent(np->pci_dev, PAGE_SIZE, &np->tx_done_q_dma);
if (np->rx_done_q == 0)
- np->rx_done_q = pci_alloc_consistent(np->pci_dev, PAGE_SIZE, &np->rx_done_q_dma);
+ np->rx_done_q = pci_alloc_consistent(np->pci_dev, sizeof(struct rx_done_desc) * DONE_Q_SIZE, &np->rx_done_q_dma);
if (np->tx_ring == 0)
np->tx_ring = pci_alloc_consistent(np->pci_dev, PAGE_SIZE, &np->tx_ring_dma);
if (np->rx_ring == 0)
np->rx_ring = pci_alloc_consistent(np->pci_dev, PAGE_SIZE, &np->rx_ring_dma);
- if (np->tx_done_q == 0 || np->rx_done_q == 0
- || np->rx_ring == 0 || np->tx_ring == 0) {
+ if (np->tx_done_q == 0 || np->rx_done_q == 0
+ || np->rx_ring == 0 || np->tx_ring == 0) {
if (np->tx_done_q)
pci_free_consistent(np->pci_dev, PAGE_SIZE,
- np->tx_done_q, np->tx_done_q_dma);
+ np->tx_done_q, np->tx_done_q_dma);
if (np->rx_done_q)
- pci_free_consistent(np->pci_dev, PAGE_SIZE,
- np->rx_done_q, np->rx_done_q_dma);
+ pci_free_consistent(np->pci_dev, sizeof(struct rx_done_desc) * DONE_Q_SIZE,
+ np->rx_done_q, np->rx_done_q_dma);
if (np->tx_ring)
pci_free_consistent(np->pci_dev, PAGE_SIZE,
- np->tx_ring, np->tx_ring_dma);
+ np->tx_ring, np->tx_ring_dma);
if (np->rx_ring)
pci_free_consistent(np->pci_dev, PAGE_SIZE,
- np->rx_ring, np->rx_ring_dma);
- MOD_DEC_USE_COUNT;
+ np->rx_ring, np->rx_ring_dma);
+ COMPAT_MOD_DEC_USE_COUNT;
return -ENOMEM;
}
init_ring(dev);
/* Set the size of the Rx buffers. */
- writel((np->rx_buf_sz<<16) | 0xA000, ioaddr + RxDescQCtrl);
+ writel((np->rx_buf_sz << RxBufferLenShift) |
+ (0 << RxMinDescrThreshShift) |
+ RxPrefetchMode | RxVariableQ |
+ RxDescSpace4,
+ ioaddr + RxDescQCtrl);
/* Set Tx descriptor to type 1 and padding to 0 bytes. */
- writel(0x02000401, ioaddr + TxDescCtrl);
+ writel((2 << TxHiPriFIFOThreshShift) |
+ (0 << TxPadLenShift) |
+ (4 << TxDMABurstSizeShift) |
+ TxDescSpaceUnlim | TxDescType1,
+ ioaddr + TxDescCtrl);
#if defined(ADDR_64BITS) && defined(__alpha__)
/* XXX We really need a 64-bit PCI dma interfaces too... -DaveM */
@@ -604,10 +1015,27 @@
writel(np->tx_ring_dma, ioaddr + TxRingPtr);
writel(np->tx_done_q_dma, ioaddr + TxCompletionAddr);
- writel(np->rx_done_q_dma, ioaddr + RxCompletionAddr);
+#ifdef full_rx_status
+ writel(np->rx_done_q_dma |
+ RxComplType3 |
+ (0 << RxComplThreshShift),
+ ioaddr + RxCompletionAddr);
+#else /* not full_rx_status */
+#ifdef csum_rx_status
+ writel(np->rx_done_q_dma |
+ RxComplType2 |
+ (0 << RxComplThreshShift),
+ ioaddr + RxCompletionAddr);
+#else /* not csum_rx_status */
+ writel(np->rx_done_q_dma |
+ RxComplType0 |
+ (0 << RxComplThreshShift),
+ ioaddr + RxCompletionAddr);
+#endif /* not csum_rx_status */
+#endif /* not full_rx_status */
if (debug > 1)
- printk(KERN_DEBUG "%s: Filling in the station address.\n", dev->name);
+ printk(KERN_DEBUG "%s: Filling in the station address.\n", dev->name);
/* Fill both the unused Tx SA register and the Rx perfect filter. */
for (i = 0; i < 6; i++)
@@ -630,29 +1058,41 @@
if (dev->if_port == 0)
dev->if_port = np->default_port;
+ netif_start_if(dev);
netif_start_queue(dev);
if (debug > 1)
- printk(KERN_DEBUG "%s: Setting the Rx and Tx modes.\n", dev->name);
+ printk(KERN_DEBUG "%s: Setting the Rx and Tx modes.\n", dev->name);
set_rx_mode(dev);
np->advertising = mdio_read(dev, np->phys[0], 4);
check_duplex(dev, 1);
/* Set the interrupt mask and enable PCI interrupts. */
- writel(IntrRxDone | IntrRxEmpty | IntrRxPCIErr |
- IntrTxDone | IntrTxEmpty | IntrTxPCIErr |
- StatsMax | LinkChange | IntrNormalSummary | IntrAbnormalSummary
- | 0x0010 , ioaddr + IntrEnable);
+ writel(IntrRxDone | IntrRxEmpty | IntrDMAErr |
+ IntrTxDone | IntrStatsMax | IntrLinkChange |
+ IntrNormalSummary | IntrAbnormalSummary |
+ IntrRxGFPDead | IntrNoTxCsum | IntrTxBadID,
+ ioaddr + IntrEnable);
writel(0x00800000 | readl(ioaddr + PCIDeviceConfig),
- ioaddr + PCIDeviceConfig);
+ ioaddr + PCIDeviceConfig);
- /* Enable the Rx and Tx units. */
+#ifdef HAS_FIRMWARE
+ /* Load Rx/Tx firmware into the frame processors */
+ for (i = 0; i < FIRMWARE_RX_SIZE * 2; i++)
+ writel(cpu_to_le32(firmware_rx[i]), ioaddr + RxGfpMem + i * 4);
+ for (i = 0; i < FIRMWARE_TX_SIZE * 2; i++)
+ writel(cpu_to_le32(firmware_tx[i]), ioaddr + TxGfpMem + i * 4);
+ /* Enable the Rx and Tx units, and the Rx/Tx frame processors. */
+ writel(0x003F, ioaddr + GenCtrl);
+#else /* not HAS_FIRMWARE */
+ /* Enable the Rx and Tx units only. */
writel(0x000F, ioaddr + GenCtrl);
+#endif /* not HAS_FIRMWARE */
if (debug > 2)
printk(KERN_DEBUG "%s: Done netdev_open().\n",
- dev->name);
+ dev->name);
/* Set the timer to check for link beat. */
init_timer(&np->timer);
@@ -666,7 +1106,7 @@
static void check_duplex(struct net_device *dev, int startup)
{
- struct netdev_private *np = (struct netdev_private *)dev->priv;
+ struct netdev_private *np = dev->priv;
long ioaddr = dev->base_addr;
int new_tx_mode ;
@@ -685,8 +1125,8 @@
np->full_duplex = duplex;
if (debug > 1)
printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d"
- " negotiated capability %4.4x.\n", dev->name,
- duplex ? "full" : "half", np->phys[0], negotiated);
+ " negotiated capability %4.4x.\n", dev->name,
+ duplex ? "full" : "half", np->phys[0], negotiated);
}
}
if (new_tx_mode != np->tx_mode) {
@@ -699,13 +1139,13 @@
static void netdev_timer(unsigned long data)
{
struct net_device *dev = (struct net_device *)data;
- struct netdev_private *np = (struct netdev_private *)dev->priv;
+ struct netdev_private *np = dev->priv;
long ioaddr = dev->base_addr;
int next_tick = 60*HZ; /* Check before driver release. */
if (debug > 3) {
printk(KERN_DEBUG "%s: Media selection timer tick, status %8.8x.\n",
- dev->name, (int)readl(ioaddr + IntrStatus));
+ dev->name, (int)readl(ioaddr + IntrStatus));
}
check_duplex(dev, 0);
#if ! defined(final_version)
@@ -715,7 +1155,7 @@
/* Bogus hardware IRQ: Fake an interrupt handler call. */
if (new_status & 1) {
printk(KERN_ERR "%s: Interrupt blocked, status %8.8x/%8.8x.\n",
- dev->name, new_status, (int)readl(ioaddr + IntrStatus));
+ dev->name, new_status, (int)readl(ioaddr + IntrStatus));
intr_handler(dev->irq, dev, 0);
}
}
@@ -727,11 +1167,11 @@
static void tx_timeout(struct net_device *dev)
{
- struct netdev_private *np = (struct netdev_private *)dev->priv;
+ struct netdev_private *np = dev->priv;
long ioaddr = dev->base_addr;
printk(KERN_WARNING "%s: Transmit timed out, status %8.8x,"
- " resetting...\n", dev->name, (int)readl(ioaddr + IntrStatus));
+ " resetting...\n", dev->name, (int)readl(ioaddr + IntrStatus));
#ifndef __alpha__
{
@@ -754,14 +1194,14 @@
dev->trans_start = jiffies;
np->stats.tx_errors++;
- return;
+ netif_wake_queue(dev);
}
/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
static void init_ring(struct net_device *dev)
{
- struct netdev_private *np = (struct netdev_private *)dev->priv;
+ struct netdev_private *np = dev->priv;
int i;
np->tx_full = 0;
@@ -801,7 +1241,7 @@
for (i = 0; i < TX_RING_SIZE; i++) {
np->tx_info[i].skb = NULL;
- np->tx_info[i].mapping = 0;
+ np->tx_info[i].first_mapping = 0;
np->tx_ring[i].status = 0;
}
return;
@@ -809,8 +1249,10 @@
static int start_tx(struct sk_buff *skb, struct net_device *dev)
{
- struct netdev_private *np = (struct netdev_private *)dev->priv;
- unsigned entry;
+ struct netdev_private *np = dev->priv;
+ unsigned int entry;
+
+ kick_tx_timer(dev, tx_timeout, TX_TIMEOUT);
/* Caution: the write order is important here, set the field
with the "ownership" bits last. */
@@ -819,41 +1261,43 @@
entry = np->cur_tx % TX_RING_SIZE;
np->tx_info[entry].skb = skb;
- np->tx_info[entry].mapping =
- pci_map_single(np->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE);
+ np->tx_info[entry].first_mapping =
+ pci_map_single(np->pci_dev, skb->data, skb_first_frag_len(skb), PCI_DMA_TODEVICE);
+
+ np->tx_ring[entry].first_addr = cpu_to_le32(np->tx_info[entry].first_mapping);
+ /* Add "| TxDescIntr" to generate Tx-done interrupts. */
+ np->tx_ring[entry].status = cpu_to_le32(skb->len | TxDescID | TxCRCEn | 1 << 16);
+
+ if (entry >= TX_RING_SIZE-1) /* Wrap ring */
+ np->tx_ring[entry].status |= cpu_to_le32(TxRingWrap | TxDescIntr);
- np->tx_ring[entry].addr = cpu_to_le32(np->tx_info[entry].mapping);
- /* Add "| TxDescIntr" to generate Tx-done interrupts. */
- np->tx_ring[entry].status = cpu_to_le32(skb->len | TxDescID);
if (debug > 5) {
- printk(KERN_DEBUG "%s: Tx #%d slot %d %8.8x %8.8x.\n",
- dev->name, np->cur_tx, entry,
- le32_to_cpu(np->tx_ring[entry].status),
- le32_to_cpu(np->tx_ring[entry].addr));
+ printk(KERN_DEBUG "%s: Tx #%d slot %d status %8.8x.\n",
+ dev->name, np->cur_tx, entry,
+ le32_to_cpu(np->tx_ring[entry].status));
}
+
np->cur_tx++;
-#if 1
- if (entry >= TX_RING_SIZE-1) { /* Wrap ring */
- np->tx_ring[entry].status |= cpu_to_le32(TxRingWrap | TxDescIntr);
+
+ if (entry >= TX_RING_SIZE-1) /* Wrap ring */
entry = -1;
- }
-#endif
+ entry++;
/* Non-x86: explicitly flush descriptor cache lines here. */
+ /* Ensure everything is written back above before the transmit is
+ initiated. - Jes */
+ wmb();
/* Update the producer index. */
- writel(++entry, dev->base_addr + TxProducerIdx);
+ writel(entry * (sizeof(struct starfire_tx_desc) / 8), dev->base_addr + TxProducerIdx);
if (np->cur_tx - np->dirty_tx >= TX_RING_SIZE - 1) {
np->tx_full = 1;
netif_stop_queue(dev);
}
+
dev->trans_start = jiffies;
- if (debug > 4) {
- printk(KERN_DEBUG "%s: Transmit frame #%d queued in slot %d.\n",
- dev->name, np->cur_tx, entry);
- }
return 0;
}
@@ -865,24 +1309,25 @@
struct netdev_private *np;
long ioaddr;
int boguscnt = max_interrupt_work;
+ int consumer;
+ int tx_status;
#ifndef final_version /* Can never occur. */
if (dev == NULL) {
- printk (KERN_ERR "Netdev interrupt handler(): IRQ %d for unknown "
- "device.\n", irq);
+ printk (KERN_ERR "Netdev interrupt handler(): IRQ %d for unknown device.\n", irq);
return;
}
#endif
ioaddr = dev->base_addr;
- np = (struct netdev_private *)dev->priv;
+ np = dev->priv;
do {
u32 intr_status = readl(ioaddr + IntrClear);
if (debug > 4)
printk(KERN_DEBUG "%s: Interrupt status %4.4x.\n",
- dev->name, intr_status);
+ dev->name, intr_status);
if (intr_status == 0)
break;
@@ -893,48 +1338,48 @@
/* Scavenge the skbuff list based on the Tx-done queue.
There are redundant checks here that may be cleaned up
after the driver has proven to be reliable. */
- {
- int consumer = readl(ioaddr + TxConsumerIdx);
- int tx_status;
- if (debug > 4)
- printk(KERN_DEBUG "%s: Tx Consumer index is %d.\n",
- dev->name, consumer);
+ consumer = readl(ioaddr + TxConsumerIdx);
+ if (debug > 4)
+ printk(KERN_DEBUG "%s: Tx Consumer index is %d.\n",
+ dev->name, consumer);
#if 0
- if (np->tx_done >= 250 || np->tx_done == 0)
- printk(KERN_DEBUG "%s: Tx completion entry %d is %8.8x, "
- "%d is %8.8x.\n", dev->name,
- np->tx_done, le32_to_cpu(np->tx_done_q[np->tx_done].status),
- (np->tx_done+1) & (DONE_Q_SIZE-1),
- le32_to_cpu(np->tx_done_q[(np->tx_done+1)&(DONE_Q_SIZE-1)].status));
+ if (np->tx_done >= 250 || np->tx_done == 0)
+ printk(KERN_DEBUG "%s: Tx completion entry %d is %8.8x, %d is %8.8x.\n",
+ dev->name, np->tx_done,
+ le32_to_cpu(np->tx_done_q[np->tx_done].status),
+ (np->tx_done+1) & (DONE_Q_SIZE-1),
+ le32_to_cpu(np->tx_done_q[(np->tx_done+1)&(DONE_Q_SIZE-1)].status));
#endif
- while ((tx_status = le32_to_cpu(np->tx_done_q[np->tx_done].status))
- != 0) {
- if (debug > 4)
- printk(KERN_DEBUG "%s: Tx completion entry %d is %8.8x.\n",
- dev->name, np->tx_done, tx_status);
- if ((tx_status & 0xe0000000) == 0xa0000000) {
- np->stats.tx_packets++;
- } else if ((tx_status & 0xe0000000) == 0x80000000) {
- struct sk_buff *skb;
- u16 entry = tx_status; /* Implicit truncate */
- entry >>= 3;
-
- skb = np->tx_info[entry].skb;
- pci_unmap_single(np->pci_dev,
- np->tx_info[entry].mapping,
- skb->len, PCI_DMA_TODEVICE);
-
- /* Scavenge the descriptor. */
- dev_kfree_skb_irq(skb);
- np->tx_info[entry].skb = NULL;
- np->tx_info[entry].mapping = 0;
- np->dirty_tx++;
- }
- np->tx_done_q[np->tx_done].status = 0;
- np->tx_done = (np->tx_done+1) & (DONE_Q_SIZE-1);
+
+ while ((tx_status = le32_to_cpu(np->tx_done_q[np->tx_done].status)) != 0) {
+ if (debug > 4)
+ printk(KERN_DEBUG "%s: Tx completion entry %d is %8.8x.\n",
+ dev->name, np->tx_done, tx_status);
+ if ((tx_status & 0xe0000000) == 0xa0000000) {
+ np->stats.tx_packets++;
+ } else if ((tx_status & 0xe0000000) == 0x80000000) {
+ struct sk_buff *skb;
+ u16 entry = tx_status; /* Implicit truncate */
+ entry /= sizeof(struct starfire_tx_desc);
+
+ skb = np->tx_info[entry].skb;
+ np->tx_info[entry].skb = NULL;
+ pci_unmap_single(np->pci_dev,
+ np->tx_info[entry].first_mapping,
+ skb_first_frag_len(skb),
+ PCI_DMA_TODEVICE);
+ np->tx_info[entry].first_mapping = 0;
+
+ /* Scavenge the descriptor. */
+ dev_kfree_skb_irq(skb);
+
+ np->dirty_tx++;
}
- writew(np->tx_done, ioaddr + CompletionQConsumerIdx + 2);
+ np->tx_done_q[np->tx_done].status = 0;
+ np->tx_done = (np->tx_done+1) & (DONE_Q_SIZE-1);
}
+ writew(np->tx_done, ioaddr + CompletionQConsumerIdx + 2);
+
if (np->tx_full && np->cur_tx - np->dirty_tx < TX_RING_SIZE - 4) {
/* The ring is no longer full, wake the queue. */
np->tx_full = 0;
@@ -947,23 +1392,23 @@
if (--boguscnt < 0) {
printk(KERN_WARNING "%s: Too much work at interrupt, "
- "status=0x%4.4x.\n",
- dev->name, intr_status);
+ "status=0x%4.4x.\n",
+ dev->name, intr_status);
break;
}
} while (1);
if (debug > 4)
printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
- dev->name, (int)readl(ioaddr + IntrStatus));
+ dev->name, (int)readl(ioaddr + IntrStatus));
#ifndef final_version
/* Code that should never be run! Remove after testing.. */
{
static int stopit = 10;
- if (!netif_running(dev) && --stopit < 0) {
+ if (!netif_running(dev) && --stopit < 0) {
printk(KERN_ERR "%s: Emergency stop, looping startup interrupt.\n",
- dev->name);
+ dev->name);
free_irq(irq, dev);
}
}
@@ -974,97 +1419,105 @@
for clarity and better register allocation. */
static int netdev_rx(struct net_device *dev)
{
- struct netdev_private *np = (struct netdev_private *)dev->priv;
+ struct netdev_private *np = dev->priv;
int boguscnt = np->dirty_rx + RX_RING_SIZE - np->cur_rx;
u32 desc_status;
if (np->rx_done_q == 0) {
printk(KERN_ERR "%s: rx_done_q is NULL! rx_done is %d. %p.\n",
- dev->name, np->rx_done, np->tx_done_q);
+ dev->name, np->rx_done, np->tx_done_q);
return 0;
}
/* If EOP is set on the next entry, it's a new packet. Send it up. */
while ((desc_status = le32_to_cpu(np->rx_done_q[np->rx_done].status)) != 0) {
+ struct sk_buff *skb;
+ u16 pkt_len;
+ int entry;
+
if (debug > 4)
- printk(KERN_DEBUG " netdev_rx() status of %d was %8.8x.\n",
- np->rx_done, desc_status);
+ printk(KERN_DEBUG " netdev_rx() status of %d was %8.8x.\n", np->rx_done, desc_status);
if (--boguscnt < 0)
break;
if ( ! (desc_status & RxOK)) {
/* There was a error. */
if (debug > 2)
- printk(KERN_DEBUG " netdev_rx() Rx error was %8.8x.\n",
- desc_status);
+ printk(KERN_DEBUG " netdev_rx() Rx error was %8.8x.\n", desc_status);
np->stats.rx_errors++;
if (desc_status & RxFIFOErr)
np->stats.rx_fifo_errors++;
- } else {
- struct sk_buff *skb;
- u16 pkt_len = desc_status; /* Implicitly Truncate */
- int entry = (desc_status >> 16) & 0x7ff;
+ goto next_rx;
+ }
+
+ pkt_len = desc_status; /* Implicitly Truncate */
+ entry = (desc_status >> 16) & 0x7ff;
#ifndef final_version
- if (debug > 4)
- printk(KERN_DEBUG " netdev_rx() normal Rx pkt length %d"
- ", bogus_cnt %d.\n",
- pkt_len, boguscnt);
+ if (debug > 4)
+ printk(KERN_DEBUG " netdev_rx() normal Rx pkt length %d, bogus_cnt %d.\n", pkt_len, boguscnt);
#endif
- /* Check if the packet is long enough to accept without copying
- to a minimally-sized skbuff. */
- if (pkt_len < rx_copybreak
- && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
- skb->dev = dev;
- skb_reserve(skb, 2); /* 16 byte align the IP header */
- pci_dma_sync_single(np->pci_dev,
- np->rx_info[entry].mapping,
- pkt_len, PCI_DMA_FROMDEVICE);
+ /* Check if the packet is long enough to accept without copying
+ to a minimally-sized skbuff. */
+ if (pkt_len < rx_copybreak
+ && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+ skb->dev = dev;
+ skb_reserve(skb, 2); /* 16 byte align the IP header */
+ pci_dma_sync_single(np->pci_dev,
+ np->rx_info[entry].mapping,
+ pkt_len, PCI_DMA_FROMDEVICE);
#if HAS_IP_COPYSUM /* Call copy + cksum if available. */
- eth_copy_and_sum(skb, np->rx_info[entry].skb->tail, pkt_len, 0);
- skb_put(skb, pkt_len);
+ eth_copy_and_sum(skb, np->rx_info[entry].skb->tail, pkt_len, 0);
+ skb_put(skb, pkt_len);
#else
- memcpy(skb_put(skb, pkt_len), np->rx_info[entry].skb->tail,
- pkt_len);
+ memcpy(skb_put(skb, pkt_len), np->rx_info[entry].skb->tail, pkt_len);
#endif
- } else {
- char *temp;
+ } else {
+ char *temp;
- pci_unmap_single(np->pci_dev, np->rx_info[entry].mapping, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
- skb = np->rx_info[entry].skb;
- temp = skb_put(skb, pkt_len);
- np->rx_info[entry].skb = NULL;
- np->rx_info[entry].mapping = 0;
-#ifndef final_version /* Remove after testing. */
- if (le32_to_cpu(np->rx_ring[entry].rxaddr & ~3) != ((unsigned long) temp))
- printk(KERN_ERR "%s: Internal fault: The skbuff addresses "
- "do not match in netdev_rx: %d vs. %p / %p.\n",
- dev->name,
- le32_to_cpu(np->rx_ring[entry].rxaddr),
- skb->head, temp);
-#endif
- }
-#ifndef final_version /* Remove after testing. */
- /* You will want this info for the initial debug. */
- if (debug > 5)
- printk(KERN_DEBUG " Rx data %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:"
- "%2.2x %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x %2.2x%2.2x "
- "%d.%d.%d.%d.\n",
- skb->data[0], skb->data[1], skb->data[2], skb->data[3],
- skb->data[4], skb->data[5], skb->data[6], skb->data[7],
- skb->data[8], skb->data[9], skb->data[10],
- skb->data[11], skb->data[12], skb->data[13],
- skb->data[14], skb->data[15], skb->data[16],
- skb->data[17]);
-#endif
- skb->protocol = eth_type_trans(skb, dev);
-#ifdef full_rx_status
- if (le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0x01000000)
- skb->ip_summed = CHECKSUM_UNNECESSARY;
+ pci_unmap_single(np->pci_dev, np->rx_info[entry].mapping, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
+ skb = np->rx_info[entry].skb;
+ temp = skb_put(skb, pkt_len);
+ np->rx_info[entry].skb = NULL;
+ np->rx_info[entry].mapping = 0;
+ }
+#ifndef final_version /* Remove after testing. */
+ /* You will want this info for the initial debug. */
+ if (debug > 5)
+ printk(KERN_DEBUG " Rx data %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:"
+ "%2.2x %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x %2.2x%2.2x "
+ "%d.%d.%d.%d.\n",
+ skb->data[0], skb->data[1], skb->data[2], skb->data[3],
+ skb->data[4], skb->data[5], skb->data[6], skb->data[7],
+ skb->data[8], skb->data[9], skb->data[10],
+ skb->data[11], skb->data[12], skb->data[13],
+ skb->data[14], skb->data[15], skb->data[16],
+ skb->data[17]);
#endif
- netif_rx(skb);
- dev->last_rx = jiffies;
- np->stats.rx_packets++;
+ skb->protocol = eth_type_trans(skb, dev);
+#if defined(full_rx_status) || defined(csum_rx_status)
+ if (le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0x01000000) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
}
+ /*
+ * This feature doesn't seem to be working, at least
+ * with the two firmware versions I have. If the GFP sees
+ * a fragment, it either ignores it completely, or reports
+ * "bad checksum" on it.
+ *
+ * Maybe I missed something -- corrections are welcome.
+ * Until then, the printk stays. :-) -Ion
+ */
+ else if (le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0x00400000) {
+ skb->ip_summed = CHECKSUM_HW;
+ skb->csum = le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0xffff;
+ printk(KERN_DEBUG "%s: checksum_hw, status2 = %x\n", dev->name, np->rx_done_q[np->rx_done].status2);
+ }
+#endif
+ netif_rx(skb);
+ dev->last_rx = jiffies;
+ np->stats.rx_packets++;
+
+next_rx:
np->cur_rx++;
np->rx_done_q[np->rx_done].status = 0;
np->rx_done = (np->rx_done + 1) & (DONE_Q_SIZE-1);
@@ -1079,10 +1532,10 @@
skb = dev_alloc_skb(np->rx_buf_sz);
np->rx_info[entry].skb = skb;
if (skb == NULL)
- break; /* Better luck next round. */
+ break; /* Better luck next round. */
np->rx_info[entry].mapping =
pci_map_single(np->pci_dev, skb->tail, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
- skb->dev = dev; /* Mark as being used by this device. */
+ skb->dev = dev; /* Mark as being used by this device. */
np->rx_ring[entry].rxaddr =
cpu_to_le32(np->rx_info[entry].mapping | RxDescValid);
}
@@ -1093,10 +1546,10 @@
}
if (debug > 5
- || memcmp(np->pad0, np->pad0 + 1, sizeof(np->pad0) -1))
+ || memcmp(np->pad0, np->pad0 + 1, sizeof(np->pad0) -1))
printk(KERN_DEBUG " exiting netdev_rx() status of %d was %8.8x %d.\n",
- np->rx_done, desc_status,
- memcmp(np->pad0, np->pad0 + 1, sizeof(np->pad0) -1));
+ np->rx_done, desc_status,
+ memcmp(np->pad0, np->pad0 + 1, sizeof(np->pad0) -1));
/* Restart Rx engine if stopped. */
return 0;
@@ -1104,36 +1557,36 @@
static void netdev_error(struct net_device *dev, int intr_status)
{
- struct netdev_private *np = (struct netdev_private *)dev->priv;
+ struct netdev_private *np = dev->priv;
- if (intr_status & LinkChange) {
+ if (intr_status & IntrLinkChange) {
printk(KERN_NOTICE "%s: Link changed: Autonegotiation advertising"
- " %4.4x partner %4.4x.\n", dev->name,
- mdio_read(dev, np->phys[0], 4),
- mdio_read(dev, np->phys[0], 5));
+ " %4.4x, partner %4.4x.\n", dev->name,
+ mdio_read(dev, np->phys[0], 4),
+ mdio_read(dev, np->phys[0], 5));
check_duplex(dev, 0);
}
- if (intr_status & StatsMax) {
+ if (intr_status & IntrStatsMax) {
get_stats(dev);
}
/* Came close to underrunning the Tx FIFO, increase threshold. */
- if (intr_status & IntrTxDataLow)
+ if (intr_status & IntrTxDataLow) {
writel(++np->tx_threshold, dev->base_addr + TxThreshold);
- if ((intr_status &
- ~(IntrAbnormalSummary|LinkChange|StatsMax|IntrTxDataLow|1)) && debug)
+ printk(KERN_NOTICE "%s: Increasing Tx FIFO threshold to %d bytes\n",
+ dev->name, np->tx_threshold * 16);
+ }
+ if ((intr_status & ~(IntrNormalMask | IntrAbnormalSummary | IntrLinkChange | IntrStatsMax | IntrTxDataLow | IntrPCIPad)) && debug)
printk(KERN_ERR "%s: Something Wicked happened! %4.4x.\n",
- dev->name, intr_status);
- /* Hmmmmm, it's not clear how to recover from PCI faults. */
- if (intr_status & IntrTxPCIErr)
+ dev->name, intr_status);
+ /* Hmmmmm, it's not clear how to recover from DMA faults. */
+ if (intr_status & IntrDMAErr)
np->stats.tx_fifo_errors++;
- if (intr_status & IntrRxPCIErr)
- np->stats.rx_fifo_errors++;
}
static struct net_device_stats *get_stats(struct net_device *dev)
{
long ioaddr = dev->base_addr;
- struct netdev_private *np = (struct netdev_private *)dev->priv;
+ struct netdev_private *np = dev->priv;
/* This adapter architecture needs no SMP locks. */
np->stats.tx_bytes = readl(ioaddr + 0x57010);
@@ -1142,12 +1595,13 @@
np->stats.tx_aborted_errors =
readl(ioaddr + 0x57024) + readl(ioaddr + 0x57028);
np->stats.tx_window_errors = readl(ioaddr + 0x57018);
- np->stats.collisions = readl(ioaddr + 0x57004) + readl(ioaddr + 0x57008);
+ np->stats.collisions =
+ readl(ioaddr + 0x57004) + readl(ioaddr + 0x57008);
/* The chip only need report frame silently dropped. */
- np->stats.rx_dropped += readw(ioaddr + RxDMAStatus);
+ np->stats.rx_dropped += readw(ioaddr + RxDMAStatus);
writew(0, ioaddr + RxDMAStatus);
- np->stats.rx_crc_errors = readl(ioaddr + 0x5703C);
+ np->stats.rx_crc_errors = readl(ioaddr + 0x5703C);
np->stats.rx_frame_errors = readl(ioaddr + 0x57040);
np->stats.rx_length_errors = readl(ioaddr + 0x57058);
np->stats.rx_missed_errors = readl(ioaddr + 0x5707C);
@@ -1188,19 +1642,19 @@
struct dev_mc_list *mclist;
int i;
- if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */
+ if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */
/* Unconditionally log net taps. */
printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name);
rx_mode = AcceptBroadcast|AcceptAllMulticast|AcceptAll|AcceptMyPhys;
} else if ((dev->mc_count > multicast_filter_limit)
- || (dev->flags & IFF_ALLMULTI)) {
+ || (dev->flags & IFF_ALLMULTI)) {
/* Too many to match, or accept all multicasts. */
rx_mode = AcceptBroadcast|AcceptAllMulticast|AcceptMyPhys;
} else if (dev->mc_count <= 15) {
/* Use the 16 element perfect filter. */
long filter_addr = ioaddr + 0x56000 + 1*16;
- for (i = 1, mclist = dev->mc_list; mclist && i <= dev->mc_count;
- i++, mclist = mclist->next) {
+ for (i = 1, mclist = dev->mc_list; mclist && i <= dev->mc_count;
+ i++, mclist = mclist->next) {
u16 *eaddrs = (u16 *)mclist->dmi_addr;
writew(cpu_to_be16(eaddrs[2]), filter_addr); filter_addr += 4;
writew(cpu_to_be16(eaddrs[1]), filter_addr); filter_addr += 4;
@@ -1219,7 +1673,7 @@
memset(mc_filter, 0, sizeof(mc_filter));
for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
- i++, mclist = mclist->next) {
+ i++, mclist = mclist->next) {
set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 23, mc_filter);
}
/* Clear the perfect filter list. */
@@ -1238,7 +1692,7 @@
static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
- struct netdev_private *np = (struct netdev_private *)dev->priv;
+ struct netdev_private *np = dev->priv;
u16 *data = (u16 *)&rq->ifr_data;
switch(cmd) {
@@ -1276,10 +1730,11 @@
static int netdev_close(struct net_device *dev)
{
long ioaddr = dev->base_addr;
- struct netdev_private *np = (struct netdev_private *)dev->priv;
+ struct netdev_private *np = dev->priv;
int i;
netif_stop_queue(dev);
+ netif_stop_if(dev);
del_timer_sync(&np->timer);
@@ -1301,15 +1756,15 @@
np->tx_ring_dma);
for (i = 0; i < 8 /* TX_RING_SIZE is huge! */; i++)
printk(KERN_DEBUG " #%d desc. %8.8x %8.8x -> %8.8x.\n",
- i, le32_to_cpu(np->tx_ring[i].status),
- le32_to_cpu(np->tx_ring[i].addr),
- le32_to_cpu(np->tx_done_q[i].status));
+ i, le32_to_cpu(np->tx_ring[i].status),
+ le32_to_cpu(np->tx_ring[i].first_addr),
+ le32_to_cpu(np->tx_done_q[i].status));
printk(KERN_DEBUG " Rx ring at %8.8x -> %p:\n",
- np->rx_ring_dma, np->rx_done_q);
+ np->rx_ring_dma, np->rx_done_q);
if (np->rx_done_q)
for (i = 0; i < 8 /* RX_RING_SIZE */; i++) {
printk(KERN_DEBUG " #%d desc. %8.8x -> %8.8x\n",
- i, le32_to_cpu(np->rx_ring[i].rxaddr), le32_to_cpu(np->rx_done_q[i].status));
+ i, le32_to_cpu(np->rx_ring[i].rxaddr), le32_to_cpu(np->rx_done_q[i].status));
}
}
#endif /* __i386__ debugging only */
@@ -1328,17 +1783,17 @@
}
for (i = 0; i < TX_RING_SIZE; i++) {
struct sk_buff *skb = np->tx_info[i].skb;
- if (skb != NULL) {
- pci_unmap_single(np->pci_dev,
- np->tx_info[i].mapping,
- skb->len, PCI_DMA_TODEVICE);
- dev_kfree_skb(skb);
- }
+ if (skb == NULL)
+ continue;
+ pci_unmap_single(np->pci_dev,
+ np->tx_info[i].first_mapping,
+ skb_first_frag_len(skb), PCI_DMA_TODEVICE);
+ np->tx_info[i].first_mapping = 0;
+ dev_kfree_skb(skb);
np->tx_info[i].skb = NULL;
- np->tx_info[i].mapping = 0;
}
- MOD_DEC_USE_COUNT;
+ COMPAT_MOD_DEC_USE_COUNT;
return 0;
}
@@ -1346,9 +1801,9 @@
static void __devexit starfire_remove_one (struct pci_dev *pdev)
{
- struct net_device *dev = pdev->driver_data;
+ struct net_device *dev = pci_get_drvdata(pdev);
struct netdev_private *np;
-
+
if (!dev)
BUG();
@@ -1356,6 +1811,7 @@
unregister_netdev(dev);
iounmap((char *)dev->base_addr);
+ pci_release_regions(pdev);
if (np->tx_done_q)
pci_free_consistent(np->pci_dev, PAGE_SIZE,
@@ -1371,6 +1827,8 @@
np->rx_ring, np->rx_ring_dma);
kfree(dev);
+
+ pci_set_drvdata(pdev, NULL);
}
@@ -1402,8 +1860,7 @@
* Local variables:
* compile-command: "gcc -DMODULE -Wall -Wstrict-prototypes -O6 -c starfire.c"
* simple-compile-command: "gcc -DMODULE -O6 -c starfire.c"
- * c-indent-level: 4
- * c-basic-offset: 4
- * tab-width: 4
+ * c-basic-offset: 8
+ * tab-width: 8
* End:
*/
Ion wrote:
> On Thu, 19 Apr 2001 21:14:32 +0100 (BST), Alan Cox <[email protected]> wrote:
>
> > 2.4.3-ac10
> > o Merge Linus 2.4.4pre4
>
> Well, it seems you have backed out my starfire changes when you merged
> Jeff Garzik's changes from 2.4.4pre4. So here's a new version, diff'ed
> against 2.4.3-ac10, which includes all of Jeff's changes from 2.4.3pre[45].
>
> BTW Jeff, do you want me to send these updates to you instead of Alan,
> diff'ed against 2.4.x-pre_latest? Right now we're just wasting each
> other's time by making conflicting changes to different trees.
I should have gotten off my butt and mentioned this... I would prefer a
patch without the 2.2.x compat stuff. So instead of all that compat
code, have
#include "starfire-2.2.h"
or similar...
And then starfire-2.2.h would only exist on 2.2.x.
--
Jeff Garzik | "The universe is like a safe to which there is a
Building 1024 | combination -- but the combination is locked up
MandrakeSoft | in the safe." -- Peter DeVries
On Thu, 19 Apr 2001, Jeff Garzik wrote:
> I should have gotten off my butt and mentioned this... I would prefer a
> patch without the 2.2.x compat stuff. So instead of all that compat
> code, have
> #include "starfire-2.2.h"
> or similar...
>
> And then starfire-2.2.h would only exist on 2.2.x.
Hard to please, aren't we. :-)
All right, is this version more pleasant to the eye? It's identical to the
previous one, but with all the 2.2 ifdef'ed code replaced with an #include
"starfire-kcomp22.h".
[Now of course starfire-kcomp22.h doesn't exist on 2.4, which -- if you
stick to your own principles from 2 months ago -- will naturally lead to
the question, what is this doing in the tree, it's referencing code that
doesn't exist in the tree, etc, etc. And round and round we go again. :-{
Or maybe not. Hopefully...]
Thanks,
Ion
--
It is better to keep your mouth shut and be thought a fool,
than to open it and remove all doubt.
-----------------------
--- /mnt/3/linux-2.4-ac/drivers/net/starfire.c Thu Apr 19 15:58:57 2001
+++ linux-2.4/drivers/net/starfire.c Thu Apr 19 21:39:24 2001
@@ -20,7 +20,7 @@
-----------------------------------------------------------
Linux kernel-specific changes:
-
+
LK1.1.1 (jgarzik):
- Use PCI driver interface
- Fix MOD_xxx races
@@ -31,9 +31,45 @@
LK1.1.3 (Andrew Morton)
- Timer cleanups
-
+
LK1.1.4 (jgarzik):
- Merge Becker version 1.03
+
+ LK1.2.1 (Ion Badulescu <[email protected]>)
+ - Support hardware Rx/Tx checksumming
+ - Use the GFP firmware taken from Adaptec's Netware driver
+
+ LK1.2.2 (Ion Badulescu)
+ - Backported to 2.2.x
+
+ LK1.2.3 (Ion Badulescu)
+ - Fix the flaky mdio interface
+ - More compat clean-ups
+
+ LK1.2.4 (Ion Badulescu)
+ - More 2.2.x initialization fixes
+
+ LK1.2.5 (Ion Badulescu)
+ - Several fixes from Manfred Spraul
+
+ LK1.2.6 (Ion Badulescu)
+ - Fixed ifup/ifdown/ifup problem in 2.4.x
+
+ LK1.2.7 (Ion Badulescu)
+ - Removed unused code
+ - Made more functions static and __init
+
+ LK1.2.8 (Ion Badulescu)
+ - Quell bogus error messages, inform about the Tx threshold
+ - Removed #ifdef CONFIG_PCI, this driver is PCI only
+
+ LK1.2.9 (Ion Badulescu)
+ - Merged Jeff Garzik's changes from 2.4.4-pre5
+ - Added 2.2.x compatibility stuff required by the above changes
+
+TODO:
+ - implement tx_timeout() properly
+ - support ethtool
*/
/* These identify the driver base version and may not be removed. */
@@ -43,24 +79,60 @@
" Updates and info at http://www.scyld.com/network/starfire.html\n";
static const char version3[] =
-" (unofficial 2.4.x kernel port, version 1.1.4, August 10, 2000)\n";
+" (unofficial 2.4.x kernel port, version 1.2.9, April 19, 2001)\n";
+
+/*
+ * Adaptec's license for their Novell drivers (which is where I got the
+ * firmware files) does not allow one to redistribute them. Thus, we can't
+ * include the firmware with this driver.
+ *
+ * However, an end-user is allowed to download and use it, after
+ * converting it to C header files using starfire_firmware.pl.
+ * Once that's done, the #undef must be changed into a #define
+ * for this driver to really use the firmware. Note that Rx/Tx
+ * hardware TCP checksumming is not possible without the firmware.
+ *
+ * I'm currently [Feb 2001] talking to Adaptec about this redistribution
+ * issue. Stay tuned...
+ */
+#undef HAS_FIRMWARE
+/*
+ * The current frame processor firmware fails to checksum a fragment
+ * of length 1. If and when this is fixed, the #define below can be removed.
+ */
+#define HAS_BROKEN_FIRMWARE
/* The user-configurable values.
These may be modified when a driver module is loaded.*/
/* Used for tuning interrupt latency vs. overhead. */
-static int interrupt_mitigation = 0x0;
+static int interrupt_mitigation;
static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */
static int max_interrupt_work = 20;
-static int mtu = 0;
+static int mtu;
/* Maximum number of multicast addresses to filter (vs. rx-all-multicast).
- The Starfire has a 512 element hash table based on the Ethernet CRC. */
-static int multicast_filter_limit = 32;
+ The Starfire has a 512 element hash table based on the Ethernet CRC. */
+static int multicast_filter_limit = 512;
-/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
- Setting to > 1518 effectively disables this feature. */
+#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
+/*
+ * Set the copy breakpoint for the copy-only-tiny-frames scheme.
+ * Setting to > 1518 effectively disables this feature.
+ *
+ * NOTE:
+ * The ia64 doesn't allow for unaligned loads even of integers being
+ * misaligned on a 2 byte boundary. Thus always force copying of
+ * packets as the starfire doesn't allow for misaligned DMAs ;-(
+ * 23/10/2000 - Jes
+ *
+ * The Alpha and the Sparc don't allow unaligned loads, either. -Ion
+ */
+#if defined(__ia64__) || defined(__alpha__) || defined(__sparc__)
+static int rx_copybreak = PKT_BUF_SZ;
+#else
static int rx_copybreak = 0;
+#endif
/* Used to pass the media type, etc.
Both 'options[]' and 'full_duplex[]' exist for driver interoperability.
@@ -84,9 +156,9 @@
/* Operational parameters that usually are not changed. */
/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT (2*HZ)
+#define TX_TIMEOUT (2*HZ)
-#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
+#define skb_first_frag_len(skb) (skb->len)
#if !defined(__OPTIMIZE__)
#warning You must compile this file with the correct options!
@@ -94,32 +166,36 @@
#error You must compile this driver with "-O".
#endif
-/* Include files, designed to support most kernel versions 2.0.0 and later. */
#include <linux/version.h>
#include <linux/module.h>
-
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/errno.h>
#include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/init.h>
+#include <linux/delay.h>
#include <asm/processor.h> /* Processor type for cache alignment. */
#include <asm/bitops.h>
#include <asm/io.h>
+#ifdef HAS_FIRMWARE
+#include "starfire_firmware.h"
+#endif /* HAS_FIRMWARE */
+
MODULE_AUTHOR("Donald Becker <[email protected]>");
MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver");
MODULE_PARM(max_interrupt_work, "i");
MODULE_PARM(mtu, "i");
MODULE_PARM(debug, "i");
MODULE_PARM(rx_copybreak, "i");
+MODULE_PARM(interrupt_mitigation, "i");
MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
@@ -152,8 +228,9 @@
See the Adaptec manual for the many possible structures, and options for
each structure. There are far too many to document here.
-For transmit this driver uses type 1 transmit descriptors, and relies on
-automatic minimum-length padding. It does not use the completion queue
+For transmit this driver uses type 0/1 transmit descriptors (depending
+on the presence of the zerocopy patches), and relies on automatic
+minimum-length padding. It does not use the completion queue
consumer index, but instead checks for non-zero status entries.
For receive this driver uses type 0 receive descriptors. The driver
@@ -170,8 +247,9 @@
A notable aspect of operation is that unaligned buffers are not permitted by
the Starfire hardware. The IP header at offset 14 in an ethernet frame thus
isn't longword aligned, which may cause problems on some machine
-e.g. Alphas. Copied frames are put into the skbuff at an offset of "+2",
-16-byte aligning the IP header.
+e.g. Alphas and IA64. For these architectures, the driver is forced to copy
+the frame into a new skbuff unconditionally. Copied frames are put into the
+skbuff at an offset of "+2", thus 16-byte aligning the IP header.
IIId. Synchronization
@@ -204,6 +282,28 @@
+/* 2.2.x compatibility code */
+#if LINUX_VERSION_CODE < 0x20300
+
+#include "starfire-kcomp-2.2.h"
+
+#else /* LINUX_VERSION_CODE > 0x20300 */
+
+#define COMPAT_MOD_INC_USE_COUNT
+#define COMPAT_MOD_DEC_USE_COUNT
+
+#define init_tx_timer(dev, func, timeout) \
+ dev->tx_timeout = func; \
+ dev->watchdog_timeo = timeout;
+#define kick_tx_timer(dev, func, timeout)
+
+#define netif_start_if(dev)
+#define netif_stop_if(dev)
+
+#endif /* LINUX_VERSION_CODE > 0x20300 */
+/* end of compatibility code */
+
+
enum chip_capability_flags {CanHaveMII=1, };
#define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_MEM | PCI_ADDR0)
#define MEM_ADDR_SZ 0x80000 /* And maps in 0.5MB(!). */
@@ -253,19 +353,32 @@
TxThreshold=0x500B0,
CompletionHiAddr=0x500B4, TxCompletionAddr=0x500B8,
RxCompletionAddr=0x500BC, RxCompletionQ2Addr=0x500C0,
- CompletionQConsumerIdx=0x500C4,
+ CompletionQConsumerIdx=0x500C4, RxDMACtrl=0x500D0,
RxDescQCtrl=0x500D4, RxDescQHiAddr=0x500DC, RxDescQAddr=0x500E0,
RxDescQIdx=0x500E8, RxDMAStatus=0x500F0, RxFilterMode=0x500F4,
- TxMode=0x55000,
+ TxMode=0x55000, TxGfpMem=0x58000, RxGfpMem=0x5a000,
};
/* Bits in the interrupt status/mask registers. */
enum intr_status_bits {
- IntrNormalSummary=0x8000, IntrAbnormalSummary=0x02000000,
- IntrRxDone=0x0300, IntrRxEmpty=0x10040, IntrRxPCIErr=0x80000,
- IntrTxDone=0x4000, IntrTxEmpty=0x1000, IntrTxPCIErr=0x80000,
- StatsMax=0x08000000, LinkChange=0xf0000000,
- IntrTxDataLow=0x00040000,
+ IntrLinkChange=0xf0000000, IntrStatsMax=0x08000000,
+ IntrAbnormalSummary=0x02000000, IntrGeneralTimer=0x01000000,
+ IntrSoftware=0x800000, IntrRxComplQ1Low=0x400000,
+ IntrTxComplQLow=0x200000, IntrPCI=0x100000,
+ IntrDMAErr=0x080000, IntrTxDataLow=0x040000,
+ IntrRxComplQ2Low=0x020000, IntrRxDescQ1Low=0x010000,
+ IntrNormalSummary=0x8000, IntrTxDone=0x4000,
+ IntrTxDMADone=0x2000, IntrTxEmpty=0x1000,
+ IntrEarlyRxQ2=0x0800, IntrEarlyRxQ1=0x0400,
+ IntrRxQ2Done=0x0200, IntrRxQ1Done=0x0100,
+ IntrRxGFPDead=0x80, IntrRxDescQ2Low=0x40,
+ IntrNoTxCsum=0x20, IntrTxBadID=0x10,
+ IntrHiPriTxBadID=0x08, IntrRxGfp=0x04,
+ IntrTxGfp=0x02, IntrPCIPad=0x01,
+ /* not quite bits */
+ IntrRxDone=IntrRxQ2Done | IntrRxQ1Done,
+ IntrRxEmpty=IntrRxDescQ1Low | IntrRxDescQ2Low,
+ IntrNormalMask=0xf0, IntrAbnormalMask=0x3f0e,
};
/* Bits in the RxFilterMode register. */
@@ -274,9 +387,40 @@
AcceptMulticast=0x10, AcceptMyPhys=0xE040,
};
+/* Bits in the TxDescCtrl register. */
+enum tx_ctrl_bits {
+ TxDescSpaceUnlim=0x00, TxDescSpace32=0x10, TxDescSpace64=0x20,
+ TxDescSpace128=0x30, TxDescSpace256=0x40,
+ TxDescType0=0x00, TxDescType1=0x01, TxDescType2=0x02,
+ TxDescType3=0x03, TxDescType4=0x04,
+ TxNoDMACompletion=0x08, TxDescQ64bit=0x80,
+ TxHiPriFIFOThreshShift=24, TxPadLenShift=16,
+ TxDMABurstSizeShift=8,
+};
+
+/* Bits in the RxDescQCtrl register. */
+enum rx_ctrl_bits {
+ RxBufferLenShift=16, RxMinDescrThreshShift=0,
+ RxPrefetchMode=0x8000, Rx2048QEntries=0x4000,
+ RxVariableQ=0x2000, RxDesc64bit=0x1000,
+ RxDescQAddr64bit=0x0100,
+ RxDescSpace4=0x000, RxDescSpace8=0x100,
+ RxDescSpace16=0x200, RxDescSpace32=0x300,
+ RxDescSpace64=0x400, RxDescSpace128=0x500,
+ RxConsumerWrEn=0x80,
+};
+
+/* Bits in the RxCompletionAddr register */
+enum rx_compl_bits {
+ RxComplQAddr64bit=0x80, TxComplProducerWrEn=0x40,
+ RxComplType0=0x00, RxComplType1=0x10,
+ RxComplType2=0x20, RxComplType3=0x30,
+ RxComplThreshShift=0,
+};
+
/* The Rx and Tx buffer descriptors. */
struct starfire_rx_desc {
- u32 rxaddr; /* Optionally 64 bits. */
+ u32 rxaddr; /* Optionally 64 bits. */
};
enum rx_desc_bits {
RxDescValid=1, RxDescEndRing=2,
@@ -285,14 +429,20 @@
/* Completion queue entry.
You must update the page allocation, init_ring and the shift count in rx()
if using a larger format. */
+#ifdef HAS_FIRMWARE
+#define csum_rx_status
+#endif /* HAS_FIRMWARE */
struct rx_done_desc {
- u32 status; /* Low 16 bits is length. */
+ u32 status; /* Low 16 bits is length. */
+#ifdef csum_rx_status
+ u32 status2; /* Low 16 bits is csum */
+#endif /* csum_rx_status */
#ifdef full_rx_status
u32 status2;
u16 vlanid;
- u16 csum; /* partial checksum */
+ u16 csum; /* partial checksum */
u32 timestamp;
-#endif
+#endif /* full_rx_status */
};
enum rx_done_bits {
RxOK=0x20000000, RxFIFOErr=0x10000000, RxBufQ2=0x08000000,
@@ -300,26 +450,31 @@
/* Type 1 Tx descriptor. */
struct starfire_tx_desc {
- u32 status; /* Upper bits are status, lower 16 length. */
- u32 addr;
+ u32 status; /* Upper bits are status, lower 16 length. */
+ u32 first_addr;
};
enum tx_desc_bits {
- TxDescID=0xB1010000, /* Also marks single fragment, add CRC. */
- TxDescIntr=0x08000000, TxRingWrap=0x04000000,
+ TxDescID=0xB0000000,
+ TxCRCEn=0x01000000, TxDescIntr=0x08000000,
+ TxRingWrap=0x04000000, TxCalTCP=0x02000000,
};
struct tx_done_report {
- u32 status; /* timestamp, index. */
+ u32 status; /* timestamp, index. */
#if 0
- u32 intrstatus; /* interrupt status */
+ u32 intrstatus; /* interrupt status */
#endif
};
-#define PRIV_ALIGN 15 /* Required alignment mask */
-struct ring_info {
+struct rx_ring_info {
struct sk_buff *skb;
dma_addr_t mapping;
};
+struct tx_ring_info {
+ struct sk_buff *skb;
+ dma_addr_t first_mapping;
+};
+#define MII_CNT 2
struct netdev_private {
/* Descriptor rings first for alignment. */
struct starfire_rx_desc *rx_ring;
@@ -327,8 +482,8 @@
dma_addr_t rx_ring_dma;
dma_addr_t tx_ring_dma;
/* The addresses of rx/tx-in-place skbuffs. */
- struct ring_info rx_info[RX_RING_SIZE];
- struct ring_info tx_info[TX_RING_SIZE];
+ struct rx_ring_info rx_info[RX_RING_SIZE];
+ struct tx_ring_info tx_info[TX_RING_SIZE];
/* Pointers to completion queues (full pages). I should cache line pad..*/
u8 pad0[100];
struct rx_done_desc *rx_done_q;
@@ -341,84 +496,86 @@
struct timer_list timer; /* Media monitoring timer. */
struct pci_dev *pci_dev;
/* Frequently used values: keep some adjacent for cache effect. */
- unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */
+ unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */
unsigned int cur_tx, dirty_tx;
- unsigned int rx_buf_sz; /* Based on MTU+slack. */
- unsigned int tx_full:1; /* The Tx queue is full. */
+ unsigned int rx_buf_sz; /* Based on MTU+slack. */
+ unsigned int tx_full:1; /* The Tx queue is full. */
/* These values are keep track of the transceiver/media in use. */
- unsigned int full_duplex:1, /* Full-duplex operation requested. */
- medialock:1, /* Xcvr set to fixed speed/duplex. */
+ unsigned int full_duplex:1, /* Full-duplex operation requested. */
+ medialock:1, /* Xcvr set to fixed speed/duplex. */
rx_flowctrl:1,
- tx_flowctrl:1; /* Use 802.3x flow control. */
- unsigned int default_port:4; /* Last dev->if_port value. */
+ tx_flowctrl:1; /* Use 802.3x flow control. */
+ unsigned int default_port:4; /* Last dev->if_port value. */
u32 tx_mode;
u8 tx_threshold;
/* MII transceiver section. */
- int mii_cnt; /* MII device addresses. */
- u16 advertising; /* NWay media advertisement */
- unsigned char phys[2]; /* MII device addresses. */
+ int mii_cnt; /* MII device addresses. */
+ u16 advertising; /* NWay media advertisement */
+ unsigned char phys[MII_CNT]; /* MII device addresses. */
};
-static int mdio_read(struct net_device *dev, int phy_id, int location);
-static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
-static int netdev_open(struct net_device *dev);
-static void check_duplex(struct net_device *dev, int startup);
-static void netdev_timer(unsigned long data);
-static void tx_timeout(struct net_device *dev);
-static void init_ring(struct net_device *dev);
-static int start_tx(struct sk_buff *skb, struct net_device *dev);
-static void intr_handler(int irq, void *dev_instance, struct pt_regs *regs);
-static void netdev_error(struct net_device *dev, int intr_status);
-static int netdev_rx(struct net_device *dev);
-static void netdev_error(struct net_device *dev, int intr_status);
-static void set_rx_mode(struct net_device *dev);
+static int mdio_read(struct net_device *dev, int phy_id, int location);
+static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
+static int netdev_open(struct net_device *dev);
+static void check_duplex(struct net_device *dev, int startup);
+static void netdev_timer(unsigned long data);
+static void tx_timeout(struct net_device *dev);
+static void init_ring(struct net_device *dev);
+static int start_tx(struct sk_buff *skb, struct net_device *dev);
+static void intr_handler(int irq, void *dev_instance, struct pt_regs *regs);
+static void netdev_error(struct net_device *dev, int intr_status);
+static int netdev_rx(struct net_device *dev);
+static void netdev_error(struct net_device *dev, int intr_status);
+static void set_rx_mode(struct net_device *dev);
static struct net_device_stats *get_stats(struct net_device *dev);
-static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static int netdev_close(struct net_device *dev);
+static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static int netdev_close(struct net_device *dev);
-static int __devinit starfire_init_one (struct pci_dev *pdev,
- const struct pci_device_id *ent)
+static int __devinit starfire_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
struct netdev_private *np;
int i, irq, option, chip_idx = ent->driver_data;
struct net_device *dev;
static int card_idx = -1;
- static int printed_version = 0;
+ static int printed_version;
long ioaddr;
- int drv_flags, io_size = netdrv_tbl[chip_idx].io_size;
+ int drv_flags, io_size;
+ int boguscnt;
card_idx++;
option = card_idx < MAX_UNITS ? options[card_idx] : 0;
-
+
if (!printed_version++)
printk(KERN_INFO "%s" KERN_INFO "%s" KERN_INFO "%s",
- version1, version2, version3);
+ version1, version2, version3);
+
+ if (pci_enable_device (pdev))
+ return -EIO;
ioaddr = pci_resource_start (pdev, 0);
+ io_size = pci_resource_len (pdev, 0);
if (!ioaddr || ((pci_resource_flags (pdev, 0) & IORESOURCE_MEM) == 0)) {
printk (KERN_ERR "starfire %d: no PCI MEM resources, aborting\n", card_idx);
return -ENODEV;
}
-
- dev = init_etherdev(NULL, sizeof(*np));
+
+ dev = alloc_etherdev(sizeof(*np));
if (!dev) {
printk (KERN_ERR "starfire %d: cannot alloc etherdev, aborting\n", card_idx);
return -ENOMEM;
}
-
- irq = pdev->irq;
+ SET_MODULE_OWNER(dev);
- if (request_mem_region (ioaddr, io_size, dev->name) == NULL) {
- printk (KERN_ERR "starfire %d: resource 0x%x @ 0x%lx busy, aborting\n",
- card_idx, io_size, ioaddr);
+ irq = pdev->irq;
+
+ if (pci_request_regions (pdev, dev->name)) {
+ printk (KERN_ERR "starfire %d: cannot reserve PCI resources, aborting\n", card_idx);
goto err_out_free_netdev;
}
-
- if (pci_enable_device (pdev))
- goto err_out_free_res;
-
+
ioaddr = (long) ioremap (ioaddr, io_size);
if (!ioaddr) {
printk (KERN_ERR "starfire %d: cannot remap 0x%x @ 0x%lx, aborting\n",
@@ -427,32 +584,42 @@
}
pci_set_master (pdev);
-
- printk(KERN_INFO "%s: %s at 0x%lx, ",
- dev->name, netdrv_tbl[chip_idx].name, ioaddr);
/* Serial EEPROM reads are hidden by the hardware. */
for (i = 0; i < 6; i++)
dev->dev_addr[i] = readb(ioaddr + EEPROMCtrl + 20-i);
- for (i = 0; i < 5; i++)
- printk("%2.2x:", dev->dev_addr[i]);
- printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);
#if ! defined(final_version) /* Dump the EEPROM contents during development. */
if (debug > 4)
for (i = 0; i < 0x20; i++)
- printk("%2.2x%s", (unsigned int)readb(ioaddr + EEPROMCtrl + i),
- i % 16 != 15 ? " " : "\n");
+ printk("%2.2x%s",
+ (unsigned int)readb(ioaddr + EEPROMCtrl + i),
+ i % 16 != 15 ? " " : "\n");
#endif
+ /* Issue soft reset */
+ writel(0x8000, ioaddr + TxMode);
+ udelay(1000);
+ writel(0, ioaddr + TxMode);
+
/* Reset the chip to erase previous misconfiguration. */
writel(1, ioaddr + PCIDeviceConfig);
+ boguscnt = 1000;
+ while (--boguscnt > 0) {
+ udelay(10);
+ if ((readl(ioaddr + PCIDeviceConfig) & 1) == 0)
+ break;
+ }
+ if (boguscnt == 0)
+ printk("%s: chipset reset never completed!\n", dev->name);
+ /* wait a little longer */
+ udelay(1000);
dev->base_addr = ioaddr;
dev->irq = irq;
np = dev->priv;
- pdev->driver_data = dev;
+ pci_set_drvdata(pdev, dev);
np->pci_dev = pdev;
drv_flags = netdrv_tbl[chip_idx].drv_flags;
@@ -468,7 +635,7 @@
if (np->default_port)
np->medialock = 1;
}
- if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0)
+ if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0)
np->full_duplex = 1;
if (np->full_duplex)
@@ -477,8 +644,7 @@
/* The chip-specific entries in the device structure. */
dev->open = &netdev_open;
dev->hard_start_xmit = &start_tx;
- dev->tx_timeout = &tx_timeout;
- dev->watchdog_timeo = TX_TIMEOUT;
+ init_tx_timer(dev, tx_timeout, TX_TIMEOUT);
dev->stop = &netdev_close;
dev->get_stats = &get_stats;
dev->set_multicast_list = &set_rx_mode;
@@ -487,16 +653,39 @@
if (mtu)
dev->mtu = mtu;
+ i = register_netdev(dev);
+ if (i)
+ goto err_out_cleardev;
+
+ printk(KERN_INFO "%s: %s at 0x%lx, ",
+ dev->name, netdrv_tbl[chip_idx].name, ioaddr);
+ for (i = 0; i < 5; i++)
+ printk("%2.2x:", dev->dev_addr[i]);
+ printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);
+
if (drv_flags & CanHaveMII) {
int phy, phy_idx = 0;
- for (phy = 0; phy < 32 && phy_idx < 4; phy++) {
- int mii_status = mdio_read(dev, phy, 1);
- if (mii_status != 0xffff && mii_status != 0x0000) {
+ int mii_status;
+ for (phy = 0; phy < 32 && phy_idx < MII_CNT; phy++) {
+ mdio_write(dev, phy, 0, 0x8000);
+ udelay(500);
+ boguscnt = 1000;
+ while (--boguscnt > 0)
+ if ((mdio_read(dev, phy, 0) & 0x8000) == 0)
+ break;
+ if (boguscnt == 0) {
+ printk("%s: PHY reset never completed!\n", dev->name);
+ continue;
+ }
+ mii_status = mdio_read(dev, phy, 1);
+ if (mii_status != 0x0000) {
np->phys[phy_idx++] = phy;
np->advertising = mdio_read(dev, phy, 4);
printk(KERN_INFO "%s: MII PHY found at address %d, status "
"0x%4.4x advertising %4.4x.\n",
dev->name, phy, mii_status, np->advertising);
+ /* there can be only one PHY on-board */
+ break;
}
}
np->mii_cnt = phy_idx;
@@ -504,8 +693,11 @@
return 0;
+err_out_cleardev:
+ pci_set_drvdata(pdev, NULL);
+ iounmap((void *)ioaddr);
err_out_free_res:
- release_mem_region (ioaddr, io_size);
+ pci_release_regions (pdev);
err_out_free_netdev:
unregister_netdev (dev);
kfree (dev);
@@ -522,7 +714,11 @@
/* ??? Should we add a busy-wait here? */
do
result = readl(mdio_addr);
- while ((result & 0xC0000000) != 0x80000000 && --boguscnt >= 0);
+ while ((result & 0xC0000000) != 0x80000000 && --boguscnt > 0);
+ if (boguscnt == 0)
+ return 0;
+ if ((result & 0xffff) == 0xffff)
+ return 0;
return result & 0xffff;
}
@@ -537,17 +733,17 @@
static int netdev_open(struct net_device *dev)
{
- struct netdev_private *np = (struct netdev_private *)dev->priv;
+ struct netdev_private *np = dev->priv;
long ioaddr = dev->base_addr;
int i, retval;
/* Do we ever need to reset the chip??? */
- MOD_INC_USE_COUNT;
+ COMPAT_MOD_INC_USE_COUNT;
retval = request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev);
if (retval) {
- MOD_DEC_USE_COUNT;
+ COMPAT_MOD_DEC_USE_COUNT;
return retval;
}
@@ -556,40 +752,48 @@
writel(1, ioaddr + PCIDeviceConfig);
if (debug > 1)
printk(KERN_DEBUG "%s: netdev_open() irq %d.\n",
- dev->name, dev->irq);
+ dev->name, dev->irq);
/* Allocate the various queues, failing gracefully. */
if (np->tx_done_q == 0)
np->tx_done_q = pci_alloc_consistent(np->pci_dev, PAGE_SIZE, &np->tx_done_q_dma);
if (np->rx_done_q == 0)
- np->rx_done_q = pci_alloc_consistent(np->pci_dev, PAGE_SIZE, &np->rx_done_q_dma);
+ np->rx_done_q = pci_alloc_consistent(np->pci_dev, sizeof(struct rx_done_desc) * DONE_Q_SIZE, &np->rx_done_q_dma);
if (np->tx_ring == 0)
np->tx_ring = pci_alloc_consistent(np->pci_dev, PAGE_SIZE, &np->tx_ring_dma);
if (np->rx_ring == 0)
np->rx_ring = pci_alloc_consistent(np->pci_dev, PAGE_SIZE, &np->rx_ring_dma);
- if (np->tx_done_q == 0 || np->rx_done_q == 0
- || np->rx_ring == 0 || np->tx_ring == 0) {
+ if (np->tx_done_q == 0 || np->rx_done_q == 0
+ || np->rx_ring == 0 || np->tx_ring == 0) {
if (np->tx_done_q)
pci_free_consistent(np->pci_dev, PAGE_SIZE,
- np->tx_done_q, np->tx_done_q_dma);
+ np->tx_done_q, np->tx_done_q_dma);
if (np->rx_done_q)
- pci_free_consistent(np->pci_dev, PAGE_SIZE,
- np->rx_done_q, np->rx_done_q_dma);
+ pci_free_consistent(np->pci_dev, sizeof(struct rx_done_desc) * DONE_Q_SIZE,
+ np->rx_done_q, np->rx_done_q_dma);
if (np->tx_ring)
pci_free_consistent(np->pci_dev, PAGE_SIZE,
- np->tx_ring, np->tx_ring_dma);
+ np->tx_ring, np->tx_ring_dma);
if (np->rx_ring)
pci_free_consistent(np->pci_dev, PAGE_SIZE,
- np->rx_ring, np->rx_ring_dma);
- MOD_DEC_USE_COUNT;
+ np->rx_ring, np->rx_ring_dma);
+ COMPAT_MOD_DEC_USE_COUNT;
return -ENOMEM;
}
init_ring(dev);
/* Set the size of the Rx buffers. */
- writel((np->rx_buf_sz<<16) | 0xA000, ioaddr + RxDescQCtrl);
+ writel((np->rx_buf_sz << RxBufferLenShift) |
+ (0 << RxMinDescrThreshShift) |
+ RxPrefetchMode | RxVariableQ |
+ RxDescSpace4,
+ ioaddr + RxDescQCtrl);
/* Set Tx descriptor to type 1 and padding to 0 bytes. */
- writel(0x02000401, ioaddr + TxDescCtrl);
+ writel((2 << TxHiPriFIFOThreshShift) |
+ (0 << TxPadLenShift) |
+ (4 << TxDMABurstSizeShift) |
+ TxDescSpaceUnlim | TxDescType1,
+ ioaddr + TxDescCtrl);
#if defined(ADDR_64BITS) && defined(__alpha__)
/* XXX We really need a 64-bit PCI dma interfaces too... -DaveM */
@@ -604,10 +808,27 @@
writel(np->tx_ring_dma, ioaddr + TxRingPtr);
writel(np->tx_done_q_dma, ioaddr + TxCompletionAddr);
- writel(np->rx_done_q_dma, ioaddr + RxCompletionAddr);
+#ifdef full_rx_status
+ writel(np->rx_done_q_dma |
+ RxComplType3 |
+ (0 << RxComplThreshShift),
+ ioaddr + RxCompletionAddr);
+#else /* not full_rx_status */
+#ifdef csum_rx_status
+ writel(np->rx_done_q_dma |
+ RxComplType2 |
+ (0 << RxComplThreshShift),
+ ioaddr + RxCompletionAddr);
+#else /* not csum_rx_status */
+ writel(np->rx_done_q_dma |
+ RxComplType0 |
+ (0 << RxComplThreshShift),
+ ioaddr + RxCompletionAddr);
+#endif /* not csum_rx_status */
+#endif /* not full_rx_status */
if (debug > 1)
- printk(KERN_DEBUG "%s: Filling in the station address.\n", dev->name);
+ printk(KERN_DEBUG "%s: Filling in the station address.\n", dev->name);
/* Fill both the unused Tx SA register and the Rx perfect filter. */
for (i = 0; i < 6; i++)
@@ -630,29 +851,41 @@
if (dev->if_port == 0)
dev->if_port = np->default_port;
+ netif_start_if(dev);
netif_start_queue(dev);
if (debug > 1)
- printk(KERN_DEBUG "%s: Setting the Rx and Tx modes.\n", dev->name);
+ printk(KERN_DEBUG "%s: Setting the Rx and Tx modes.\n", dev->name);
set_rx_mode(dev);
np->advertising = mdio_read(dev, np->phys[0], 4);
check_duplex(dev, 1);
/* Set the interrupt mask and enable PCI interrupts. */
- writel(IntrRxDone | IntrRxEmpty | IntrRxPCIErr |
- IntrTxDone | IntrTxEmpty | IntrTxPCIErr |
- StatsMax | LinkChange | IntrNormalSummary | IntrAbnormalSummary
- | 0x0010 , ioaddr + IntrEnable);
+ writel(IntrRxDone | IntrRxEmpty | IntrDMAErr |
+ IntrTxDone | IntrStatsMax | IntrLinkChange |
+ IntrNormalSummary | IntrAbnormalSummary |
+ IntrRxGFPDead | IntrNoTxCsum | IntrTxBadID,
+ ioaddr + IntrEnable);
writel(0x00800000 | readl(ioaddr + PCIDeviceConfig),
- ioaddr + PCIDeviceConfig);
+ ioaddr + PCIDeviceConfig);
- /* Enable the Rx and Tx units. */
+#ifdef HAS_FIRMWARE
+ /* Load Rx/Tx firmware into the frame processors */
+ for (i = 0; i < FIRMWARE_RX_SIZE * 2; i++)
+ writel(cpu_to_le32(firmware_rx[i]), ioaddr + RxGfpMem + i * 4);
+ for (i = 0; i < FIRMWARE_TX_SIZE * 2; i++)
+ writel(cpu_to_le32(firmware_tx[i]), ioaddr + TxGfpMem + i * 4);
+ /* Enable the Rx and Tx units, and the Rx/Tx frame processors. */
+ writel(0x003F, ioaddr + GenCtrl);
+#else /* not HAS_FIRMWARE */
+ /* Enable the Rx and Tx units only. */
writel(0x000F, ioaddr + GenCtrl);
+#endif /* not HAS_FIRMWARE */
if (debug > 2)
printk(KERN_DEBUG "%s: Done netdev_open().\n",
- dev->name);
+ dev->name);
/* Set the timer to check for link beat. */
init_timer(&np->timer);
@@ -666,7 +899,7 @@
static void check_duplex(struct net_device *dev, int startup)
{
- struct netdev_private *np = (struct netdev_private *)dev->priv;
+ struct netdev_private *np = dev->priv;
long ioaddr = dev->base_addr;
int new_tx_mode ;
@@ -685,8 +918,8 @@
np->full_duplex = duplex;
if (debug > 1)
printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d"
- " negotiated capability %4.4x.\n", dev->name,
- duplex ? "full" : "half", np->phys[0], negotiated);
+ " negotiated capability %4.4x.\n", dev->name,
+ duplex ? "full" : "half", np->phys[0], negotiated);
}
}
if (new_tx_mode != np->tx_mode) {
@@ -699,13 +932,13 @@
static void netdev_timer(unsigned long data)
{
struct net_device *dev = (struct net_device *)data;
- struct netdev_private *np = (struct netdev_private *)dev->priv;
+ struct netdev_private *np = dev->priv;
long ioaddr = dev->base_addr;
int next_tick = 60*HZ; /* Check before driver release. */
if (debug > 3) {
printk(KERN_DEBUG "%s: Media selection timer tick, status %8.8x.\n",
- dev->name, (int)readl(ioaddr + IntrStatus));
+ dev->name, (int)readl(ioaddr + IntrStatus));
}
check_duplex(dev, 0);
#if ! defined(final_version)
@@ -715,7 +948,7 @@
/* Bogus hardware IRQ: Fake an interrupt handler call. */
if (new_status & 1) {
printk(KERN_ERR "%s: Interrupt blocked, status %8.8x/%8.8x.\n",
- dev->name, new_status, (int)readl(ioaddr + IntrStatus));
+ dev->name, new_status, (int)readl(ioaddr + IntrStatus));
intr_handler(dev->irq, dev, 0);
}
}
@@ -727,11 +960,11 @@
static void tx_timeout(struct net_device *dev)
{
- struct netdev_private *np = (struct netdev_private *)dev->priv;
+ struct netdev_private *np = dev->priv;
long ioaddr = dev->base_addr;
printk(KERN_WARNING "%s: Transmit timed out, status %8.8x,"
- " resetting...\n", dev->name, (int)readl(ioaddr + IntrStatus));
+ " resetting...\n", dev->name, (int)readl(ioaddr + IntrStatus));
#ifndef __alpha__
{
@@ -754,14 +987,14 @@
dev->trans_start = jiffies;
np->stats.tx_errors++;
- return;
+ netif_wake_queue(dev);
}
/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
static void init_ring(struct net_device *dev)
{
- struct netdev_private *np = (struct netdev_private *)dev->priv;
+ struct netdev_private *np = dev->priv;
int i;
np->tx_full = 0;
@@ -801,7 +1034,7 @@
for (i = 0; i < TX_RING_SIZE; i++) {
np->tx_info[i].skb = NULL;
- np->tx_info[i].mapping = 0;
+ np->tx_info[i].first_mapping = 0;
np->tx_ring[i].status = 0;
}
return;
@@ -809,8 +1042,10 @@
static int start_tx(struct sk_buff *skb, struct net_device *dev)
{
- struct netdev_private *np = (struct netdev_private *)dev->priv;
- unsigned entry;
+ struct netdev_private *np = dev->priv;
+ unsigned int entry;
+
+ kick_tx_timer(dev, tx_timeout, TX_TIMEOUT);
/* Caution: the write order is important here, set the field
with the "ownership" bits last. */
@@ -819,41 +1054,43 @@
entry = np->cur_tx % TX_RING_SIZE;
np->tx_info[entry].skb = skb;
- np->tx_info[entry].mapping =
- pci_map_single(np->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE);
+ np->tx_info[entry].first_mapping =
+ pci_map_single(np->pci_dev, skb->data, skb_first_frag_len(skb), PCI_DMA_TODEVICE);
+
+ np->tx_ring[entry].first_addr = cpu_to_le32(np->tx_info[entry].first_mapping);
+ /* Add "| TxDescIntr" to generate Tx-done interrupts. */
+ np->tx_ring[entry].status = cpu_to_le32(skb->len | TxDescID | TxCRCEn | 1 << 16);
+
+ if (entry >= TX_RING_SIZE-1) /* Wrap ring */
+ np->tx_ring[entry].status |= cpu_to_le32(TxRingWrap | TxDescIntr);
- np->tx_ring[entry].addr = cpu_to_le32(np->tx_info[entry].mapping);
- /* Add "| TxDescIntr" to generate Tx-done interrupts. */
- np->tx_ring[entry].status = cpu_to_le32(skb->len | TxDescID);
if (debug > 5) {
- printk(KERN_DEBUG "%s: Tx #%d slot %d %8.8x %8.8x.\n",
- dev->name, np->cur_tx, entry,
- le32_to_cpu(np->tx_ring[entry].status),
- le32_to_cpu(np->tx_ring[entry].addr));
+ printk(KERN_DEBUG "%s: Tx #%d slot %d status %8.8x.\n",
+ dev->name, np->cur_tx, entry,
+ le32_to_cpu(np->tx_ring[entry].status));
}
+
np->cur_tx++;
-#if 1
- if (entry >= TX_RING_SIZE-1) { /* Wrap ring */
- np->tx_ring[entry].status |= cpu_to_le32(TxRingWrap | TxDescIntr);
+
+ if (entry >= TX_RING_SIZE-1) /* Wrap ring */
entry = -1;
- }
-#endif
+ entry++;
/* Non-x86: explicitly flush descriptor cache lines here. */
+ /* Ensure everything is written back above before the transmit is
+ initiated. - Jes */
+ wmb();
/* Update the producer index. */
- writel(++entry, dev->base_addr + TxProducerIdx);
+ writel(entry * (sizeof(struct starfire_tx_desc) / 8), dev->base_addr + TxProducerIdx);
if (np->cur_tx - np->dirty_tx >= TX_RING_SIZE - 1) {
np->tx_full = 1;
netif_stop_queue(dev);
}
+
dev->trans_start = jiffies;
- if (debug > 4) {
- printk(KERN_DEBUG "%s: Transmit frame #%d queued in slot %d.\n",
- dev->name, np->cur_tx, entry);
- }
return 0;
}
@@ -865,24 +1102,25 @@
struct netdev_private *np;
long ioaddr;
int boguscnt = max_interrupt_work;
+ int consumer;
+ int tx_status;
#ifndef final_version /* Can never occur. */
if (dev == NULL) {
- printk (KERN_ERR "Netdev interrupt handler(): IRQ %d for unknown "
- "device.\n", irq);
+ printk (KERN_ERR "Netdev interrupt handler(): IRQ %d for unknown device.\n", irq);
return;
}
#endif
ioaddr = dev->base_addr;
- np = (struct netdev_private *)dev->priv;
+ np = dev->priv;
do {
u32 intr_status = readl(ioaddr + IntrClear);
if (debug > 4)
printk(KERN_DEBUG "%s: Interrupt status %4.4x.\n",
- dev->name, intr_status);
+ dev->name, intr_status);
if (intr_status == 0)
break;
@@ -893,48 +1131,48 @@
/* Scavenge the skbuff list based on the Tx-done queue.
There are redundant checks here that may be cleaned up
after the driver has proven to be reliable. */
- {
- int consumer = readl(ioaddr + TxConsumerIdx);
- int tx_status;
- if (debug > 4)
- printk(KERN_DEBUG "%s: Tx Consumer index is %d.\n",
- dev->name, consumer);
+ consumer = readl(ioaddr + TxConsumerIdx);
+ if (debug > 4)
+ printk(KERN_DEBUG "%s: Tx Consumer index is %d.\n",
+ dev->name, consumer);
#if 0
- if (np->tx_done >= 250 || np->tx_done == 0)
- printk(KERN_DEBUG "%s: Tx completion entry %d is %8.8x, "
- "%d is %8.8x.\n", dev->name,
- np->tx_done, le32_to_cpu(np->tx_done_q[np->tx_done].status),
- (np->tx_done+1) & (DONE_Q_SIZE-1),
- le32_to_cpu(np->tx_done_q[(np->tx_done+1)&(DONE_Q_SIZE-1)].status));
+ if (np->tx_done >= 250 || np->tx_done == 0)
+ printk(KERN_DEBUG "%s: Tx completion entry %d is %8.8x, %d is %8.8x.\n",
+ dev->name, np->tx_done,
+ le32_to_cpu(np->tx_done_q[np->tx_done].status),
+ (np->tx_done+1) & (DONE_Q_SIZE-1),
+ le32_to_cpu(np->tx_done_q[(np->tx_done+1)&(DONE_Q_SIZE-1)].status));
#endif
- while ((tx_status = le32_to_cpu(np->tx_done_q[np->tx_done].status))
- != 0) {
- if (debug > 4)
- printk(KERN_DEBUG "%s: Tx completion entry %d is %8.8x.\n",
- dev->name, np->tx_done, tx_status);
- if ((tx_status & 0xe0000000) == 0xa0000000) {
- np->stats.tx_packets++;
- } else if ((tx_status & 0xe0000000) == 0x80000000) {
- struct sk_buff *skb;
- u16 entry = tx_status; /* Implicit truncate */
- entry >>= 3;
-
- skb = np->tx_info[entry].skb;
- pci_unmap_single(np->pci_dev,
- np->tx_info[entry].mapping,
- skb->len, PCI_DMA_TODEVICE);
-
- /* Scavenge the descriptor. */
- dev_kfree_skb_irq(skb);
- np->tx_info[entry].skb = NULL;
- np->tx_info[entry].mapping = 0;
- np->dirty_tx++;
- }
- np->tx_done_q[np->tx_done].status = 0;
- np->tx_done = (np->tx_done+1) & (DONE_Q_SIZE-1);
+
+ while ((tx_status = le32_to_cpu(np->tx_done_q[np->tx_done].status)) != 0) {
+ if (debug > 4)
+ printk(KERN_DEBUG "%s: Tx completion entry %d is %8.8x.\n",
+ dev->name, np->tx_done, tx_status);
+ if ((tx_status & 0xe0000000) == 0xa0000000) {
+ np->stats.tx_packets++;
+ } else if ((tx_status & 0xe0000000) == 0x80000000) {
+ struct sk_buff *skb;
+ u16 entry = tx_status; /* Implicit truncate */
+ entry /= sizeof(struct starfire_tx_desc);
+
+ skb = np->tx_info[entry].skb;
+ np->tx_info[entry].skb = NULL;
+ pci_unmap_single(np->pci_dev,
+ np->tx_info[entry].first_mapping,
+ skb_first_frag_len(skb),
+ PCI_DMA_TODEVICE);
+ np->tx_info[entry].first_mapping = 0;
+
+ /* Scavenge the descriptor. */
+ dev_kfree_skb_irq(skb);
+
+ np->dirty_tx++;
}
- writew(np->tx_done, ioaddr + CompletionQConsumerIdx + 2);
+ np->tx_done_q[np->tx_done].status = 0;
+ np->tx_done = (np->tx_done+1) & (DONE_Q_SIZE-1);
}
+ writew(np->tx_done, ioaddr + CompletionQConsumerIdx + 2);
+
if (np->tx_full && np->cur_tx - np->dirty_tx < TX_RING_SIZE - 4) {
/* The ring is no longer full, wake the queue. */
np->tx_full = 0;
@@ -947,23 +1185,23 @@
if (--boguscnt < 0) {
printk(KERN_WARNING "%s: Too much work at interrupt, "
- "status=0x%4.4x.\n",
- dev->name, intr_status);
+ "status=0x%4.4x.\n",
+ dev->name, intr_status);
break;
}
} while (1);
if (debug > 4)
printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
- dev->name, (int)readl(ioaddr + IntrStatus));
+ dev->name, (int)readl(ioaddr + IntrStatus));
#ifndef final_version
/* Code that should never be run! Remove after testing.. */
{
static int stopit = 10;
- if (!netif_running(dev) && --stopit < 0) {
+ if (!netif_running(dev) && --stopit < 0) {
printk(KERN_ERR "%s: Emergency stop, looping startup interrupt.\n",
- dev->name);
+ dev->name);
free_irq(irq, dev);
}
}
@@ -974,97 +1212,105 @@
for clarity and better register allocation. */
static int netdev_rx(struct net_device *dev)
{
- struct netdev_private *np = (struct netdev_private *)dev->priv;
+ struct netdev_private *np = dev->priv;
int boguscnt = np->dirty_rx + RX_RING_SIZE - np->cur_rx;
u32 desc_status;
if (np->rx_done_q == 0) {
printk(KERN_ERR "%s: rx_done_q is NULL! rx_done is %d. %p.\n",
- dev->name, np->rx_done, np->tx_done_q);
+ dev->name, np->rx_done, np->tx_done_q);
return 0;
}
/* If EOP is set on the next entry, it's a new packet. Send it up. */
while ((desc_status = le32_to_cpu(np->rx_done_q[np->rx_done].status)) != 0) {
+ struct sk_buff *skb;
+ u16 pkt_len;
+ int entry;
+
if (debug > 4)
- printk(KERN_DEBUG " netdev_rx() status of %d was %8.8x.\n",
- np->rx_done, desc_status);
+ printk(KERN_DEBUG " netdev_rx() status of %d was %8.8x.\n", np->rx_done, desc_status);
if (--boguscnt < 0)
break;
if ( ! (desc_status & RxOK)) {
/* There was a error. */
if (debug > 2)
- printk(KERN_DEBUG " netdev_rx() Rx error was %8.8x.\n",
- desc_status);
+ printk(KERN_DEBUG " netdev_rx() Rx error was %8.8x.\n", desc_status);
np->stats.rx_errors++;
if (desc_status & RxFIFOErr)
np->stats.rx_fifo_errors++;
- } else {
- struct sk_buff *skb;
- u16 pkt_len = desc_status; /* Implicitly Truncate */
- int entry = (desc_status >> 16) & 0x7ff;
+ goto next_rx;
+ }
+
+ pkt_len = desc_status; /* Implicitly Truncate */
+ entry = (desc_status >> 16) & 0x7ff;
#ifndef final_version
- if (debug > 4)
- printk(KERN_DEBUG " netdev_rx() normal Rx pkt length %d"
- ", bogus_cnt %d.\n",
- pkt_len, boguscnt);
+ if (debug > 4)
+ printk(KERN_DEBUG " netdev_rx() normal Rx pkt length %d, bogus_cnt %d.\n", pkt_len, boguscnt);
#endif
- /* Check if the packet is long enough to accept without copying
- to a minimally-sized skbuff. */
- if (pkt_len < rx_copybreak
- && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
- skb->dev = dev;
- skb_reserve(skb, 2); /* 16 byte align the IP header */
- pci_dma_sync_single(np->pci_dev,
- np->rx_info[entry].mapping,
- pkt_len, PCI_DMA_FROMDEVICE);
+ /* Check if the packet is long enough to accept without copying
+ to a minimally-sized skbuff. */
+ if (pkt_len < rx_copybreak
+ && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+ skb->dev = dev;
+ skb_reserve(skb, 2); /* 16 byte align the IP header */
+ pci_dma_sync_single(np->pci_dev,
+ np->rx_info[entry].mapping,
+ pkt_len, PCI_DMA_FROMDEVICE);
#if HAS_IP_COPYSUM /* Call copy + cksum if available. */
- eth_copy_and_sum(skb, np->rx_info[entry].skb->tail, pkt_len, 0);
- skb_put(skb, pkt_len);
+ eth_copy_and_sum(skb, np->rx_info[entry].skb->tail, pkt_len, 0);
+ skb_put(skb, pkt_len);
#else
- memcpy(skb_put(skb, pkt_len), np->rx_info[entry].skb->tail,
- pkt_len);
+ memcpy(skb_put(skb, pkt_len), np->rx_info[entry].skb->tail, pkt_len);
#endif
- } else {
- char *temp;
+ } else {
+ char *temp;
- pci_unmap_single(np->pci_dev, np->rx_info[entry].mapping, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
- skb = np->rx_info[entry].skb;
- temp = skb_put(skb, pkt_len);
- np->rx_info[entry].skb = NULL;
- np->rx_info[entry].mapping = 0;
-#ifndef final_version /* Remove after testing. */
- if (le32_to_cpu(np->rx_ring[entry].rxaddr & ~3) != ((unsigned long) temp))
- printk(KERN_ERR "%s: Internal fault: The skbuff addresses "
- "do not match in netdev_rx: %d vs. %p / %p.\n",
- dev->name,
- le32_to_cpu(np->rx_ring[entry].rxaddr),
- skb->head, temp);
-#endif
- }
-#ifndef final_version /* Remove after testing. */
- /* You will want this info for the initial debug. */
- if (debug > 5)
- printk(KERN_DEBUG " Rx data %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:"
- "%2.2x %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x %2.2x%2.2x "
- "%d.%d.%d.%d.\n",
- skb->data[0], skb->data[1], skb->data[2], skb->data[3],
- skb->data[4], skb->data[5], skb->data[6], skb->data[7],
- skb->data[8], skb->data[9], skb->data[10],
- skb->data[11], skb->data[12], skb->data[13],
- skb->data[14], skb->data[15], skb->data[16],
- skb->data[17]);
-#endif
- skb->protocol = eth_type_trans(skb, dev);
-#ifdef full_rx_status
- if (le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0x01000000)
- skb->ip_summed = CHECKSUM_UNNECESSARY;
+ pci_unmap_single(np->pci_dev, np->rx_info[entry].mapping, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
+ skb = np->rx_info[entry].skb;
+ temp = skb_put(skb, pkt_len);
+ np->rx_info[entry].skb = NULL;
+ np->rx_info[entry].mapping = 0;
+ }
+#ifndef final_version /* Remove after testing. */
+ /* You will want this info for the initial debug. */
+ if (debug > 5)
+ printk(KERN_DEBUG " Rx data %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:"
+ "%2.2x %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x %2.2x%2.2x "
+ "%d.%d.%d.%d.\n",
+ skb->data[0], skb->data[1], skb->data[2], skb->data[3],
+ skb->data[4], skb->data[5], skb->data[6], skb->data[7],
+ skb->data[8], skb->data[9], skb->data[10],
+ skb->data[11], skb->data[12], skb->data[13],
+ skb->data[14], skb->data[15], skb->data[16],
+ skb->data[17]);
#endif
- netif_rx(skb);
- dev->last_rx = jiffies;
- np->stats.rx_packets++;
+ skb->protocol = eth_type_trans(skb, dev);
+#if defined(full_rx_status) || defined(csum_rx_status)
+ if (le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0x01000000) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ }
+ /*
+ * This feature doesn't seem to be working, at least
+ * with the two firmware versions I have. If the GFP sees
+ * a fragment, it either ignores it completely, or reports
+ * "bad checksum" on it.
+ *
+ * Maybe I missed something -- corrections are welcome.
+ * Until then, the printk stays. :-) -Ion
+ */
+ else if (le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0x00400000) {
+ skb->ip_summed = CHECKSUM_HW;
+ skb->csum = le32_to_cpu(np->rx_done_q[np->rx_done].status2) & 0xffff;
+ printk(KERN_DEBUG "%s: checksum_hw, status2 = %x\n", dev->name, np->rx_done_q[np->rx_done].status2);
}
+#endif
+ netif_rx(skb);
+ dev->last_rx = jiffies;
+ np->stats.rx_packets++;
+
+next_rx:
np->cur_rx++;
np->rx_done_q[np->rx_done].status = 0;
np->rx_done = (np->rx_done + 1) & (DONE_Q_SIZE-1);
@@ -1079,10 +1325,10 @@
skb = dev_alloc_skb(np->rx_buf_sz);
np->rx_info[entry].skb = skb;
if (skb == NULL)
- break; /* Better luck next round. */
+ break; /* Better luck next round. */
np->rx_info[entry].mapping =
pci_map_single(np->pci_dev, skb->tail, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
- skb->dev = dev; /* Mark as being used by this device. */
+ skb->dev = dev; /* Mark as being used by this device. */
np->rx_ring[entry].rxaddr =
cpu_to_le32(np->rx_info[entry].mapping | RxDescValid);
}
@@ -1093,10 +1339,10 @@
}
if (debug > 5
- || memcmp(np->pad0, np->pad0 + 1, sizeof(np->pad0) -1))
+ || memcmp(np->pad0, np->pad0 + 1, sizeof(np->pad0) -1))
printk(KERN_DEBUG " exiting netdev_rx() status of %d was %8.8x %d.\n",
- np->rx_done, desc_status,
- memcmp(np->pad0, np->pad0 + 1, sizeof(np->pad0) -1));
+ np->rx_done, desc_status,
+ memcmp(np->pad0, np->pad0 + 1, sizeof(np->pad0) -1));
/* Restart Rx engine if stopped. */
return 0;
@@ -1104,36 +1350,36 @@
static void netdev_error(struct net_device *dev, int intr_status)
{
- struct netdev_private *np = (struct netdev_private *)dev->priv;
+ struct netdev_private *np = dev->priv;
- if (intr_status & LinkChange) {
+ if (intr_status & IntrLinkChange) {
printk(KERN_NOTICE "%s: Link changed: Autonegotiation advertising"
- " %4.4x partner %4.4x.\n", dev->name,
- mdio_read(dev, np->phys[0], 4),
- mdio_read(dev, np->phys[0], 5));
+ " %4.4x, partner %4.4x.\n", dev->name,
+ mdio_read(dev, np->phys[0], 4),
+ mdio_read(dev, np->phys[0], 5));
check_duplex(dev, 0);
}
- if (intr_status & StatsMax) {
+ if (intr_status & IntrStatsMax) {
get_stats(dev);
}
/* Came close to underrunning the Tx FIFO, increase threshold. */
- if (intr_status & IntrTxDataLow)
+ if (intr_status & IntrTxDataLow) {
writel(++np->tx_threshold, dev->base_addr + TxThreshold);
- if ((intr_status &
- ~(IntrAbnormalSummary|LinkChange|StatsMax|IntrTxDataLow|1)) && debug)
+ printk(KERN_NOTICE "%s: Increasing Tx FIFO threshold to %d bytes\n",
+ dev->name, np->tx_threshold * 16);
+ }
+ if ((intr_status & ~(IntrNormalMask | IntrAbnormalSummary | IntrLinkChange | IntrStatsMax | IntrTxDataLow | IntrPCIPad)) && debug)
printk(KERN_ERR "%s: Something Wicked happened! %4.4x.\n",
- dev->name, intr_status);
- /* Hmmmmm, it's not clear how to recover from PCI faults. */
- if (intr_status & IntrTxPCIErr)
+ dev->name, intr_status);
+ /* Hmmmmm, it's not clear how to recover from DMA faults. */
+ if (intr_status & IntrDMAErr)
np->stats.tx_fifo_errors++;
- if (intr_status & IntrRxPCIErr)
- np->stats.rx_fifo_errors++;
}
static struct net_device_stats *get_stats(struct net_device *dev)
{
long ioaddr = dev->base_addr;
- struct netdev_private *np = (struct netdev_private *)dev->priv;
+ struct netdev_private *np = dev->priv;
/* This adapter architecture needs no SMP locks. */
np->stats.tx_bytes = readl(ioaddr + 0x57010);
@@ -1142,12 +1388,13 @@
np->stats.tx_aborted_errors =
readl(ioaddr + 0x57024) + readl(ioaddr + 0x57028);
np->stats.tx_window_errors = readl(ioaddr + 0x57018);
- np->stats.collisions = readl(ioaddr + 0x57004) + readl(ioaddr + 0x57008);
+ np->stats.collisions =
+ readl(ioaddr + 0x57004) + readl(ioaddr + 0x57008);
/* The chip only need report frame silently dropped. */
- np->stats.rx_dropped += readw(ioaddr + RxDMAStatus);
+ np->stats.rx_dropped += readw(ioaddr + RxDMAStatus);
writew(0, ioaddr + RxDMAStatus);
- np->stats.rx_crc_errors = readl(ioaddr + 0x5703C);
+ np->stats.rx_crc_errors = readl(ioaddr + 0x5703C);
np->stats.rx_frame_errors = readl(ioaddr + 0x57040);
np->stats.rx_length_errors = readl(ioaddr + 0x57058);
np->stats.rx_missed_errors = readl(ioaddr + 0x5707C);
@@ -1188,19 +1435,19 @@
struct dev_mc_list *mclist;
int i;
- if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */
+ if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */
/* Unconditionally log net taps. */
printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name);
rx_mode = AcceptBroadcast|AcceptAllMulticast|AcceptAll|AcceptMyPhys;
} else if ((dev->mc_count > multicast_filter_limit)
- || (dev->flags & IFF_ALLMULTI)) {
+ || (dev->flags & IFF_ALLMULTI)) {
/* Too many to match, or accept all multicasts. */
rx_mode = AcceptBroadcast|AcceptAllMulticast|AcceptMyPhys;
} else if (dev->mc_count <= 15) {
/* Use the 16 element perfect filter. */
long filter_addr = ioaddr + 0x56000 + 1*16;
- for (i = 1, mclist = dev->mc_list; mclist && i <= dev->mc_count;
- i++, mclist = mclist->next) {
+ for (i = 1, mclist = dev->mc_list; mclist && i <= dev->mc_count;
+ i++, mclist = mclist->next) {
u16 *eaddrs = (u16 *)mclist->dmi_addr;
writew(cpu_to_be16(eaddrs[2]), filter_addr); filter_addr += 4;
writew(cpu_to_be16(eaddrs[1]), filter_addr); filter_addr += 4;
@@ -1219,7 +1466,7 @@
memset(mc_filter, 0, sizeof(mc_filter));
for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
- i++, mclist = mclist->next) {
+ i++, mclist = mclist->next) {
set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 23, mc_filter);
}
/* Clear the perfect filter list. */
@@ -1238,7 +1485,7 @@
static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
- struct netdev_private *np = (struct netdev_private *)dev->priv;
+ struct netdev_private *np = dev->priv;
u16 *data = (u16 *)&rq->ifr_data;
switch(cmd) {
@@ -1276,10 +1523,11 @@
static int netdev_close(struct net_device *dev)
{
long ioaddr = dev->base_addr;
- struct netdev_private *np = (struct netdev_private *)dev->priv;
+ struct netdev_private *np = dev->priv;
int i;
netif_stop_queue(dev);
+ netif_stop_if(dev);
del_timer_sync(&np->timer);
@@ -1301,15 +1549,15 @@
np->tx_ring_dma);
for (i = 0; i < 8 /* TX_RING_SIZE is huge! */; i++)
printk(KERN_DEBUG " #%d desc. %8.8x %8.8x -> %8.8x.\n",
- i, le32_to_cpu(np->tx_ring[i].status),
- le32_to_cpu(np->tx_ring[i].addr),
- le32_to_cpu(np->tx_done_q[i].status));
+ i, le32_to_cpu(np->tx_ring[i].status),
+ le32_to_cpu(np->tx_ring[i].first_addr),
+ le32_to_cpu(np->tx_done_q[i].status));
printk(KERN_DEBUG " Rx ring at %8.8x -> %p:\n",
- np->rx_ring_dma, np->rx_done_q);
+ np->rx_ring_dma, np->rx_done_q);
if (np->rx_done_q)
for (i = 0; i < 8 /* RX_RING_SIZE */; i++) {
printk(KERN_DEBUG " #%d desc. %8.8x -> %8.8x\n",
- i, le32_to_cpu(np->rx_ring[i].rxaddr), le32_to_cpu(np->rx_done_q[i].status));
+ i, le32_to_cpu(np->rx_ring[i].rxaddr), le32_to_cpu(np->rx_done_q[i].status));
}
}
#endif /* __i386__ debugging only */
@@ -1328,17 +1576,17 @@
}
for (i = 0; i < TX_RING_SIZE; i++) {
struct sk_buff *skb = np->tx_info[i].skb;
- if (skb != NULL) {
- pci_unmap_single(np->pci_dev,
- np->tx_info[i].mapping,
- skb->len, PCI_DMA_TODEVICE);
- dev_kfree_skb(skb);
- }
+ if (skb == NULL)
+ continue;
+ pci_unmap_single(np->pci_dev,
+ np->tx_info[i].first_mapping,
+ skb_first_frag_len(skb), PCI_DMA_TODEVICE);
+ np->tx_info[i].first_mapping = 0;
+ dev_kfree_skb(skb);
np->tx_info[i].skb = NULL;
- np->tx_info[i].mapping = 0;
}
- MOD_DEC_USE_COUNT;
+ COMPAT_MOD_DEC_USE_COUNT;
return 0;
}
@@ -1346,9 +1594,9 @@
static void __devexit starfire_remove_one (struct pci_dev *pdev)
{
- struct net_device *dev = pdev->driver_data;
+ struct net_device *dev = pci_get_drvdata(pdev);
struct netdev_private *np;
-
+
if (!dev)
BUG();
@@ -1356,6 +1604,7 @@
unregister_netdev(dev);
iounmap((char *)dev->base_addr);
+ pci_release_regions(pdev);
if (np->tx_done_q)
pci_free_consistent(np->pci_dev, PAGE_SIZE,
@@ -1371,6 +1620,8 @@
np->rx_ring, np->rx_ring_dma);
kfree(dev);
+
+ pci_set_drvdata(pdev, NULL);
}
@@ -1402,8 +1653,7 @@
* Local variables:
* compile-command: "gcc -DMODULE -Wall -Wstrict-prototypes -O6 -c starfire.c"
* simple-compile-command: "gcc -DMODULE -O6 -c starfire.c"
- * c-indent-level: 4
- * c-basic-offset: 4
- * tab-width: 4
+ * c-basic-offset: 8
+ * tab-width: 8
* End:
*/
On Thu, 19 Apr 2001, Alan Cox wrote:
> 2.4.3-ac10
> o Merge Linus 2.4.4pre4
> o Reorder frame buffer probes (Geert Uytterhoeven)
These got somewhat mixed. Remove the duplicates:
--- linux-2.4.3-ac10/drivers/video/fbmem.c.orig Fri Apr 20 09:58:50 2001
+++ linux-2.4.3-ac10/drivers/video/fbmem.c Fri Apr 20 11:33:28 2001
@@ -205,9 +205,6 @@
#if defined(CONFIG_FB_SIS) && (defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315))
{ "sisfb", sisfb_init, sisfb_setup },
#endif
-#ifdef CONFIG_FB_E1355
- { "e1355fb", e1355fb_init, e1355fb_setup },
-#endif
/*
* Generic drivers that are used as fallbacks
@@ -275,9 +272,6 @@
#endif
#ifdef CONFIG_FB_E1355
{ "e1355fb", e1355fb_init, e1355fb_setup },
-#endif
-#ifdef CONFIG_FB_DC
- { "dcfb", dcfb_init, NULL },
#endif
#ifdef CONFIG_FB_DC
{ "dcfb", dcfb_init, NULL },
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds